@opengeni/api-router 0.21.14 → 0.22.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.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createAppComposition,
3
3
  startSlackInteractionPump
4
- } from "./chunk-R5PDSH2A.js";
4
+ } from "./chunk-HWXJW5C7.js";
5
5
 
6
6
  // src/index.ts
7
7
  import {
@@ -0,0 +1,3 @@
1
+ import { type ApiRouteDeps } from "@opengeni/core";
2
+ import type { Hono } from "hono";
3
+ export declare function registerResumableTranscriptionRoutes(app: Hono, deps: ApiRouteDeps): void;
@@ -0,0 +1,10 @@
1
+ import type { TranscriptionSegmenter } from "@opengeni/core";
2
+ export declare class TranscriptionSegmenterError extends Error {
3
+ readonly code: "unavailable" | "invalid_audio" | "cancelled" | "too_large" | "unknown";
4
+ readonly retryable: boolean;
5
+ readonly name = "TranscriptionSegmenterError";
6
+ constructor(message: string, code: "unavailable" | "invalid_audio" | "cancelled" | "too_large" | "unknown", retryable: boolean);
7
+ }
8
+ export declare function createFfmpegTranscriptionSegmenter(input: {
9
+ ffmpegPath: string;
10
+ }): TranscriptionSegmenter;
@@ -7,4 +7,9 @@ export declare function createTranscriptionService(input: {
7
7
  fetch?: typeof fetch;
8
8
  codexFetch?: typeof fetch;
9
9
  probeCodex?: (context?: TranscriptionAvailabilityContext) => boolean | Promise<boolean>;
10
+ /** Test seam for exercising timeout and late-completion behavior quickly. */
11
+ providerRequestTimeoutMilliseconds?: number;
12
+ /** Test seam for evaluating persisted absolute deadlines after delayed setup. */
13
+ now?: () => Date;
10
14
  }): TranscriptionService;
15
+ export declare function remainingTranscriptionProviderRequestMilliseconds(providerDeadlineAt: Date, now: Date): number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/api-router",
3
- "version": "0.21.14",
3
+ "version": "0.22.2",
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": {
@@ -44,17 +44,17 @@
44
44
  "@modelcontextprotocol/sdk": "^1.29.0",
45
45
  "@opengeni/agent-proto": "^0.3.0",
46
46
  "@opengeni/codex": "^0.2.11",
47
- "@opengeni/config": "^0.10.14",
48
- "@opengeni/contracts": "^0.38.3",
49
- "@opengeni/core": "^0.20.16",
50
- "@opengeni/db": "^0.27.11",
51
- "@opengeni/documents": "^0.5.7",
52
- "@opengeni/events": "^0.3.77",
53
- "@opengeni/github": "^0.4.30",
47
+ "@opengeni/config": "^0.11.0",
48
+ "@opengeni/contracts": "^0.39.0",
49
+ "@opengeni/core": "^0.21.2",
50
+ "@opengeni/db": "^0.28.1",
51
+ "@opengeni/documents": "^0.5.10",
52
+ "@opengeni/events": "^0.3.80",
53
+ "@opengeni/github": "^0.4.31",
54
54
  "@opengeni/network": "^0.2.0",
55
- "@opengeni/observability": "^0.4.16",
56
- "@opengeni/runtime": "^0.18.15",
57
- "@opengeni/storage": "^0.2.67",
55
+ "@opengeni/observability": "^0.5.0",
56
+ "@opengeni/runtime": "^0.18.17",
57
+ "@opengeni/storage": "^0.2.68",
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
@@ -13,6 +13,7 @@ import {
13
13
  OPENGENI_CORRELATION_HEADER,
14
14
  resolveWorkspaceMemoryEnabled,
15
15
  VOICE_INPUT_ACCEPTED_MIME_TYPES,
16
+ TRANSCRIPTION_RECORDING_PROVIDER_SEGMENT_SECONDS,
16
17
  type AccessGrant,
17
18
  type ErrorCode,
18
19
  } from "@opengeni/contracts";
@@ -77,6 +78,7 @@ import { registerInsightsRoutes } from "./routes/insights";
77
78
  import { registerTranscriptionRoutes } from "./routes/transcriptions";
78
79
  import { projectClientModel } from "./model-catalog";
79
80
  import { createTranscriptionService } from "./transcription/service";
81
+ import { createFfmpegTranscriptionSegmenter } from "./transcription/segmenter";
80
82
  import { registerSlackInteractionRoutes } from "./integrations/slack-interactions";
81
83
 
82
84
  export type {
@@ -103,8 +105,15 @@ export { replaySessionEvents, sseSessionStream, sseWorkspaceControlStream } from
103
105
  export const API_MAX_REQUEST_BODY_BYTES = 8 * 1024 * 1024;
104
106
 
105
107
  /** Effective Hono bodyLimit — API JSON ceiling or voice multipart + multipart overhead. */
106
- export function apiRequestBodyLimitBytes(settings: { voiceInputMaxSizeBytes: number }): number {
107
- return Math.max(API_MAX_REQUEST_BODY_BYTES, settings.voiceInputMaxSizeBytes + 64 * 1024);
108
+ export function apiRequestBodyLimitBytes(settings: {
109
+ voiceInputMaxSizeBytes: number;
110
+ voiceInputResumableMaxChunkSizeBytes?: number;
111
+ }): number {
112
+ return Math.max(
113
+ API_MAX_REQUEST_BODY_BYTES,
114
+ settings.voiceInputMaxSizeBytes + 64 * 1024,
115
+ (settings.voiceInputResumableMaxChunkSizeBytes ?? 0) + 64 * 1024,
116
+ );
108
117
  }
109
118
  const API_PUBLIC_ERROR_MESSAGE_MAX_BYTES = 512;
110
119
 
@@ -204,6 +213,12 @@ export function createAppComposition(deps: AppDependencies): {
204
213
  ...(deps.codexFetch ? { codexFetch: deps.codexFetch } : {}),
205
214
  })
206
215
  : deps.transcription;
216
+ const transcriptionSegmenter =
217
+ deps.transcriptionSegmenter === undefined
218
+ ? createFfmpegTranscriptionSegmenter({
219
+ ffmpegPath: deps.settings.voiceInputFfmpegPath,
220
+ })
221
+ : deps.transcriptionSegmenter;
207
222
  const routeDeps: ApiRouteDeps = {
208
223
  ...deps,
209
224
  observability,
@@ -214,6 +229,7 @@ export function createAppComposition(deps: AppDependencies): {
214
229
  documentIndexer,
215
230
  getDocumentServices,
216
231
  transcription,
232
+ transcriptionSegmenter,
217
233
  ...(sandboxClient ? { sandboxClient } : {}),
218
234
  resumeBoxById,
219
235
  };
@@ -440,6 +456,24 @@ export function createAppComposition(deps: AppDependencies): {
440
456
  maxDurationSeconds: deps.settings.voiceInputMaxDurationSeconds,
441
457
  maxSizeBytes: deps.settings.voiceInputMaxSizeBytes,
442
458
  acceptedMimeTypes: [...VOICE_INPUT_ACCEPTED_MIME_TYPES],
459
+ ...(deps.settings.voiceInputResumableEnabled &&
460
+ objectStorage &&
461
+ transcription &&
462
+ transcriptionSegmenter &&
463
+ (await transcription.available()) &&
464
+ (await transcriptionSegmenter.available())
465
+ ? {
466
+ resumable: {
467
+ maxDurationSeconds: deps.settings.voiceInputResumableMaxDurationSeconds,
468
+ maxSizeBytes: deps.settings.voiceInputResumableMaxSizeBytes,
469
+ maxChunkSizeBytes: deps.settings.voiceInputResumableMaxChunkSizeBytes,
470
+ providerSegmentSeconds: Math.min(
471
+ TRANSCRIPTION_RECORDING_PROVIDER_SEGMENT_SECONDS,
472
+ deps.settings.voiceInputMaxDurationSeconds,
473
+ ),
474
+ },
475
+ }
476
+ : {}),
443
477
  },
444
478
  productAccessMode: deps.settings.productAccessMode,
445
479
  auth: clientAuthConfig(deps.settings),
package/src/mcp/server.ts CHANGED
@@ -1928,7 +1928,7 @@ function registerFleetTools(
1928
1928
  "sandboxes_list",
1929
1929
  {
1930
1930
  description:
1931
- "List the sandboxes this session can run on: its own session sandbox plus enrolled selfhosted machines. `liveness` is conservative: online requires observed provider existence and verified workspace readiness. Provider, lease, route, archive, restore, workspace, lease epoch, and route epoch are also reported separately. Use an entry `id` as an attach/swap/run_on target.",
1931
+ "List the sandboxes this session can run on: its own session sandbox plus enrolled selfhosted machines. `liveness` is conservative: online requires observed provider existence and verified workspace readiness. An idle session-home sandbox may report offline/cold/draining and still wake or restore on the next ordinary sandbox operation; never infer that shell/files are unavailable from list liveness alone—only a typed operation/attach failure proves that. Provider, lease, route, archive, restore, workspace, lease epoch, and route epoch are also reported separately. Use an entry `id` as an attach/swap/run_on target.",
1932
1932
  inputSchema: {},
1933
1933
  },
1934
1934
  async () => json(await listFleet(services, await fleetContext())),