@opengeni/runtime 0.5.0 → 0.6.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.
- package/dist/{chunk-Q36E4MDM.js → chunk-DYBF7ZEB.js} +54 -3
- package/dist/chunk-DYBF7ZEB.js.map +1 -0
- package/dist/{index-BrdnxaAW.d.ts → index-BTo_bZvN.d.ts} +12 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/sandbox/index.d.ts +1 -1
- package/dist/sandbox/index.js +3 -1
- package/package.json +2 -2
- package/src/image-history.ts +3 -3
- package/src/index.ts +1 -0
- package/src/sandbox/index.ts +2 -0
- package/src/sandbox/providers/modal.ts +112 -2
- package/src/screenshot-omitted-card.ts +15 -0
- package/dist/chunk-Q36E4MDM.js.map +0 -1
package/dist/sandbox/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { collectSandboxEnvironment, parseExposedPorts } from '@opengeni/config';
|
|
2
2
|
export { CAPABILITY_DESCRIPTORS, CapabilityDescriptor, DESKTOP_STREAM_PORT, StreamTokenPayload, StreamTokenPayload as StreamTokenPayloadType, TERMINAL_STREAM_PORT } from '@opengeni/contracts';
|
|
3
3
|
import '@openai/agents/sandbox';
|
|
4
|
-
export { A as ActiveBackendResolverDeps, a as ActiveBackendUnresolvableError, b as ActivePointer, C as ChannelAConflictError, c as ChannelAEmitter, d as ChannelAExecArgs, e as ChannelAExecResult, f as ChannelANotFoundError, g as ChannelASession, h as ChannelAUnsupportedError, i as ChannelAValidationError, j as ControlRpc, D as DEFAULT_DESKTOP_GEOMETRY, k as DISPLAY_STACK_TIMEOUT_MS, l as DesktopGeometry, m as DisplayStackError, n as DisplayStackUnsupportedError, E as EnsureDisplayStackOptions, o as EnsureDisplayStackResult, p as EnsureTerminalServerOptions, q as EnsureTerminalServerResult, r as EstablishedSandboxSession, s as ExposeStreamPortInput, t as ExposeStreamPortResult, u as ExposedPortEndpoint, F as FinalizeRecordingResult, L as LiveModalSandboxLeaseAttribution, M as MintStreamTokenInput, v as MockAgentResponder, w as MockAgentResponderOptions, x as MockExecHandler, y as
|
|
4
|
+
export { A as ActiveBackendResolverDeps, a as ActiveBackendUnresolvableError, b as ActivePointer, C as ChannelAConflictError, c as ChannelAEmitter, d as ChannelAExecArgs, e as ChannelAExecResult, f as ChannelANotFoundError, g as ChannelASession, h as ChannelAUnsupportedError, i as ChannelAValidationError, j as ControlRpc, D as DEFAULT_DESKTOP_GEOMETRY, k as DISPLAY_STACK_TIMEOUT_MS, l as DesktopGeometry, m as DisplayStackError, n as DisplayStackUnsupportedError, E as EnsureDisplayStackOptions, o as EnsureDisplayStackResult, p as EnsureTerminalServerOptions, q as EnsureTerminalServerResult, r as EstablishedSandboxSession, s as ExposeStreamPortInput, t as ExposeStreamPortResult, u as ExposedPortEndpoint, F as FinalizeRecordingResult, L as LiveModalSandboxLeaseAttribution, M as MintStreamTokenInput, v as MockAgentResponder, w as MockAgentResponderOptions, x as MockExecHandler, y as ModalModuleLoader, z as ModalOrphanSweepResult, B as ModalSandboxAttribution, N as NatsControlRpc, G as NatsRequestConnection, H as NegotiationContext, I as NumstatEntry, P as PROVIDER_REGISTRY, J as ProviderConstructionContext, K as ProviderRegistration, O as RecordingCodec, Q as RecordingContentType, S as RecordingError, T as RecordingProcess, U as RecordingUnavailableError, V as ResolvedActiveBackend, W as RoutableBackendSession, X as RoutableSandbox, Y as RoutingSandboxSession, Z as RoutingSandboxSessionDeps, _ as RoutingTransitionEvent, $ as RoutingUnsupportedError, a0 as SELFHOSTED_DEFAULT_TIMEOUT_MS, a1 as SELFHOSTED_RECONNECT_WINDOW_MS, a2 as SELFHOSTED_RELAY_STREAM_PATH, a3 as STREAM_PORT, a4 as STREAM_TOKEN_DEFAULT_TTL_SECONDS, a5 as SandboxChannelAService, a6 as SandboxChannelAServiceOptions, a7 as SandboxConfigError, a8 as SandboxCreatedCallback, a9 as SandboxProviderUnavailableError, aa as SelfhostedApplyDiff, ab as SelfhostedControlError, ac as SelfhostedEditor, ad as SelfhostedEnrollment, ae as SelfhostedExecArgs, af as SelfhostedExecResult, ag as SelfhostedImageOutput, ah as SelfhostedLivenessState, ai as SelfhostedNegotiationInput, aj as SelfhostedRelayConfig, ak as SelfhostedSandboxClient, al as SelfhostedSession, am as SelfhostedSessionBuild, an as SelfhostedSessionDeps, ao as SelfhostedSessionState, ap as SelfhostedUnavailableReason, aq as StartRecordingInput, ar as StreamPortUnavailableError, as as TERMINAL_SERVER_TIMEOUT_MS, at as TerminalServerError, au as TerminalServerUnsupportedError, av as agentErrorToControlError, aw as assertDescriptorRegistryInvariants, ax as assertProviderRegistryInvariants, ay as assertSafeRelPath, az as backendSupportsOs, aA as buildDisplayStackScript, aB as buildSelfhostedBackendSession, aC as buildStreamUrl, aD as buildTerminalServerScript, aE as contentTypeForCodec, aF as createSandboxClient, aG as createSandboxClientForBackend, aH as decodeModalSnapshotId, aI as deletePriorPersistedSnapshot, aJ as deleteRecordingArtifacts, aK as deserializeSandboxSessionStateEnvelope, aL as desktopCapableBackend, aM as ensureDisplayStack, aN as ensureModalRegistryImage, aO as ensureTerminalServer, aP as establishSandboxSessionFromEnvelope, aQ as exposeStreamPort, aR as extForCodec, aS as isExecSessionLostBanner, aT as isProviderSandboxNotFoundError, aU as isSelfhostedProviderNotFoundError, aV as isWorkspaceEscapeError, aW as makeActiveBackendResolver, aX as mintStreamToken, aY as modalSandboxAttributionEnvironment, aZ as modalSandboxAttributionTags, a_ as negotiateCapabilities, a$ as negotiateSelfhostedCapabilities, b0 as offlineAgentError, b1 as offlineControlResponse, b2 as parseExecBannerSessionId, b3 as parseNumstatZ, b4 as parsePorcelainV2, b5 as parseUnifiedPatch, b6 as readRecordingBytes, b7 as readWorkspaceArchiveFromEnvelopeSessionState, b8 as recordingStorageKey, b9 as restoredSandboxSessionStateFromEntry, ba as sandboxStateEntryFromRunState, bb as selectBackend, bc as selfhostedLiveness, bd as serializeEstablishedSandboxEnvelope, be as setSelfhostedApplyDiff, bf as startRecording, bg as stopRecording, bh as stripExecBanner, bi as subjectFor, bj as sweepModalOrphanSandboxes, bk as tagModalSandbox, bl as tearDownDisplayStack, bm as tearDownTerminalServer, bn as terminateModalSandboxById, bo as timeoutAgentError, bp as timeoutControlResponse, bq as verifyStreamToken } from '../index-BTo_bZvN.js';
|
|
5
5
|
import 'modal';
|
|
6
6
|
import '@opengeni/agent-proto';
|
package/dist/sandbox/index.js
CHANGED
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
deserializeSandboxSessionStateEnvelope,
|
|
54
54
|
desktopCapableBackend,
|
|
55
55
|
ensureDisplayStack,
|
|
56
|
+
ensureModalRegistryImage,
|
|
56
57
|
ensureTerminalServer,
|
|
57
58
|
establishSandboxSessionFromEnvelope,
|
|
58
59
|
exposeStreamPort,
|
|
@@ -95,7 +96,7 @@ import {
|
|
|
95
96
|
timeoutAgentError,
|
|
96
97
|
timeoutControlResponse,
|
|
97
98
|
verifyStreamToken
|
|
98
|
-
} from "../chunk-
|
|
99
|
+
} from "../chunk-DYBF7ZEB.js";
|
|
99
100
|
export {
|
|
100
101
|
ActiveBackendUnresolvableError,
|
|
101
102
|
CAPABILITY_DESCRIPTORS,
|
|
@@ -151,6 +152,7 @@ export {
|
|
|
151
152
|
deserializeSandboxSessionStateEnvelope,
|
|
152
153
|
desktopCapableBackend,
|
|
153
154
|
ensureDisplayStack,
|
|
155
|
+
ensureModalRegistryImage,
|
|
154
156
|
ensureTerminalServer,
|
|
155
157
|
establishSandboxSessionFromEnvelope,
|
|
156
158
|
exposeStreamPort,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@opengeni/agent-proto": "^0.2.1",
|
|
34
|
-
"@opengeni/config": "^0.
|
|
34
|
+
"@opengeni/config": "^0.4.0",
|
|
35
35
|
"@opengeni/contracts": "^0.9.0",
|
|
36
36
|
"@openai/agents": "^0.11.6",
|
|
37
37
|
"@openai/agents-extensions": "^0.11.6",
|
package/src/image-history.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AgentInputItem } from "@openai/agents";
|
|
2
|
+
import { SCREENSHOT_OMITTED_IMAGE_DATA_URL } from "./screenshot-omitted-card";
|
|
2
3
|
|
|
3
4
|
export const SCREENSHOT_OMITTED_PLACEHOLDER =
|
|
4
5
|
"[screenshot omitted: an older desktop frame — the full image remains in the session event log]";
|
|
@@ -59,7 +60,7 @@ function collectItemImageOccurrences(
|
|
|
59
60
|
return;
|
|
60
61
|
}
|
|
61
62
|
if (item.type === "computer_call_result" || item.type === "computer_call_output") {
|
|
62
|
-
collectComputerOutputImages(item, path,
|
|
63
|
+
collectComputerOutputImages(item, path, out);
|
|
63
64
|
return;
|
|
64
65
|
}
|
|
65
66
|
if (item.type === "function_call_result" || item.type === "function_call_output") {
|
|
@@ -70,7 +71,6 @@ function collectItemImageOccurrences(
|
|
|
70
71
|
function collectComputerOutputImages(
|
|
71
72
|
item: Record<string, unknown>,
|
|
72
73
|
path: PathSegment[],
|
|
73
|
-
placeholder: string,
|
|
74
74
|
out: ImageOccurrence[],
|
|
75
75
|
): void {
|
|
76
76
|
const output = item.output;
|
|
@@ -79,7 +79,7 @@ function collectComputerOutputImages(
|
|
|
79
79
|
}
|
|
80
80
|
for (const key of ["data", "image_url", "imageUrl"]) {
|
|
81
81
|
if (isImageDataUrl(output[key])) {
|
|
82
|
-
out.push({ path: [...path, "output", key], replacement:
|
|
82
|
+
out.push({ path: [...path, "output", key], replacement: SCREENSHOT_OMITTED_IMAGE_DATA_URL });
|
|
83
83
|
return;
|
|
84
84
|
}
|
|
85
85
|
}
|
package/src/index.ts
CHANGED
|
@@ -180,6 +180,7 @@ export {
|
|
|
180
180
|
elideStaleScreenshotImages,
|
|
181
181
|
SCREENSHOT_OMITTED_PLACEHOLDER,
|
|
182
182
|
} from "./image-history";
|
|
183
|
+
export { SCREENSHOT_OMITTED_IMAGE_DATA_URL } from "./screenshot-omitted-card";
|
|
183
184
|
export type { ElideStaleScreenshotsOptions, ElideStaleScreenshotsResult } from "./image-history";
|
|
184
185
|
|
|
185
186
|
ensureReadableStreamFrom();
|
package/src/sandbox/index.ts
CHANGED
|
@@ -55,12 +55,14 @@ export {
|
|
|
55
55
|
type ProviderConstructionContext,
|
|
56
56
|
} from "./providers";
|
|
57
57
|
export {
|
|
58
|
+
ensureModalRegistryImage,
|
|
58
59
|
modalSandboxAttributionEnvironment,
|
|
59
60
|
modalSandboxAttributionTags,
|
|
60
61
|
sweepModalOrphanSandboxes,
|
|
61
62
|
tagModalSandbox,
|
|
62
63
|
terminateModalSandboxById,
|
|
63
64
|
type LiveModalSandboxLeaseAttribution,
|
|
65
|
+
type ModalModuleLoader,
|
|
64
66
|
type ModalOrphanSweepResult,
|
|
65
67
|
type ModalSandboxAttribution,
|
|
66
68
|
} from "./providers/modal";
|
|
@@ -87,8 +87,9 @@ export const modalProvider: ProviderRegistration = {
|
|
|
87
87
|
if (settings.modalWorkspacePersistence) {
|
|
88
88
|
options.workspacePersistence = settings.modalWorkspacePersistence;
|
|
89
89
|
}
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
const imageSelector = resolveModalImageSelector(settings);
|
|
91
|
+
if (imageSelector) {
|
|
92
|
+
options.image = imageSelector;
|
|
92
93
|
}
|
|
93
94
|
if (settings.modalTokenId) {
|
|
94
95
|
options.tokenId = settings.modalTokenId;
|
|
@@ -106,6 +107,115 @@ export const modalProvider: ProviderRegistration = {
|
|
|
106
107
|
type ModalModule = typeof import("modal");
|
|
107
108
|
type ModalClientLike = InstanceType<ModalModule["ModalClient"]>;
|
|
108
109
|
|
|
110
|
+
// --- Private-registry image resolution (OPENGENI_MODAL_IMAGE_REGISTRY_SECRET) ------
|
|
111
|
+
//
|
|
112
|
+
// The Agents-extension Modal backend resolves `modalImageRef` via
|
|
113
|
+
// `Image.fromRegistry(tag)` with NO secret, so it can only pull PUBLIC images. To run
|
|
114
|
+
// a PRIVATE image we resolve the named Modal Secret and pre-build the authenticated
|
|
115
|
+
// `fromRegistry(tag, secret)` image ONCE per process, then hand the provider `build`
|
|
116
|
+
// a `ModalImageSelector.fromImage(...)`. `build` is synchronous and modal is imported
|
|
117
|
+
// lazily (never loaded for non-modal backends), so resolution can't happen inside
|
|
118
|
+
// `build`; the worker awaits `ensureModalRegistryImage` at boot for global refs and
|
|
119
|
+
// at turn time for pack-scoped refs, then `build` reads the settled result. Modal
|
|
120
|
+
// images are lazy, workspace-scoped definitions, so an image built by this module's
|
|
121
|
+
// client is usable by the ModalSandboxClient's own client.
|
|
122
|
+
|
|
123
|
+
/** Loader seam so unit tests can inject a fake modal module. */
|
|
124
|
+
export type ModalModuleLoader = () => Promise<Pick<ModalModule, "ModalClient">>;
|
|
125
|
+
|
|
126
|
+
const defaultModalLoader: ModalModuleLoader = () => import("modal");
|
|
127
|
+
|
|
128
|
+
/** Settled, synchronously-readable resolved images, keyed per config. */
|
|
129
|
+
const resolvedRegistryImages = new Map<string, unknown>();
|
|
130
|
+
/** In-flight resolutions, for cross-call de-duplication. */
|
|
131
|
+
const inFlightRegistryImages = new Map<string, Promise<void>>();
|
|
132
|
+
|
|
133
|
+
function registryImageCacheKey(settings: Settings): string {
|
|
134
|
+
return [
|
|
135
|
+
settings.modalImageRef ?? "",
|
|
136
|
+
settings.modalImageRegistrySecret ?? "",
|
|
137
|
+
settings.modalEnvironment ?? "",
|
|
138
|
+
].join("|");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Resolve + cache the private-registry Modal image. No-op unless BOTH
|
|
143
|
+
* `modalImageRef` and `modalImageRegistrySecret` are set. Memoized per
|
|
144
|
+
* (imageRef, secret, environment) so it runs once per worker process. Awaited at
|
|
145
|
+
* worker boot for the deployment-global image and at turn time for pack-scoped
|
|
146
|
+
* images BEFORE the first sandbox using that ref is created; `build` then reads the
|
|
147
|
+
* resolved image and otherwise falls back to the public `fromTag` path.
|
|
148
|
+
*/
|
|
149
|
+
export async function ensureModalRegistryImage(
|
|
150
|
+
settings: Settings,
|
|
151
|
+
loadModal: ModalModuleLoader = defaultModalLoader,
|
|
152
|
+
): Promise<void> {
|
|
153
|
+
if (!settings.modalImageRegistrySecret || !settings.modalImageRef) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const key = registryImageCacheKey(settings);
|
|
157
|
+
if (resolvedRegistryImages.has(key)) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
let pending = inFlightRegistryImages.get(key);
|
|
161
|
+
if (!pending) {
|
|
162
|
+
pending = (async () => {
|
|
163
|
+
const modal = await loadModal();
|
|
164
|
+
const client = new modal.ModalClient(modalClientOptions(settings));
|
|
165
|
+
// Resolve the Secret via the AUTHENTICATED client (client.secrets.fromName),
|
|
166
|
+
// NOT the static `modal.Secret.fromName`, which resolves against
|
|
167
|
+
// `getDefaultClient()` — i.e. the standard MODAL_TOKEN_ID/MODAL_TOKEN_SECRET env
|
|
168
|
+
// or ~/.modal.toml — and so would throw "Profile is missing token_id" in any host
|
|
169
|
+
// that supplies the token only through OpenGeni settings (OPENGENI_MODAL_TOKEN_ID).
|
|
170
|
+
const secret = await client.secrets.fromName(
|
|
171
|
+
settings.modalImageRegistrySecret!,
|
|
172
|
+
settings.modalEnvironment ? { environment: settings.modalEnvironment } : undefined,
|
|
173
|
+
);
|
|
174
|
+
// fromRegistry is synchronous and returns a lazy image definition (built
|
|
175
|
+
// server-side at sandbox create); the resolved secretId travels with it.
|
|
176
|
+
const image = client.images.fromRegistry(settings.modalImageRef!, secret);
|
|
177
|
+
resolvedRegistryImages.set(key, image);
|
|
178
|
+
})().finally(() => {
|
|
179
|
+
inFlightRegistryImages.delete(key);
|
|
180
|
+
});
|
|
181
|
+
inFlightRegistryImages.set(key, pending);
|
|
182
|
+
}
|
|
183
|
+
await pending;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** The resolved private-registry image for these settings, or undefined if none. */
|
|
187
|
+
function cachedModalRegistryImage(settings: Settings): unknown | undefined {
|
|
188
|
+
if (!settings.modalImageRegistrySecret || !settings.modalImageRef) {
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
return resolvedRegistryImages.get(registryImageCacheKey(settings));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Choose the image selector for a Modal sandbox client from settings. Returns:
|
|
196
|
+
* - `fromImage(resolved)` when a private-registry secret is configured AND the
|
|
197
|
+
* image has been resolved (ensureModalRegistryImage ran before create);
|
|
198
|
+
* - `fromTag(modalImageRef)` for the public path (no secret, or cold cache — the
|
|
199
|
+
* resume/attach paths never pull an image so the tag branch is harmless there);
|
|
200
|
+
* - `undefined` when no image ref is set (Modal uses its default image).
|
|
201
|
+
* Exported for unit tests.
|
|
202
|
+
*/
|
|
203
|
+
export function resolveModalImageSelector(settings: Settings): ModalImageSelector | undefined {
|
|
204
|
+
if (!settings.modalImageRef) {
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
const registryImage = cachedModalRegistryImage(settings);
|
|
208
|
+
return registryImage
|
|
209
|
+
? ModalImageSelector.fromImage(registryImage as Parameters<typeof ModalImageSelector.fromImage>[0])
|
|
210
|
+
: ModalImageSelector.fromTag(settings.modalImageRef);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Test-only: clear the resolved/in-flight image caches. */
|
|
214
|
+
export function __resetModalRegistryImageCacheForTest(): void {
|
|
215
|
+
resolvedRegistryImages.clear();
|
|
216
|
+
inFlightRegistryImages.clear();
|
|
217
|
+
}
|
|
218
|
+
|
|
109
219
|
function modalClientOptions(settings: Settings): ConstructorParameters<ModalModule["ModalClient"]>[0] {
|
|
110
220
|
return {
|
|
111
221
|
...(settings.modalTokenId ? { tokenId: settings.modalTokenId } : {}),
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// The legible "screenshot omitted" card that image-history substitutes for an
|
|
2
|
+
// ELIDED `computer_call_output` screenshot. The hosted computer tool requires
|
|
3
|
+
// `computer_call_output.output.image_url` to remain a syntactically valid URL;
|
|
4
|
+
// the text placeholder is valid for tool-result text paths but 400s this image
|
|
5
|
+
// channel once older screenshots are elided.
|
|
6
|
+
//
|
|
7
|
+
// This is a valid 8-bit RGBA PNG (signature + chunk CRCs emitted by the
|
|
8
|
+
// dependency-free generator) rendered from a fixed message:
|
|
9
|
+
// SCREENSHOT OMITTED
|
|
10
|
+
// EARLIER FRAME ELIDED
|
|
11
|
+
// TO SAVE CONTEXT.
|
|
12
|
+
//
|
|
13
|
+
// Regenerate with: `bun run scripts/gen-screenshot-omitted-card.mjs`
|
|
14
|
+
export const SCREENSHOT_OMITTED_IMAGE_DATA_URL =
|
|
15
|
+
"data:image/png;base64,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";
|