@opengeni/api-router 2.12.3 → 2.12.4-canary.1

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.
@@ -725,7 +725,7 @@ export function helloReportsOpStream(hello: Hello): boolean {
725
725
  return hello.capabilities?.opStream === true;
726
726
  }
727
727
 
728
- function helloRuntimeCapabilities(hello: Hello): Record<string, boolean> {
728
+ export function helloRuntimeCapabilities(hello: Hello): Record<string, boolean> {
729
729
  const caps = hello.capabilities;
730
730
  // Absence is an older-agent/unknown signal, not a fabricated set of false claims.
731
731
  // Keep the durable cursor empty so reconnects from legacy agents remain a
@@ -741,6 +741,7 @@ function helloRuntimeCapabilities(hello: Hello): Record<string, boolean> {
741
741
  browserBridge: caps.browserBridge === true,
742
742
  operationResourcePolicy: caps.operationResourcePolicy === true,
743
743
  operationCpuQuota: caps.operationCpuQuota === true,
744
+ transactionalFsWrite: caps.transactionalFsWrite === true,
744
745
  };
745
746
  }
746
747
 
@@ -32,7 +32,11 @@ import {
32
32
  type EstablishedSandboxSession,
33
33
  type WorkspaceArchiveDescriptor,
34
34
  } from "@opengeni/runtime/sandbox";
35
- import type { ObjectStorage } from "@opengeni/storage";
35
+ import {
36
+ downloadWorkspaceArchiveSpool,
37
+ WorkspaceArchiveStorageError,
38
+ type ObjectStorage,
39
+ } from "@opengeni/storage";
36
40
 
37
41
  function hasWorkspaceArchive(envelope: Record<string, unknown> | null): boolean {
38
42
  const sessionState =
@@ -73,6 +77,14 @@ async function materializeArchiveObjectRef(
73
77
  "workspace archive object storage is not configured",
74
78
  );
75
79
  }
80
+ const descriptor = parseWorkspaceArchiveDescriptor(sessionState.workspaceArchiveMeta);
81
+ if (
82
+ process.platform === "linux" &&
83
+ descriptor?.version === 1 &&
84
+ descriptor.workspace.projection === "sdk_local_archive_v1"
85
+ ) {
86
+ return envelope;
87
+ }
76
88
  return {
77
89
  ...envelope,
78
90
  sessionState: await inlineWorkspaceArchiveForRestore(sessionState, (key) =>
@@ -209,6 +221,26 @@ export async function establishApiSandboxSpawner(input: {
209
221
  established = await establishSandboxSessionFromEnvelope(input.settings, hydrateEnvelope, {
210
222
  sessionId: input.sessionId,
211
223
  recovery: "create-or-restore",
224
+ ...(input.objectStorage
225
+ ? {
226
+ loadHostWorkspaceArchive: async (ref) => {
227
+ try {
228
+ return await downloadWorkspaceArchiveSpool(input.objectStorage!, ref.key, {
229
+ bytes: ref.bytes,
230
+ sha256: ref.sha256,
231
+ });
232
+ } catch (error) {
233
+ if (error instanceof WorkspaceArchiveStorageError) {
234
+ throw new WorkspaceArchiveIntegrityError(error.code, error.message, {
235
+ retryable: error.retryable,
236
+ cause: error,
237
+ });
238
+ }
239
+ throw error;
240
+ }
241
+ },
242
+ }
243
+ : {}),
212
244
  backendOverride: input.backend as never,
213
245
  environment: input.environment,
214
246
  onSandboxCreated: async (created) => {
@@ -220,8 +220,14 @@ function extensionForMimeType(mimeType: string): string {
220
220
  }
221
221
 
222
222
  async function commandSucceeds(command: string, args: string[]): Promise<boolean> {
223
- const result = await runCommand(command, args);
224
- return !result.spawnError && result.exitCode === 0;
223
+ try {
224
+ const result = await runCommand(command, args);
225
+ return !result.spawnError && result.exitCode === 0;
226
+ } catch {
227
+ // Some runtimes throw during spawn instead of emitting an error event.
228
+ // An unavailable optional audio tool must not prevent client startup.
229
+ return false;
230
+ }
225
231
  }
226
232
 
227
233
  async function runCommand(