@giselles-ai/sandbox-agent 0.1.11 → 0.1.12

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.d.ts CHANGED
@@ -1,6 +1,29 @@
1
1
  import { z } from 'zod';
2
2
  import { Sandbox } from '@vercel/sandbox';
3
3
 
4
+ type AgentType = "codex" | "gemini";
5
+ declare class Agent {
6
+ private _type;
7
+ private _snapshotId;
8
+ private _pendingOps;
9
+ private constructor();
10
+ static create(type: AgentType, options: {
11
+ snapshotId: string;
12
+ }): Agent;
13
+ get type(): AgentType;
14
+ get snapshotId(): string;
15
+ get dirty(): boolean;
16
+ addFiles(files: Array<{
17
+ path: string;
18
+ content: Buffer;
19
+ }>): this;
20
+ runCommands(commands: Array<{
21
+ cmd: string;
22
+ args?: string[];
23
+ }>): this;
24
+ prepare(): Promise<void>;
25
+ }
26
+
4
27
  type BaseChatRequest = {
5
28
  message: string;
6
29
  session_id?: string;
@@ -78,4 +101,4 @@ type GeminiAgentOptions = {
78
101
  };
79
102
  declare function createGeminiAgent(options?: GeminiAgentOptions): ChatAgent<GeminiAgentRequest>;
80
103
 
81
- export { type BaseChatRequest, type ChatAgent, type ChatCommand, type RunChatInput, type StdoutMapper, createCodexAgent, createCodexStdoutMapper, createGeminiAgent, runChat };
104
+ export { Agent, type BaseChatRequest, type ChatAgent, type ChatCommand, type RunChatInput, type StdoutMapper, createCodexAgent, createCodexStdoutMapper, createGeminiAgent, runChat };
package/dist/index.js CHANGED
@@ -1,3 +1,76 @@
1
+ // src/agent.ts
2
+ import { Sandbox } from "@vercel/sandbox";
3
+ var Agent = class _Agent {
4
+ _type;
5
+ _snapshotId;
6
+ _pendingOps = [];
7
+ constructor(type, snapshotId) {
8
+ this._type = type;
9
+ this._snapshotId = snapshotId;
10
+ }
11
+ static create(type, options) {
12
+ const trimmed = options.snapshotId.trim();
13
+ if (!trimmed) {
14
+ throw new Error("snapshotId is required.");
15
+ }
16
+ return new _Agent(type, trimmed);
17
+ }
18
+ get type() {
19
+ return this._type;
20
+ }
21
+ get snapshotId() {
22
+ return this._snapshotId;
23
+ }
24
+ get dirty() {
25
+ return this._pendingOps.length > 0;
26
+ }
27
+ addFiles(files) {
28
+ if (files.length === 0) {
29
+ return this;
30
+ }
31
+ this._pendingOps.push({
32
+ kind: "writeFiles",
33
+ files
34
+ });
35
+ return this;
36
+ }
37
+ runCommands(commands) {
38
+ for (const command of commands) {
39
+ this._pendingOps.push({
40
+ kind: "runCommand",
41
+ cmd: command.cmd,
42
+ args: command.args ?? []
43
+ });
44
+ }
45
+ return this;
46
+ }
47
+ async prepare() {
48
+ if (!this.dirty) {
49
+ return;
50
+ }
51
+ const ops = this._pendingOps;
52
+ const sandbox = await Sandbox.create({
53
+ source: { type: "snapshot", snapshotId: this._snapshotId }
54
+ });
55
+ console.log(
56
+ `[sandbox] created sandbox=${sandbox.sandboxId} from snapshot=${this._snapshotId}`
57
+ );
58
+ for (const op of ops) {
59
+ switch (op.kind) {
60
+ case "writeFiles":
61
+ await sandbox.writeFiles(op.files);
62
+ break;
63
+ case "runCommand":
64
+ await sandbox.runCommand(op.cmd, op.args);
65
+ break;
66
+ }
67
+ }
68
+ const snapshot = await sandbox.snapshot();
69
+ this._snapshotId = snapshot.snapshotId;
70
+ this._pendingOps = [];
71
+ }
72
+ };
73
+
1
74
  // src/agents/codex-agent.ts
2
75
  import * as TOML from "@iarna/toml";
3
76
  import { z } from "zod";
@@ -39,6 +112,18 @@ function mapEvent(event) {
39
112
  content: typeof event.message === "string" ? event.message : JSON.stringify(event)
40
113
  };
41
114
  }
115
+ if (type === "item.completed") {
116
+ const item = event.item;
117
+ if (item?.type === "agent_message" && typeof item.text === "string") {
118
+ return {
119
+ type: "message",
120
+ role: "assistant",
121
+ content: item.text,
122
+ delta: false
123
+ };
124
+ }
125
+ return null;
126
+ }
42
127
  if (type === "response.completed") {
43
128
  return null;
44
129
  }
@@ -158,12 +243,7 @@ function assertBrowserToolRelayCredentials(parsed) {
158
243
  function createCodexAgent(options = {}) {
159
244
  const env = options.env ?? {};
160
245
  const snapshotId = options.snapshotId?.trim() || requiredEnv(env, "SANDBOX_SNAPSHOT_ID");
161
- const apiKey = env.CODEX_API_KEY?.trim() || env.OPENAI_API_KEY?.trim();
162
- if (!apiKey) {
163
- throw new Error(
164
- "Missing required environment variable: CODEX_API_KEY or OPENAI_API_KEY"
165
- );
166
- }
246
+ const apiKey = requiredEnv(env, "CODEX_API_KEY");
167
247
  const browserToolEnabled = options.tools?.browser !== void 0;
168
248
  const browserToolRelayUrl = options.tools?.browser?.relayUrl?.trim();
169
249
  if (browserToolEnabled) {
@@ -194,9 +274,7 @@ function createCodexAgent(options = {}) {
194
274
  return {
195
275
  cmd: "codex",
196
276
  args,
197
- env: {
198
- OPENAI_API_KEY: apiKey
199
- }
277
+ env: { CODEX_API_KEY: apiKey }
200
278
  };
201
279
  },
202
280
  createStdoutMapper() {
@@ -325,7 +403,7 @@ function createGeminiAgent(options = {}) {
325
403
 
326
404
  // src/chat-run.ts
327
405
  import { Writable } from "stream";
328
- import { Sandbox } from "@vercel/sandbox";
406
+ import { Sandbox as Sandbox2 } from "@vercel/sandbox";
329
407
  function emitText(controller, text, encoder) {
330
408
  if (text.length === 0) {
331
409
  return;
@@ -379,19 +457,23 @@ function runChat(input) {
379
457
  const mapper = input.agent.createStdoutMapper?.();
380
458
  void (async () => {
381
459
  try {
382
- const sandbox = parsed.sandbox_id ? await Sandbox.get({ sandboxId: parsed.sandbox_id }) : await (async () => {
460
+ const sandbox = parsed.sandbox_id ? await Sandbox2.get({ sandboxId: parsed.sandbox_id }) : await (async () => {
383
461
  const snapshotId = input.agent.snapshotId?.trim();
384
462
  if (!snapshotId) {
385
463
  throw new Error(
386
464
  "Agent must provide snapshotId when sandbox_id is not provided."
387
465
  );
388
466
  }
389
- return Sandbox.create({
467
+ const created = await Sandbox2.create({
390
468
  source: {
391
469
  type: "snapshot",
392
470
  snapshotId
393
471
  }
394
472
  });
473
+ console.log(
474
+ `[sandbox] created sandbox=${created.sandboxId} from snapshot=${snapshotId}`
475
+ );
476
+ return created;
395
477
  })();
396
478
  enqueueEvent({ type: "sandbox", sandbox_id: sandbox.sandboxId });
397
479
  await input.agent.prepareSandbox({
@@ -408,6 +490,7 @@ function runChat(input) {
408
490
  stdout: new Writable({
409
491
  write(chunk, _encoding, callback) {
410
492
  const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
493
+ console.log("[sandbox-agent] raw stdout:", text);
411
494
  if (mapper) {
412
495
  for (const line of mapper.push(text)) {
413
496
  enqueueStdout(line);
@@ -455,6 +538,7 @@ function runChat(input) {
455
538
  );
456
539
  }
457
540
  export {
541
+ Agent,
458
542
  createCodexAgent,
459
543
  createCodexStdoutMapper,
460
544
  createGeminiAgent,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@giselles-ai/sandbox-agent",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "Apache-2.0",