@opengeni/runtime 0.6.1 → 0.7.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.
Files changed (45) hide show
  1. package/dist/{chunk-DYBF7ZEB.js → chunk-RYDCVTMW.js} +1958 -207
  2. package/dist/chunk-RYDCVTMW.js.map +1 -0
  3. package/dist/{index-BTo_bZvN.d.ts → index-DIiiwQY2.d.ts} +689 -52
  4. package/dist/index.d.ts +296 -123
  5. package/dist/index.js +1907 -809
  6. package/dist/index.js.map +1 -1
  7. package/dist/sandbox/index.d.ts +1 -1
  8. package/dist/sandbox/index.js +79 -3
  9. package/package.json +21 -20
  10. package/src/codex-tool-search.ts +185 -31
  11. package/src/context-compaction.ts +78 -243
  12. package/src/history-sanitizer.ts +172 -20
  13. package/src/index.ts +2687 -920
  14. package/src/metrics.ts +28 -2
  15. package/src/sandbox/capabilities.ts +12 -3
  16. package/src/sandbox/channel-a.ts +420 -72
  17. package/src/sandbox/display-stack.ts +18 -4
  18. package/src/sandbox/errors.ts +13 -0
  19. package/src/sandbox/index.ts +398 -112
  20. package/src/sandbox/op-correlation.ts +70 -0
  21. package/src/sandbox/providers/index.ts +9 -3
  22. package/src/sandbox/providers/modal.ts +84 -14
  23. package/src/sandbox/providers/selfhosted.ts +1 -4
  24. package/src/sandbox/recording.ts +146 -90
  25. package/src/sandbox/routing/backend-resolver.ts +144 -10
  26. package/src/sandbox/routing/routing-session.ts +129 -25
  27. package/src/sandbox/select.ts +60 -8
  28. package/src/sandbox/selfhosted/capabilities.ts +59 -25
  29. package/src/sandbox/selfhosted/control-rpc.ts +160 -28
  30. package/src/sandbox/selfhosted/fault-rendering.ts +226 -0
  31. package/src/sandbox/selfhosted/op-observer.ts +54 -0
  32. package/src/sandbox/selfhosted/op-stream.ts +801 -0
  33. package/src/sandbox/selfhosted/op-testing.ts +468 -0
  34. package/src/sandbox/selfhosted/op-transport.ts +151 -0
  35. package/src/sandbox/selfhosted/retry-policy.ts +177 -0
  36. package/src/sandbox/selfhosted/session.ts +498 -55
  37. package/src/sandbox/selfhosted/testing.ts +60 -19
  38. package/src/sandbox/stream-port.ts +17 -5
  39. package/src/sandbox/stream-token.ts +8 -2
  40. package/src/sandbox/terminal-server.ts +18 -4
  41. package/src/sandbox-computer.ts +332 -70
  42. package/src/usage-telemetry.ts +73 -0
  43. package/dist/chunk-DYBF7ZEB.js.map +0 -1
  44. package/src/image-history.ts +0 -149
  45. package/src/screenshot-omitted-card.ts +0 -15
@@ -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 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';
4
+ export { A as ActiveBackendResolverDeps, a as ActiveBackendUnresolvableError, b as ActivePointer, B as BackendUnresolvableCode, 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 FAULT_FIELD_WHAT_HAPPENED, v as FAULT_FIELD_WHAT_PRESERVED, w as FAULT_FIELD_WHAT_TO_TRY, x as FAULT_FIELD_WHICH_LAYER, L as LiveModalSandboxLeaseAttribution, M as MintStreamTokenInput, y as MockAgentResponder, z as MockAgentResponderOptions, G as MockExecHandler, H as ModalModuleLoader, I as ModalOrphanSweepResult, J as ModalSandboxAttribution, N as NEVER_SENT_DETAIL_KEY, K as NatsControlRpc, O as NatsOpStreamConnection, P as NatsOpStreamTransport, Q as NatsRequestConnection, S as NegotiationContext, T as NumstatEntry, U as OP_STREAM_ACK_INTERVAL_MS, V as OP_STREAM_DEFAULT_WINDOW_BYTES, W as OP_STREAM_RECONNECT_HOLD_MS, X as OP_STREAM_SILENCE_TIMEOUT_MS, Y as OpStreamExecOutcome, Z as OpStreamJournal, _ as OpStreamSubscription, $ as OpStreamTransport, a0 as OpStreamUnavailableError, a1 as PROVIDER_REGISTRY, a2 as ProviderConstructionContext, a3 as ProviderRegistration, a4 as REPOSITORY_DISCOVERY_LIMIT, a5 as RecordingArtifactMetadata, a6 as RecordingCodec, a7 as RecordingContentType, a8 as RecordingError, a9 as RecordingProcess, aa as RecordingUnavailableError, ab as RepositoryDiscoveryDegradedReason, ac as RepositoryDiscoveryResult, ad as ResolvedActiveBackend, ae as RoutableBackendSession, af as RoutableSandbox, ag as RoutingSandboxSession, ah as RoutingSandboxSessionDeps, ai as RoutingTransitionEvent, aj as RoutingUnsupportedError, ak as SELFHOSTED_DEFAULT_TIMEOUT_MS, al as SELFHOSTED_DRAINING_MAX_RETRIES, am as SELFHOSTED_EXEC_DRAINING_MAX_RETRIES, an as SELFHOSTED_IDEMPOTENT_READONLY_OPS, ao as SELFHOSTED_INFRASTRUCTURE_FAULT_CLASSES, ap as SELFHOSTED_NEVER_SENT_MAX_RETRIES, aq as SELFHOSTED_RECONNECT_WINDOW_MS, ar as SELFHOSTED_RELAY_STREAM_PATH, as as SELFHOSTED_RETRY_BACKOFF_BASE_MS, at as SELFHOSTED_RETRY_BACKOFF_CAP_MS, au as SELFHOSTED_RETRY_BACKOFF_FACTOR, av as SELFHOSTED_TIMEOUT_MAX_RETRIES, aw as STREAM_PORT, ax as STREAM_TOKEN_DEFAULT_TTL_SECONDS, ay as SandboxChannelAService, az as SandboxChannelAServiceOptions, aA as SandboxConfigError, aB as SandboxCreatedCallback, aC as SandboxProviderUnavailableError, aD as SandboxResumeStateUnavailableError, aE as SelfhostedApplyDiff, aF as SelfhostedControlError, aG as SelfhostedEditor, aH as SelfhostedEnrollment, aI as SelfhostedExecArgs, aJ as SelfhostedExecResult, aK as SelfhostedImageOutput, aL as SelfhostedLivenessState, aM as SelfhostedNegotiationInput, aN as SelfhostedOpObservation, aO as SelfhostedOpObserver, aP as SelfhostedOpStreamDeps, aQ as SelfhostedRelayConfig, aR as SelfhostedRetryClock, aS as SelfhostedRetryDecision, aT as SelfhostedSandboxClient, aU as SelfhostedSession, aV as SelfhostedSessionBuild, aW as SelfhostedSessionDeps, aX as SelfhostedSessionState, aY as SelfhostedUnavailableReason, aZ as StartRecordingInput, a_ as StreamPortUnavailableError, a$ as SwapTargetEstablishability, b0 as TERMINAL_SERVER_TIMEOUT_MS, b1 as TerminalServerError, b2 as TerminalServerUnsupportedError, b3 as agentErrorToControlError, b4 as assertDescriptorRegistryInvariants, b5 as assertProviderRegistryInvariants, b6 as assertSafeRelPath, b7 as backendSupportsOs, b8 as buildDisplayStackScript, b9 as buildSelfhostedBackendSession, ba as buildStreamUrl, bb as buildTerminalServerScript, bc as contentTypeForCodec, bd as createSandboxClient, be as createSandboxClientForBackend, bf as decideSelfhostedRetry, bg as decodeModalSnapshotId, bh as defaultSelfhostedRetryClock, bi as deletePriorPersistedSnapshot, bj as deleteRecordingArtifacts, bk as deserializeSandboxSessionStateEnvelope, bl as desktopCapableBackend, bm as drainingExhaustedError, bn as drainingMessage, bo as ensureDisplayStack, bp as ensureModalRegistryImage, bq as ensureTerminalServer, br as establishSandboxSessionFromEnvelope, bs as execDeadlineHint, bt as exposeStreamPort, bu as extForCodec, bv as inspectRecordingArtifact, bw as isExecSessionLostBanner, bx as isProviderSandboxNotFoundError, by as isSelfhostedProviderNotFoundError, bz as isWorkspaceEscapeError, bA as makeActiveBackendResolver, bB as mintStreamToken, bC as modalSandboxAttributionEnvironment, bD as modalSandboxAttributionTags, bE as negotiateCapabilities, bF as negotiateSelfhostedCapabilities, bG as nextDurableOpId, bH as offlineAgentError, bI as offlineControlResponse, bJ as opAckSubject, bK as opFrameSubject, bL as parseExecBannerSessionId, bM as parseNumstatZ, bN as parsePorcelainV2, bO as parseUnifiedPatch, bP as payloadTooLargeMessage, bQ as readWorkspaceArchiveFromEnvelopeSessionState, bR as recordingStorageKey, bS as renderSelfhostedFault, bT as restoredSandboxSessionStateFromEntry, bU as runWithToolCallCorrelation, bV as sandboxStateEntryFromRunState, bW as sanitizeOpIdToken, bX as selectBackend, bY as selfhostedFaultClass, bZ as selfhostedLiveness, b_ as selfhostedRetryBackoffMs, b$ as serializeEstablishedSandboxEnvelope, c0 as setSelfhostedApplyDiff, c1 as startRecording, c2 as stopRecording, c3 as stripExecBanner, c4 as subjectFor, c5 as swapTargetEstablishability, c6 as sweepModalOrphanSandboxes, c7 as tagModalSandbox, c8 as tearDownDisplayStack, c9 as tearDownTerminalServer, ca as terminateModalSandboxById, cb as timeoutAgentError, cc as timeoutControlResponse, cd as uploadRecordingArtifact, ce as verifyStreamToken } from '../index-DIiiwQY2.js';
5
5
  import 'modal';
6
6
  import '@opengeni/agent-proto';
@@ -10,21 +10,43 @@ import {
10
10
  DISPLAY_STACK_TIMEOUT_MS,
11
11
  DisplayStackError,
12
12
  DisplayStackUnsupportedError,
13
+ FAULT_FIELD_WHAT_HAPPENED,
14
+ FAULT_FIELD_WHAT_PRESERVED,
15
+ FAULT_FIELD_WHAT_TO_TRY,
16
+ FAULT_FIELD_WHICH_LAYER,
13
17
  MockAgentResponder,
18
+ NEVER_SENT_DETAIL_KEY,
14
19
  NatsControlRpc,
20
+ NatsOpStreamTransport,
21
+ OP_STREAM_ACK_INTERVAL_MS,
22
+ OP_STREAM_DEFAULT_WINDOW_BYTES,
23
+ OP_STREAM_RECONNECT_HOLD_MS,
24
+ OP_STREAM_SILENCE_TIMEOUT_MS,
25
+ OpStreamUnavailableError,
15
26
  PROVIDER_REGISTRY,
27
+ REPOSITORY_DISCOVERY_LIMIT,
16
28
  RecordingError,
17
29
  RecordingUnavailableError,
18
30
  RoutingSandboxSession,
19
31
  RoutingUnsupportedError,
20
32
  SELFHOSTED_DEFAULT_TIMEOUT_MS,
33
+ SELFHOSTED_DRAINING_MAX_RETRIES,
34
+ SELFHOSTED_EXEC_DRAINING_MAX_RETRIES,
35
+ SELFHOSTED_IDEMPOTENT_READONLY_OPS,
36
+ SELFHOSTED_INFRASTRUCTURE_FAULT_CLASSES,
37
+ SELFHOSTED_NEVER_SENT_MAX_RETRIES,
21
38
  SELFHOSTED_RECONNECT_WINDOW_MS,
22
39
  SELFHOSTED_RELAY_STREAM_PATH,
40
+ SELFHOSTED_RETRY_BACKOFF_BASE_MS,
41
+ SELFHOSTED_RETRY_BACKOFF_CAP_MS,
42
+ SELFHOSTED_RETRY_BACKOFF_FACTOR,
43
+ SELFHOSTED_TIMEOUT_MAX_RETRIES,
23
44
  STREAM_PORT,
24
45
  STREAM_TOKEN_DEFAULT_TTL_SECONDS,
25
46
  SandboxChannelAService,
26
47
  SandboxConfigError,
27
48
  SandboxProviderUnavailableError,
49
+ SandboxResumeStateUnavailableError,
28
50
  SelfhostedControlError,
29
51
  SelfhostedSandboxClient,
30
52
  SelfhostedSession,
@@ -47,17 +69,23 @@ import {
47
69
  contentTypeForCodec,
48
70
  createSandboxClient,
49
71
  createSandboxClientForBackend,
72
+ decideSelfhostedRetry,
50
73
  decodeModalSnapshotId,
74
+ defaultSelfhostedRetryClock,
51
75
  deletePriorPersistedSnapshot,
52
76
  deleteRecordingArtifacts,
53
77
  deserializeSandboxSessionStateEnvelope,
54
78
  desktopCapableBackend,
79
+ drainingExhaustedError,
80
+ drainingMessage,
55
81
  ensureDisplayStack,
56
82
  ensureModalRegistryImage,
57
83
  ensureTerminalServer,
58
84
  establishSandboxSessionFromEnvelope,
85
+ execDeadlineHint,
59
86
  exposeStreamPort,
60
87
  extForCodec,
88
+ inspectRecordingArtifact,
61
89
  isExecSessionLostBanner,
62
90
  isProviderSandboxNotFoundError,
63
91
  isSelfhostedProviderNotFoundError,
@@ -68,26 +96,35 @@ import {
68
96
  modalSandboxAttributionTags,
69
97
  negotiateCapabilities,
70
98
  negotiateSelfhostedCapabilities,
99
+ nextDurableOpId,
71
100
  offlineAgentError,
72
101
  offlineControlResponse,
102
+ opAckSubject,
103
+ opFrameSubject,
73
104
  parseExecBannerSessionId,
74
105
  parseExposedPorts,
75
106
  parseNumstatZ,
76
107
  parsePorcelainV2,
77
108
  parseUnifiedPatch,
78
- readRecordingBytes,
109
+ payloadTooLargeMessage,
79
110
  readWorkspaceArchiveFromEnvelopeSessionState,
80
111
  recordingStorageKey,
112
+ renderSelfhostedFault,
81
113
  restoredSandboxSessionStateFromEntry,
114
+ runWithToolCallCorrelation,
82
115
  sandboxStateEntryFromRunState,
116
+ sanitizeOpIdToken,
83
117
  selectBackend,
118
+ selfhostedFaultClass,
84
119
  selfhostedLiveness,
120
+ selfhostedRetryBackoffMs,
85
121
  serializeEstablishedSandboxEnvelope,
86
122
  setSelfhostedApplyDiff,
87
123
  startRecording,
88
124
  stopRecording,
89
125
  stripExecBanner,
90
126
  subjectFor,
127
+ swapTargetEstablishability,
91
128
  sweepModalOrphanSandboxes,
92
129
  tagModalSandbox,
93
130
  tearDownDisplayStack,
@@ -95,8 +132,9 @@ import {
95
132
  terminateModalSandboxById,
96
133
  timeoutAgentError,
97
134
  timeoutControlResponse,
135
+ uploadRecordingArtifact,
98
136
  verifyStreamToken
99
- } from "../chunk-DYBF7ZEB.js";
137
+ } from "../chunk-RYDCVTMW.js";
100
138
  export {
101
139
  ActiveBackendUnresolvableError,
102
140
  CAPABILITY_DESCRIPTORS,
@@ -109,21 +147,43 @@ export {
109
147
  DISPLAY_STACK_TIMEOUT_MS,
110
148
  DisplayStackError,
111
149
  DisplayStackUnsupportedError,
150
+ FAULT_FIELD_WHAT_HAPPENED,
151
+ FAULT_FIELD_WHAT_PRESERVED,
152
+ FAULT_FIELD_WHAT_TO_TRY,
153
+ FAULT_FIELD_WHICH_LAYER,
112
154
  MockAgentResponder,
155
+ NEVER_SENT_DETAIL_KEY,
113
156
  NatsControlRpc,
157
+ NatsOpStreamTransport,
158
+ OP_STREAM_ACK_INTERVAL_MS,
159
+ OP_STREAM_DEFAULT_WINDOW_BYTES,
160
+ OP_STREAM_RECONNECT_HOLD_MS,
161
+ OP_STREAM_SILENCE_TIMEOUT_MS,
162
+ OpStreamUnavailableError,
114
163
  PROVIDER_REGISTRY,
164
+ REPOSITORY_DISCOVERY_LIMIT,
115
165
  RecordingError,
116
166
  RecordingUnavailableError,
117
167
  RoutingSandboxSession,
118
168
  RoutingUnsupportedError,
119
169
  SELFHOSTED_DEFAULT_TIMEOUT_MS,
170
+ SELFHOSTED_DRAINING_MAX_RETRIES,
171
+ SELFHOSTED_EXEC_DRAINING_MAX_RETRIES,
172
+ SELFHOSTED_IDEMPOTENT_READONLY_OPS,
173
+ SELFHOSTED_INFRASTRUCTURE_FAULT_CLASSES,
174
+ SELFHOSTED_NEVER_SENT_MAX_RETRIES,
120
175
  SELFHOSTED_RECONNECT_WINDOW_MS,
121
176
  SELFHOSTED_RELAY_STREAM_PATH,
177
+ SELFHOSTED_RETRY_BACKOFF_BASE_MS,
178
+ SELFHOSTED_RETRY_BACKOFF_CAP_MS,
179
+ SELFHOSTED_RETRY_BACKOFF_FACTOR,
180
+ SELFHOSTED_TIMEOUT_MAX_RETRIES,
122
181
  STREAM_PORT,
123
182
  STREAM_TOKEN_DEFAULT_TTL_SECONDS,
124
183
  SandboxChannelAService,
125
184
  SandboxConfigError,
126
185
  SandboxProviderUnavailableError,
186
+ SandboxResumeStateUnavailableError,
127
187
  SelfhostedControlError,
128
188
  SelfhostedSandboxClient,
129
189
  SelfhostedSession,
@@ -146,17 +206,23 @@ export {
146
206
  contentTypeForCodec,
147
207
  createSandboxClient,
148
208
  createSandboxClientForBackend,
209
+ decideSelfhostedRetry,
149
210
  decodeModalSnapshotId,
211
+ defaultSelfhostedRetryClock,
150
212
  deletePriorPersistedSnapshot,
151
213
  deleteRecordingArtifacts,
152
214
  deserializeSandboxSessionStateEnvelope,
153
215
  desktopCapableBackend,
216
+ drainingExhaustedError,
217
+ drainingMessage,
154
218
  ensureDisplayStack,
155
219
  ensureModalRegistryImage,
156
220
  ensureTerminalServer,
157
221
  establishSandboxSessionFromEnvelope,
222
+ execDeadlineHint,
158
223
  exposeStreamPort,
159
224
  extForCodec,
225
+ inspectRecordingArtifact,
160
226
  isExecSessionLostBanner,
161
227
  isProviderSandboxNotFoundError,
162
228
  isSelfhostedProviderNotFoundError,
@@ -167,26 +233,35 @@ export {
167
233
  modalSandboxAttributionTags,
168
234
  negotiateCapabilities,
169
235
  negotiateSelfhostedCapabilities,
236
+ nextDurableOpId,
170
237
  offlineAgentError,
171
238
  offlineControlResponse,
239
+ opAckSubject,
240
+ opFrameSubject,
172
241
  parseExecBannerSessionId,
173
242
  parseExposedPorts,
174
243
  parseNumstatZ,
175
244
  parsePorcelainV2,
176
245
  parseUnifiedPatch,
177
- readRecordingBytes,
246
+ payloadTooLargeMessage,
178
247
  readWorkspaceArchiveFromEnvelopeSessionState,
179
248
  recordingStorageKey,
249
+ renderSelfhostedFault,
180
250
  restoredSandboxSessionStateFromEntry,
251
+ runWithToolCallCorrelation,
181
252
  sandboxStateEntryFromRunState,
253
+ sanitizeOpIdToken,
182
254
  selectBackend,
255
+ selfhostedFaultClass,
183
256
  selfhostedLiveness,
257
+ selfhostedRetryBackoffMs,
184
258
  serializeEstablishedSandboxEnvelope,
185
259
  setSelfhostedApplyDiff,
186
260
  startRecording,
187
261
  stopRecording,
188
262
  stripExecBanner,
189
263
  subjectFor,
264
+ swapTargetEstablishability,
190
265
  sweepModalOrphanSandboxes,
191
266
  tagModalSandbox,
192
267
  tearDownDisplayStack,
@@ -194,6 +269,7 @@ export {
194
269
  terminateModalSandboxById,
195
270
  timeoutAgentError,
196
271
  timeoutControlResponse,
272
+ uploadRecordingArtifact,
197
273
  verifyStreamToken
198
274
  };
199
275
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,8 +1,17 @@
1
1
  {
2
2
  "name": "@opengeni/runtime",
3
- "version": "0.6.1",
4
- "type": "module",
3
+ "version": "0.7.1",
5
4
  "license": "Apache-2.0",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/Cloudgeni-ai/opengeni.git",
8
+ "directory": "packages/runtime"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "src"
13
+ ],
14
+ "type": "module",
6
15
  "main": "./dist/index.js",
7
16
  "module": "./dist/index.js",
8
17
  "types": "./dist/index.d.ts",
@@ -16,32 +25,24 @@
16
25
  "import": "./dist/sandbox/index.js"
17
26
  }
18
27
  },
19
- "files": [
20
- "dist",
21
- "src"
22
- ],
23
28
  "publishConfig": {
24
29
  "access": "public",
25
30
  "provenance": true
26
31
  },
27
32
  "scripts": {
28
33
  "build": "tsup",
29
- "typecheck": "tsc --noEmit",
34
+ "typecheck": "tsgo --noEmit",
30
35
  "prepublishOnly": "bash ../../scripts/prepublish-guard"
31
36
  },
32
37
  "dependencies": {
33
- "@opengeni/agent-proto": "^0.2.1",
34
- "@opengeni/config": "^0.4.0",
35
- "@opengeni/contracts": "^0.9.0",
36
- "@openai/agents": "^0.11.6",
37
- "@openai/agents-extensions": "^0.11.6",
38
- "modal": "^0.7.4",
39
- "openai": "6.36.0",
40
- "@opengeni/codex": "^0.2.1"
41
- },
42
- "repository": {
43
- "type": "git",
44
- "url": "git+https://github.com/Cloudgeni-ai/opengeni.git",
45
- "directory": "packages/runtime"
38
+ "@noble/hashes": "^1.8.0",
39
+ "@openai/agents": "0.13.3",
40
+ "@openai/agents-extensions": "0.13.3",
41
+ "@opengeni/agent-proto": "^0.3.0",
42
+ "@opengeni/codex": "^0.2.3",
43
+ "@opengeni/config": "^0.5.1",
44
+ "@opengeni/contracts": "^0.10.0",
45
+ "modal": "0.7.6",
46
+ "openai": "6.47.0"
46
47
  }
47
48
  }
@@ -10,7 +10,7 @@
10
10
  // from model context), searches by capability, and only the matched tools are
11
11
  // disclosed back and become callable.
12
12
  //
13
- // PROVEN LIVE (Phase 0 probe against /codex/responses on gpt-5.5): the backend
13
+ // PROVEN LIVE (Phase 0 probe against /codex/responses on gpt-5.6-sol): the backend
14
14
  // HONORS `defer_loading:true` on function tools — 50 fat tools dropped input_tokens
15
15
  // 6766 → 108 — AND makes a tool callable purely because a prior `tool_search_output`
16
16
  // disclosed it (V3). The model emits `tool_search_call` on our slug.
@@ -33,13 +33,15 @@ const DEFAULT_SEARCH_LIMIT = 8;
33
33
  const MAX_SEARCH_LIMIT = 20;
34
34
 
35
35
  /** True for a materialized codex_apps connector function tool. */
36
- export function isCodexAppsFunctionTool(tool: unknown): tool is Tool & { name: string; deferLoading?: boolean } {
36
+ export function isCodexAppsFunctionTool(
37
+ tool: unknown,
38
+ ): tool is Tool & { name: string; deferLoading?: boolean } {
37
39
  return (
38
- !!tool
39
- && typeof tool === "object"
40
- && (tool as { type?: unknown }).type === "function"
41
- && typeof (tool as { name?: unknown }).name === "string"
42
- && (tool as { name: string }).name.startsWith(CODEX_APPS_TOOL_PREFIX)
40
+ !!tool &&
41
+ typeof tool === "object" &&
42
+ (tool as { type?: unknown }).type === "function" &&
43
+ typeof (tool as { name?: unknown }).name === "string" &&
44
+ (tool as { name: string }).name.startsWith(CODEX_APPS_TOOL_PREFIX)
43
45
  );
44
46
  }
45
47
 
@@ -47,10 +49,48 @@ export function isCodexAppsFunctionTool(tool: unknown): tool is Tool & { name: s
47
49
  // should match on capability words, not drown in glue words (parity with
48
50
  // codex-rs, whose search normalizes tokens server-side).
49
51
  const STOPWORDS = new Set([
50
- "a", "an", "the", "and", "or", "of", "to", "in", "on", "for", "with", "by", "at",
51
- "is", "are", "be", "do", "does", "my", "me", "your", "you", "it", "its", "this",
52
- "that", "from", "as", "up", "out", "all", "some", "any", "can", "will", "would",
53
- "should", "want", "need", "please", "user", "users",
52
+ "a",
53
+ "an",
54
+ "the",
55
+ "and",
56
+ "or",
57
+ "of",
58
+ "to",
59
+ "in",
60
+ "on",
61
+ "for",
62
+ "with",
63
+ "by",
64
+ "at",
65
+ "is",
66
+ "are",
67
+ "be",
68
+ "do",
69
+ "does",
70
+ "my",
71
+ "me",
72
+ "your",
73
+ "you",
74
+ "it",
75
+ "its",
76
+ "this",
77
+ "that",
78
+ "from",
79
+ "as",
80
+ "up",
81
+ "out",
82
+ "all",
83
+ "some",
84
+ "any",
85
+ "can",
86
+ "will",
87
+ "would",
88
+ "should",
89
+ "want",
90
+ "need",
91
+ "please",
92
+ "user",
93
+ "users",
54
94
  ]);
55
95
 
56
96
  /** Light suffix stemmer so "emails"/"email", "creating"/"create" co-match (min-stem guards, no over-stripping). */
@@ -75,9 +115,15 @@ function tokenize(text: string): string[] {
75
115
  /** The searchable text of a connector tool: name (weighted ×2) + description + param names. */
76
116
  function toolSearchText(tool: Tool): string {
77
117
  const raw = (tool as { name?: string }).name ?? "";
78
- const name = raw.startsWith(CODEX_APPS_TOOL_PREFIX) ? raw.slice(CODEX_APPS_TOOL_PREFIX.length) : raw;
79
- const description = typeof (tool as { description?: unknown }).description === "string" ? (tool as { description: string }).description : "";
80
- const params = (tool as { parameters?: { properties?: Record<string, unknown> } }).parameters?.properties;
118
+ const name = raw.startsWith(CODEX_APPS_TOOL_PREFIX)
119
+ ? raw.slice(CODEX_APPS_TOOL_PREFIX.length)
120
+ : raw;
121
+ const description =
122
+ typeof (tool as { description?: unknown }).description === "string"
123
+ ? (tool as { description: string }).description
124
+ : "";
125
+ const params = (tool as { parameters?: { properties?: Record<string, unknown> } }).parameters
126
+ ?.properties;
81
127
  const paramNames = params && typeof params === "object" ? Object.keys(params).join(" ") : "";
82
128
  return `${name} ${name} ${description} ${paramNames}`;
83
129
  }
@@ -127,12 +173,20 @@ export function bm25RankTools(tools: Tool[], query: string, limit: number): Tool
127
173
  function parseSearchArgs(raw: unknown): { query: string; limit: number } {
128
174
  let obj: Record<string, unknown> = {};
129
175
  try {
130
- obj = typeof raw === "string" ? (raw.length ? JSON.parse(raw) : {}) : (raw && typeof raw === "object" ? (raw as Record<string, unknown>) : {});
176
+ obj =
177
+ typeof raw === "string"
178
+ ? raw.length
179
+ ? JSON.parse(raw)
180
+ : {}
181
+ : raw && typeof raw === "object"
182
+ ? (raw as Record<string, unknown>)
183
+ : {};
131
184
  } catch {
132
185
  obj = {};
133
186
  }
134
187
  const query = typeof obj.query === "string" ? obj.query : "";
135
- const limitRaw = typeof obj.limit === "number" && Number.isFinite(obj.limit) ? obj.limit : DEFAULT_SEARCH_LIMIT;
188
+ const limitRaw =
189
+ typeof obj.limit === "number" && Number.isFinite(obj.limit) ? obj.limit : DEFAULT_SEARCH_LIMIT;
136
190
  return { query, limit: Math.max(1, Math.min(MAX_SEARCH_LIMIT, Math.round(limitRaw))) };
137
191
  }
138
192
 
@@ -147,10 +201,12 @@ function parseSearchArgs(raw: unknown): { query: string; limit: number } {
147
201
  */
148
202
  export function renderSearchToolDescription(connectorNamespaces: ReadonlySet<string>): string {
149
203
  const base =
150
- "Search the user's connected app tools by capability. "
151
- + "Describe in plain language WHAT you need to do (for example: \"send an email\", \"create a calendar event\") "
152
- + "rather than guessing exact tool names. Returns the matching connector tools, which then become callable.";
153
- const sources = Array.from(connectorNamespaces).filter((n) => typeof n === "string" && n.length > 0).sort();
204
+ "Search the user's connected app tools by capability. " +
205
+ 'Describe in plain language WHAT you need to do (for example: "send an email", "create a calendar event") ' +
206
+ "rather than guessing exact tool names. Returns the matching connector tools, which then become callable.";
207
+ const sources = Array.from(connectorNamespaces)
208
+ .filter((n) => typeof n === "string" && n.length > 0)
209
+ .sort();
154
210
  if (sources.length === 0) {
155
211
  return `${base}\nConnected sources: none currently available.`;
156
212
  }
@@ -160,7 +216,10 @@ export function renderSearchToolDescription(connectorNamespaces: ReadonlySet<str
160
216
  const SEARCH_TOOL_PARAMETERS = {
161
217
  type: "object",
162
218
  properties: {
163
- query: { type: "string", description: "Plain-language description of the capability you need." },
219
+ query: {
220
+ type: "string",
221
+ description: "Plain-language description of the capability you need.",
222
+ },
164
223
  limit: { type: "number", description: "Maximum number of tools to return (default 8)." },
165
224
  },
166
225
  required: ["query"],
@@ -173,7 +232,10 @@ const SEARCH_TOOL_PARAMETERS = {
173
232
  * return — the SDK emits the disclosing `tool_search_output` and flips the loaded
174
233
  * gate; returning copies would throw). Stateless — reads the pool per call.
175
234
  */
176
- function codexToolSearchExecutor(args: { availableTools?: Tool[]; toolCall?: { arguments?: unknown } }): Tool[] {
235
+ function codexToolSearchExecutor(args: {
236
+ availableTools?: Tool[];
237
+ toolCall?: { arguments?: unknown };
238
+ }): Tool[] {
177
239
  const deferred = (args.availableTools ?? []).filter(isCodexAppsFunctionTool);
178
240
  if (deferred.length === 0) return [];
179
241
  const { query, limit } = parseSearchArgs(args.toolCall?.arguments);
@@ -182,16 +244,79 @@ function codexToolSearchExecutor(args: { availableTools?: Tool[]; toolCall?: { a
182
244
 
183
245
  const NO_NAMESPACES: ReadonlySet<string> = new Set();
184
246
 
185
- /** Build the client-executed tool_search tool that discloses codex_apps connectors on demand. */
186
- export function buildCodexToolSearchTool(connectorNamespaces: ReadonlySet<string> = NO_NAMESPACES): Tool {
247
+ /** True when the namespace set contains at least one usable (non-empty string) source — mirrors {@link renderSearchToolDescription}'s filter, so it is TRUE exactly when the render produces the "following sources" list and FALSE when it produces "none currently available". */
248
+ function hasConnectorSources(connectorNamespaces: ReadonlySet<string>): boolean {
249
+ for (const namespace of connectorNamespaces) {
250
+ if (typeof namespace === "string" && namespace.length > 0) {
251
+ return true;
252
+ }
253
+ }
254
+ return false;
255
+ }
256
+
257
+ /**
258
+ * A per-TURN freeze cell for the tool_search description (AM-8). The connector Set
259
+ * `installCodexToolSearch` reads is LIVE and by-reference — it fills as the turn's
260
+ * codex_apps tools/list resolves and can change between a turn's model calls.
261
+ * Re-rendering the description per call from a changed Set flips the tools block,
262
+ * and because tools precede the history in the request prefix, ANY change misses the
263
+ * ENTIRE conversation prefix from that point on — a proven prompt-cache breaker.
264
+ *
265
+ * We therefore freeze the description ONCE, at the first model call whose Set has
266
+ * been populated (connectors discovered), and reuse that frozen string for the rest
267
+ * of the turn — trading a slightly staler connector list for a byte-stable prefix.
268
+ * The freeze is created per {@link installCodexToolSearch} (once per turn) and shared
269
+ * by reference into every clone re-install, so all of a turn's clones agree.
270
+ */
271
+ export type CodexToolSearchDescriptionFreeze = { value: string | null };
272
+
273
+ /**
274
+ * Resolve the tool_search description for this model call, honoring the per-turn
275
+ * freeze (AM-8):
276
+ * - Already frozen ⇒ return the frozen string (byte-stable for the rest of the turn).
277
+ * - Not yet frozen + connectors DISCOVERED (non-empty Set) ⇒ render and FREEZE it,
278
+ * locking the discovered list against a later same-turn Set mutation.
279
+ * - Not yet frozen + Set still EMPTY ⇒ render live ("none currently available") but
280
+ * do NOT freeze. This is the load-bearing safety of AM-8: the Set fills lazily and
281
+ * best-effort, so an empty Set means "not discovered yet", not "no connectors".
282
+ * Freezing "none" here would silently disable the turn's connectors (capability
283
+ * loss). Leaving it unfrozen is still byte-stable while the Set stays empty (the
284
+ * empty render is a constant), and lets a later call freeze the real list once it
285
+ * resolves — at most ONE prefix transition, versus today's per-call churn.
286
+ * With no freeze cell (the default / direct callers + tests) this is a live render,
287
+ * byte-for-byte the pre-AM-8 behavior.
288
+ */
289
+ function resolveSearchToolDescription(
290
+ connectorNamespaces: ReadonlySet<string>,
291
+ freeze?: CodexToolSearchDescriptionFreeze,
292
+ ): string {
293
+ if (freeze?.value != null) {
294
+ return freeze.value;
295
+ }
296
+ const rendered = renderSearchToolDescription(connectorNamespaces);
297
+ if (freeze && hasConnectorSources(connectorNamespaces)) {
298
+ freeze.value = rendered;
299
+ }
300
+ return rendered;
301
+ }
302
+
303
+ /** Build the client-executed tool_search tool from an already-rendered description. */
304
+ function buildCodexToolSearchToolFromDescription(description: string): Tool {
187
305
  return toolSearchTool({
188
306
  execution: "client",
189
- description: renderSearchToolDescription(connectorNamespaces),
307
+ description,
190
308
  parameters: SEARCH_TOOL_PARAMETERS as unknown as Record<string, unknown>,
191
309
  execute: codexToolSearchExecutor as never,
192
310
  }) as unknown as Tool;
193
311
  }
194
312
 
313
+ /** Build the client-executed tool_search tool that discloses codex_apps connectors on demand. */
314
+ export function buildCodexToolSearchTool(
315
+ connectorNamespaces: ReadonlySet<string> = NO_NAMESPACES,
316
+ ): Tool {
317
+ return buildCodexToolSearchToolFromDescription(renderSearchToolDescription(connectorNamespaces));
318
+ }
319
+
195
320
  /** True for the built-in tool_search tool (so we never add a second one). */
196
321
  function isToolSearchTool(tool: unknown): boolean {
197
322
  const t = tool as { name?: unknown; providerData?: { type?: unknown } } | null;
@@ -214,16 +339,26 @@ function isToolSearchTool(tool: unknown): boolean {
214
339
  * reflects the LIVE connector namespaces, so an empty turn reads
215
340
  * "none currently available".
216
341
  */
217
- export function applyCodexToolSearch(tools: Tool[], connectorNamespaces: ReadonlySet<string> = NO_NAMESPACES): Tool[] {
342
+ export function applyCodexToolSearch(
343
+ tools: Tool[],
344
+ connectorNamespaces: ReadonlySet<string> = NO_NAMESPACES,
345
+ descriptionFreeze?: CodexToolSearchDescriptionFreeze,
346
+ ): Tool[] {
218
347
  for (const tool of tools) {
219
- if (isCodexAppsFunctionTool(tool) && (tool as { deferLoading?: boolean }).deferLoading !== true) {
348
+ if (
349
+ isCodexAppsFunctionTool(tool) &&
350
+ (tool as { deferLoading?: boolean }).deferLoading !== true
351
+ ) {
220
352
  (tool as { deferLoading?: boolean }).deferLoading = true;
221
353
  }
222
354
  }
223
355
  if (tools.some(isToolSearchTool)) {
224
356
  return tools;
225
357
  }
226
- return [...tools, buildCodexToolSearchTool(connectorNamespaces)];
358
+ // AM-8: render through the per-turn freeze so the tools-block prefix stays
359
+ // byte-stable across a turn's model calls once connectors are discovered.
360
+ const description = resolveSearchToolDescription(connectorNamespaces, descriptionFreeze);
361
+ return [...tools, buildCodexToolSearchToolFromDescription(description)];
227
362
  }
228
363
 
229
364
  type CloneCapableAgent = {
@@ -251,15 +386,34 @@ type CloneCapableAgent = {
251
386
  * (prepareAgentTools), so by the time the wrapper post-processes getAllTools the
252
387
  * current turn's connector sources are known.
253
388
  */
254
- export function installCodexToolSearch(agent: CloneCapableAgent, connectorNamespaces: ReadonlySet<string> = NO_NAMESPACES): void {
389
+ export function installCodexToolSearch(
390
+ agent: CloneCapableAgent,
391
+ connectorNamespaces: ReadonlySet<string> = NO_NAMESPACES,
392
+ ): void {
393
+ // ONE freeze cell per install (i.e. per turn), shared BY REFERENCE into every
394
+ // clone re-install below so the whole turn — the built agent and every clone the
395
+ // sandbox runtime resolves tools on — agrees on the same frozen description
396
+ // (AM-8). Created here, at the top-level install, never per clone.
397
+ installCodexToolSearchWithFreeze(agent, connectorNamespaces, { value: null });
398
+ }
399
+
400
+ function installCodexToolSearchWithFreeze(
401
+ agent: CloneCapableAgent,
402
+ connectorNamespaces: ReadonlySet<string>,
403
+ descriptionFreeze: CodexToolSearchDescriptionFreeze,
404
+ ): void {
255
405
  const originalGetAllTools = agent.getAllTools.bind(agent);
256
406
  agent.getAllTools = (async (runContext: unknown) =>
257
- applyCodexToolSearch(await originalGetAllTools(runContext), connectorNamespaces)) as typeof agent.getAllTools;
407
+ applyCodexToolSearch(
408
+ await originalGetAllTools(runContext),
409
+ connectorNamespaces,
410
+ descriptionFreeze,
411
+ )) as typeof agent.getAllTools;
258
412
  const originalClone = agent.clone?.bind(agent);
259
413
  if (originalClone) {
260
414
  const cloneWithToolSearch: NonNullable<CloneCapableAgent["clone"]> = (config: unknown) => {
261
415
  const cloned = originalClone(config);
262
- installCodexToolSearch(cloned, connectorNamespaces);
416
+ installCodexToolSearchWithFreeze(cloned, connectorNamespaces, descriptionFreeze);
263
417
  return cloned;
264
418
  };
265
419
  agent.clone = cloneWithToolSearch;