@opengeni/api-router 0.12.12 → 0.14.3

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 (87) hide show
  1. package/dist/app.d.ts +18 -38
  2. package/dist/app.js +3 -1
  3. package/dist/auth/managed-auth.d.ts +35 -0
  4. package/dist/{chunk-5TULDPWX.js → chunk-36PW33ND.js} +4111 -1277
  5. package/dist/chunk-36PW33ND.js.map +1 -0
  6. package/dist/codex-redemption-security.d.ts +15 -0
  7. package/dist/github-access.d.ts +12 -0
  8. package/dist/github-browser-flow.d.ts +14 -0
  9. package/dist/http/auth.d.ts +3 -0
  10. package/dist/http/common.d.ts +3 -0
  11. package/dist/http/sse.d.ts +70 -0
  12. package/dist/index.d.ts +11 -13
  13. package/dist/index.js +1 -1
  14. package/dist/integrations/google-drive.d.ts +76 -0
  15. package/dist/integrations/oauth-client.d.ts +42 -0
  16. package/dist/integrations/provider-domain.d.ts +7 -0
  17. package/dist/integrations/slack-bot.d.ts +343 -0
  18. package/dist/mcp/documents.d.ts +8 -0
  19. package/dist/mcp/files.d.ts +5 -0
  20. package/dist/mcp/server.d.ts +107 -0
  21. package/dist/mcp/session-view.d.ts +191 -0
  22. package/dist/mcp/toolspace.d.ts +61 -0
  23. package/dist/model-catalog.d.ts +39 -0
  24. package/dist/observability.d.ts +3 -0
  25. package/dist/routes/api-keys.d.ts +3 -0
  26. package/dist/routes/billing.d.ts +16 -0
  27. package/dist/routes/capabilities.d.ts +3 -0
  28. package/dist/routes/catalog-assets.d.ts +5 -0
  29. package/dist/routes/codex.d.ts +10 -0
  30. package/dist/routes/connections.d.ts +3 -0
  31. package/dist/routes/documents.d.ts +3 -0
  32. package/dist/routes/enrollments.d.ts +3 -0
  33. package/dist/routes/environments.d.ts +5 -0
  34. package/dist/routes/files.d.ts +4 -0
  35. package/dist/routes/github.d.ts +3 -0
  36. package/dist/routes/insights.d.ts +3 -0
  37. package/dist/routes/install.d.ts +5 -0
  38. package/dist/routes/machines.d.ts +3 -0
  39. package/dist/routes/packs.d.ts +3 -0
  40. package/dist/routes/preference-registry.d.ts +5 -0
  41. package/dist/routes/rigs.d.ts +3 -0
  42. package/dist/routes/scheduled-tasks.d.ts +3 -0
  43. package/dist/routes/sessions.d.ts +15 -0
  44. package/dist/routes/social.d.ts +3 -0
  45. package/dist/routes/transcriptions.d.ts +3 -0
  46. package/dist/routes/workspace-capture.d.ts +59 -0
  47. package/dist/routes/workspace-instruction-policies.d.ts +3 -0
  48. package/dist/routes/workspace-state.d.ts +3 -0
  49. package/dist/routes/workspaces.d.ts +5 -0
  50. package/dist/sandbox/access.d.ts +21 -0
  51. package/dist/sandbox/auth-callout.d.ts +30 -0
  52. package/dist/sandbox/channel-a.d.ts +37 -0
  53. package/dist/sandbox/enrollment.d.ts +120 -0
  54. package/dist/sandbox/machines.d.ts +29 -0
  55. package/dist/sandbox/metrics-ingestion.d.ts +128 -0
  56. package/dist/sandbox/rematerialize.d.ts +24 -0
  57. package/dist/sandbox/viewer.d.ts +251 -0
  58. package/dist/transcription/providers/azure-openai.d.ts +9 -0
  59. package/dist/transcription/providers/codex-subscription.d.ts +9 -0
  60. package/dist/transcription/providers/openai.d.ts +9 -0
  61. package/dist/transcription/service.d.ts +10 -0
  62. package/dist/workspace-state-projection.d.ts +16 -0
  63. package/package.json +13 -13
  64. package/src/app.ts +67 -5
  65. package/src/integrations/google-drive.ts +869 -0
  66. package/src/integrations/oauth-client.ts +41 -6
  67. package/src/integrations/slack-bot.ts +756 -26
  68. package/src/mcp/server.ts +200 -3
  69. package/src/mcp/session-view.ts +1 -0
  70. package/src/mcp/toolspace.ts +17 -9
  71. package/src/routes/connections.ts +137 -7
  72. package/src/routes/documents.ts +13 -2
  73. package/src/routes/github.ts +7 -5
  74. package/src/routes/insights.ts +30 -0
  75. package/src/routes/preference-registry.ts +482 -0
  76. package/src/routes/sessions.ts +10 -0
  77. package/src/routes/transcriptions.ts +155 -0
  78. package/src/routes/workspace-state.ts +61 -0
  79. package/src/sandbox/channel-a.ts +2 -0
  80. package/src/sandbox/rematerialize.ts +111 -4
  81. package/src/sandbox/viewer.ts +29 -12
  82. package/src/transcription/providers/azure-openai.ts +45 -0
  83. package/src/transcription/providers/codex-subscription.ts +100 -0
  84. package/src/transcription/providers/openai.ts +93 -0
  85. package/src/transcription/service.ts +121 -0
  86. package/src/workspace-state-projection.ts +244 -0
  87. package/dist/chunk-5TULDPWX.js.map +0 -1
@@ -0,0 +1,9 @@
1
+ import { type TranscriptionProvider, TranscriptionServiceError } from "@opengeni/core";
2
+ export declare function createOpenAiTranscriptionProvider(input: {
3
+ apiKey: string;
4
+ baseUrl: string;
5
+ model: string;
6
+ fetch?: typeof fetch;
7
+ }): TranscriptionProvider;
8
+ export declare function responseError(status: number): TranscriptionServiceError;
9
+ export declare function fetchError(error: unknown): TranscriptionServiceError;
@@ -0,0 +1,10 @@
1
+ import { type Settings } from "@opengeni/config";
2
+ import { type TranscriptionAvailabilityContext, type TranscriptionService } from "@opengeni/core";
3
+ import type { Database } from "@opengeni/db";
4
+ export declare function createTranscriptionService(input: {
5
+ settings: Settings;
6
+ db: Database;
7
+ fetch?: typeof fetch;
8
+ codexFetch?: typeof fetch;
9
+ probeCodex?: (context?: TranscriptionAvailabilityContext) => boolean | Promise<boolean>;
10
+ }): TranscriptionService;
@@ -0,0 +1,16 @@
1
+ import { type WorkspaceInstructionPolicyListResponse, type WorkspaceStateResponse as WorkspaceStateResponseType } from "@opengeni/contracts";
2
+ import type { WorkspaceStateMemoryRecord } from "@opengeni/db";
3
+ import type { DocumentInventory } from "@opengeni/documents";
4
+ type KnowledgeProjectionInput = {
5
+ documents: DocumentInventory;
6
+ memories: WorkspaceStateMemoryRecord[];
7
+ };
8
+ export type WorkspaceStateProjectionInput = {
9
+ workspaceId: string;
10
+ generatedAt: string;
11
+ workspaceAgentInstructions: string | null;
12
+ policies: WorkspaceInstructionPolicyListResponse;
13
+ knowledge: KnowledgeProjectionInput | null;
14
+ };
15
+ export declare function projectWorkspaceState(input: WorkspaceStateProjectionInput): WorkspaceStateResponseType;
16
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/api-router",
3
- "version": "0.12.12",
3
+ "version": "0.14.3",
4
4
  "description": "OpenGeni HTTP surface: the Hono adapter/router (createApp), routes, MCP HTTP transport, and HTTP access adapters over @opengeni/core. An engine-distribution surface — its runtime closure includes engine-internal packages.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -33,8 +33,8 @@
33
33
  "scripts": {
34
34
  "dev": "bun --watch src/index.ts",
35
35
  "start": "bun src/index.ts",
36
- "typecheck": "tsgo --noEmit",
37
- "build": "tsup",
36
+ "typecheck": "tsc --noEmit",
37
+ "build": "bun ../../scripts/build-typescript-package.ts",
38
38
  "prepublishOnly": "bash ../../scripts/prepublish-guard"
39
39
  },
40
40
  "dependencies": {
@@ -43,18 +43,18 @@
43
43
  "@hono/zod-validator": "^0.7.6",
44
44
  "@modelcontextprotocol/sdk": "^1.29.0",
45
45
  "@opengeni/agent-proto": "^0.3.0",
46
- "@opengeni/codex": "^0.2.7",
47
- "@opengeni/config": "^0.7.13",
48
- "@opengeni/contracts": "^0.23.0",
49
- "@opengeni/core": "^0.12.10",
50
- "@opengeni/db": "^0.14.3",
51
- "@opengeni/documents": "^0.2.45",
52
- "@opengeni/events": "^0.3.36",
53
- "@opengeni/github": "^0.4.0",
46
+ "@opengeni/codex": "^0.2.9",
47
+ "@opengeni/config": "^0.7.22",
48
+ "@opengeni/contracts": "^0.26.1",
49
+ "@opengeni/core": "^0.14.3",
50
+ "@opengeni/db": "^0.16.2",
51
+ "@opengeni/documents": "^0.2.59",
52
+ "@opengeni/events": "^0.3.50",
53
+ "@opengeni/github": "^0.4.9",
54
54
  "@opengeni/network": "^0.1.1",
55
55
  "@opengeni/observability": "^0.3.0",
56
- "@opengeni/runtime": "^0.14.3",
57
- "@opengeni/storage": "^0.2.37",
56
+ "@opengeni/runtime": "^0.14.15",
57
+ "@opengeni/storage": "^0.2.46",
58
58
  "@temporalio/client": "^1.17.0",
59
59
  "better-auth": "^1.6.14",
60
60
  "hono": "^4.12.18",
package/src/app.ts CHANGED
@@ -12,6 +12,7 @@ import {
12
12
  OPENGENI_API_CONTRACT_REVISION,
13
13
  OPENGENI_CORRELATION_HEADER,
14
14
  resolveWorkspaceMemoryEnabled,
15
+ VOICE_INPUT_ACCEPTED_MIME_TYPES,
15
16
  type AccessGrant,
16
17
  type ErrorCode,
17
18
  } from "@opengeni/contracts";
@@ -31,6 +32,7 @@ import { HTTPException } from "hono/http-exception";
31
32
  import type { ContentfulStatusCode } from "hono/utils/http-status";
32
33
  import type { ApiRouteDeps, AppDependencies } from "@opengeni/core";
33
34
  import {
35
+ CodexCompactionV2ProviderLockedError,
34
36
  hasPermission,
35
37
  requireAccessGrant,
36
38
  requirePermission,
@@ -65,7 +67,12 @@ import { registerSessionRoutes } from "./routes/sessions";
65
67
  import { registerSocialRoutes } from "./routes/social";
66
68
  import { registerWorkspaceRoutes } from "./routes/workspaces";
67
69
  import { registerWorkspaceInstructionPolicyRoutes } from "./routes/workspace-instruction-policies";
70
+ import { registerWorkspaceStateRoutes } from "./routes/workspace-state";
71
+ import { registerPreferenceRegistryRoutes } from "./routes/preference-registry";
72
+ import { registerInsightsRoutes } from "./routes/insights";
73
+ import { registerTranscriptionRoutes } from "./routes/transcriptions";
68
74
  import { projectClientModel } from "./model-catalog";
75
+ import { createTranscriptionService } from "./transcription/service";
69
76
 
70
77
  export type {
71
78
  ApiRouteDeps,
@@ -89,6 +96,11 @@ export { workflowIdForSession } from "@opengeni/core";
89
96
  export { replaySessionEvents, sseSessionStream, sseWorkspaceControlStream } from "./http/sse";
90
97
 
91
98
  export const API_MAX_REQUEST_BODY_BYTES = 8 * 1024 * 1024;
99
+
100
+ /** Effective Hono bodyLimit — API JSON ceiling or voice multipart + multipart overhead. */
101
+ export function apiRequestBodyLimitBytes(settings: { voiceInputMaxSizeBytes: number }): number {
102
+ return Math.max(API_MAX_REQUEST_BODY_BYTES, settings.voiceInputMaxSizeBytes + 64 * 1024);
103
+ }
92
104
  const API_PUBLIC_ERROR_MESSAGE_MAX_BYTES = 512;
93
105
 
94
106
  export function createApp(deps: AppDependencies): Hono {
@@ -142,6 +154,14 @@ export function createApp(deps: AppDependencies): Hono {
142
154
  const resumeBoxById = deps.resumeBoxById ?? makeResumeBoxById(sandboxClient);
143
155
  const observability =
144
156
  deps.observability ?? createObservability(deps.settings, { component: "api" });
157
+ const transcription =
158
+ deps.transcription === undefined
159
+ ? createTranscriptionService({
160
+ settings: deps.settings,
161
+ db: deps.db,
162
+ ...(deps.codexFetch ? { codexFetch: deps.codexFetch } : {}),
163
+ })
164
+ : deps.transcription;
145
165
  const routeDeps: ApiRouteDeps = {
146
166
  ...deps,
147
167
  observability,
@@ -151,6 +171,7 @@ export function createApp(deps: AppDependencies): Hono {
151
171
  objectStorage,
152
172
  documentIndexer,
153
173
  getDocumentServices,
174
+ transcription,
154
175
  ...(sandboxClient ? { sandboxClient } : {}),
155
176
  resumeBoxById,
156
177
  };
@@ -191,7 +212,7 @@ export function createApp(deps: AppDependencies): Hono {
191
212
  app.use(
192
213
  "*",
193
214
  bodyLimit({
194
- maxSize: API_MAX_REQUEST_BODY_BYTES,
215
+ maxSize: apiRequestBodyLimitBytes(deps.settings),
195
216
  onError: (c) =>
196
217
  c.json({ code: "PAYLOAD_TOO_LARGE", message: "Request body is too large." }, 413),
197
218
  }),
@@ -321,7 +342,7 @@ export function createApp(deps: AppDependencies): Hono {
321
342
  }),
322
343
  );
323
344
 
324
- app.get("/v1/config/client", (c) => {
345
+ app.get("/v1/config/client", async (c) => {
325
346
  c.header("cache-control", "no-store");
326
347
  const catalogSettings = deps.settings.codexSubscriptionEnabled
327
348
  ? withCodexCatalogProvider(deps.settings)
@@ -348,6 +369,12 @@ export function createApp(deps: AppDependencies): Hono {
348
369
  enabled: objectStorage !== null,
349
370
  maxSizeBytes: objectStorage?.maxSinglePutSizeBytes ?? 5_000_000_000,
350
371
  },
372
+ voiceInput: {
373
+ available: (await transcription?.available()) ?? false,
374
+ maxDurationSeconds: deps.settings.voiceInputMaxDurationSeconds,
375
+ maxSizeBytes: deps.settings.voiceInputMaxSizeBytes,
376
+ acceptedMimeTypes: [...VOICE_INPUT_ACCEPTED_MIME_TYPES],
377
+ },
351
378
  productAccessMode: deps.settings.productAccessMode,
352
379
  auth: clientAuthConfig(deps.settings),
353
380
  // Channel-A structured services (P4.4) ride exec/readFile/createEditor,
@@ -428,7 +455,10 @@ export function createApp(deps: AppDependencies): Hono {
428
455
  registerGitHubRoutes(app, routeDeps);
429
456
  registerInstallRoutes(app, routeDeps);
430
457
  registerWorkspaceRoutes(app, routeDeps);
458
+ registerInsightsRoutes(app, routeDeps);
431
459
  registerWorkspaceInstructionPolicyRoutes(app, routeDeps);
460
+ registerWorkspaceStateRoutes(app, routeDeps);
461
+ registerPreferenceRegistryRoutes(app, routeDeps);
432
462
  registerSocialRoutes(app, routeDeps);
433
463
  registerConnectionRoutes(app, routeDeps);
434
464
  registerCapabilityRoutes(app, routeDeps);
@@ -441,6 +471,7 @@ export function createApp(deps: AppDependencies): Hono {
441
471
  registerSessionRoutes(app, routeDeps);
442
472
  registerScheduledTaskRoutes(app, routeDeps);
443
473
  registerCodexRoutes(app, routeDeps);
474
+ registerTranscriptionRoutes(app, routeDeps);
444
475
 
445
476
  app.notFound((c) => {
446
477
  if (!new URL(c.req.url).pathname.startsWith("/v1/")) return c.text("Not Found", 404);
@@ -460,8 +491,9 @@ export function createApp(deps: AppDependencies): Hono {
460
491
  });
461
492
 
462
493
  app.onError((error, c) => {
463
- const status = httpStatusForError(error);
464
- const code = errorCodeForStatus(status);
494
+ const compactionLock = codexCompactionV2ProviderLockedError(error);
495
+ const status = compactionLock ? 422 : httpStatusForError(error);
496
+ const code: ErrorCode = compactionLock ? compactionLock.code : errorCodeForStatus(status);
465
497
  const requestId = correlationIds.get(c.req.raw) ?? crypto.randomUUID();
466
498
  c.header(OPENGENI_CORRELATION_HEADER, requestId);
467
499
  if (new URL(c.req.url).pathname.startsWith("/v1/")) {
@@ -471,7 +503,9 @@ export function createApp(deps: AppDependencies): Hono {
471
503
  error: {
472
504
  status,
473
505
  code,
474
- message: publicErrorMessage(error, status),
506
+ message: compactionLock
507
+ ? (boundedPublicMessage(compactionLock.message) ?? "Request failed.")
508
+ : publicErrorMessage(error, status),
475
509
  retryable: retryableHttpStatus(status),
476
510
  requestId,
477
511
  },
@@ -494,6 +528,13 @@ async function requireMcpAccessGrant(
494
528
  if (isToolspaceGrant(deps.settings, grant)) {
495
529
  return grant;
496
530
  }
531
+ // A worker-signed session-bound grant is allowed to reach the transport
532
+ // without inheriting broad workspace read access. The exact session
533
+ // authorization seam runs immediately after this gate, and tool registration
534
+ // still exposes only capabilities permitted by the delegated grant.
535
+ if (grant.metadata?.delegated === true && typeof grant.metadata.sessionId === "string") {
536
+ return grant;
537
+ }
497
538
  requirePermission(grant, "workspace:read");
498
539
  return grant;
499
540
  }
@@ -531,7 +572,23 @@ export function allowedCorsOrigin(pattern: string, origin: string): boolean {
531
572
  return new RegExp(`^(?:${pattern})$`).test(origin);
532
573
  }
533
574
 
575
+ function codexCompactionV2ProviderLockedError(
576
+ error: unknown,
577
+ ): CodexCompactionV2ProviderLockedError | null {
578
+ if (error instanceof CodexCompactionV2ProviderLockedError) return error;
579
+ if (
580
+ error instanceof HTTPException &&
581
+ error.cause instanceof CodexCompactionV2ProviderLockedError
582
+ ) {
583
+ return error.cause;
584
+ }
585
+ return null;
586
+ }
587
+
534
588
  export function httpStatusForError(error: unknown): number {
589
+ if (codexCompactionV2ProviderLockedError(error)) {
590
+ return 422;
591
+ }
535
592
  if (error instanceof HTTPException) {
536
593
  return error.status;
537
594
  }
@@ -543,6 +600,7 @@ export function httpStatusForError(error: unknown): number {
543
600
 
544
601
  export function errorCodeForStatus(status: number): ErrorCode {
545
602
  if (status === 401) return "unauthenticated";
603
+ if (status === 402) return "payment_required";
546
604
  if (status === 403) return "forbidden";
547
605
  if (status === 404) return "not_found";
548
606
  if (status === 409) return "conflict";
@@ -691,6 +749,10 @@ const routeLabelPatterns: Array<{ pattern: RegExp; label: string }> = [
691
749
  { pattern: /^\/v1\/billing$/, label: "/v1/billing" },
692
750
  { pattern: /^\/v1\/billing\/checkout$/, label: "/v1/billing/checkout" },
693
751
  { pattern: /^\/v1\/billing\/usage$/, label: "/v1/billing/usage" },
752
+ {
753
+ pattern: /^\/v1\/workspaces\/[^/]+\/insights$/,
754
+ label: "/v1/workspaces/:workspaceId/insights",
755
+ },
694
756
  {
695
757
  pattern: /^\/v1\/billing\/entitlements$/,
696
758
  label: "/v1/billing/entitlements",