@opengeni/runtime 0.2.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.
Files changed (65) hide show
  1. package/dist/chunk-2PO56VAL.js +3478 -0
  2. package/dist/chunk-2PO56VAL.js.map +1 -0
  3. package/dist/index.d.ts +912 -0
  4. package/dist/index.js +3663 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/sandbox/index.d.ts +1738 -0
  7. package/dist/sandbox/index.js +187 -0
  8. package/dist/sandbox/index.js.map +1 -0
  9. package/package.json +49 -0
  10. package/src/bundled_hashicorp_terraform_skills/LICENSE +373 -0
  11. package/src/bundled_hashicorp_terraform_skills/README.md +18 -0
  12. package/src/bundled_hashicorp_terraform_skills/UPSTREAM_GIT_SHA +1 -0
  13. package/src/bundled_hashicorp_terraform_skills/azure-verified-modules/SKILL.md +613 -0
  14. package/src/bundled_hashicorp_terraform_skills/checkov/SKILL.md +43 -0
  15. package/src/bundled_hashicorp_terraform_skills/refactor-module/SKILL.md +538 -0
  16. package/src/bundled_hashicorp_terraform_skills/social-media-marketing/SKILL.md +35 -0
  17. package/src/bundled_hashicorp_terraform_skills/terraform-search-import/SKILL.md +372 -0
  18. package/src/bundled_hashicorp_terraform_skills/terraform-search-import/references/MANUAL-IMPORT.md +113 -0
  19. package/src/bundled_hashicorp_terraform_skills/terraform-search-import/scripts/list_resources.sh +38 -0
  20. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/SKILL.md +480 -0
  21. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/api-monitoring.md +543 -0
  22. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/component-blocks.md +476 -0
  23. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/deployment-blocks.md +391 -0
  24. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/examples.md +1529 -0
  25. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/linked-stacks.md +187 -0
  26. package/src/bundled_hashicorp_terraform_skills/terraform-stacks/references/troubleshooting.md +671 -0
  27. package/src/bundled_hashicorp_terraform_skills/terraform-style-guide/SKILL.md +353 -0
  28. package/src/bundled_hashicorp_terraform_skills/terraform-test/SKILL.md +451 -0
  29. package/src/bundled_hashicorp_terraform_skills/terraform-test/references/CI_CD.md +80 -0
  30. package/src/bundled_hashicorp_terraform_skills/terraform-test/references/EXAMPLES.md +314 -0
  31. package/src/bundled_hashicorp_terraform_skills/terraform-test/references/MOCK_PROVIDERS.md +171 -0
  32. package/src/codex-tool-search.ts +267 -0
  33. package/src/context-compaction.ts +538 -0
  34. package/src/history-sanitizer.ts +719 -0
  35. package/src/index.ts +3299 -0
  36. package/src/sandbox/capabilities.ts +69 -0
  37. package/src/sandbox/channel-a.ts +1031 -0
  38. package/src/sandbox/display-stack.ts +231 -0
  39. package/src/sandbox/errors.ts +34 -0
  40. package/src/sandbox/index.ts +832 -0
  41. package/src/sandbox/providers/blaxel.ts +35 -0
  42. package/src/sandbox/providers/cloudflare.ts +24 -0
  43. package/src/sandbox/providers/daytona.ts +34 -0
  44. package/src/sandbox/providers/docker.ts +17 -0
  45. package/src/sandbox/providers/e2b.ts +36 -0
  46. package/src/sandbox/providers/index.ts +107 -0
  47. package/src/sandbox/providers/local.ts +13 -0
  48. package/src/sandbox/providers/modal.ts +55 -0
  49. package/src/sandbox/providers/none.ts +13 -0
  50. package/src/sandbox/providers/runloop.ts +32 -0
  51. package/src/sandbox/providers/selfhosted.ts +96 -0
  52. package/src/sandbox/providers/types.ts +38 -0
  53. package/src/sandbox/providers/vercel.ts +29 -0
  54. package/src/sandbox/recording.ts +286 -0
  55. package/src/sandbox/routing/backend-resolver.ts +189 -0
  56. package/src/sandbox/routing/routing-session.ts +455 -0
  57. package/src/sandbox/select.ts +371 -0
  58. package/src/sandbox/selfhosted/capabilities.ts +255 -0
  59. package/src/sandbox/selfhosted/control-rpc.ts +351 -0
  60. package/src/sandbox/selfhosted/session.ts +930 -0
  61. package/src/sandbox/selfhosted/testing.ts +230 -0
  62. package/src/sandbox/stream-port.ts +185 -0
  63. package/src/sandbox/stream-token.ts +90 -0
  64. package/src/sandbox/terminal-server.ts +203 -0
  65. package/src/sandbox-computer.ts +835 -0
@@ -0,0 +1,231 @@
1
+ // @opengeni/runtime/sandbox — the desktop display-stack launcher (P4.1).
2
+ //
3
+ // The agent-loop-free home for `ensureDisplayStack`: the exec-launched,
4
+ // flock-idempotent procedure that brings up the Channel-B pixel stack
5
+ // (Xvfb :0 -> XFCE -> x11vnc -> websockify:6080 -> noVNC) on a live,
6
+ // externally-owned box. It is driven over the box's `exec`/`execCommand` channel
7
+ // (NOT a container CMD) so it re-establishes after a snapshot rollover / box
8
+ // re-election, and it is safe to call from the API on a viewer op OR from the
9
+ // agent turn — a second concurrent call serializes on the in-box flock and
10
+ // no-ops when the stack is already up.
11
+ //
12
+ // It lives under @opengeni/runtime/sandbox so the API-direct control plane
13
+ // (apps/api) and the worker (apps/worker) both pull it from the same single
14
+ // agent-loop-free leaf.
15
+ //
16
+ // Productionized from the PROVEN spike (spikes/desktop-stack PASSED locally:
17
+ // noVNC 200, WS 101 + RFB banner, OCR'd a secret off the framebuffer) + the
18
+ // gVisor harness (V2 PASSED live on Modal: XTEST input read-back under runsc).
19
+
20
+ import { DESKTOP_STREAM_PORT } from "@opengeni/contracts";
21
+
22
+ // Re-export under the canonical name the module spec uses (STREAM_PORT) while
23
+ // keeping DESKTOP_STREAM_PORT as the single source of truth (contracts).
24
+ export { DESKTOP_STREAM_PORT };
25
+ export const STREAM_PORT = DESKTOP_STREAM_PORT;
26
+
27
+ // The whole-stack launch is bounded by the readiness gates inside the script
28
+ // (four loops of 50 * 0.1s = ~5s each, ~20s worst case) PLUS first-boot XFCE/dbus
29
+ // + font-cache warm-up on a cold gVisor box. 60s gives headroom over the spike's
30
+ // observed ~5-10s warm path without masking a genuine wedge.
31
+ export const DISPLAY_STACK_TIMEOUT_MS = 60_000;
32
+
33
+ /** Desktop geometry for the framebuffer. v1 has no live RANDR: a resolution
34
+ * change is a full down -> up restart (a separate op). */
35
+ export type DesktopGeometry = {
36
+ width: number; // default 1280
37
+ height: number; // default 800
38
+ dpi: number; // default 96
39
+ };
40
+
41
+ export const DEFAULT_DESKTOP_GEOMETRY: DesktopGeometry = { width: 1280, height: 800, dpi: 96 };
42
+
43
+ /** Thrown when a stage of the launch script failed. exitCode 11/12/13 map to
44
+ * Xvfb / x11vnc / websockify respectively (the stage that died). Degradation is
45
+ * surfaced as a value to viewers by the caller; this error is for diagnostics. */
46
+ export class DisplayStackError extends Error {
47
+ readonly exitCode: number;
48
+ readonly stage: "xvfb" | "x11vnc" | "websockify" | "unknown";
49
+
50
+ constructor(exitCode: number, output: string) {
51
+ const stage =
52
+ exitCode === 11 ? "xvfb" : exitCode === 12 ? "x11vnc" : exitCode === 13 ? "websockify" : "unknown";
53
+ super(`desktop display stack failed at stage "${stage}" (exit ${exitCode})${output ? `:\n${output}` : ""}`);
54
+ this.name = "DisplayStackError";
55
+ this.exitCode = exitCode;
56
+ this.stage = stage;
57
+ }
58
+ }
59
+
60
+ /** Thrown when the provider session cannot run commands (a headless-only
61
+ * backend with neither `exec` nor `execCommand`). The desktop tier degrades to
62
+ * Channel-A-only — the caller maps this to `DesktopStream.transport: null`. */
63
+ export class DisplayStackUnsupportedError extends Error {
64
+ constructor(message: string) {
65
+ super(message);
66
+ this.name = "DisplayStackUnsupportedError";
67
+ }
68
+ }
69
+
70
+ // The structural slice of a provider session we need: run a command (preferring
71
+ // `exec` for the structured exit code, falling back to `execCommand`).
72
+ type ExecResultLike = {
73
+ output?: string;
74
+ stdout?: string;
75
+ stderr?: string;
76
+ exitCode?: number | null;
77
+ };
78
+ type ExecCapableSession = {
79
+ exec?: (args: { cmd: string; yieldTimeMs?: number; maxOutputTokens?: number }) => Promise<ExecResultLike>;
80
+ execCommand?: (args: { cmd: string; yieldTimeMs?: number; maxOutputTokens?: number }) => Promise<string>;
81
+ };
82
+
83
+ export type EnsureDisplayStackOptions = {
84
+ geometry?: DesktopGeometry;
85
+ /** The exposed stream port; defaults to 6080. */
86
+ port?: number;
87
+ /** Per-exec timeout; defaults to DISPLAY_STACK_TIMEOUT_MS. */
88
+ timeoutMs?: number;
89
+ };
90
+
91
+ export type EnsureDisplayStackResult = {
92
+ /** The exposed port the stack listens on (websockify/noVNC). */
93
+ port: number;
94
+ geometry: DesktopGeometry;
95
+ /** The raw `OPENGENI_DESKTOP_UP …` marker line, for diagnostics. Never
96
+ * surfaced to viewers. */
97
+ marker: string;
98
+ };
99
+
100
+ /**
101
+ * Build the shell command that runs the idempotent up-script under an in-box
102
+ * `flock`. The script is shipped in the image at /usr/local/bin/opengeni-desktop-up
103
+ * (the canonical desktop image); we set the geometry/port env and wrap the call
104
+ * in `flock` so two concurrent ensureDisplayStack callers (the API viewer op +
105
+ * the agent turn, both racing after a rollover) serialize without a double
106
+ * launch. The up-script's own per-stage PID guards make the second call a no-op.
107
+ *
108
+ * Exported (pure, side-effect-free) so the ensureDisplayStack unit test can
109
+ * assert the exact command sequence without a live box.
110
+ */
111
+ export function buildDisplayStackScript(options: EnsureDisplayStackOptions = {}): string {
112
+ const geometry = options.geometry ?? DEFAULT_DESKTOP_GEOMETRY;
113
+ const port = options.port ?? DESKTOP_STREAM_PORT;
114
+ const env =
115
+ `DESKTOP_W=${geometry.width} DESKTOP_H=${geometry.height} ` +
116
+ `DESKTOP_DPI=${geometry.dpi} STREAM_PORT=${port}`;
117
+ // FAST PRE-CHECK (lock-free) before the outer flock: if the exposed port and
118
+ // x11vnc are ALREADY listening, the stack is up — print the marker and short-
119
+ // circuit, so a no-op caller (the agent turn re-ensuring after a viewer attach
120
+ // already brought the stack up) never serializes behind a lock holder and never
121
+ // burns the 45s flock -w timeout. `nc -z` to the two loopback ports is the cheap
122
+ // (sub-millisecond) "already up?" signal; on a miss we fall through to the
123
+ // flock-wrapped up-script (which ALSO pre-checks under its own lock).
124
+ //
125
+ // flock -w bounds the wait so a wedged holder can't deadlock the caller; the
126
+ // up-script itself ALSO takes the same lock (belt + braces) so this works even
127
+ // against an older image that predates the wrapper.
128
+ return (
129
+ `if nc -z 127.0.0.1 ${port} >/dev/null 2>&1 && nc -z 127.0.0.1 5900 >/dev/null 2>&1; then ` +
130
+ `echo "OPENGENI_DESKTOP_UP port=${port} geometry=${geometry.width}x${geometry.height} dpi=${geometry.dpi} (precheck)"; ` +
131
+ `else ` +
132
+ `mkdir -p /tmp/opengeni-desktop && ` +
133
+ `flock -w 45 /tmp/opengeni-desktop/up.outer.lock ` +
134
+ `env ${env} opengeni-desktop-up; ` +
135
+ `fi`
136
+ );
137
+ }
138
+
139
+ function execResultOutput(result: ExecResultLike | string): string {
140
+ if (typeof result === "string") {
141
+ return result;
142
+ }
143
+ return [result.output, result.stderr, result.stdout]
144
+ .filter((v): v is string => typeof v === "string" && v.length > 0)
145
+ .join("\n");
146
+ }
147
+
148
+ function execResultExitCode(result: ExecResultLike | string): number | null {
149
+ if (typeof result === "string") {
150
+ return null; // execCommand returns a bare string — no exit code available.
151
+ }
152
+ return typeof result.exitCode === "number" ? result.exitCode : null;
153
+ }
154
+
155
+ // Parse the exit code the up-script signals via its trailing marker. When we ran
156
+ // through `exec` we have the real exitCode; when we only had `execCommand` (a
157
+ // bare string), we infer success from the OPENGENI_DESKTOP_UP marker and infer
158
+ // the failing stage from the stage-failure message the script prints to stderr.
159
+ function inferExitFromOutput(output: string): number {
160
+ if (/OPENGENI_DESKTOP_UP\b/.test(output)) {
161
+ return 0;
162
+ }
163
+ if (/Xvfb failed to come up/.test(output)) {
164
+ return 11;
165
+ }
166
+ if (/x11vnc failed on/.test(output)) {
167
+ return 12;
168
+ }
169
+ if (/websockify failed on/.test(output)) {
170
+ return 13;
171
+ }
172
+ return -1;
173
+ }
174
+
175
+ /**
176
+ * Idempotently bring up the desktop display stack on the live box. Safe to call
177
+ * N times (the in-box flock + the up-script's PID guards make a second call a
178
+ * no-op). Resolves with the exposed port + geometry on success; throws
179
+ * `DisplayStackError` on a stage failure and `DisplayStackUnsupportedError` when
180
+ * the session cannot run commands.
181
+ *
182
+ * `session` is the externally-owned provider session (the `established.session`
183
+ * from establishSandboxSessionFromEnvelope, or any SandboxSessionLike). We
184
+ * prefer `session.exec` (structured `{exitCode}`) and fall back to
185
+ * `session.execCommand` (bare string), inferring success from the up-script's
186
+ * marker line in the fallback case.
187
+ */
188
+ export async function ensureDisplayStack(
189
+ session: unknown,
190
+ options: EnsureDisplayStackOptions = {},
191
+ ): Promise<EnsureDisplayStackResult> {
192
+ const s = session as ExecCapableSession;
193
+ if (typeof s?.exec !== "function" && typeof s?.execCommand !== "function") {
194
+ throw new DisplayStackUnsupportedError(
195
+ "provider session cannot run commands (no exec/execCommand) — desktop tier unavailable",
196
+ );
197
+ }
198
+
199
+ const geometry = options.geometry ?? DEFAULT_DESKTOP_GEOMETRY;
200
+ const port = options.port ?? DESKTOP_STREAM_PORT;
201
+ const timeoutMs = options.timeoutMs ?? DISPLAY_STACK_TIMEOUT_MS;
202
+ const cmd = buildDisplayStackScript({ geometry, port });
203
+
204
+ const result =
205
+ typeof s.exec === "function"
206
+ ? await s.exec({ cmd, yieldTimeMs: timeoutMs, maxOutputTokens: 20_000 })
207
+ : await s.execCommand!({ cmd, yieldTimeMs: timeoutMs, maxOutputTokens: 20_000 });
208
+
209
+ const output = execResultOutput(result);
210
+ const exitCode = execResultExitCode(result) ?? inferExitFromOutput(output);
211
+
212
+ if (exitCode !== 0) {
213
+ throw new DisplayStackError(exitCode, output);
214
+ }
215
+
216
+ const marker = (output.match(/OPENGENI_DESKTOP_UP[^\n]*/) ?? [""])[0];
217
+ return { port, geometry, marker };
218
+ }
219
+
220
+ /** Tear the stack down (down-script). Best-effort; never throws on a missing
221
+ * process. Used by the geometry-change restart and cold/drain. */
222
+ export async function tearDownDisplayStack(session: unknown): Promise<void> {
223
+ const s = session as ExecCapableSession;
224
+ if (typeof s?.exec === "function") {
225
+ await s.exec({ cmd: "opengeni-desktop-down", yieldTimeMs: 10_000, maxOutputTokens: 4_000 });
226
+ return;
227
+ }
228
+ if (typeof s?.execCommand === "function") {
229
+ await s.execCommand({ cmd: "opengeni-desktop-down", yieldTimeMs: 10_000, maxOutputTokens: 4_000 });
230
+ }
231
+ }
@@ -0,0 +1,34 @@
1
+ // Typed sandbox-construction errors for the provider registry (module 03 §5.1).
2
+ //
3
+ // SandboxConfigError is thrown by validateCredentials() and the factory on any
4
+ // missing/contradictory provider config — a fail-fast typed error so an
5
+ // unknown/misconfigured backend surfaces clearly instead of failing deep inside
6
+ // the SDK at create() time.
7
+
8
+ import type { SandboxBackend } from "@opengeni/contracts";
9
+
10
+ export class SandboxConfigError extends Error {
11
+ readonly backend: SandboxBackend | string;
12
+
13
+ constructor(backend: SandboxBackend | string, message: string) {
14
+ super(`[sandbox:${backend}] ${message}`);
15
+ this.name = "SandboxConfigError";
16
+ this.backend = backend;
17
+ }
18
+ }
19
+
20
+ // Thrown by a provider's build() when its SDK client class is genuinely not
21
+ // available in the installed @openai/agents-extensions. Per the P0.3 ruling we
22
+ // NEVER fake a build body; if a provider cannot be constructed we register the
23
+ // descriptor and make build() throw this. (As of @openai/agents-extensions
24
+ // 0.11.6 every provider ships a concrete client, so this is currently unused —
25
+ // it is the documented contract for a future drop that loses a provider.)
26
+ export class SandboxProviderUnavailableError extends Error {
27
+ readonly backend: SandboxBackend | string;
28
+
29
+ constructor(backend: SandboxBackend | string) {
30
+ super(`provider ${backend} not available in installed @openai/agents-extensions`);
31
+ this.name = "SandboxProviderUnavailableError";
32
+ this.backend = backend;
33
+ }
34
+ }