-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[OSS Vibe Coding Platform] Implement Workflow DevKit #1287
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
Merged
VaguelySerious
merged 2 commits into
peter/pre-tidy-for-workflows
from
pranaygp/11-06-implement_workflow_devkit
Nov 18, 2025
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
apps/vibe-coding-platform/ai/tools/create-sandbox.description.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| 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). | ||
|
|
||
| ## When to Use This Tool | ||
|
|
||
| Use this tool **once per session** when: | ||
|
|
||
| 1. You begin working on a new user request that requires code execution or file creation | ||
| 2. No sandbox currently exists for the session | ||
| 3. The user asks to start a new project, scaffold an application, or test code in a live environment | ||
| 4. The user requests a fresh or reset environment | ||
|
|
||
| ## Sandbox Capabilities | ||
|
|
||
| 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\` | ||
|
|
||
| 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. | ||
|
|
||
| ## Best Practices | ||
|
|
||
| - Create the sandbox at the beginning of the session or when the user initiates a coding task | ||
| - Track and reuse the sandbox ID throughout the session | ||
| - Do not create a second sandbox unless explicitly instructed | ||
| - If the user requests an environment reset, you may create a new sandbox **after confirming their intent** | ||
|
|
||
| ## Examples of When to Use This Tool | ||
|
|
||
| <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. | ||
| *Calls Create Sandbox* | ||
| </example> | ||
|
|
||
| ## When NOT to Use This Tool | ||
|
|
||
| Skip using this tool when: | ||
|
|
||
| 1. A sandbox has already been created for the current session | ||
| 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 | ||
|
|
||
| ## 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. | ||
| ` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,11 @@ | ||
| import type { UIMessage, UIMessageStreamWriter } from 'ai' | ||
| import type { UIMessageChunk } 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.prompt' | ||
| import z from 'zod/v3' | ||
| import { getWritable } from 'workflow' | ||
|
|
||
| const inputSchema = z.object({ | ||
|
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. The refactor for tools is very simple
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. I recommend reviewing with "hide whitespace" enabled |
||
| timeout: z | ||
|
|
@@ -24,61 +25,60 @@ const inputSchema = z.object({ | |
| ), | ||
| }) | ||
|
|
||
| const createSandboxStep = | ||
| (writer: UIMessageStreamWriter<UIMessage<never, DataPart>>) => | ||
| async ( | ||
| { timeout, ports }: z.infer<typeof inputSchema>, | ||
| { toolCallId }: { toolCallId: string } | ||
| ) => { | ||
| async function createSandboxStep( | ||
| { timeout, ports }: z.infer<typeof inputSchema>, | ||
| { toolCallId }: { toolCallId: string } | ||
| ) { | ||
| 'use step' | ||
|
|
||
| const writable = getWritable<UIMessageChunk<never, DataPart>>() | ||
| const writer = writable.getWriter() | ||
|
|
||
| writer.write({ | ||
| id: toolCallId, | ||
| type: 'data-create-sandbox', | ||
| data: { status: 'loading' }, | ||
| }) | ||
|
|
||
| try { | ||
| const sandbox = await Sandbox.create({ | ||
| timeout: timeout ?? 600000, | ||
| ports, | ||
| }) | ||
|
|
||
| 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, | ||
| }: { | ||
| writer: UIMessageStreamWriter<UIMessage<never, DataPart>> | ||
| }) => | ||
| export const createSandbox = () => | ||
| tool({ | ||
| description, | ||
| inputSchema, | ||
| execute: createSandboxStep(writer), | ||
| execute: createSandboxStep, | ||
| }) | ||
64 changes: 64 additions & 0 deletions
64
apps/vibe-coding-platform/ai/tools/generate-files.description.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| export default `Use this tool to generate and upload code files into an existing Vercel Sandbox. It leverages an LLM to create file contents based on the current conversation context and user intent, then writes them directly into the sandbox file system. | ||
|
|
||
| The generated files should be considered correct on first iteration and suitable for immediate use in the sandbox environment. This tool is essential for scaffolding applications, adding new features, writing configuration files, or fixing missing components. | ||
|
|
||
| All file paths must be relative to the sandbox root (e.g., \`src/index.ts\`, \`package.json\`, \`components/Button.tsx\`). | ||
|
|
||
| ## When to Use This Tool | ||
|
|
||
| Use Generate Files when: | ||
|
|
||
| 1. You need to create one or more new files as part of a feature, scaffold, or fix | ||
| 2. The user requests code that implies file creation (e.g., new routes, APIs, components, services) | ||
| 3. You need to bootstrap a new application structure inside a sandbox | ||
| 4. You're completing a multi-step task that involves generating or updating source code | ||
| 5. A prior command failed due to a missing file, and you need to supply it | ||
|
|
||
| ## File Generation Guidelines | ||
|
|
||
| - Every file must be complete, valid, and runnable where applicable | ||
| - File contents must reflect the user's intent and the overall session context | ||
| - File paths must be well-structured and use consistent naming conventions | ||
| - Generated files should assume compatibility with other existing files in the sandbox | ||
|
|
||
| ## Best Practices | ||
|
|
||
| - Avoid redundant file generation if the file already exists and is unchanged | ||
| - Use conventional file/folder structures for the tech stack in use | ||
| - If replacing an existing file, ensure the update fully satisfies the user's request | ||
|
|
||
| ## Examples of When to Use This Tool | ||
|
|
||
| <example> | ||
| User: Add a \`NavBar.tsx\` component and include it in \`App.tsx\` | ||
| Assistant: I'll generate the \`NavBar.tsx\` file and update \`App.tsx\` to include it. | ||
| *Uses Generate Files to create:* | ||
| - \`components/NavBar.tsx\` | ||
| - Modified \`App.tsx\` with import and usage of \`NavBar\` | ||
| </example> | ||
|
|
||
| <example> | ||
| User: Let's scaffold a simple Express server with a \`/ping\` route. | ||
| Assistant: I'll generate the necessary files to start the Express app. | ||
| *Uses Generate Files to create:* | ||
| - \`package.json\` with Express as a dependency | ||
| - \`index.js\` with basic server and \`/ping\` route | ||
| </example> | ||
|
|
||
| ## When NOT to Use This Tool | ||
|
|
||
| Avoid using this tool when: | ||
|
|
||
| 1. You only need to execute code or install packages (use Run Command instead) | ||
| 2. You're waiting for a command to finish (use Wait Command) | ||
| 3. You want to preview a running server or UI (use Get Sandbox URL) | ||
| 4. You haven't created a sandbox yet (use Create Sandbox first) | ||
|
|
||
| ## Output Behavior | ||
|
|
||
| After generation, the tool will return a list of the files created, including their paths and contents. These can then be inspected, referenced, or used in subsequent commands. | ||
|
|
||
| ## Summary | ||
|
|
||
| Use Generate Files to programmatically create or update files in your Vercel Sandbox. It enables fast iteration, contextual coding, and dynamic file management — all driven by user intent and conversation context. | ||
| ` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Sadly I had to change these from
mdfiles since workflow devkit doesn't currently let you provide your own loaders to the workflow bundling interfaceHope this isn't a blocker. We'd like to support custom loaders in devkit but that isn't high priority