Skip to content

Commit 76af091

Browse files
Merge pull request #120 from codesandbox/new-version-fixes-2
Improved template builder help and keep active fix
2 parents 6294684 + a5a9bb1 commit 76af091

File tree

4 files changed

+71
-55
lines changed

4 files changed

+71
-55
lines changed

README.md

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -27,53 +27,20 @@ Create an API token by going to https://codesandbox.io/t/api, and clicking on th
2727
```javascript
2828
import { CodeSandbox } from "@codesandbox/sdk";
2929

30-
// Create the client with your token
31-
const sdk = new CodeSandbox(token);
30+
const sdk = new CodeSandbox(process.env.CSB_API_KEY);
31+
const sandbox = await sdk.sandboxes.create();
32+
const client = await sandbox.connect();
3233

33-
// This creates a new sandbox by forking our default template sandbox.
34-
// You can also pass in other template ids, or create your own template to fork from.
35-
const sandbox = await sdk.sandbox.create();
34+
const output = await client.commands.run("echo 'Hello World'");
3635

37-
// You can run JS code directly
38-
await sandbox.shells.js.run("console.log(1+1)");
39-
// Or Python code (if it's installed in the template)
40-
await sandbox.shells.python.run("print(1+1)");
41-
42-
// Or anything else
43-
await sandbox.shells.run("echo 'Hello, world!'");
44-
45-
// We have a FS API to interact with the filesystem
46-
await sandbox.fs.writeTextFile("./hello.txt", "world");
47-
48-
// And you can clone sandboxes! This does not only clone the filesystem, processes that are running in the original sandbox will also be cloned!
49-
const sandbox2 = await sandbox.fork();
50-
51-
// Check that the file is still there
52-
await sandbox2.fs.readTextFile("./hello.txt");
53-
54-
// You can also get the opened ports, with the URL to access those
55-
console.log(sandbox2.ports.getOpenedPorts());
56-
57-
// Getting metrics...
58-
const metrics = await sandbox2.getMetrics();
59-
console.log(
60-
`Memory: ${metrics.memory.usedKiB} KiB / ${metrics.memory.totalKiB} KiB`
61-
);
62-
console.log(`CPU: ${(metrics.cpu.used / metrics.cpu.cores) * 100}%`);
63-
64-
// Finally, you can hibernate a sandbox. This will snapshot the sandbox and stop it. Next time you start the sandbox, it will continue where it left off, as we created a memory snapshot.
65-
await sandbox.hibernate();
66-
await sandbox2.hibernate();
67-
68-
// Open the sandbox again
69-
const resumedSandbox = await sdk.sandbox.open(sandbox.id);
36+
console.log(output); // Hello World
7037
```
7138

7239
## CodeSandbox Integration
7340

7441
This SDK uses the API token from your workspace in CodeSandbox to authenticate and create sandboxes. Because of this, the sandboxes will be created inside your workspace, and the resources will be billed to your workspace.
7542

76-
You could, for example, create a private template in your workspace that has all the dependencies you need (even running servers), and then use that template to fork sandboxes from. This way, you can control the environment that the sandboxes run in.
43+
Build your own template that has all the dependencies you need (even running servers), and then use that template to create sandboxes from. This way, you can control the environment that the sandboxes run in.
7744

7845
## Example Use Cases
7946

@@ -83,6 +50,6 @@ Code interpretation: Run code in a sandbox to interpret it. This way, you can ru
8350

8451
Development environments: Create a sandbox for each developer, and run their code in the sandbox. This way, you can run multiple development environments in parallel without them interfering with each other.
8552

86-
AI Agents: Create a sandbox for each AI agent, and run the agent in the sandbox. This way, you can run multiple agents in parallel without them interfering with each other. Using the forking mechanism, you can also A/B test different agents.
53+
AI Agents: Create a sandbox for each AI agent, and run the agent in the sandbox. This way, you can run multiple agents in parallel without them interfering with each other.
8754

8855
CI/CD: Run tests inside a sandbox, and hibernate the sandbox when the tests are done. This way, you can quickly start the sandbox again when you need to run the tests again or evaluate the results.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@codesandbox/sdk",
3-
"version": "2.0.0",
3+
"version": "2.1.0",
44
"description": "The CodeSandbox SDK",
55
"author": "CodeSandbox",
66
"license": "MIT",

src/SandboxClient/index.ts

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Hosts } from "./hosts";
1212
import { IAgentClient } from "../node/agent-client-interface";
1313
import { setup } from "../pitcher-protocol";
1414
import { Barrier } from "../utils/barrier";
15+
import { clear } from "console";
1516

1617
export * from "./filesystem";
1718
export * from "./ports";
@@ -126,6 +127,30 @@ export class SandboxClient {
126127
this.hosts = new Hosts(this.agentClient.sandboxId, hostToken);
127128
this.interpreters = new Interpreters(this.disposable, this.commands);
128129
this.disposable.onWillDispose(() => this.agentClient.dispose());
130+
131+
this.disposable.onWillDispose(() => {
132+
if (this.keepAliveInterval) {
133+
clearInterval(this.keepAliveInterval);
134+
this.keepAliveInterval = null;
135+
}
136+
});
137+
138+
this.agentClient.onStateChange((state) => {
139+
if (!this.shouldKeepAlive) {
140+
return;
141+
}
142+
143+
// We can not call `keepActiveWhileConnected` here, because it would
144+
// reset the interval, which would turn off the "shouldKeepAlive" flag
145+
if (state === "DISCONNECTED" || state === "HIBERNATED") {
146+
if (this.keepAliveInterval) {
147+
clearInterval(this.keepAliveInterval);
148+
}
149+
this.keepAliveInterval = null;
150+
} else if (state === "CONNECTED") {
151+
this.keepActiveWhileConnected(true);
152+
}
153+
});
129154
}
130155

131156
/**
@@ -219,6 +244,11 @@ export class SandboxClient {
219244
* reconnect to the sandbox.
220245
*/
221246
public disconnect() {
247+
if (this.keepAliveInterval) {
248+
clearInterval(this.keepAliveInterval);
249+
this.keepAliveInterval = null;
250+
}
251+
222252
return this.agentClient.disconnect();
223253
}
224254

@@ -230,22 +260,19 @@ export class SandboxClient {
230260
}
231261

232262
private keepAliveInterval: NodeJS.Timeout | null = null;
263+
private shouldKeepAlive = false;
233264
/**
234265
* If enabled, we will keep the sandbox from hibernating as long as the SDK is connected to it.
235266
*/
236267
public keepActiveWhileConnected(enabled: boolean) {
268+
// Used to manage the interval when disconnects happen
269+
this.shouldKeepAlive = enabled;
270+
237271
if (enabled) {
238272
if (!this.keepAliveInterval) {
239273
this.keepAliveInterval = setInterval(() => {
240274
this.agentClient.system.update();
241275
}, 1000 * 30);
242-
243-
this.disposable.onWillDispose(() => {
244-
if (this.keepAliveInterval) {
245-
clearInterval(this.keepAliveInterval);
246-
this.keepAliveInterval = null;
247-
}
248-
});
249276
}
250277
} else {
251278
if (this.keepAliveInterval) {

src/bin/commands/build.ts

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -377,12 +377,21 @@ export const buildCommand: yargs.CommandModule<
377377
);
378378
})
379379
);
380-
spinner.succeed(`\n${spinnerMessages.join("\n")}`);
380+
spinner.start(`\n${spinnerMessages.join("\n")}`);
381381
} else {
382-
spinner.succeed(`\n${spinnerMessages.join("\n")}`);
382+
spinner.start(`\n${spinnerMessages.join("\n")}`);
383383
}
384384
}
385385

386+
spinner.start(
387+
`\n${spinnerMessages.join(
388+
"\n"
389+
)}\n\nCreating template reference and example...`
390+
);
391+
392+
let referenceString;
393+
let id;
394+
386395
if (alias) {
387396
await vmAssignTagAlias({
388397
client: apiClient,
@@ -395,13 +404,26 @@ export const buildCommand: yargs.CommandModule<
395404
},
396405
});
397406

398-
console.log(
399-
`Alias ${alias.namespace}@${alias.alias} updated to: ${templateData.tag}`
400-
);
401-
process.exit(0);
407+
id = `${alias.namespace}@${alias.alias}`;
408+
referenceString = `Alias ${id} now referencing: ${templateData.tag}`;
409+
} else {
410+
id = templateData.tag;
411+
referenceString = `Template created with tag: ${templateData.tag}`;
402412
}
403413

404-
console.log("Template created: " + templateData.tag);
414+
const sandbox = await sdk.sandboxes.create({
415+
id,
416+
});
417+
418+
spinner.succeed(
419+
`\n${spinnerMessages.join("\n")}\n\n${referenceString}
420+
421+
sdk.sandboxes.create({
422+
id: "${id}"
423+
})
424+
425+
Verify Sandbox at: https://codesandbox.io/s/${sandbox.id}\n\n`
426+
);
405427

406428
process.exit(0);
407429
} catch (error) {

0 commit comments

Comments
 (0)