@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 +24 -1
- package/dist/index.js +96 -12
- package/package.json +1 -1
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
|
|
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
|
|
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
|
-
|
|
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,
|