Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
ac0272c
Add PTY types to shared package
whoiskatrin Dec 18, 2025
99db220
Add PtyManager for container PTY lifecycle
whoiskatrin Dec 18, 2025
4f15ccd
Add PTY handler and route registration
whoiskatrin Dec 18, 2025
020f697
Add PTY message handling to WebSocket adapter
whoiskatrin Dec 18, 2025
6a66c9b
Add PTY methods to transport interface
whoiskatrin Dec 18, 2025
09eca50
Add PtyClient for SDK PTY operations
whoiskatrin Dec 18, 2025
4dede27
Add pty namespace to Sandbox class
whoiskatrin Dec 18, 2025
fbf4fa1
Add E2E tests for PTY workflow
whoiskatrin Dec 18, 2025
d43b3fd
Add changeset for PTY support
whoiskatrin Dec 18, 2025
40258ee
Skip PTY tests when PTY allocation fails
whoiskatrin Dec 19, 2025
405d7c7
Fix pty manager tests
whoiskatrin Dec 19, 2025
b9cc460
fix any types, logger
whoiskatrin Dec 19, 2025
794235b
fix silent logging
whoiskatrin Dec 19, 2025
2534791
fix pty tests for resizing
whoiskatrin Dec 21, 2025
1f311eb
update claude review yml
whoiskatrin Dec 21, 2025
93328a3
revert review change
whoiskatrin Dec 21, 2025
0e2e8ce
update http tests
whoiskatrin Dec 22, 2025
05c2342
more test updates
whoiskatrin Dec 22, 2025
8c0194b
remove the plugin for review
whoiskatrin Dec 22, 2025
f03f896
Add error handling to PTY callbacks and terminal operations
whoiskatrin Dec 22, 2025
2b20949
Improve
whoiskatrin Dec 22, 2025
0a7ca34
add structured exit codes
whoiskatrin Dec 22, 2025
119510e
change fire and forget strategy
whoiskatrin Dec 22, 2025
c9d5f1f
add more e2e tests
whoiskatrin Dec 22, 2025
2e04768
more fixes and tests
whoiskatrin Dec 22, 2025
d256de3
fix ws
whoiskatrin Dec 22, 2025
c85afc7
update error propagation
whoiskatrin Dec 22, 2025
407744d
update resizing tests
whoiskatrin Dec 23, 2025
b81cb3d
add collab terminal example
whoiskatrin Dec 23, 2025
7ddaaa9
Potential fix for code scanning alert no. 40: Insecure randomness
whoiskatrin Dec 23, 2025
76e628e
Potential fix for code scanning alert no. 41: Insecure randomness
whoiskatrin Dec 23, 2025
9c21e86
Update dependency in examples
whoiskatrin Dec 23, 2025
98754c7
Add PTY listeners cleanup
whoiskatrin Dec 23, 2025
7f6bce2
minor nits
whoiskatrin Dec 23, 2025
e213b13
update tests setup
whoiskatrin Dec 23, 2025
edd6a00
Add logging for PTY listener registration errors and improve error ha…
whoiskatrin Dec 23, 2025
76ceaa4
Enhance error handling and logging in WebSocketTransport and PtyHandl…
whoiskatrin Dec 23, 2025
bc159c6
Add connection-specific PTY listener cleanup on WebSocket close
whoiskatrin Dec 23, 2025
3cfc363
Remove outdated comment regarding connection cleanup functions in Web…
whoiskatrin Dec 23, 2025
51ee876
Fix error handling in PTY management by updating kill method to retur…
whoiskatrin Dec 23, 2025
d51f141
implement signal handling for Ctrl+C, Ctrl+Z, and Ctrl+\ in the PTY m…
whoiskatrin Jan 5, 2026
1ea663e
Merge main into pty-support
whoiskatrin Jan 5, 2026
499e3b7
Potential fix for code scanning alert no. 43: Insecure randomness
whoiskatrin Jan 5, 2026
bed6e22
Changes based on review comments
whoiskatrin Jan 8, 2026
b11b99f
Update dependencies and improve PTY handling in collaborative termina…
whoiskatrin Jan 8, 2026
1f0f7f6
Update PTY workflow tests to expect correct HTTP status codes for err…
whoiskatrin Jan 8, 2026
84a20a7
extractPtyId method to retrieve PTY IDs from responses, and update ha…
whoiskatrin Jan 8, 2026
0aa8995
Update PTY workflow tests to expect 'message' field in error response…
whoiskatrin Jan 8, 2026
fd1adc5
Fixed handlers for tests
whoiskatrin Jan 9, 2026
5918151
Use PR-specific Docker build cache scope to avoid cross-PR cache poll…
whoiskatrin Jan 9, 2026
a841501
Add debug logging to router for route registration and matching
whoiskatrin Jan 9, 2026
96edf05
Add INFO-level route logging to debug container caching issues
whoiskatrin Jan 9, 2026
a2898ea
Add retry logic for WebSocket server readiness in e2e tests
whoiskatrin Jan 9, 2026
f5f612a
Remove debug logging added during PTY route investigation
whoiskatrin Jan 9, 2026
099bb36
Fix sync-docs workflow to handle PR bodies with special characters
whoiskatrin Jan 9, 2026
a3f8b02
Fix sync-docs workflow shell escaping for opencode run
whoiskatrin Jan 9, 2026
10e3f36
Merge main into pty-support, resolve sync-docs conflict
whoiskatrin Jan 9, 2026
491b642
Merge remote-tracking branch 'origin/main' into pty-support
ghostwriternr Jan 13, 2026
5c7de26
Fix lint errors and align env type signatures
ghostwriternr Jan 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .changeset/pty-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
'@cloudflare/sandbox': minor
---

Add PTY (pseudo-terminal) support for interactive terminal sessions.

New `sandbox.pty` namespace with:

- `create()` - Create a new PTY session
- `attach(sessionId)` - Attach PTY to existing session
- `getById(id)` - Reconnect to existing PTY
- `list()` - List all PTY sessions

PTY handles support:

- `write(data)` - Send input
- `resize(cols, rows)` - Resize terminal
- `kill()` - Terminate PTY
- `onData(cb)` - Receive output
- `onExit(cb)` - Handle exit
- `exited` - Promise for exit code
- Async iteration for scripting

Example:

```typescript
const pty = await sandbox.pty.create({ cols: 80, rows: 24 });
pty.onData((data) => terminal.write(data));
pty.write('ls -la\n');
```
2 changes: 0 additions & 2 deletions .github/workflows/pullrequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@ jobs:
set -e
VERSION="${{ needs.unit-tests.outputs.version }}"

echo "Starting parallel builds..."

docker buildx build \
--cache-from type=gha,scope=sandbox-base \
--cache-to type=gha,mode=max,scope=sandbox-base \
Expand Down
107 changes: 52 additions & 55 deletions .github/workflows/sync-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,23 +53,35 @@ jobs:

- name: Create prompt for OpenCode
id: create-prompt
env:
PR_BODY: ${{ github.event.pull_request.body }}
run: |
# Store PR metadata in environment variables to avoid shell escaping issues
PR_NUMBER="${{ github.event.pull_request.number }}"
PR_TITLE="${{ github.event.pull_request.title }}"
PR_URL="https://github.com/${{ github.repository }}/pull/${{ github.event.pull_request.number }}"

cat > /tmp/claude_prompt.md << EOF
# Use quoted heredoc to prevent interpretation of special characters
cat > /tmp/claude_prompt.md <<'STATIC_EOF'
# Intelligent Documentation Sync Task

## Context
- **Source Repository:** ${{ github.repository }}
- **Original PR Number:** ${PR_NUMBER}
- **Original PR Title:** ${PR_TITLE}
- **Original PR URL:** ${PR_URL}
- **Changed Files:** ${{ steps.changed-files.outputs.changed_files }}
- **PR Description:**
${{ github.event.pull_request.body }}
STATIC_EOF

# Append dynamic content safely using printf
{
echo "- **Source Repository:** ${{ github.repository }}"
echo "- **Original PR Number:** ${PR_NUMBER}"
echo "- **Original PR Title:** ${PR_TITLE}"
echo "- **Original PR URL:** ${PR_URL}"
echo "- **Changed Files:** ${{ steps.changed-files.outputs.changed_files }}"
echo "- **PR Description:**"
printf '%s\n' "$PR_BODY"
} >> /tmp/claude_prompt.md

# Append the rest of the static content
cat >> /tmp/claude_prompt.md <<'STATIC_EOF'


⚠️ **IMPORTANT**: All PR metadata above is the ONLY source of truth. Use these values EXACTLY as written.
DO NOT fetch PR title/URL from GitHub APIs.
Expand All @@ -78,12 +90,12 @@ jobs:

**First, gather the information you need:**
1. Review the list of changed files above
2. Use \`gh pr diff ${PR_NUMBER}\` to see the full diff for this PR
2. Use `gh pr diff PR_NUMBER_HERE` (replace with actual number from Context) to see the full diff for this PR
3. Use the Read tool to examine specific files if needed

You have access to two repositories:
1. The current directory (our main repo at ${{ github.repository }})
2. ./cloudflare-docs (already cloned with branch sync-docs-pr-${{ github.event.pull_request.number }} checked out)
1. The current directory (our main repo)
2. ./cloudflare-docs (already cloned with branch sync-docs-pr-PR_NUMBER_HERE checked out)

**Step 1: Evaluate if Documentation Sync is Needed**

Expand All @@ -110,48 +122,33 @@ jobs:

If you determine documentation updates are required, YOU MUST COMPLETE ALL STEPS:

1. Navigate to ./cloudflare-docs (already cloned, branch sync-docs-pr-${PR_NUMBER} checked out)
1. Navigate to ./cloudflare-docs (already cloned, branch checked out)
2. Adapt changes for cloudflare-docs repository structure and style
3. Create or update the appropriate markdown files
4. Ensure content follows cloudflare-docs conventions

5. **CRITICAL - Commit changes:**
Run exactly: `cd cloudflare-docs && git add . && git commit -m "Sync docs from cloudflare/sandbox-sdk#${PR_NUMBER}: ${PR_TITLE}"`
Run: cd cloudflare-docs && git add . && git commit -m "Sync docs from cloudflare/sandbox-sdk#PR_NUMBER: PR_TITLE"
(Replace PR_NUMBER and PR_TITLE with actual values from Context section)

6. **CRITICAL - Push to remote:**
Run exactly: `cd cloudflare-docs && git push origin sync-docs-pr-${PR_NUMBER}`
Run: cd cloudflare-docs && git push origin sync-docs-pr-PR_NUMBER
(Replace PR_NUMBER with actual value from Context section)

7. **CRITICAL - Create or update PR in cloudflare-docs:**
⚠️ **CRITICAL**: Use the exact PR_NUMBER, PR_TITLE, and PR_URL values from the Context section above.

Copy and run this EXACT script (replace PLACEHOLDER values with actual values from Context):
```bash
# Set variables from Context section above
PR_NUMBER="PLACEHOLDER_PR_NUMBER"
PR_TITLE="PLACEHOLDER_PR_TITLE"
PR_URL="PLACEHOLDER_PR_URL"
Use the exact PR_NUMBER, PR_TITLE, and PR_URL values from the Context section above.

# Check if PR already exists
EXISTING_PR=$(gh pr list --repo cloudflare/cloudflare-docs --head sync-docs-pr-${PR_NUMBER} --json number --jq '.[0].number')
Check if PR exists: gh pr list --repo cloudflare/cloudflare-docs --head sync-docs-pr-PR_NUMBER --json number --jq '.[0].number'

# Create PR title and body
PR_TITLE_TEXT="📚 Sync docs from cloudflare/sandbox-sdk#${PR_NUMBER}: ${PR_TITLE}"
PR_BODY_TEXT="Syncs documentation changes from [cloudflare/sandbox-sdk#${PR_NUMBER}](${PR_URL}): **${PR_TITLE}**"
If PR exists, update it:
gh pr edit EXISTING_PR_NUMBER --repo cloudflare/cloudflare-docs --title "Sync docs from cloudflare/sandbox-sdk#PR_NUMBER: PR_TITLE" --body "Syncs documentation changes from cloudflare/sandbox-sdk#PR_NUMBER (PR_URL): PR_TITLE"

if [ -n "$EXISTING_PR" ] && [ "$EXISTING_PR" != "null" ]; then
# Update existing PR
echo "Updating existing PR #$EXISTING_PR"
gh pr edit $EXISTING_PR --repo cloudflare/cloudflare-docs --title "$PR_TITLE_TEXT" --body "$PR_BODY_TEXT"
else
# Create new PR
echo "Creating new PR"
gh pr create --repo cloudflare/cloudflare-docs --base main --head sync-docs-pr-${PR_NUMBER} --title "$PR_TITLE_TEXT" --body "$PR_BODY_TEXT"
fi
```
If PR does not exist, create it:
gh pr create --repo cloudflare/cloudflare-docs --base main --head sync-docs-pr-PR_NUMBER --title "Sync docs from cloudflare/sandbox-sdk#PR_NUMBER: PR_TITLE" --body "Syncs documentation changes from cloudflare/sandbox-sdk#PR_NUMBER (PR_URL): PR_TITLE"

⚠️ THE TASK IS NOT COMPLETE UNTIL ALL 7 STEPS ARE DONE. Do not stop after editing files.
THE TASK IS NOT COMPLETE UNTIL ALL 7 STEPS ARE DONE. Do not stop after editing files.

## Documentation Writing Guidelines (Diátaxis Framework)
## Documentation Writing Guidelines (Diataxis Framework)

When writing the documentation content, adapt your approach based on what changed:

Expand All @@ -175,54 +172,54 @@ jobs:
- Single functions = reference + example (concise)
- Multi-step workflows = separate how-to guides
- Keep reference neutral and factual
- Don't overexplain simple functions
- Do not overexplain simple functions

## Cloudflare Docs Style Requirements

**CRITICAL**: Follow all rules from the [Cloudflare Style Guide](https://developers.cloudflare.com/style-guide/) and these specific requirements:
**CRITICAL**: Follow all rules from the Cloudflare Style Guide (https://developers.cloudflare.com/style-guide/) and these specific requirements:

**Grammar & Formatting:**
- Do not use contractions, exclamation marks, or non-standard quotes like \`''""\`
- Do not use contractions, exclamation marks, or non-standard quotes
- Fix common spelling errors, specifically misspellings of "wrangler"
- Remove whitespace characters from the end of lines
- Remove duplicate words
- Do not use HTML for ordered lists

**Links:**
- Use full relative links (\`/sandbox-sdk/configuration/\`) instead of full URLs, local dev links, or dot notation
- Use full relative links (/sandbox-sdk/configuration/) instead of full URLs, local dev links, or dot notation
- Always use trailing slashes for links without anchors
- Use meaningful link words (page titles) - avoid "here", "this page", "read more"
- Add cross-links to relevant documentation pages where appropriate

**Components (MUST USE):**
- All components need to be imported below frontmatter: \`import { ComponentName } from "~/components";\`
- **WranglerConfig component**: Replace \`toml\` or \`json\` code blocks showing Wrangler configuration with the [\`WranglerConfig\` component](https://developers.cloudflare.com/style-guide/components/wrangler-config/). This is CRITICAL - always use this component for wrangler.toml/wrangler.jsonc examples.
- **DashButton component**: Replace \`https://dash.cloudflare.com\` in steps with the [\`DashButton\` component](https://developers.cloudflare.com/style-guide/components/dash-button/)
- **APIRequest component**: Replace \`sh\` code blocks with API requests to \`https://api.cloudflare.com\` with the [\`APIRequest\` component](https://developers.cloudflare.com/style-guide/components/api-request/)
- **FileTree component**: Replace \`txt\` blocks showing file trees with the [\`FileTree\` component](https://developers.cloudflare.com/style-guide/components/file-tree/)
- **PackageManagers component**: Replace \`sh\` blocks with npm commands using the [\`PackageManagers\` component](https://developers.cloudflare.com/style-guide/components/package-managers/)
- **TypeScriptExample component**: Replace \`ts\`/\`typescript\` code blocks with the [\`TypeScriptExample\` component](https://developers.cloudflare.com/style-guide/components/typescript-example/) (except in step-by-step TypeScript-specific tutorials)
- All components need to be imported below frontmatter: import { ComponentName } from "~/components";
- **WranglerConfig component**: Replace toml or json code blocks showing Wrangler configuration with the WranglerConfig component. This is CRITICAL - always use this component for wrangler.toml/wrangler.jsonc examples.
- **DashButton component**: Replace https://dash.cloudflare.com in steps with the DashButton component
- **APIRequest component**: Replace sh code blocks with API requests to https://api.cloudflare.com with the APIRequest component
- **FileTree component**: Replace txt blocks showing file trees with the FileTree component
- **PackageManagers component**: Replace sh blocks with npm commands using the PackageManagers component
- **TypeScriptExample component**: Replace ts/typescript code blocks with the TypeScriptExample component (except in step-by-step TypeScript-specific tutorials)

**JSX & Partials:**
- When using JSX fragments for conditional rendering, use props variable to account for reusability
- Only use \`<Markdown />\` component in JSX conditionals, and only if needed
- Only use Markdown component in JSX conditionals, and only if needed
- Do not duplicate content in ternary/binary conditions
- For variables in links, use HTML instead of Markdown

**Step 3: Provide Clear Output**

Clearly state your decision:
- If syncing: Explain what documentation changes you're making and why
- If not syncing: Explain why documentation updates aren't needed for this PR
- If syncing: Explain what documentation changes you are making and why
- If not syncing: Explain why documentation updates are not needed for this PR

## Important Notes
- Use the GH_TOKEN environment variable for authentication with gh CLI
- Adapt paths, links, and references as needed for cloudflare-docs structure
- Follow existing patterns in the cloudflare-docs repository
- **DEFAULT TO SYNCING**: When in doubt about whether changes warrant a sync, ALWAYS create the sync PR for human review. It's better to create an unnecessary PR than to miss important documentation updates.
- **DEFAULT TO SYNCING**: When in doubt about whether changes warrant a sync, ALWAYS create the sync PR for human review. It is better to create an unnecessary PR than to miss important documentation updates.

Begin your evaluation now.
EOF
STATIC_EOF

echo "prompt<<PROMPT_EOF" >> $GITHUB_OUTPUT
cat /tmp/claude_prompt.md >> $GITHUB_OUTPUT
Expand Down
17 changes: 17 additions & 0 deletions examples/collaborative-terminal/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Collaborative Terminal Dockerfile
#
# IMPORTANT: PTY support requires sandbox image version 0.7.0 or later.
#
# For local development with PTY support, first build the base image:
# cd ../.. # Go to monorepo root
# docker build --platform linux/amd64 -f packages/sandbox/Dockerfile --target default -t sandbox-pty-local .
#
# The wrangler dev server will then use this Dockerfile which extends sandbox-pty-local.
#
FROM sandbox-local

# Create home directory for terminal sessions
RUN mkdir -p /home/user && chmod 777 /home/user

# Expose container port
EXPOSE 3000
Loading
Loading