-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[vibe-coding-platform] Implement Workflow DevKit #1302
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
e318a80
1769cce
a6bef74
3a3b39a
fadc628
1ad8d9b
cbcfdc6
0ab2ffd
20bc2f0
0563a1f
0dc9f84
7dc57c3
83b1c85
5221f7d
f2131fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| Use this tool to create a new Vercel Sandbox — an ephemeral, isolated Linux container that serves as your development environment for the current session. This sandbox provides a secure workspace where you can upload files, install dependencies, run commands, start development servers, and preview web apps. Each sandbox is uniquely identified and must be referenced for all subsequent operations (e.g., file generation, command execution, or URL access). | ||
| export default `Use this tool to create a new Vercel Sandbox — an ephemeral, isolated Linux container that serves as your development environment for the current session. This sandbox provides a secure workspace where you can upload files, install dependencies, run commands, start development servers, and preview web apps. Each sandbox is uniquely identified and must be referenced for all subsequent operations (e.g., file generation, command execution, or URL access). | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Markdown files aren't supported by workflow compiler plugin, so we had to rename all of the prompts to typescript files |
||
|
|
||
| ## When to Use This Tool | ||
|
|
||
|
|
@@ -13,17 +13,17 @@ Use this tool **once per session** when: | |
|
|
||
| After creation, the sandbox allows you to: | ||
|
|
||
| - Upload and manage files via `Generate Files` | ||
| - Execute shell commands with `Run Command` and `Wait Command` | ||
| - Access running servers through public URLs using `Get Sandbox URL` | ||
| - Upload and manage files via \`Generate Files\` | ||
| - Execute shell commands with \`Run Command\` and \`Wait Command\` | ||
| - Access running servers through public URLs using \`Get Sandbox URL\` | ||
|
|
||
| Each sandbox mimics a real-world development environment and supports rapid iteration and testing without polluting the local system. The base system is Amazon Linux 2023 with the following additional packages: | ||
|
|
||
| ``` | ||
| \`\`\` | ||
| bind-utils bzip2 findutils git gzip iputils libicu libjpeg libpng ncurses-libs openssl openssl-libs pnpm procps tar unzip which whois zstd | ||
| ``` | ||
| \`\`\` | ||
|
|
||
| You can install additional packages using the `dnf` package manager. You can NEVER use port 8080 as it is reserved for internal applications. When requested, you need to use a different port. | ||
| You can install additional packages using the \`dnf\` package manager. You can NEVER use port 8080 as it is reserved for internal applications. When requested, you need to use a different port. | ||
|
|
||
| ## Best Practices | ||
|
|
||
|
|
@@ -36,7 +36,7 @@ You can install additional packages using the `dnf` package manager. You can NEV | |
|
|
||
| <example> | ||
| User: Can we start fresh? I want to rebuild the project from scratch. | ||
| Assistant: Got it — I’ll create a new sandbox so we can start clean. | ||
| Assistant: Got it — I'll create a new sandbox so we can start clean. | ||
| *Calls Create Sandbox* | ||
| </example> | ||
|
|
||
|
|
@@ -48,8 +48,9 @@ Skip using this tool when: | |
| 2. You only need to upload files (use Generate Files) | ||
| 3. You want to execute or wait for a command (use Run Command / Wait Command) | ||
| 4. You want to preview the application (use Get Sandbox URL) | ||
| 5. The user hasn’t asked to reset the environment | ||
| 5. The user hasn't asked to reset the environment | ||
|
|
||
| ## Summary | ||
|
|
||
| Use Create Sandbox to initialize a secure, temporary development environment — but **only once per session**. Treat the sandbox as the core workspace for all follow-up actions unless the user explicitly asks to discard and start anew. | ||
| ` | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,75 +1,82 @@ | ||
| import type { UIMessageStreamWriter, UIMessage } from 'ai' | ||
| import type { UIMessage, UIMessageChunk, UIMessageStreamWriter } from 'ai' | ||
| import type { DataPart } from '../messages/data-parts' | ||
| import { Sandbox } from '@vercel/sandbox' | ||
| import { getRichError } from './get-rich-error' | ||
| import { tool } from 'ai' | ||
| import description from './create-sandbox.md' | ||
| import description from './create-sandbox.prompt' | ||
| import z from 'zod/v3' | ||
|
|
||
| interface Params { | ||
| writer: UIMessageStreamWriter<UIMessage<never, DataPart>> | ||
| } | ||
| const inputSchema = z.object({ | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All of the step files have been changed to extract the inputSchem and executor in their own functions, outside of the tool definition. No other changes have been made (AFAIK) |
||
| timeout: z | ||
| .number() | ||
| .min(600000) | ||
| .max(2700000) | ||
| .optional() | ||
| .describe( | ||
| 'Maximum time in milliseconds the Vercel Sandbox will remain active before automatically shutting down. Minimum 600000ms (10 minutes), maximum 2700000ms (45 minutes). Defaults to 600000ms (10 minutes). The sandbox will terminate all running processes when this timeout is reached.' | ||
| ), | ||
| ports: z | ||
| .array(z.number()) | ||
| .max(2) | ||
| .optional() | ||
| .describe( | ||
| 'Array of network ports to expose and make accessible from outside the Vercel Sandbox. These ports allow web servers, APIs, or other services running inside the Vercel Sandbox to be reached externally. Common ports include 3000 (Next.js), 8000 (Python servers), 5000 (Flask), etc.' | ||
| ), | ||
| }) | ||
|
|
||
| const createSandboxStep = | ||
| (writer: UIMessageStreamWriter<UIMessage<never, DataPart>>) => | ||
| async ( | ||
| { timeout, ports }: z.infer<typeof inputSchema>, | ||
| { toolCallId }: { toolCallId: string } | ||
| ) => { | ||
| writer.write({ | ||
| id: toolCallId, | ||
| type: 'data-create-sandbox', | ||
| data: { status: 'loading' }, | ||
| }) | ||
|
|
||
| try { | ||
| const sandbox = await Sandbox.create({ | ||
| timeout: timeout ?? 600000, | ||
| ports, | ||
| }) | ||
|
|
||
| export const createSandbox = ({ writer }: Params) => | ||
| tool({ | ||
| description, | ||
| inputSchema: z.object({ | ||
| timeout: z | ||
| .number() | ||
| .min(600000) | ||
| .max(2700000) | ||
| .optional() | ||
| .describe( | ||
| 'Maximum time in milliseconds the Vercel Sandbox will remain active before automatically shutting down. Minimum 600000ms (10 minutes), maximum 2700000ms (45 minutes). Defaults to 600000ms (10 minutes). The sandbox will terminate all running processes when this timeout is reached.' | ||
| ), | ||
| ports: z | ||
| .array(z.number()) | ||
| .max(2) | ||
| .optional() | ||
| .describe( | ||
| 'Array of network ports to expose and make accessible from outside the Vercel Sandbox. These ports allow web servers, APIs, or other services running inside the Vercel Sandbox to be reached externally. Common ports include 3000 (Next.js), 8000 (Python servers), 5000 (Flask), etc.' | ||
| ), | ||
| }), | ||
| execute: async ({ timeout, ports }, { toolCallId }) => { | ||
| writer.write({ | ||
| id: toolCallId, | ||
| type: 'data-create-sandbox', | ||
| data: { status: 'loading' }, | ||
| data: { sandboxId: sandbox.sandboxId, status: 'done' }, | ||
| }) | ||
|
|
||
| try { | ||
| const sandbox = await Sandbox.create({ | ||
| timeout: timeout ?? 600000, | ||
| ports, | ||
| }) | ||
|
|
||
| writer.write({ | ||
| id: toolCallId, | ||
| type: 'data-create-sandbox', | ||
| data: { sandboxId: sandbox.sandboxId, status: 'done' }, | ||
| }) | ||
| return ( | ||
| `Sandbox created with ID: ${sandbox.sandboxId}.` + | ||
| `\nYou can now upload files, run commands, and access services on the exposed ports.` | ||
| ) | ||
| } catch (error) { | ||
| const richError = getRichError({ | ||
| action: 'Creating Sandbox', | ||
| error, | ||
| }) | ||
|
|
||
| return ( | ||
| `Sandbox created with ID: ${sandbox.sandboxId}.` + | ||
| `\nYou can now upload files, run commands, and access services on the exposed ports.` | ||
| ) | ||
| } catch (error) { | ||
| const richError = getRichError({ | ||
| action: 'Creating Sandbox', | ||
| error, | ||
| }) | ||
| writer.write({ | ||
| id: toolCallId, | ||
| type: 'data-create-sandbox', | ||
| data: { | ||
| error: { message: richError.error.message }, | ||
| status: 'error', | ||
| }, | ||
| }) | ||
|
|
||
| writer.write({ | ||
| id: toolCallId, | ||
| type: 'data-create-sandbox', | ||
| data: { | ||
| error: { message: richError.error.message }, | ||
| status: 'error', | ||
| }, | ||
| }) | ||
| console.log('Error creating Sandbox:', richError.error) | ||
| return richError.message | ||
| } | ||
| } | ||
|
|
||
| console.log('Error creating Sandbox:', richError.error) | ||
| return richError.message | ||
| } | ||
| }, | ||
| export const createSandbox = ( | ||
| writer: UIMessageStreamWriter<UIMessage<never, DataPart>> | ||
| ) => | ||
| tool({ | ||
| description, | ||
| inputSchema, | ||
| execute: createSandboxStep(writer), | ||
| }) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added Haiku while I was at it