@opengeni/api-router 2.12.1-canary.0 → 2.12.3-canary.0

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/app.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  withDefaultEnabledCapabilityMcpTools,
25
25
  workflowIdForSession,
26
26
  workspaceActorContextExempt
27
- } from "./chunk-Y3EPAIEQ.js";
27
+ } from "./chunk-4AQMKVQM.js";
28
28
  export {
29
29
  API_MAX_REQUEST_BODY_BYTES,
30
30
  allowedCorsOrigin,
@@ -6041,6 +6041,8 @@ async function workspaceArtifactDownloads(storage, ref, audience) {
6041
6041
  // src/mcp/server.ts
6042
6042
  import {
6043
6043
  CreateScheduledTaskRequest,
6044
+ CreateSessionRequest,
6045
+ GoalSpec,
6044
6046
  boundSessionMcpText as capSessionDiscoveryText,
6045
6047
  compactSessionMcpListRow,
6046
6048
  sessionMcpIncludesRelatedWork,
@@ -6534,6 +6536,10 @@ import {
6534
6536
  withoutSandboxProviderIdentity,
6535
6537
  WorkspaceArchiveIntegrityError
6536
6538
  } from "@opengeni/runtime/sandbox";
6539
+ import {
6540
+ downloadWorkspaceArchiveSpool,
6541
+ WorkspaceArchiveStorageError
6542
+ } from "@opengeni/storage";
6537
6543
  function hasWorkspaceArchive(envelope) {
6538
6544
  const sessionState = envelope?.sessionState && typeof envelope.sessionState === "object" && !Array.isArray(envelope.sessionState) ? envelope.sessionState : null;
6539
6545
  return typeof sessionState?.workspaceArchive === "string" && sessionState.workspaceArchive.length > 0 || parseWorkspaceArchiveObjectRef(sessionState?.workspaceArchiveRef) !== null;
@@ -6555,6 +6561,10 @@ async function materializeArchiveObjectRef(envelope, objectStorage) {
6555
6561
  "workspace archive object storage is not configured"
6556
6562
  );
6557
6563
  }
6564
+ const descriptor = parseWorkspaceArchiveDescriptor(sessionState.workspaceArchiveMeta);
6565
+ if (process.platform === "linux" && descriptor?.version === 1 && descriptor.workspace.projection === "sdk_local_archive_v1") {
6566
+ return envelope;
6567
+ }
6558
6568
  return {
6559
6569
  ...envelope,
6560
6570
  sessionState: await inlineWorkspaceArchiveForRestore(
@@ -6645,6 +6655,24 @@ async function establishApiSandboxSpawner(input) {
6645
6655
  established = await establishSandboxSessionFromEnvelope(input.settings, hydrateEnvelope, {
6646
6656
  sessionId: input.sessionId,
6647
6657
  recovery: "create-or-restore",
6658
+ ...input.objectStorage ? {
6659
+ loadHostWorkspaceArchive: async (ref) => {
6660
+ try {
6661
+ return await downloadWorkspaceArchiveSpool(input.objectStorage, ref.key, {
6662
+ bytes: ref.bytes,
6663
+ sha256: ref.sha256
6664
+ });
6665
+ } catch (error) {
6666
+ if (error instanceof WorkspaceArchiveStorageError) {
6667
+ throw new WorkspaceArchiveIntegrityError(error.code, error.message, {
6668
+ retryable: error.retryable,
6669
+ cause: error
6670
+ });
6671
+ }
6672
+ throw error;
6673
+ }
6674
+ }
6675
+ } : {},
6648
6676
  backendOverride: input.backend,
6649
6677
  environment: input.environment,
6650
6678
  onSandboxCreated: async (created) => {
@@ -24927,6 +24955,30 @@ function orchestrationFailureCode(tool, error) {
24927
24955
  const suffix = error.status === 401 ? "unauthenticated" : error.status === 403 ? "forbidden" : error.status === 404 ? "not_found" : error.status === 409 ? "conflict" : error.status === 429 ? "limit_exceeded" : error.status >= 500 ? "unavailable" : "rejected";
24928
24956
  return `${tool}_${suffix}`.slice(0, ORCHESTRATION_FAILURE_CODE_MAX_LENGTH);
24929
24957
  }
24958
+ function sessionCreateValidationFailureResult(error) {
24959
+ const details = error.issues.slice(0, 5).map((issue) => {
24960
+ const [field, goalField] = issue.path;
24961
+ let path = typeof field === "string" && Object.hasOwn(CreateSessionRequest.out.shape, field) ? field : "request";
24962
+ if (field === "goal" && typeof goalField === "string" && Object.hasOwn(GoalSpec.shape, goalField)) {
24963
+ path += `.${goalField}`;
24964
+ }
24965
+ const expected = issue.code === "invalid_type" && ["string", "number", "boolean", "object", "array", "int"].includes(issue.expected) ? `expected ${issue.expected === "int" ? "integer" : issue.expected}` : "failed schema validation";
24966
+ return `${path} ${expected}`;
24967
+ });
24968
+ const envelope = {
24969
+ error: {
24970
+ code: "session_create_invalid_request",
24971
+ message: boundedOrchestrationFailureMessage(
24972
+ `Invalid session create request: ${details.join("; ") || "request failed schema validation"}${error.issues.length > 5 ? "; additional fields failed validation" : ""}.`
24973
+ )
24974
+ }
24975
+ };
24976
+ return {
24977
+ content: [{ type: "text", text: JSON.stringify(envelope, null, 2) }],
24978
+ structuredContent: envelope,
24979
+ isError: true
24980
+ };
24981
+ }
24930
24982
  function orchestrationFailureEnvelope(tool, error) {
24931
24983
  if (error instanceof SessionSpawnDeniedError) {
24932
24984
  const denial = sessionSpawnDenialEnvelope(error);
@@ -28818,7 +28870,7 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
28818
28870
  "Concise semantic title for the child session. Omit only when the delegated goal or initial message already provides a suitable title; OpenGeni derives a sensitive-safe bounded fallback from that text."
28819
28871
  ),
28820
28872
  instructions: z43.string().min(1).max(SESSION_INSTRUCTIONS_MAX_CHARACTERS).optional(),
28821
- goal: z43.unknown().optional(),
28873
+ goal: GoalSpec.optional(),
28822
28874
  resources: z43.array(z43.unknown()).optional().describe(
28823
28875
  "Omit to inherit parent repositories only. Files are never inherited automatically; explicitly include file resources to attach them. An empty array inherits no resources."
28824
28876
  ),
@@ -28897,18 +28949,21 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
28897
28949
  await authorizeFirstPartySession(deps, grant, callerSessionId, "session.child.create");
28898
28950
  }
28899
28951
  const { machineTarget, title, projectId, ...request } = args;
28952
+ const rawRequest = {
28953
+ ...request,
28954
+ ...projectId !== void 0 ? { channelId: projectId } : {},
28955
+ ...machineTarget ? {
28956
+ targetSandboxId: machineTarget.targetSandboxId,
28957
+ ...machineTarget.workingDir !== void 0 ? { workingDir: machineTarget.workingDir } : {}
28958
+ } : {}
28959
+ };
28960
+ const validation = CreateSessionRequest.safeParse(rawRequest);
28961
+ if (!validation.success) return sessionCreateValidationFailureResult(validation.error);
28900
28962
  const result = await createSessionForRequestWithOutcome(
28901
28963
  deps,
28902
28964
  grant,
28903
28965
  grant.workspaceId,
28904
- {
28905
- ...request,
28906
- ...projectId !== void 0 ? { channelId: projectId } : {},
28907
- ...machineTarget ? {
28908
- targetSandboxId: machineTarget.targetSandboxId,
28909
- ...machineTarget.workingDir !== void 0 ? { workingDir: machineTarget.workingDir } : {}
28910
- } : {}
28911
- },
28966
+ rawRequest,
28912
28967
  void 0,
28913
28968
  title === void 0 ? {} : { automaticTitleCandidate: title }
28914
28969
  );
@@ -55805,7 +55860,7 @@ import {
55805
55860
  GatewayRealtimeConnectRequest,
55806
55861
  ClientSessionEvent,
55807
55862
  CompactSessionContextRequest,
55808
- CreateSessionRequest,
55863
+ CreateSessionRequest as CreateSessionRequest2,
55809
55864
  DeleteSessionQueueItemRequest,
55810
55865
  EditSessionQueueItemRequest,
55811
55866
  EndSessionRealtimeRequest,
@@ -57055,14 +57110,14 @@ function registerSessionRoutes(app, deps) {
57055
57110
  message: "durable interactive terminals require a session-home provider lease"
57056
57111
  });
57057
57112
  }
57058
- const process = await getRetainedProcess(db, {
57113
+ const process2 = await getRetainedProcess(db, {
57059
57114
  workspaceId: ctx.workspaceId,
57060
57115
  sessionId: ctx.session.id,
57061
57116
  processId: pty.retainedProcessId
57062
57117
  });
57063
- if (!process || process.state !== "active" || process.ownerActorKind !== "direct" || process.accountId !== ctx.accountId || process.leaseId !== pty.leaseId || process.sandboxGroupId !== pty.sandboxGroupId || process.parentAdmissionId !== pty.openAdmissionId || process.leaseEpoch !== pty.leaseEpoch || process.providerBackend !== pty.providerBackend || process.providerInstanceId !== pty.providerInstanceId || process.routeKind !== pty.routeKind || process.routeTargetId !== pty.routeTargetId || process.routeEpoch !== pty.routeEpoch || process.providerSessionId !== pty.execSessionId || // Only a persistable home backend can currently be reconstructed by an
57118
+ if (!process2 || process2.state !== "active" || process2.ownerActorKind !== "direct" || process2.accountId !== ctx.accountId || process2.leaseId !== pty.leaseId || process2.sandboxGroupId !== pty.sandboxGroupId || process2.parentAdmissionId !== pty.openAdmissionId || process2.leaseEpoch !== pty.leaseEpoch || process2.providerBackend !== pty.providerBackend || process2.providerInstanceId !== pty.providerInstanceId || process2.routeKind !== pty.routeKind || process2.routeTargetId !== pty.routeTargetId || process2.routeEpoch !== pty.routeEpoch || process2.providerSessionId !== pty.execSessionId || // Only a persistable home backend can currently be reconstructed by an
57064
57119
  // API request without consulting the mutable active pointer.
57065
- process.routeTargetId !== null || handle.lease.id !== process.leaseId || handle.lease.sandboxGroupId !== process.sandboxGroupId || handle.lease.leaseEpoch !== process.leaseEpoch || handle.lease.backend !== process.providerBackend || handle.lease.instanceId !== process.providerInstanceId) {
57120
+ process2.routeTargetId !== null || handle.lease.id !== process2.leaseId || handle.lease.sandboxGroupId !== process2.sandboxGroupId || handle.lease.leaseEpoch !== process2.leaseEpoch || handle.lease.backend !== process2.providerBackend || handle.lease.instanceId !== process2.providerInstanceId) {
57066
57121
  throw new HTTPException70(409, {
57067
57122
  message: "pty retained-process identity is stale; reopen the terminal"
57068
57123
  });
@@ -57071,28 +57126,28 @@ function registerSessionRoutes(app, deps) {
57071
57126
  accountId: ctx.accountId,
57072
57127
  workspaceId: ctx.workspaceId,
57073
57128
  sessionId: ctx.session.id,
57074
- processId: process.id
57129
+ processId: process2.id
57075
57130
  });
57076
57131
  handle.routingSession.adoptRetainedProcess({
57077
57132
  process: {
57078
- id: process.id,
57079
- providerSessionId: process.providerSessionId,
57133
+ id: process2.id,
57134
+ providerSessionId: process2.providerSessionId,
57080
57135
  ...providerCommand ? { providerCommand } : {}
57081
57136
  },
57082
57137
  backend: {
57083
57138
  sandboxId: null,
57084
- leaseEpoch: process.leaseEpoch,
57085
- providerInstanceId: process.providerInstanceId,
57086
- activeEpoch: process.routeEpoch
57139
+ leaseEpoch: process2.leaseEpoch,
57140
+ providerInstanceId: process2.providerInstanceId,
57141
+ activeEpoch: process2.routeEpoch
57087
57142
  }
57088
57143
  });
57089
- return process;
57144
+ return process2;
57090
57145
  };
57091
- const emitPtyExited = async (ctx, ptyId, process) => {
57146
+ const emitPtyExited = async (ctx, ptyId, process2) => {
57092
57147
  const exited = {
57093
57148
  ptyId,
57094
- exitCode: process.exitCode,
57095
- reason: process.state === "exited" ? "exit" : "lost"
57149
+ exitCode: process2.exitCode,
57150
+ reason: process2.state === "exited" ? "exit" : "lost"
57096
57151
  };
57097
57152
  await appendAndPublishEvents4(db, bus, ctx.workspaceId, ctx.session.id, [
57098
57153
  { type: "terminal.pty.exited", payload: exited }
@@ -57207,7 +57262,7 @@ function registerSessionRoutes(app, deps) {
57207
57262
  }
57208
57263
  let session;
57209
57264
  try {
57210
- CreateSessionRequest.parse(payload);
57265
+ CreateSessionRequest2.parse(payload);
57211
57266
  const origin = await resolveSiteSessionOrigin(
57212
57267
  db,
57213
57268
  workspaceId,
@@ -60398,12 +60453,12 @@ function registerSessionRoutes(app, deps) {
60398
60453
  const opened = await service.ptyOpen(req, ptyId);
60399
60454
  const execSessionId = opened.execSessionId;
60400
60455
  const retained = execSessionId === null ? null : handle.routingSession.retainedProcessIdentity(execSessionId);
60401
- const process = retained ? await getRetainedProcess(db, {
60456
+ const process2 = retained ? await getRetainedProcess(db, {
60402
60457
  workspaceId: ctx.workspaceId,
60403
60458
  sessionId: ctx.session.id,
60404
60459
  processId: retained.id
60405
60460
  }) : null;
60406
- if (execSessionId === null || !retained || !process || process.state !== "active" || process.ownerActorKind !== "direct" || process.providerSessionId !== execSessionId || process.routeTargetId !== null || process.leaseId !== handle.lease.id || process.sandboxGroupId !== handle.lease.sandboxGroupId || process.leaseEpoch !== handle.lease.leaseEpoch || process.providerBackend !== handle.lease.backend || process.providerInstanceId !== handle.lease.instanceId) {
60461
+ if (execSessionId === null || !retained || !process2 || process2.state !== "active" || process2.ownerActorKind !== "direct" || process2.providerSessionId !== execSessionId || process2.routeTargetId !== null || process2.leaseId !== handle.lease.id || process2.sandboxGroupId !== handle.lease.sandboxGroupId || process2.leaseEpoch !== handle.lease.leaseEpoch || process2.providerBackend !== handle.lease.backend || process2.providerInstanceId !== handle.lease.instanceId) {
60407
60462
  if (execSessionId !== null && handle.routingSession.hasRetainedProcess(execSessionId)) {
60408
60463
  await drainOpenedPty(handle, execSessionId);
60409
60464
  }
@@ -60412,17 +60467,17 @@ function registerSessionRoutes(app, deps) {
60412
60467
  });
60413
60468
  }
60414
60469
  const identity = {
60415
- leaseId: process.leaseId,
60416
- sandboxGroupId: process.sandboxGroupId,
60417
- retainedProcessId: process.id,
60418
- openAdmissionId: process.parentAdmissionId,
60419
- execSessionId: process.providerSessionId,
60420
- leaseEpoch: process.leaseEpoch,
60421
- providerBackend: process.providerBackend,
60422
- providerInstanceId: process.providerInstanceId,
60423
- routeKind: process.routeKind,
60424
- routeTargetId: process.routeTargetId,
60425
- routeEpoch: process.routeEpoch
60470
+ leaseId: process2.leaseId,
60471
+ sandboxGroupId: process2.sandboxGroupId,
60472
+ retainedProcessId: process2.id,
60473
+ openAdmissionId: process2.parentAdmissionId,
60474
+ execSessionId: process2.providerSessionId,
60475
+ leaseEpoch: process2.leaseEpoch,
60476
+ providerBackend: process2.providerBackend,
60477
+ providerInstanceId: process2.providerInstanceId,
60478
+ routeKind: process2.routeKind,
60479
+ routeTargetId: process2.routeTargetId,
60480
+ routeEpoch: process2.routeEpoch
60426
60481
  };
60427
60482
  try {
60428
60483
  await insertPtySession(db, {
@@ -76525,4 +76580,4 @@ export {
76525
76580
  withDefaultEnabledCapabilityMcpTools,
76526
76581
  workflowIdForSession4 as workflowIdForSession
76527
76582
  };
76528
- //# sourceMappingURL=chunk-Y3EPAIEQ.js.map
76583
+ //# sourceMappingURL=chunk-4AQMKVQM.js.map