@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 +1 -1
- package/dist/{chunk-Y3EPAIEQ.js → chunk-4AQMKVQM.js} +93 -38
- package/dist/chunk-4AQMKVQM.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/sandbox/rematerialize.d.ts +1 -1
- package/package.json +19 -19
- package/src/mcp/server.ts +60 -13
- package/src/sandbox/rematerialize.ts +33 -1
- package/dist/chunk-Y3EPAIEQ.js.map +0 -1
package/dist/app.js
CHANGED
|
@@ -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:
|
|
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
|
|
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 (!
|
|
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
|
-
|
|
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:
|
|
57129
|
+
processId: process2.id
|
|
57075
57130
|
});
|
|
57076
57131
|
handle.routingSession.adoptRetainedProcess({
|
|
57077
57132
|
process: {
|
|
57078
|
-
id:
|
|
57079
|
-
providerSessionId:
|
|
57133
|
+
id: process2.id,
|
|
57134
|
+
providerSessionId: process2.providerSessionId,
|
|
57080
57135
|
...providerCommand ? { providerCommand } : {}
|
|
57081
57136
|
},
|
|
57082
57137
|
backend: {
|
|
57083
57138
|
sandboxId: null,
|
|
57084
|
-
leaseEpoch:
|
|
57085
|
-
providerInstanceId:
|
|
57086
|
-
activeEpoch:
|
|
57139
|
+
leaseEpoch: process2.leaseEpoch,
|
|
57140
|
+
providerInstanceId: process2.providerInstanceId,
|
|
57141
|
+
activeEpoch: process2.routeEpoch
|
|
57087
57142
|
}
|
|
57088
57143
|
});
|
|
57089
|
-
return
|
|
57144
|
+
return process2;
|
|
57090
57145
|
};
|
|
57091
|
-
const emitPtyExited = async (ctx, ptyId,
|
|
57146
|
+
const emitPtyExited = async (ctx, ptyId, process2) => {
|
|
57092
57147
|
const exited = {
|
|
57093
57148
|
ptyId,
|
|
57094
|
-
exitCode:
|
|
57095
|
-
reason:
|
|
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
|
-
|
|
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
|
|
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 || !
|
|
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:
|
|
60416
|
-
sandboxGroupId:
|
|
60417
|
-
retainedProcessId:
|
|
60418
|
-
openAdmissionId:
|
|
60419
|
-
execSessionId:
|
|
60420
|
-
leaseEpoch:
|
|
60421
|
-
providerBackend:
|
|
60422
|
-
providerInstanceId:
|
|
60423
|
-
routeKind:
|
|
60424
|
-
routeTargetId:
|
|
60425
|
-
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-
|
|
76583
|
+
//# sourceMappingURL=chunk-4AQMKVQM.js.map
|