@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
@@ -72,7 +72,10 @@ export class MockAgentResponder implements ControlRpc {
72
72
  this.hostname = opts.hostname ?? "mock-machine";
73
73
  this.execHandler = opts.exec ?? ((req) => defaultEcho(req, this.hostname));
74
74
  for (const [path, content] of Object.entries(opts.files ?? {})) {
75
- this.files.set(normalize(path), typeof content === "string" ? encoder.encode(content) : content);
75
+ this.files.set(
76
+ normalize(path),
77
+ typeof content === "string" ? encoder.encode(content) : content,
78
+ );
76
79
  }
77
80
  }
78
81
 
@@ -87,13 +90,27 @@ export class MockAgentResponder implements ControlRpc {
87
90
  return bytes ? decoder.decode(bytes) : undefined;
88
91
  }
89
92
 
90
- async request(subject: string, req: ControlRequest, _opts: { timeoutMs: number }): Promise<ControlResponse> {
93
+ async request(
94
+ subject: string,
95
+ req: ControlRequest,
96
+ _opts: { timeoutMs: number },
97
+ ): Promise<ControlResponse> {
91
98
  this.requests.push({ subject, req });
92
99
  if (!this.online) {
93
- return errorResponse(req.requestId, ErrorCode.ERROR_CODE_AGENT_OFFLINE, "the enrolled agent is offline", false);
100
+ return errorResponse(
101
+ req.requestId,
102
+ ErrorCode.ERROR_CODE_AGENT_OFFLINE,
103
+ "the enrolled agent is offline",
104
+ false,
105
+ );
94
106
  }
95
107
  if (this.draining) {
96
- return errorResponse(req.requestId, ErrorCode.ERROR_CODE_DRAINING, "the agent is draining", true);
108
+ return errorResponse(
109
+ req.requestId,
110
+ ErrorCode.ERROR_CODE_DRAINING,
111
+ "the agent is draining",
112
+ true,
113
+ );
97
114
  }
98
115
  const op = req.op;
99
116
  if (!op) {
@@ -101,7 +118,10 @@ export class MockAgentResponder implements ControlRpc {
101
118
  }
102
119
  switch (op.$case) {
103
120
  case "ping":
104
- return ok(req.requestId, { $case: "ping", ping: { nonce: op.ping.nonce, agentMonotonicMs: "0" } });
121
+ return ok(req.requestId, {
122
+ $case: "ping",
123
+ ping: { nonce: op.ping.nonce, agentMonotonicMs: "0" },
124
+ });
105
125
  case "exec": {
106
126
  const res = await this.execHandler(op.exec);
107
127
  return ok(req.requestId, { $case: "exec", exec: res });
@@ -109,7 +129,12 @@ export class MockAgentResponder implements ControlRpc {
109
129
  case "fsRead": {
110
130
  const bytes = this.files.get(normalize(op.fsRead.path));
111
131
  if (!bytes) {
112
- return errorResponse(req.requestId, ErrorCode.ERROR_CODE_NOT_FOUND, `no such file: ${op.fsRead.path}`, false);
132
+ return errorResponse(
133
+ req.requestId,
134
+ ErrorCode.ERROR_CODE_NOT_FOUND,
135
+ `no such file: ${op.fsRead.path}`,
136
+ false,
137
+ );
113
138
  }
114
139
  const res: FsReadResponse = { content: bytes, totalSize: String(bytes.length) };
115
140
  return ok(req.requestId, { $case: "fsRead", fsRead: res });
@@ -147,16 +172,16 @@ export class MockAgentResponder implements ControlRpc {
147
172
  const bytes = this.files.get(normalize(op.fsStat.path));
148
173
  const res: FsStatResponse = bytes
149
174
  ? {
150
- exists: true,
151
- entry: {
152
- name: normalize(op.fsStat.path).split("/").pop() ?? "",
153
- path: op.fsStat.path,
154
- kind: FsEntryKind.FS_ENTRY_KIND_FILE,
155
- size: String(bytes.length),
156
- modifiedMs: "0",
157
- mode: 0o644,
158
- },
159
- }
175
+ exists: true,
176
+ entry: {
177
+ name: normalize(op.fsStat.path).split("/").pop() ?? "",
178
+ path: op.fsStat.path,
179
+ kind: FsEntryKind.FS_ENTRY_KIND_FILE,
180
+ size: String(bytes.length),
181
+ modifiedMs: "0",
182
+ mode: 0o644,
183
+ },
184
+ }
160
185
  : { exists: false, entry: undefined };
161
186
  return ok(req.requestId, { $case: "fsStat", fsStat: res });
162
187
  }
@@ -170,7 +195,13 @@ export class MockAgentResponder implements ControlRpc {
170
195
  return ok(req.requestId, {
171
196
  $case: "desktopEnsure",
172
197
  desktopEnsure: {
173
- channel: { channelId: "mock-desktop", workspaceId: "", agentId: "", kind: 1, port: 6080 },
198
+ channel: {
199
+ channelId: "mock-desktop",
200
+ workspaceId: "",
201
+ agentId: "",
202
+ kind: 1,
203
+ port: 6080,
204
+ },
174
205
  display: { id: ":99", width: 1024, height: 768, virtual: true },
175
206
  },
176
207
  });
@@ -188,7 +219,12 @@ export class MockAgentResponder implements ControlRpc {
188
219
  });
189
220
  }
190
221
  default:
191
- return errorResponse(req.requestId, ErrorCode.ERROR_CODE_UNSUPPORTED, `mock does not implement ${op.$case}`, false);
222
+ return errorResponse(
223
+ req.requestId,
224
+ ErrorCode.ERROR_CODE_UNSUPPORTED,
225
+ `mock does not implement ${op.$case}`,
226
+ false,
227
+ );
192
228
  }
193
229
  }
194
230
  }
@@ -211,7 +247,12 @@ function ok(requestId: string, result: NonNullable<ControlResponse["result"]>):
211
247
  return { requestId, error: undefined, result };
212
248
  }
213
249
 
214
- function errorResponse(requestId: string, code: ErrorCode, message: string, retryable: boolean): ControlResponse {
250
+ function errorResponse(
251
+ requestId: string,
252
+ code: ErrorCode,
253
+ message: string,
254
+ retryable: boolean,
255
+ ): ControlResponse {
215
256
  const error: AgentError = { code, message, retryable, detail: {} };
216
257
  return { requestId, error, result: undefined };
217
258
  }
@@ -48,7 +48,10 @@ type PortResolvableSession = {
48
48
  * `transport:null` (a value, never a crash) — a headless-only provider or a
49
49
  * transient tunnel failure must not fail the whole handshake. */
50
50
  export class StreamPortUnavailableError extends Error {
51
- constructor(message: string, readonly cause?: unknown) {
51
+ constructor(
52
+ message: string,
53
+ readonly cause?: unknown,
54
+ ) {
52
55
  super(message);
53
56
  this.name = "StreamPortUnavailableError";
54
57
  }
@@ -103,7 +106,11 @@ const DEFAULT_RESOLUTION: [number, number] = [1280, 800];
103
106
  * the holder + validated at the in-box websockify edge).
104
107
  */
105
108
  export function buildStreamUrl(endpoint: ExposedPortEndpoint): string {
106
- if (typeof endpoint.host !== "string" || endpoint.host.length === 0 || typeof endpoint.port !== "number") {
109
+ if (
110
+ typeof endpoint.host !== "string" ||
111
+ endpoint.host.length === 0 ||
112
+ typeof endpoint.port !== "number"
113
+ ) {
107
114
  throw new StreamPortUnavailableError(
108
115
  `provider returned a malformed exposed-port endpoint (host=${String(endpoint.host)}, port=${String(endpoint.port)})`,
109
116
  );
@@ -112,13 +119,18 @@ export function buildStreamUrl(endpoint: ExposedPortEndpoint): string {
112
119
  const scheme = tls ? "wss" : "ws";
113
120
  const defaultPort = tls ? 443 : 80;
114
121
  // Bracket a bare IPv6 host (urlForExposedPort parity).
115
- const host = endpoint.host.includes(":") && !endpoint.host.startsWith("[") ? `[${endpoint.host}]` : endpoint.host;
122
+ const host =
123
+ endpoint.host.includes(":") && !endpoint.host.startsWith("[")
124
+ ? `[${endpoint.host}]`
125
+ : endpoint.host;
116
126
  // The path: default the root `/` (Modal/Daytona/Blaxel edge), or the
117
127
  // provider-supplied path (the selfhosted relay's `/stream` route, M8b). Always
118
128
  // leading-slash-normalized.
119
- const rawPath = typeof endpoint.path === "string" && endpoint.path.length > 0 ? endpoint.path : "/";
129
+ const rawPath =
130
+ typeof endpoint.path === "string" && endpoint.path.length > 0 ? endpoint.path : "/";
120
131
  const path = rawPath.startsWith("/") ? rawPath : `/${rawPath}`;
121
- const origin = endpoint.port === defaultPort ? `${scheme}://${host}` : `${scheme}://${host}:${endpoint.port}`;
132
+ const origin =
133
+ endpoint.port === defaultPort ? `${scheme}://${host}` : `${scheme}://${host}:${endpoint.port}`;
122
134
  const authority = `${origin}${path}`;
123
135
  const query = endpoint.query ?? "";
124
136
  return query ? `${authority}?${query}` : authority;
@@ -54,7 +54,10 @@ export type MintStreamTokenInput = {
54
54
  * envelope (`ogs_` prefix). The token is RECORDED against the holder row by the
55
55
  * caller and is NEVER appended to the data-plane URL as a query param.
56
56
  */
57
- export async function mintStreamToken(secret: string, input: MintStreamTokenInput): Promise<string> {
57
+ export async function mintStreamToken(
58
+ secret: string,
59
+ input: MintStreamTokenInput,
60
+ ): Promise<string> {
58
61
  const nowSeconds = input.nowSeconds ?? Math.floor(Date.now() / 1000);
59
62
  const ttlSeconds = input.ttlSeconds ?? STREAM_TOKEN_DEFAULT_TTL_SECONDS;
60
63
  const payload: StreamTokenPayloadType = StreamTokenPayload.parse({
@@ -87,4 +90,7 @@ export async function verifyStreamToken(
87
90
  return verifyStreamTokenEnvelope(secret, token, nowSeconds);
88
91
  }
89
92
 
90
- export { StreamTokenPayload, type StreamTokenPayload as StreamTokenPayloadType } from "@opengeni/contracts";
93
+ export {
94
+ StreamTokenPayload,
95
+ type StreamTokenPayload as StreamTokenPayloadType,
96
+ } from "@opengeni/contracts";
@@ -43,7 +43,9 @@ export class TerminalServerError extends Error {
43
43
 
44
44
  constructor(exitCode: number, output: string) {
45
45
  const stage = exitCode === 14 ? "ttyd" : "unknown";
46
- super(`terminal server failed at stage "${stage}" (exit ${exitCode})${output ? `:\n${output}` : ""}`);
46
+ super(
47
+ `terminal server failed at stage "${stage}" (exit ${exitCode})${output ? `:\n${output}` : ""}`,
48
+ );
47
49
  this.name = "TerminalServerError";
48
50
  this.exitCode = exitCode;
49
51
  this.stage = stage;
@@ -70,8 +72,16 @@ type ExecResultLike = {
70
72
  exitCode?: number | null;
71
73
  };
72
74
  type ExecCapableSession = {
73
- exec?: (args: { cmd: string; yieldTimeMs?: number; maxOutputTokens?: number }) => Promise<ExecResultLike>;
74
- execCommand?: (args: { cmd: string; yieldTimeMs?: number; maxOutputTokens?: number }) => Promise<string>;
75
+ exec?: (args: {
76
+ cmd: string;
77
+ yieldTimeMs?: number;
78
+ maxOutputTokens?: number;
79
+ }) => Promise<ExecResultLike>;
80
+ execCommand?: (args: {
81
+ cmd: string;
82
+ yieldTimeMs?: number;
83
+ maxOutputTokens?: number;
84
+ }) => Promise<string>;
75
85
  };
76
86
 
77
87
  export type EnsureTerminalServerOptions = {
@@ -198,6 +208,10 @@ export async function tearDownTerminalServer(session: unknown): Promise<void> {
198
208
  return;
199
209
  }
200
210
  if (typeof s?.execCommand === "function") {
201
- await s.execCommand({ cmd: "opengeni-terminal-down", yieldTimeMs: 10_000, maxOutputTokens: 4_000 });
211
+ await s.execCommand({
212
+ cmd: "opengeni-terminal-down",
213
+ yieldTimeMs: 10_000,
214
+ maxOutputTokens: 4_000,
215
+ });
202
216
  }
203
217
  }