@buda-ai/connector 0.1.1 → 0.1.2
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/README.md +22 -1
- package/agent-templates/scripts/skill-scanner.sh +125 -0
- package/agent-templates/shared/AGENTS.md +220 -0
- package/agent-templates/shared/BOOTSTRAP.md +15 -0
- package/agent-templates/shared/HEARTBEAT.md +5 -0
- package/agent-templates/shared/IDENTITY.md +29 -0
- package/agent-templates/shared/MEMORY.md +19 -0
- package/agent-templates/shared/SOUL.md +43 -0
- package/agent-templates/shared/TOOLS.md +85 -0
- package/agent-templates/shared/USER.md +23 -0
- package/agent-templates/system-skills/app-builder/README.md +8 -0
- package/agent-templates/system-skills/app-builder/SKILL.md +678 -0
- package/agent-templates/system-skills/app-builder/buda.app.schema.json +165 -0
- package/agent-templates/system-skills/app-builder/evals/evals.json +23 -0
- package/agent-templates/system-skills/app-builder/scripts/check-preview-url.mjs +184 -0
- package/agent-templates/system-skills/buda-automations/SKILL.md +175 -0
- package/agent-templates/system-skills/buda-automations/scripts/create-automation.sh +226 -0
- package/agent-templates/system-skills/buda-automations/scripts/delete-automation.sh +73 -0
- package/agent-templates/system-skills/buda-automations/scripts/list-automations.sh +77 -0
- package/agent-templates/system-skills/buda-far/SKILL.md +221 -0
- package/agent-templates/system-skills/buda-far/far_gen.py +1499 -0
- package/agent-templates/system-skills/buda-machine-info/SKILL.md +67 -0
- package/agent-templates/system-skills/buda-machine-info/scripts/get-info.sh +25 -0
- package/agent-templates/system-skills/buda-machine-info/scripts/send-file.mjs +62 -0
- package/agent-templates/system-skills/buda-web-preview/SKILL.md +462 -0
- package/agent-templates/system-skills/find-skills/SKILL.md +142 -0
- package/agent-templates/system-skills/skill-creator/LICENSE.txt +202 -0
- package/agent-templates/system-skills/skill-creator/SKILL.md +479 -0
- package/agent-templates/system-skills/skill-creator/agents/analyzer.md +274 -0
- package/agent-templates/system-skills/skill-creator/agents/comparator.md +202 -0
- package/agent-templates/system-skills/skill-creator/agents/grader.md +223 -0
- package/agent-templates/system-skills/skill-creator/assets/eval_review.html +146 -0
- package/agent-templates/system-skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/agent-templates/system-skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/agent-templates/system-skills/skill-creator/references/schemas.md +430 -0
- package/agent-templates/system-skills/skill-creator/scripts/__init__.py +0 -0
- package/agent-templates/system-skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/agent-templates/system-skills/skill-creator/scripts/generate_report.py +326 -0
- package/agent-templates/system-skills/skill-creator/scripts/improve_description.py +248 -0
- package/agent-templates/system-skills/skill-creator/scripts/package_skill.py +136 -0
- package/agent-templates/system-skills/skill-creator/scripts/quick_validate.py +103 -0
- package/agent-templates/system-skills/skill-creator/scripts/run_eval.py +310 -0
- package/agent-templates/system-skills/skill-creator/scripts/run_loop.py +332 -0
- package/agent-templates/system-skills/skill-creator/scripts/utils.py +47 -0
- package/dist/cli.js +2747 -180
- package/package.json +10 -6
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: buda-machine-info
|
|
3
|
+
description: "Use this skill when the user asks about their Buda sandbox environment: CPU, memory, disk, OS, kernel, or installed software versions. Trigger on direct questions (\"how much RAM?\", \"what OS?\", \"check disk space\") and indirect ones (\"can this run Docker?\", \"am I out of memory?\", \"what tools are available?\"). Also use when troubleshooting resource constraints or deciding whether the sandbox can handle a workload, even without keywords like \"system info\" or \"specs\"."
|
|
4
|
+
compatibility: Requires /proc/meminfo, /etc/os-release, lscpu, df, and common CLI tools (node, git, python3). Auto-available in Buda sandboxes.
|
|
5
|
+
metadata:
|
|
6
|
+
author: buda
|
|
7
|
+
version: "1.0"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# System & Machine Information
|
|
11
|
+
|
|
12
|
+
Retrieve hardware specs, resource usage, and installed tool versions for the
|
|
13
|
+
current Buda sandbox environment.
|
|
14
|
+
|
|
15
|
+
## When to use this skill
|
|
16
|
+
|
|
17
|
+
- User asks about CPU, memory, disk, OS, or kernel details
|
|
18
|
+
- User wants to know available disk space or memory
|
|
19
|
+
- User asks what software versions are installed (Node, Python, Git, etc.)
|
|
20
|
+
- User says "system info", "my specs", "what machine is this", "show environment"
|
|
21
|
+
- User needs to troubleshoot resource constraints (out of memory, disk full)
|
|
22
|
+
- User is deciding whether the sandbox can handle a workload
|
|
23
|
+
|
|
24
|
+
## Step-by-step instructions
|
|
25
|
+
|
|
26
|
+
1. Run the info script:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bash scripts/get-info.sh
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
2. Parse the output and present it to the user in a clear, readable format.
|
|
33
|
+
3. If the user asked about a specific resource (e.g., "how much disk space"),
|
|
34
|
+
highlight the relevant section rather than dumping everything.
|
|
35
|
+
|
|
36
|
+
## Output sections
|
|
37
|
+
|
|
38
|
+
The script reports the following:
|
|
39
|
+
|
|
40
|
+
| Section | What it shows |
|
|
41
|
+
|------------------|----------------------------------------------------|
|
|
42
|
+
| Operating System | Distro name and version (from `/etc/os-release`) |
|
|
43
|
+
| Kernel | Linux kernel version (`uname -r`) |
|
|
44
|
+
| CPU | Model name and vCPU count |
|
|
45
|
+
| Memory | Total and available RAM in GB |
|
|
46
|
+
| Disk Usage | Mount point, total size, free space, usage percent |
|
|
47
|
+
| Versions | Node.js, Git, and Python versions |
|
|
48
|
+
|
|
49
|
+
## Baseline specs (Buda sandbox defaults)
|
|
50
|
+
|
|
51
|
+
For quick reference when the user asks without needing a live check:
|
|
52
|
+
|
|
53
|
+
- **OS:** Debian 12 (bookworm)
|
|
54
|
+
- **CPU:** Intel Xeon Platinum 8488C (8 vCPUs)
|
|
55
|
+
- **Memory:** 32 GB total
|
|
56
|
+
- **Disk:** /agent (200 GB)
|
|
57
|
+
|
|
58
|
+
Always prefer running the script for live data — these are just defaults that
|
|
59
|
+
may vary by sandbox tier.
|
|
60
|
+
|
|
61
|
+
## Tips
|
|
62
|
+
|
|
63
|
+
- If the user asks "can I run X here?", run the script first, then assess
|
|
64
|
+
whether the available resources are sufficient.
|
|
65
|
+
- When memory or disk is low, proactively suggest cleanup actions.
|
|
66
|
+
- For version checks, if a specific tool is missing from the output, note that
|
|
67
|
+
it may not be installed and suggest how to install it.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# system-info script
|
|
3
|
+
echo "=== System Report $(date) ==="
|
|
4
|
+
|
|
5
|
+
echo -e "\n[Operating System]"
|
|
6
|
+
cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2 | tr -d '"'
|
|
7
|
+
|
|
8
|
+
echo -e "\n[Kernel]"
|
|
9
|
+
uname -r
|
|
10
|
+
|
|
11
|
+
echo -e "\n[CPU]"
|
|
12
|
+
lscpu | grep "Model name" | sed 's/Model name: *//'
|
|
13
|
+
echo "CPU(s): $(lscpu | grep '^CPU(s):' | awk '{print $2}')"
|
|
14
|
+
|
|
15
|
+
echo -e "\n[Memory]"
|
|
16
|
+
echo "Total: $(grep MemTotal /proc/meminfo | awk '{print $2/1024/1024 " GB"}')"
|
|
17
|
+
echo "Available: $(grep MemAvailable /proc/meminfo | awk '{print $2/1024/1024 " GB"}')"
|
|
18
|
+
|
|
19
|
+
echo -e "\n[Disk Usage]"
|
|
20
|
+
df -h | grep -E '/$|/agent' | awk '{print $1, $6, $2, $4, $5, "used"}'
|
|
21
|
+
|
|
22
|
+
echo -e "\n[Versions]"
|
|
23
|
+
echo "Node: $(node -v)"
|
|
24
|
+
echo "Git: $(git --version)"
|
|
25
|
+
echo "Python: $(python3 --version)"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* send-file.mjs
|
|
4
|
+
*
|
|
5
|
+
* Resolves a file path relative to /agent and returns a [send:] marker
|
|
6
|
+
* if the file exists, or an empty string if it does not.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* node scripts/send-file.mjs <path>
|
|
10
|
+
*
|
|
11
|
+
* Path rules (mirrors the system prompt convention):
|
|
12
|
+
* - Relative path (no leading slash): resolved against /agent
|
|
13
|
+
* e.g. "uploads/photo.jpg" → /agent/uploads/photo.jpg
|
|
14
|
+
* - Absolute path starting with /agent: used as-is
|
|
15
|
+
* e.g. "/agent/chart.png" → /agent/chart.png
|
|
16
|
+
* - Any other absolute path: used as-is (escape hatch)
|
|
17
|
+
*
|
|
18
|
+
* Output:
|
|
19
|
+
* [send:uploads/photo.jpg] — file exists (path is relative to /agent)
|
|
20
|
+
* (empty string) — file does not exist
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { existsSync } from "node:fs";
|
|
24
|
+
import { isAbsolute, resolve } from "node:path";
|
|
25
|
+
|
|
26
|
+
const AGENT_ROOT = "/agent";
|
|
27
|
+
|
|
28
|
+
function resolveAgentPath(input) {
|
|
29
|
+
if (!input) return null;
|
|
30
|
+
|
|
31
|
+
// Strip a leading /agent prefix so the returned marker stays relative
|
|
32
|
+
if (input.startsWith("/agent/")) {
|
|
33
|
+
return { abs: input, rel: input.slice("/agent/".length) };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Other absolute paths — use as-is, keep the full path in the marker
|
|
37
|
+
if (isAbsolute(input)) {
|
|
38
|
+
return { abs: input, rel: input };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Relative path — resolve against /agent
|
|
42
|
+
const abs = resolve(AGENT_ROOT, input);
|
|
43
|
+
return { abs, rel: input };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const input = process.argv[2];
|
|
47
|
+
|
|
48
|
+
if (!input) {
|
|
49
|
+
// No argument — print nothing (empty result)
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const resolved = resolveAgentPath(input);
|
|
54
|
+
|
|
55
|
+
if (!resolved || !existsSync(resolved.abs)) {
|
|
56
|
+
// File does not exist — return empty string
|
|
57
|
+
process.stdout.write("");
|
|
58
|
+
process.exit(0);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// File exists — emit the [send:] marker
|
|
62
|
+
process.stdout.write(`[send:${resolved.rel}]`);
|
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: buda-web-preview
|
|
3
|
+
description: "Use this skill when the user wants to create, view, run, or preview any web page, HTML file, game, landing page, demo, prototype, or frontend project."
|
|
4
|
+
triggers:
|
|
5
|
+
- "make a cat game"
|
|
6
|
+
- "create a landing page"
|
|
7
|
+
- "build a todo app"
|
|
8
|
+
- "Check HTML"
|
|
9
|
+
- "See HTML"
|
|
10
|
+
- "Preview HTML file"
|
|
11
|
+
- "show me a preview"
|
|
12
|
+
- "start a dev server"
|
|
13
|
+
- "run it in the background"
|
|
14
|
+
- "give me the link"
|
|
15
|
+
- "start a web server"
|
|
16
|
+
- "start http server"
|
|
17
|
+
- "serve the files"
|
|
18
|
+
- "run bun dev"
|
|
19
|
+
- "use browser"
|
|
20
|
+
- "use local browser"
|
|
21
|
+
- "open page"
|
|
22
|
+
- "做个小游戏"
|
|
23
|
+
- "做个网页"
|
|
24
|
+
- "帮我写个HTML"
|
|
25
|
+
- "打开HTML"
|
|
26
|
+
- "查看HTML"
|
|
27
|
+
- "搭个演示页面"
|
|
28
|
+
- "搭个网页应用"
|
|
29
|
+
- "使用浏览器"
|
|
30
|
+
- "本地浏览器"
|
|
31
|
+
- "打开浏览器"
|
|
32
|
+
- "启用Web服务"
|
|
33
|
+
metadata:
|
|
34
|
+
author: buda
|
|
35
|
+
version: "1.3"
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
# Web Preview Skill
|
|
39
|
+
|
|
40
|
+
Launch a live browser preview for any web page, game, or frontend project you create.
|
|
41
|
+
|
|
42
|
+
Launch a live browser preview for any web page, HTML, when user want to use browser to check something.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## When to use this skill
|
|
46
|
+
|
|
47
|
+
Activate whenever the user wants to **see** something in a browser, not just read code:
|
|
48
|
+
|
|
49
|
+
- "Make me a cat game" / "做个小猫游戏"
|
|
50
|
+
- "Create a landing page" / "做个首页"
|
|
51
|
+
- "Build a todo app" / "做个待办事项"
|
|
52
|
+
- "Build a todo app" / "做个网页"
|
|
53
|
+
- "Write me an HTML page" / "帮我写个HTML"
|
|
54
|
+
- "Show me the HTML page" / "帮我查看HTML"
|
|
55
|
+
- "Open Browser to open page" / " 使用浏览器去打开文件"
|
|
56
|
+
- "open HTML file" / "打开HTML 文件"
|
|
57
|
+
- "I want to see a demo" / "给我演示一下"
|
|
58
|
+
- Any request for a game, animation, interactive component, or visual prototype
|
|
59
|
+
|
|
60
|
+
## Core rule: Write files, don't paste code in chat
|
|
61
|
+
|
|
62
|
+
**NEVER** return the full HTML/CSS/JS as a chat message. Always write it to real files.
|
|
63
|
+
|
|
64
|
+
Users want to **see** it running — not read a code block.
|
|
65
|
+
|
|
66
|
+
## Non-negotiable runtime rules
|
|
67
|
+
|
|
68
|
+
1. **Always run dev servers in background**. Never run foreground commands that block the session.
|
|
69
|
+
2. **Never assume a port** for framework dev servers. Parse the actual runtime output to detect it.
|
|
70
|
+
3. **Call `get_preview_url`** After the server is reachable, call the `get_preview_url` tool with the detected port (and optional `path`). Buda opens the signed external preview in Local Browser. You may still print `http://localhost:PORT` in chat as a fallback.
|
|
71
|
+
4. **Verify service health before announcing link**. Only print port + preview URL after a successful reachability check.
|
|
72
|
+
5. **Always bind to `0.0.0.0`**, not `localhost` or `127.0.0.1`. This is required so the sandbox exposes the port to the external network, allowing users to open it in Local Browser. A server bound only to `127.0.0.1` is not reachable from outside the sandbox.
|
|
73
|
+
5. **Restart means stop then start**. Kill previous process first, then launch a new one.
|
|
74
|
+
6. **Use timeout-based polling**. Avoid infinite waits; fail fast with logs if startup is not ready.
|
|
75
|
+
7. **Use a port between 3000 and 3999**. Always pick the preview port within the `3000`–`3999` range. If the chosen port is occupied, fall back to another free port in the same range.
|
|
76
|
+
8. **Never hardcode working directory**. Derive paths relative to the project directory. Do not assume `/agent/` unless that is the actual project root.
|
|
77
|
+
9. **Support multiple simultaneous dev servers**. PID/log files must be scoped per project (use a hash or sanitized project path), not a single global `/tmp/buda-preview.*`.
|
|
78
|
+
10. **Read `buda.app.json` first**. If a `buda.app.json` exists in the project directory, read it to get the dev command, port, and other settings before falling back to defaults.
|
|
79
|
+
|
|
80
|
+
## AI Browser vs Local Browser
|
|
81
|
+
|
|
82
|
+
- Use this skill and `get_preview_url` when the user wants to preview a local dev server or generated app. Buda opens that preview in **Local Browser**.
|
|
83
|
+
- Do not use AI Browser for sandbox localhost previews unless the user explicitly wants the AI-controlled CDP browser to visit the signed external preview URL.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Step-by-step
|
|
88
|
+
|
|
89
|
+
### 0. Check for `buda.app.json` (always do this first)
|
|
90
|
+
|
|
91
|
+
Before starting any server, check if a `buda.app.json` exists in the project directory:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
PROJECT_DIR="<absolute-path-to-project>"
|
|
95
|
+
|
|
96
|
+
if [ -f "$PROJECT_DIR/buda.app.json" ]; then
|
|
97
|
+
echo "Found buda.app.json, reading config..."
|
|
98
|
+
cat "$PROJECT_DIR/buda.app.json"
|
|
99
|
+
fi
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Schema: `/system/.agents/skills/app-builder/buda.app.schema.json`
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
Key fields to read for preview:
|
|
106
|
+
|
|
107
|
+
| Field | Description |
|
|
108
|
+
|---|---|
|
|
109
|
+
| `framework` | `"static"` \| `"vite"` \| `"next"` — determines server strategy |
|
|
110
|
+
| `port` | Dev server port (required for non-static) |
|
|
111
|
+
| `scripts.install` | Dependency install command (e.g. `bun install`) |
|
|
112
|
+
| `scripts.dev` | Dev server start command |
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
Example — Vite app:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"name": "my_app",
|
|
120
|
+
"version": "1.0.0",
|
|
121
|
+
"type": "web",
|
|
122
|
+
"description": "A Vite + React application",
|
|
123
|
+
"framework": "vite",
|
|
124
|
+
"port": 5173,
|
|
125
|
+
"scripts": {
|
|
126
|
+
"install": "bun install",
|
|
127
|
+
"dev": "./node_modules/.bin/vite --host 0.0.0.0",
|
|
128
|
+
"build": "./node_modules/.bin/tsc -b && ./node_modules/.bin/vite build",
|
|
129
|
+
"start": "./node_modules/.bin/vite preview --host 0.0.0.0"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
How to use it:
|
|
135
|
+
|
|
136
|
+
- `framework: "static"` → serve the project directory with `npx serve`, no install step needed.
|
|
137
|
+
- Otherwise → run `scripts.install` first, then `scripts.dev` as the start command.
|
|
138
|
+
- Use `port` as the expected port (still verify reachability with curl).
|
|
139
|
+
- If `buda.app.json` is absent, fall back to the standard detection logic below.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
### Per-project runtime state files
|
|
144
|
+
|
|
145
|
+
To support multiple dev servers running simultaneously, scope PID/log/URL files to the project. Use a short hash of the project path:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
PROJECT_DIR="<absolute-path-to-project>"
|
|
149
|
+
PROJECT_HASH="$(echo "$PROJECT_DIR" | md5sum | cut -c1-8)"
|
|
150
|
+
|
|
151
|
+
PID_FILE="/tmp/buda-preview-${PROJECT_HASH}.pid"
|
|
152
|
+
LOG_FILE="/tmp/buda-preview-${PROJECT_HASH}.log"
|
|
153
|
+
URL_FILE="/tmp/buda-preview-${PROJECT_HASH}.url"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Never use a shared global `/tmp/buda-preview.pid` — doing so would cause one project's server to clobber another's.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### Stop existing preview process for a project (required before restart)
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
PROJECT_DIR="<absolute-path-to-project>"
|
|
164
|
+
PROJECT_HASH="$(echo "$PROJECT_DIR" | md5sum | cut -c1-8)"
|
|
165
|
+
PID_FILE="/tmp/buda-preview-${PROJECT_HASH}.pid"
|
|
166
|
+
URL_FILE="/tmp/buda-preview-${PROJECT_HASH}.url"
|
|
167
|
+
|
|
168
|
+
if [ -f "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
|
|
169
|
+
kill "$(cat "$PID_FILE")" 2>/dev/null || true
|
|
170
|
+
sleep 1
|
|
171
|
+
kill -9 "$(cat "$PID_FILE")" 2>/dev/null || true
|
|
172
|
+
fi
|
|
173
|
+
rm -f "$PID_FILE"
|
|
174
|
+
|
|
175
|
+
# Optional: kill by previous detected port if still occupied
|
|
176
|
+
if [ -f "$URL_FILE" ]; then
|
|
177
|
+
PORT="$(sed -E 's#.*:([0-9]+).*#\1#' "$URL_FILE")"
|
|
178
|
+
if [ -n "$PORT" ]; then
|
|
179
|
+
ss -ltnp "sport = :$PORT" 2>/dev/null \
|
|
180
|
+
| sed -nE 's/.*pid=([0-9]+).*/\1/p' \
|
|
181
|
+
| xargs -r kill 2>/dev/null || true
|
|
182
|
+
fi
|
|
183
|
+
fi
|
|
184
|
+
rm -f "$URL_FILE"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Run this stop block whenever:
|
|
188
|
+
- user says "restart"
|
|
189
|
+
- you need to re-run a server command
|
|
190
|
+
- you suspect a stale preview process is still alive
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
### For static HTML pages (no framework needed)
|
|
195
|
+
|
|
196
|
+
Use this when the user asks for a simple page, game, animation, or visual demo.
|
|
197
|
+
|
|
198
|
+
**1. Write files**
|
|
199
|
+
|
|
200
|
+
Write to the actual project directory. Do **not** hardcode `/agent/preview/`. Use the real path where the project lives:
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
<PROJECT_DIR>/index.html ← always required
|
|
204
|
+
<PROJECT_DIR>/style.css ← when styling is needed
|
|
205
|
+
<PROJECT_DIR>/script.js ← when JS logic is needed
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**2. Resolve start command and port**
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
PROJECT_DIR="<absolute-path-to-project>"
|
|
212
|
+
PROJECT_HASH="$(echo "$PROJECT_DIR" | md5sum | cut -c1-8)"
|
|
213
|
+
PID_FILE="/tmp/buda-preview-${PROJECT_HASH}.pid"
|
|
214
|
+
LOG_FILE="/tmp/buda-preview-${PROJECT_HASH}.log"
|
|
215
|
+
URL_FILE="/tmp/buda-preview-${PROJECT_HASH}.url"
|
|
216
|
+
PORT=3000
|
|
217
|
+
|
|
218
|
+
# Read buda.app.json if present
|
|
219
|
+
if [ -f "$PROJECT_DIR/buda.app.json" ]; then
|
|
220
|
+
CFG_PORT="$(node -e "try{const c=require('$PROJECT_DIR/buda.app.json');process.stdout.write(String(c.port||''))}catch(e){}" 2>/dev/null)"
|
|
221
|
+
[ -n "$CFG_PORT" ] && PORT="$CFG_PORT"
|
|
222
|
+
fi
|
|
223
|
+
|
|
224
|
+
# Find a free port in 3000-3999 if chosen port is occupied
|
|
225
|
+
while ss -ltn "sport = :$PORT" 2>/dev/null | grep -q ":$PORT"; do
|
|
226
|
+
PORT=$((PORT + 1))
|
|
227
|
+
[ "$PORT" -gt 3999 ] && PORT=3000
|
|
228
|
+
done
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**3. Start the preview server**
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
# Always stop old process first (restart-safe)
|
|
235
|
+
if [ -f "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
|
|
236
|
+
kill "$(cat "$PID_FILE")" 2>/dev/null || true
|
|
237
|
+
sleep 1
|
|
238
|
+
kill -9 "$(cat "$PID_FILE")" 2>/dev/null || true
|
|
239
|
+
fi
|
|
240
|
+
ss -ltnp "sport = :$PORT" 2>/dev/null \
|
|
241
|
+
| sed -nE 's/.*pid=([0-9]+).*/\1/p' \
|
|
242
|
+
| xargs -r kill 2>/dev/null || true
|
|
243
|
+
|
|
244
|
+
# Bind to 0.0.0.0 so the port is reachable from outside the sandbox
|
|
245
|
+
nohup npx serve "$PROJECT_DIR" -l "0.0.0.0:$PORT" > "$LOG_FILE" 2>&1 &
|
|
246
|
+
echo $! > "$PID_FILE"
|
|
247
|
+
|
|
248
|
+
# Wait until reachable
|
|
249
|
+
READY=0
|
|
250
|
+
for _ in $(seq 1 30); do
|
|
251
|
+
if ! kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
|
|
252
|
+
echo "Preview process exited before becoming ready. Last log lines:"
|
|
253
|
+
tail -n 40 "$LOG_FILE" 2>/dev/null || true
|
|
254
|
+
break
|
|
255
|
+
fi
|
|
256
|
+
if curl -fsS --connect-timeout 2 --max-time 10 \
|
|
257
|
+
-o /dev/null "http://127.0.0.1:$PORT/"; then
|
|
258
|
+
URL="http://localhost:$PORT/"
|
|
259
|
+
echo "$URL" > "$URL_FILE"
|
|
260
|
+
echo "Preview ready on port $PORT"
|
|
261
|
+
echo "$URL"
|
|
262
|
+
READY=1
|
|
263
|
+
break
|
|
264
|
+
fi
|
|
265
|
+
sleep 1
|
|
266
|
+
done
|
|
267
|
+
if [ "$READY" != 1 ]; then
|
|
268
|
+
echo "Preview did not become reachable within 30s (port $PORT). Check $LOG_FILE"
|
|
269
|
+
tail -n 40 "$LOG_FILE" 2>/dev/null || true
|
|
270
|
+
fi
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**4. Open preview**
|
|
274
|
+
|
|
275
|
+
Call `get_preview_url` with the detected port, for example:
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
{ "port": 3000, "path": "/" }
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**5. Reply**
|
|
282
|
+
|
|
283
|
+
After writing files, starting the server, and calling `get_preview_url`, reply briefly:
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
✅ Preview launched!
|
|
287
|
+
|
|
288
|
+
Buda opened the preview in Local Browser.
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Then, ask the user if they'd like to deploy the web app — this feature is available on any purchased plan.
|
|
292
|
+
|
|
293
|
+
Do **not** paste the full source code unless the user asks.
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
### For Node.js / framework projects (React, Vite, Next.js, Express...)
|
|
298
|
+
|
|
299
|
+
Use this when the user asks for a React app, Express server, or any project with a `package.json`.
|
|
300
|
+
|
|
301
|
+
**1. Scaffold the project**
|
|
302
|
+
|
|
303
|
+
Create files under the actual project directory. Do **not** hardcode a working directory.
|
|
304
|
+
|
|
305
|
+
**2. Resolve start command**
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
PROJECT_DIR="<absolute-path-to-project>"
|
|
309
|
+
|
|
310
|
+
# Priority 1: buda.app.json
|
|
311
|
+
DEV_CMD=""
|
|
312
|
+
INSTALL_CMD=""
|
|
313
|
+
if [ -f "$PROJECT_DIR/buda.app.json" ]; then
|
|
314
|
+
DEV_CMD="$(node -e "try{const c=require('$PROJECT_DIR/buda.app.json');process.stdout.write((c.scripts&&c.scripts.dev)||'')}catch(e){}" 2>/dev/null)"
|
|
315
|
+
INSTALL_CMD="$(node -e "try{const c=require('$PROJECT_DIR/buda.app.json');process.stdout.write((c.scripts&&c.scripts.install)||'')}catch(e){}" 2>/dev/null)"
|
|
316
|
+
fi
|
|
317
|
+
|
|
318
|
+
# Priority 2: package.json scripts.dev
|
|
319
|
+
if [ -z "$DEV_CMD" ] && [ -f "$PROJECT_DIR/package.json" ]; then
|
|
320
|
+
HAS_DEV="$(node -e "try{const p=require('$PROJECT_DIR/package.json');process.stdout.write(p.scripts&&p.scripts.dev?'yes':'')}catch(e){}" 2>/dev/null)"
|
|
321
|
+
[ "$HAS_DEV" = "yes" ] && DEV_CMD="bun run dev"
|
|
322
|
+
fi
|
|
323
|
+
|
|
324
|
+
# Priority 3: fallback
|
|
325
|
+
[ -z "$DEV_CMD" ] && DEV_CMD="bun run dev"
|
|
326
|
+
[ -z "$INSTALL_CMD" ] && INSTALL_CMD="bun install"
|
|
327
|
+
|
|
328
|
+
echo "Install: $INSTALL_CMD"
|
|
329
|
+
echo "Dev: $DEV_CMD"
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**3. Install and start**
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
PROJECT_HASH="$(echo "$PROJECT_DIR" | md5sum | cut -c1-8)"
|
|
336
|
+
PID_FILE="/tmp/buda-preview-${PROJECT_HASH}.pid"
|
|
337
|
+
LOG_FILE="/tmp/buda-preview-${PROJECT_HASH}.log"
|
|
338
|
+
URL_FILE="/tmp/buda-preview-${PROJECT_HASH}.url"
|
|
339
|
+
|
|
340
|
+
cd "$PROJECT_DIR"
|
|
341
|
+
$INSTALL_CMD
|
|
342
|
+
|
|
343
|
+
# Always stop old process first (restart-safe)
|
|
344
|
+
if [ -f "$PID_FILE" ] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
|
|
345
|
+
kill "$(cat "$PID_FILE")" 2>/dev/null || true
|
|
346
|
+
sleep 1
|
|
347
|
+
kill -9 "$(cat "$PID_FILE")" 2>/dev/null || true
|
|
348
|
+
fi
|
|
349
|
+
rm -f "$URL_FILE"
|
|
350
|
+
|
|
351
|
+
nohup $DEV_CMD > "$LOG_FILE" 2>&1 &
|
|
352
|
+
echo $! > "$PID_FILE"
|
|
353
|
+
|
|
354
|
+
# Detect runtime URL from logs, then verify before announce
|
|
355
|
+
URL=""
|
|
356
|
+
for i in $(seq 1 60); do
|
|
357
|
+
URL="$(
|
|
358
|
+
sed -nE 's#.*(https?://(localhost|127\.0\.0\.1|0\.0\.0\.0):[0-9]+/?).*#\1#p' "$LOG_FILE" | tail -n 1
|
|
359
|
+
)"
|
|
360
|
+
if [ -n "$URL" ]; then
|
|
361
|
+
PORT="$(echo "$URL" | sed -E 's#.*:([0-9]+).*#\1#')"
|
|
362
|
+
if curl -fsS --connect-timeout 2 --max-time 10 -o /dev/null "http://127.0.0.1:$PORT/" \
|
|
363
|
+
|| curl -fsS --connect-timeout 2 --max-time 10 -o /dev/null "$URL"; then
|
|
364
|
+
CANONICAL_URL="http://localhost:$PORT/"
|
|
365
|
+
echo "$CANONICAL_URL" > "$URL_FILE"
|
|
366
|
+
echo "Preview ready on port $PORT"
|
|
367
|
+
echo "$CANONICAL_URL"
|
|
368
|
+
break
|
|
369
|
+
fi
|
|
370
|
+
fi
|
|
371
|
+
sleep 1
|
|
372
|
+
done
|
|
373
|
+
|
|
374
|
+
# If no URL detected/verified, report failure with logs
|
|
375
|
+
if [ -z "$URL" ]; then
|
|
376
|
+
echo "Dev server did not become ready in time. Check $LOG_FILE"
|
|
377
|
+
tail -n 40 "$LOG_FILE" 2>/dev/null || true
|
|
378
|
+
fi
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Important:
|
|
382
|
+
- Do not output a preview link until a port is detected and reachable.
|
|
383
|
+
- Reply with the preview link as plain text only; do not wrap it in `<code>`, or any other element, so buda can intercept it and open the preview.
|
|
384
|
+
- If startup fails, share concise error + log file path.
|
|
385
|
+
- For Vite, `--strictPort` may be used when you need a fixed port; otherwise parse the actual port from logs.
|
|
386
|
+
- Never use `python3 http.server` as a web server.
|
|
387
|
+
|
|
388
|
+
**4. Keep reply short** — same as static case.
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## Common output patterns the system detects
|
|
393
|
+
|
|
394
|
+
After the dev server starts (or restarts) successfully, check whether `scripts.dev` in `buda.app.json` matches the actual command used. If it differs, update it — if the file exists.
|
|
395
|
+
|
|
396
|
+
After **every** dev/static server start, always print preview metadata in bash output.
|
|
397
|
+
When the service restarts (manual restart, crash + restart, port switch), print it again.
|
|
398
|
+
|
|
399
|
+
Required output on each (re)start:
|
|
400
|
+
- `Preview time: 2026-04-14 10:32:11` (local time is fine)
|
|
401
|
+
- `http://localhost:3000` ← preferred plain link line for click/open
|
|
402
|
+
|
|
403
|
+
Compatible patterns the system can also detect:
|
|
404
|
+
- `http://localhost:3000`
|
|
405
|
+
- `Local: http://localhost:3000` (Vite/Next.js)
|
|
406
|
+
- `App listening on port 3000` (Express)
|
|
407
|
+
- `Serving HTTP on 0.0.0.0 port 3000`
|
|
408
|
+
|
|
409
|
+
Always make sure preview link output appears in bash logs for every (re)start, so users can click immediately.
|
|
410
|
+
|
|
411
|
+
If logs don't print a URL, use a fallback probe (bounded by timeout):
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
for p in 3000 3001 4173 5173 8000 8080; do
|
|
415
|
+
if curl -fsS --connect-timeout 2 --max-time 10 -o /dev/null "http://127.0.0.1:$p/"; then
|
|
416
|
+
echo "Preview ready on port $p"
|
|
417
|
+
echo "http://localhost:$p/"
|
|
418
|
+
break
|
|
419
|
+
fi
|
|
420
|
+
done
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
## Choosing between static vs Node
|
|
424
|
+
|
|
425
|
+
| Situation | Use |
|
|
426
|
+
| ---------------------------------------------- | ------------------------------ |
|
|
427
|
+
| Simple page, game, animation, landing page | Static (npx serve) |
|
|
428
|
+
| User explicitly asks for React / Vue / Next.js | Node (bun run dev) |
|
|
429
|
+
| User asks for a backend / API | Node (Vite / Express / FastAPI)|
|
|
430
|
+
| Prototype with vanilla JS | Static (npx serve) |
|
|
431
|
+
| When in doubt | Ask user |
|
|
432
|
+
|
|
433
|
+
## Updating the preview
|
|
434
|
+
|
|
435
|
+
If the user wants changes:
|
|
436
|
+
- Edit the file(s) directly
|
|
437
|
+
- No need to restart the server for static HTML (just refresh the page)
|
|
438
|
+
- For Node projects, hot reload usually handles it automatically
|
|
439
|
+
|
|
440
|
+
If the user explicitly asks to restart:
|
|
441
|
+
- Execute stop block first (kill old process and free old port)
|
|
442
|
+
- Run startup flow again
|
|
443
|
+
- Re-detect and re-verify port before replying with link
|
|
444
|
+
|
|
445
|
+
## Tips
|
|
446
|
+
|
|
447
|
+
- For games: use canvas or simple DOM — no framework needed
|
|
448
|
+
- For landing pages: keep it self-contained in one HTML file when possible
|
|
449
|
+
- Don't run `python3 http.server` as a web server
|
|
450
|
+
- For complex projects: use Vite (`bun create vite`) for fast setup, always set `host: '0.0.0.0'` and `allowedHosts: true`
|
|
451
|
+
- **Every server must bind to `0.0.0.0`** — this is what makes the sandbox port reachable externally so the user can open it in Local Browser
|
|
452
|
+
|
|
453
|
+
```js
|
|
454
|
+
// https://vite.dev/config/
|
|
455
|
+
export default defineConfig({
|
|
456
|
+
plugins: [react()],
|
|
457
|
+
server: {
|
|
458
|
+
host: '0.0.0.0', // required — bind to all interfaces, not just localhost
|
|
459
|
+
allowedHosts: true // required — allow sandbox external hostname
|
|
460
|
+
}
|
|
461
|
+
})
|
|
462
|
+
```
|