@opengeni/runtime 2.4.2-canary.0 → 2.4.2-canary.2

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/index.js CHANGED
@@ -244,7 +244,7 @@ import {
244
244
  workspaceEnvironmentInstructions,
245
245
  wrapAttemptToolDefinitions,
246
246
  wrapAttemptToolExecute
247
- } from "./chunk-23WUCTIT.js";
247
+ } from "./chunk-AJGE4GG3.js";
248
248
  import {
249
249
  ActiveBackendUnresolvableError,
250
250
  BROWSER_CONTROL_ADMIN_TOKEN_FILE,
@@ -514,7 +514,7 @@ import {
514
514
  withRunCredentialsClient,
515
515
  withRunCredentialsSession,
516
516
  withoutSandboxProviderIdentity
517
- } from "./chunk-72SCUP4B.js";
517
+ } from "./chunk-WATBACLT.js";
518
518
  import "./chunk-YRKIQK25.js";
519
519
  import {
520
520
  SKILL_MAX_FILES,
@@ -265,7 +265,7 @@ import {
265
265
  withRunCredentialsClient,
266
266
  withRunCredentialsSession,
267
267
  withoutSandboxProviderIdentity
268
- } from "../chunk-72SCUP4B.js";
268
+ } from "../chunk-WATBACLT.js";
269
269
  import "../chunk-YRKIQK25.js";
270
270
  import "../chunk-ORKCCH5X.js";
271
271
  import "../chunk-PZ5AY32C.js";
@@ -24,6 +24,7 @@ export type ProviderCommandSession = {
24
24
  getProviderCommandOutput?(result: unknown): ProviderCommandOutput | null;
25
25
  acknowledgeCommandOutput?(result: string): Promise<void>;
26
26
  };
27
+ export declare const MAX_PROVIDER_COMMAND_HANDLE = 2147483647;
27
28
  /** The alias is allocated by serialized workspace mutation admission, not by
28
29
  * an SDK instance or a process-writable counter. It remains route-scoped. */
29
30
  export declare function withProviderCommandHandle<T>(handle: number | undefined, fn: () => T): T;
@@ -24,11 +24,12 @@ export type ModalProviderOutputPage = {
24
24
  * returned locator/cursors outside the command's write authority. */
25
25
  export declare class ModalCommandControl {
26
26
  private readonly client;
27
- private readonly sandboxId;
27
+ private readonly sandboxIdentity;
28
28
  private readonly root;
29
29
  private readonly environment;
30
30
  private constructor();
31
- static forSandbox(client: CommandClient, sandboxId: string, root: string, environment?: Record<string, string> | (() => Record<string, string>)): ModalCommandControl;
31
+ static forSandbox(client: CommandClient, sandboxId: string | (() => string), root: string, environment?: Record<string, string> | (() => Record<string, string>)): ModalCommandControl;
32
+ private get sandboxId();
32
33
  start(args: ChannelAExecArgs, signal?: AbortSignal): Promise<ModalProviderCommand>;
33
34
  read(command: ModalProviderCommand, yieldTimeMs: number, signal?: AbortSignal): Promise<ModalProviderOutputPage>;
34
35
  write(command: ModalProviderCommand, chars: string, messageIndex: number): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  import type { ChannelASession } from "../channel-a.js";
2
2
  import { type ProviderCommandSession } from "../provider-command-session.js";
3
- import { ModalCommandControl } from "./modal-command-control.js";
3
+ import type { ModalCommandControl } from "./modal-command-control.js";
4
4
  /** Bridges the SDK's numeric/banner surface to provider-owned execution
5
5
  * locators. The local maps are only caches: a fresh adapter can adopt the same
6
6
  * handle from protected persistence and replay any unacknowledged page. */
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  prepareAgentTools
3
- } from "./chunk-23WUCTIT.js";
4
- import "./chunk-72SCUP4B.js";
3
+ } from "./chunk-AJGE4GG3.js";
4
+ import "./chunk-WATBACLT.js";
5
5
  import "./chunk-YRKIQK25.js";
6
6
  import "./chunk-7K6WOXFS.js";
7
7
  import "./chunk-UZ66CGC2.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/runtime",
3
- "version": "2.4.2-canary.0",
3
+ "version": "2.4.2-canary.2",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -62,16 +62,16 @@
62
62
  "@openai/agents": "0.14.3",
63
63
  "@openai/agents-core": "0.14.3",
64
64
  "@openai/agents-extensions": "0.14.3",
65
- "@opengeni/agent-proto": "^0.5.1-canary.20",
66
- "@opengeni/capabilities": "^0.3.3-canary.2",
67
- "@opengeni/codemode": "^0.5.2-canary.0",
68
- "@opengeni/codex": "^0.2.22-canary.2",
69
- "@opengeni/config": "^1.0.3-canary.0",
70
- "@opengeni/contracts": "^2.15.1-canary.0",
71
- "@opengeni/network": "^0.3.1-canary.2",
72
- "@opengeni/sdk": "^4.0.1-canary.0",
73
- "@opengeni/tool-gateway": "^0.1.3-canary.0",
74
- "@opengeni/xai-subscription": "^0.1.4-canary.2",
65
+ "@opengeni/agent-proto": "^0.5.1-canary.22",
66
+ "@opengeni/capabilities": "^0.3.3-canary.4",
67
+ "@opengeni/codemode": "^0.5.2-canary.2",
68
+ "@opengeni/codex": "^0.2.22-canary.4",
69
+ "@opengeni/config": "^1.0.3-canary.2",
70
+ "@opengeni/contracts": "^2.15.1-canary.2",
71
+ "@opengeni/network": "^0.3.1-canary.4",
72
+ "@opengeni/sdk": "^4.0.1-canary.2",
73
+ "@opengeni/tool-gateway": "^0.1.3-canary.2",
74
+ "@opengeni/xai-subscription": "^0.1.4-canary.4",
75
75
  "debug": "4.4.3",
76
76
  "modal": "0.9.0",
77
77
  "openai": "6.47.0",
@@ -30,12 +30,13 @@ export type ProviderCommandSession = {
30
30
  };
31
31
 
32
32
  const admission = new AsyncLocalStorage<number>();
33
+ export const MAX_PROVIDER_COMMAND_HANDLE = 2147483647;
33
34
 
34
35
  /** The alias is allocated by serialized workspace mutation admission, not by
35
36
  * an SDK instance or a process-writable counter. It remains route-scoped. */
36
37
  export function withProviderCommandHandle<T>(handle: number | undefined, fn: () => T): T {
37
38
  if (handle === undefined) return fn();
38
- if (!Number.isSafeInteger(handle) || handle <= 0 || handle > 2147483647)
39
+ if (!Number.isSafeInteger(handle) || handle <= 0 || handle > MAX_PROVIDER_COMMAND_HANDLE)
39
40
  throw new Error("Invalid admitted provider command handle");
40
41
  return admission.run(handle, fn);
41
42
  }
@@ -117,14 +117,14 @@ function decodePage(prior: string, input: Uint8Array[], terminal: boolean) {
117
117
  export class ModalCommandControl {
118
118
  private constructor(
119
119
  private readonly client: ControlPlane,
120
- private readonly sandboxId: string,
120
+ private readonly sandboxIdentity: string | (() => string),
121
121
  private readonly root: string,
122
122
  private readonly environment: Record<string, string> | (() => Record<string, string>) = {},
123
123
  ) {}
124
124
 
125
125
  static forSandbox(
126
126
  client: CommandClient,
127
- sandboxId: string,
127
+ sandboxId: string | (() => string),
128
128
  root: string,
129
129
  environment: Record<string, string> | (() => Record<string, string>) = {},
130
130
  ): ModalCommandControl {
@@ -133,16 +133,24 @@ export class ModalCommandControl {
133
133
  return new ModalCommandControl(commandControlPlane(client), sandboxId, root, environment);
134
134
  }
135
135
 
136
+ private get sandboxId(): string {
137
+ return typeof this.sandboxIdentity === "function"
138
+ ? this.sandboxIdentity()
139
+ : this.sandboxIdentity;
140
+ }
141
+
136
142
  async start(args: ChannelAExecArgs, signal?: AbortSignal): Promise<ModalProviderCommand> {
137
143
  signal?.throwIfAborted();
138
144
  const workdir = posix.resolve(this.root, args.workdir ?? this.root);
139
145
  if (workdir !== this.root && !workdir.startsWith(`${this.root.replace(/\/$/u, "")}/`))
140
146
  throw new Error("Command workdir is outside the sandbox workspace");
141
- const task = await this.client.sandboxGetTaskId(
142
- { sandboxId: this.sandboxId },
143
- signal ? { signal } : undefined,
144
- );
147
+ // Hydration replaces the SDK sandbox. Freeze its current identity for this
148
+ // start so an asynchronous replacement cannot relabel the returned locator.
149
+ const sandboxId = this.sandboxId;
150
+ const task = await this.client.sandboxGetTaskId({ sandboxId }, signal ? { signal } : undefined);
145
151
  if (!task.taskId || task.taskResult) throw new Error("Modal command task is unavailable");
152
+ if (sandboxId !== this.sandboxId)
153
+ throw new Error("Modal sandbox changed during command preparation");
146
154
  const login = args.shell ? (args.login ?? true) : false;
147
155
  let command = [args.shell ?? "/bin/sh", login ? "-lc" : "-c", args.cmd];
148
156
  if (args.runAs) {
@@ -194,7 +202,7 @@ export class ModalCommandControl {
194
202
  if (!result.execId) throw new Error("Modal command start returned no execution identity");
195
203
  return {
196
204
  kind: "modal-control-v1",
197
- sandboxId: this.sandboxId,
205
+ sandboxId,
198
206
  taskId: task.taskId,
199
207
  execId: result.execId,
200
208
  ...(args.tty ? { pty: true } : {}),
@@ -1,15 +1,16 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { truncateOutput } from "@openai/agents-core/sandbox/internal";
3
3
  import type { ChannelASession } from "../channel-a";
4
- import { markTypedExecHandleLoss } from "../exec-banner";
5
4
  import { ModalProcessObservationUnavailableError } from "../errors";
5
+ import { markTypedExecHandleLoss, parseExecResponseBanner } from "../exec-banner";
6
6
  import {
7
- admittedProviderCommandHandle,
7
+ MAX_PROVIDER_COMMAND_HANDLE,
8
8
  type ProviderCommandOutput,
9
9
  type ProviderCommandPersistence,
10
10
  type ProviderCommandSession,
11
+ admittedProviderCommandHandle,
11
12
  } from "../provider-command-session";
12
- import { ModalCommandControl, type ModalProviderCommand } from "./modal-command-control";
13
+ import type { ModalCommandControl, ModalProviderCommand } from "./modal-command-control";
13
14
 
14
15
  type Entry = {
15
16
  command: ModalProviderCommand;
@@ -37,11 +38,33 @@ export function installModalCommandSession(
37
38
  ): void {
38
39
  markTypedExecHandleLoss(session);
39
40
  const originalExec = session.execCommand?.bind(session);
41
+ const originalWrite = session.writeStdin?.bind(session);
40
42
  const cancelLegacyStart = session.cancelPendingExecCommand?.bind(session);
41
43
  const pendingStarts = new Set<AbortController>();
42
44
  const entries = new Map<number, Entry>();
45
+ // Current SDK setup commands are not retained/admitted commands. Give their
46
+ // live observer handles a disjoint, adapter-local range; never use a missing
47
+ // retained alias as permission to poll an unrelated SDK process with that id.
48
+ const setupHandles = new Map<number, number>();
49
+ let nextSetupHandle = MAX_PROVIDER_COMMAND_HANDLE + 1;
43
50
  const receipts = new Map<string, { handle: number; page: ProviderCommandOutput }>();
44
51
 
52
+ const setupPage = (raw: string, handle: number, sdkHandle: number): string => {
53
+ const banner = parseExecResponseBanner(raw);
54
+ if (banner.kind === "exited") {
55
+ setupHandles.delete(handle);
56
+ return raw;
57
+ }
58
+ if (banner.kind !== "running" || banner.sessionId !== sdkHandle)
59
+ throw new ModalProcessObservationUnavailableError(handle);
60
+ // The parser validated the unique status in the metadata header, before
61
+ // command-controlled Output. Replace only that first trusted status line.
62
+ return raw.replace(
63
+ /^Process running with session ID \d+(?=\r?$)/mu,
64
+ `Process running with session ID ${handle}`,
65
+ );
66
+ };
67
+
45
68
  const formatPage = (
46
69
  handle: number,
47
70
  page: ProviderCommandOutput,
@@ -83,11 +106,17 @@ export function installModalCommandSession(
83
106
 
84
107
  session.execCommand = async (args) => {
85
108
  const handle = admittedProviderCommandHandle();
86
- // SDK-internal setup/readiness commands have no mutation admission. They
87
- // retain their existing foreground path and never publish durable handles.
109
+ // Setup/readiness may yield too. Retain only its original local observer,
110
+ // without publishing a durable locator or replaying its command.
88
111
  if (handle === undefined) {
89
112
  if (!originalExec) throw new Error("Modal command requires mutation admission");
90
- return originalExec(args);
113
+ if (!Number.isSafeInteger(nextSetupHandle)) throw new Error("Modal setup handles exhausted");
114
+ const setupHandle = nextSetupHandle++;
115
+ const raw = await originalExec(args);
116
+ const banner = parseExecResponseBanner(raw);
117
+ if (banner.kind !== "running") return raw;
118
+ setupHandles.set(setupHandle, banner.sessionId);
119
+ return setupPage(raw, setupHandle, banner.sessionId);
91
120
  }
92
121
  if (entries.has(handle)) throw new Error("Modal command handle is already bound");
93
122
  const cancellation = new AbortController();
@@ -106,7 +135,11 @@ export function installModalCommandSession(
106
135
  } catch {
107
136
  // Start succeeded. A failed/cancelled first observation must still
108
137
  // publish the known locator for durable retention and exact cleanup.
109
- return formatPage(handle, { command: entry.command, chunks: [], exitCode: null });
138
+ return formatPage(handle, {
139
+ command: entry.command,
140
+ chunks: [],
141
+ exitCode: null,
142
+ });
110
143
  }
111
144
  } finally {
112
145
  pendingStarts.delete(cancellation);
@@ -128,7 +161,7 @@ export function installModalCommandSession(
128
161
  return entry ? structuredClone(entry.command) : null;
129
162
  };
130
163
  session.bindProviderCommand = (handle, command, persistence) => {
131
- if (!Number.isSafeInteger(handle) || handle <= 0)
164
+ if (!Number.isSafeInteger(handle) || handle <= 0 || handle > MAX_PROVIDER_COMMAND_HANDLE)
132
165
  throw new Error("Invalid retained Modal command handle");
133
166
  const existing = entries.get(handle);
134
167
  if (existing && !sameExecution(existing.command, command))
@@ -150,6 +183,11 @@ export function installModalCommandSession(
150
183
  receipts.delete(result);
151
184
  };
152
185
  session.writeStdin = async (args) => {
186
+ const sdkHandle = setupHandles.get(args.sessionId);
187
+ if (sdkHandle !== undefined && originalWrite) {
188
+ const raw = await originalWrite({ ...args, sessionId: sdkHandle });
189
+ return setupPage(raw, args.sessionId, sdkHandle);
190
+ }
153
191
  const entry = entries.get(args.sessionId);
154
192
  if (!entry?.persistence)
155
193
  throw new ModalProcessObservationUnavailableError(args.sessionId, {
@@ -562,7 +562,11 @@ export function installOpenGeniModalSnapshotPolicy<T extends object>(session: T)
562
562
  profile: mutable.modal.profile,
563
563
  ...(mutable.modal.logger ? { logger: mutable.modal.logger } : {}),
564
564
  },
565
- mutable.state.sandboxId,
565
+ () => {
566
+ const sandboxId = mutable.state?.sandboxId;
567
+ if (!sandboxId) throw new Error("Modal session sandbox identity is unavailable");
568
+ return sandboxId;
569
+ },
566
570
  mutable.state.manifest.root,
567
571
  () => mutable.state?.environment ?? {},
568
572
  ),