Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
251 commits
Select commit Hold shift + click to select a range
8934c67
feat(tools): add GITHUB_LIST_INSTALLATIONS app-only tool
tlgimenes Apr 9, 2026
082323e
feat(tools): add GITHUB_LIST_REPOS app-only tool
tlgimenes Apr 9, 2026
f8236ad
feat(tools): register GitHub tools in tool registry
tlgimenes Apr 9, 2026
e1c017a
feat(ui): add GitHubRepoDialog for repo selection flow
tlgimenes Apr 9, 2026
380700a
feat(ui): add GitHubRepoButton component
tlgimenes Apr 9, 2026
df98452
feat(ui): add GitHub button to shell header
tlgimenes Apr 9, 2026
23393ad
fix(ui): use KEYS constants for query keys, fix TS error in dialog
tlgimenes Apr 9, 2026
1712a31
fix(github): address code review findings
tlgimenes Apr 9, 2026
c5eb90c
refactor(github): switch to device flow, remove Better Auth dependency
tlgimenes Apr 9, 2026
6fc9f79
fix(github): use correct Deco CMS GitHub App client ID, remove debug …
tlgimenes Apr 9, 2026
e23cfa7
feat(ui): start device flow immediately on button click, skip interme…
tlgimenes Apr 9, 2026
bc83658
feat(ui): auto-copy device code to clipboard, add copy button
tlgimenes Apr 9, 2026
daa60c0
feat(github): auto-sync instructions and detect runtime on repo connect
tlgimenes Apr 10, 2026
2b2c82a
feat(vm): add Freestyle VM preview with terminal and dev server iframe
tlgimenes Apr 10, 2026
9ce40c1
fix(vm): remove web terminal integration, fix error handling and stat…
tlgimenes Apr 10, 2026
3bcf527
fix(vm): add w-full to preview component for proper centering
tlgimenes Apr 10, 2026
a9d9e28
fix(vm): deduplicate VMs by (virtualMcpId, userId) pair
tlgimenes Apr 10, 2026
a9e684d
feat(vm): add Deno support, configurable port, detect port from scripts
tlgimenes Apr 10, 2026
44394dc
fix(vm): add open-in-new-tab button, fix domain fallback, guard empty…
tlgimenes Apr 10, 2026
60a2007
fix(vm): use style.dev domains instead of ports config
tlgimenes Apr 10, 2026
3efa6e4
fix(vm): add socat port proxy for localhost-bound dev servers
tlgimenes Apr 10, 2026
017b8ba
fix(vm): use deco.studio domain for VM preview URLs
tlgimenes Apr 10, 2026
59832ea
fix(vm): fix systemd exec quoting — split bash -c into separate args
tlgimenes Apr 10, 2026
f99c904
fix(vm): use wrapper shell scripts instead of inline bash -c commands
tlgimenes Apr 10, 2026
c24c56c
fix(vm): install deno/bun via curl instead of Freestyle integrations
tlgimenes Apr 10, 2026
a152877
fix(vm): install runtimes to /usr/local and remove socat proxy
tlgimenes Apr 10, 2026
04cdb68
fix(vm): add iframe proxy to strip X-Frame-Options headers
tlgimenes Apr 10, 2026
e49c12b
feat(preview): add visual editor mode with element selection and AI p…
tlgimenes Apr 10, 2026
cb01259
fix(preview): purple highlight color + open chat on visual editor send
tlgimenes Apr 10, 2026
bdadec3
feat(vm): add shared VmEntry/VmMetadata types and patchActiveVms helper
tlgimenes Apr 10, 2026
b898a92
refactor(vm): use named VirtualMCPUpdateData type in patchActiveVms cast
tlgimenes Apr 10, 2026
8daf3ed
feat(vm): read/write active VM entries from Virtual MCP metadata in s…
tlgimenes Apr 10, 2026
2475cff
test(vm): add VM_START unit tests for cached-VM and new-VM paths
tlgimenes Apr 10, 2026
b608d14
feat(vm): derive vmId from metadata in VM_STOP, fix deletion order
tlgimenes Apr 10, 2026
4933e2c
test(vm): add VM_STOP unit tests
tlgimenes Apr 10, 2026
faa9cd9
chore(vm): delete in-memory registry (replaced by DB-backed metadata)
tlgimenes Apr 10, 2026
e887322
feat(vm): update VM_STOP call to pass only virtualMcpId
tlgimenes Apr 10, 2026
a41a241
fix(vm): cast mock.calls to fix Bun type definition limitation in tests
tlgimenes Apr 10, 2026
40c2e9f
feat(vm): add web terminal to VM creation via VmWebTerminal
tlgimenes Apr 10, 2026
e520701
feat(preview): split view with resizable terminal panel
tlgimenes Apr 10, 2026
2039da1
fix(vm): use pre-installed ttyd instead of VmWebTerminal to avoid ins…
tlgimenes Apr 10, 2026
de5ca1f
fix(vm): manually install ttyd with retries instead of relying on VmW…
tlgimenes Apr 10, 2026
10fcef5
fix(vm): use base image ttyd on port 7681 instead of installing manually
tlgimenes Apr 10, 2026
9bb91b8
style(preview): vscode-style thin separator between preview and termi…
tlgimenes Apr 10, 2026
256a118
fix(vm): install ttyd to /opt/ instead of /usr/local/bin/ to avoid re…
tlgimenes Apr 10, 2026
e47f23c
fix(vm): install ttyd to /tmp/ to avoid overlay fs write restrictions
tlgimenes Apr 10, 2026
417845f
fix(vm): make terminal read-only and show dev-server logs instead of …
tlgimenes Apr 10, 2026
1ae8011
fix(preview): detect stale VM (503) and reset to idle state instead o…
tlgimenes Apr 10, 2026
196bcf8
fix(vm): server-side liveness probe clears stale VMs returning 503
tlgimenes Apr 10, 2026
4c758fb
fix(preview): force-reload iframe when dev server becomes ready to cl…
tlgimenes Apr 10, 2026
5df03f7
docs: add VM preview UX redesign spec
tlgimenes Apr 10, 2026
1a3fcde
docs: add suspended VM handling to UX redesign spec
tlgimenes Apr 10, 2026
f7ccfa0
docs: update VM preview UX spec with critique feedback — fix blockers…
tlgimenes Apr 10, 2026
50981f4
docs: restore suspended state + smart preview detection with concrete…
tlgimenes Apr 10, 2026
c9e9c33
docs: add VM_PROBE tool — frontend owns state, backend is proxy only
tlgimenes Apr 10, 2026
e89c0cb
docs: add VM preview UX redesign implementation plan
tlgimenes Apr 10, 2026
6447d58
feat(vm): add shared requireVmEntry and resolveRuntimeConfig helpers
tlgimenes Apr 10, 2026
bcb02ec
feat(vm): add VM_PROBE tool for backend-proxied HEAD requests
tlgimenes Apr 10, 2026
c661f48
feat(vm): add VM_EXEC tool for running install/dev commands in a Free…
tlgimenes Apr 10, 2026
85c4d63
refactor(vm): strip VM_START to infrastructure-only systemd, add isNe…
tlgimenes Apr 10, 2026
125f4b5
refactor(vm): use requireVmEntry helper in VM_STOP
tlgimenes Apr 10, 2026
3c51622
feat(preview): new state machine with terminal-first flow, preview de…
tlgimenes Apr 10, 2026
7244a6f
feat(preview): add terminal dropdown with reinstall/restart actions
tlgimenes Apr 10, 2026
2b47bcd
feat(preview): show vmId as tooltip on stop button for debugging
tlgimenes Apr 10, 2026
8bcbdfb
style(preview): remove Terminal label from dropdown, keep icon only
tlgimenes Apr 10, 2026
639406b
style(preview): use shadcn Tooltip for vmId on stop button
tlgimenes Apr 10, 2026
ef0ccf1
fix(preview): add shadcn Tooltip to running-state stop button too
tlgimenes Apr 10, 2026
47c6961
style(preview): tooltip text 'Stop VM {vmId}' for clarity
tlgimenes Apr 10, 2026
7afb11a
refactor(preview): single stable React tree — iframes stay mounted, C…
tlgimenes Apr 10, 2026
948f8d4
style(preview): show vmId as badge in address bar, remove tooltip fro…
tlgimenes Apr 10, 2026
d1f7aa3
style(preview): add 'Stop VM' tooltip back on stop button
tlgimenes Apr 10, 2026
c2dabe8
fix(preview): context-aware status labels — Installing/Resuming/Resta…
tlgimenes Apr 10, 2026
2c3b26f
fix(preview): use 'Connecting...' label for creating state — works fo…
tlgimenes Apr 10, 2026
6ad3454
fix(vm): use freestyle vm.start() to resume VMs, vm.stop() for gracef…
tlgimenes Apr 10, 2026
da07d3f
fix(vm): improve reinstall UX — inline errors, remove installing stat…
tlgimenes Apr 10, 2026
f41d7db
refactor(vm): async VM_EXEC, replace ttyd with Node.js log viewer
tlgimenes Apr 10, 2026
77b95bc
fix(vm): deploy log viewer on resumed VMs via ensureLogViewer
tlgimenes Apr 10, 2026
807bf7d
fix(vm): use base64 encoding for ensureLogViewer, deduplicate log vie…
tlgimenes Apr 10, 2026
57c1ac5
fix(vm): fix \n literal in log separators, use echo for newlines
tlgimenes Apr 10, 2026
9d2a750
refactor(vm): use Freestyle runtime integrations, fix systemd exec an…
tlgimenes Apr 10, 2026
da2401e
refactor(vm): replace custom log viewer with @freestyle-sh/with-web-t…
tlgimenes Apr 10, 2026
78db6f9
refactor(vm): flatten plugins, move constants to module scope, use Sy…
tlgimenes Apr 10, 2026
f136b17
fix(vm): use md5(virtualMcpId:userId) for VM domain generation
tlgimenes Apr 10, 2026
91f80f8
fix(vm): use VmSpec.with() for runtime/terminal integrations
tlgimenes Apr 10, 2026
0b06d57
fix(vm): always include VmNodeJs in spec; fix terminal iframe height
tlgimenes Apr 11, 2026
5094562
fix(vm): prepend runtime bin path for deno/bun exec commands
tlgimenes Apr 11, 2026
3845fa9
fix(vm): clear storage entry before freestyle delete; skip await on v…
tlgimenes Apr 11, 2026
4e233fe
fix(vm): log vm.delete() errors instead of swallowing them
tlgimenes Apr 11, 2026
96dfdce
refactor(vm): use VmSpec fluent API for repo, files, and systemd config
tlgimenes Apr 11, 2026
d3d22e7
fix(vm): restart dev server on VM resume instead of assuming it's hea…
tlgimenes Apr 11, 2026
50dd389
fix(vm): fix iframe-proxy startup and exec timeouts
tlgimenes Apr 11, 2026
3c15017
fix(vm): fix iframe-proxy systemd service and VM deletion
tlgimenes Apr 11, 2026
a4e0d6b
fix(vm): source NVM from /etc/profile.d/nvm.sh in iframe-proxy wrapper
tlgimenes Apr 11, 2026
b10e8a0
fix(preview): reuse current thread in visual editor prompt and gate v…
tlgimenes Apr 11, 2026
ea9cd9d
refactor(preview): consolidate duplicate preview iframes into single …
tlgimenes Apr 11, 2026
59f618e
fix(vm): update start.test.ts mock to match VmSpec fluent API refactor
tlgimenes Apr 11, 2026
ffa4f03
feat(github): paginate installations and repos list tools; fix test f…
tlgimenes Apr 11, 2026
c90b4e7
fix(vm): clear activeVms on repo change; use sticky+recreate; comment…
tlgimenes Apr 11, 2026
963acf9
refactor(vm): rename iframe-proxy to daemon; add SSE endpoint, log ta…
tlgimenes Apr 11, 2026
dc97f21
test(vm): update start tests for daemon rename; fix stale terminalUrl…
tlgimenes Apr 11, 2026
2e2b3b1
feat(vm): add useVmEvents SSE hook for daemon event stream
tlgimenes Apr 11, 2026
d913ebe
feat(vm): add custom VmTerminal component for log rendering
tlgimenes Apr 11, 2026
c78fe97
feat(vm): replace polling with daemon SSE; add custom terminal; SSE-b…
tlgimenes Apr 11, 2026
5523f16
chore(vm): remove VM_PROBE tool; daemon SSE replaces frontend polling
tlgimenes Apr 11, 2026
6b989ef
fix(vm): deactivate visual editor overlays when switching to interact…
tlgimenes Apr 11, 2026
55fb724
chore(vm): add ansi-to-html type declarations
tlgimenes Apr 11, 2026
473327f
feat(vm): add 30-minute idle timeout and fix stop test mock
tlgimenes Apr 11, 2026
4c7f308
feat(vm): use Freestyle Git + GitHub Sync for private repo cloning
tlgimenes Apr 11, 2026
7180d18
fix(vm): handle oneshot service exit code in install chain and improv…
tlgimenes Apr 13, 2026
34df32d
feat(vm): split log tailing into install.log and dev.log with replay-…
tlgimenes Apr 13, 2026
e08d3ce
feat(vm): redirect install and dev output to separate log files
tlgimenes Apr 13, 2026
e1742e7
feat(vm): split useVmEvents into installLogs and devLogs
tlgimenes Apr 13, 2026
ba6a484
feat(vm): wire install and dev tabs to split log streams
tlgimenes Apr 13, 2026
d468626
fix(vm): improve GitHub App UX — empty states, labels, and log cleanup
tlgimenes Apr 13, 2026
2400db7
Feat/easy to use ai (#3109)
pedrofrxncx Apr 13, 2026
7bad311
feat(chat): add voice input with real-time transcription (#3105)
guitavano Apr 13, 2026
d93ec87
chore(vm): add ansi-to-html type declarations
tlgimenes Apr 11, 2026
e869b4a
feat(vm): move process spawning into daemon, delete VM_EXEC
tlgimenes Apr 13, 2026
741b8e0
feat(vm): use script PTY wrapper instead of bash -c for rich terminal…
tlgimenes Apr 13, 2026
ab9afb3
feat(vm): add kill process button and daemon endpoint
tlgimenes Apr 14, 2026
945564d
feat(vm): stream daemon logs to SSE as "daemon" source
tlgimenes Apr 14, 2026
a6761eb
feat(web): move terminal to persistent bottom panel with nested resiz…
tlgimenes Apr 14, 2026
6655f4c
feat(web): add split-button pattern to VM ID, daemon tab, and process…
tlgimenes Apr 14, 2026
8e3b292
refactor(vm): update VmMetadata to use connectionId instead of Freest…
tlgimenes Apr 14, 2026
f69260a
feat(vm): replace Freestyle GitHub Sync with token-based git clone
tlgimenes Apr 14, 2026
77e6b75
refactor(web): update query keys for GitHub repo search
tlgimenes Apr 14, 2026
a17d41b
feat(web): add GitHub repo picker using mcp-github connection
tlgimenes Apr 14, 2026
ce1f3ec
refactor(web): simplify GitHubRepoButton to use new repo picker
tlgimenes Apr 14, 2026
716d56d
refactor(web): simplify repository settings to use new repo picker
tlgimenes Apr 14, 2026
8f148bb
chore: remove GitHub Device Flow tools and old repo dialog
tlgimenes Apr 14, 2026
202827e
fix: update VM start tests for token-based clone mechanism
tlgimenes Apr 14, 2026
82ad31e
refactor(web): move preview files into components/vm/preview/
tlgimenes Apr 14, 2026
534fe05
refactor(web): move env files into components/vm/env/
tlgimenes Apr 14, 2026
b623fe1
refactor(web): move use-vm-events hook into components/vm/hooks/
tlgimenes Apr 14, 2026
cda10ae
refactor(web): update consumer imports for vm/ folder reorganization
tlgimenes Apr 14, 2026
dd02987
chore: remove unused isRunning variable in env.tsx
tlgimenes Apr 14, 2026
06c27ac
fix(web): improve GitHub repo button visibility and connection resolu…
tlgimenes Apr 14, 2026
c0992ed
fix(web): resolve all lint warnings across vm and layout components
tlgimenes Apr 14, 2026
9b66c29
fix(web): conditionally render terminal button based on vibecode pref…
tlgimenes Apr 14, 2026
4b95a4c
feat(web): improve repo picker with owner display and 5-result limit
tlgimenes Apr 14, 2026
ba76a0a
fix(web): handle search_repositories response format with items wrapper
tlgimenes Apr 14, 2026
2f18fe4
fix(web): extract repo owner from full_name when owner field is absent
tlgimenes Apr 14, 2026
bfbab16
fix(web): eagerly attach GitHub connection to virtual MCP on picker open
tlgimenes Apr 14, 2026
68a3f61
refactor(web): use useVirtualMCPActions for all virtual MCP updates i…
tlgimenes Apr 14, 2026
c57e824
feat(web): refactor GitHub repo picker to org-first browsing flow
tlgimenes Apr 14, 2026
835d74b
fix(web): fix type error on githubRepo.connectionId metadata access
tlgimenes Apr 14, 2026
20cd7e7
fix(github): use /user/installations API for GitHub App tokens
tlgimenes Apr 14, 2026
2e30b40
feat(github): add "install GitHub App" link for unlisted accounts
tlgimenes Apr 14, 2026
462895b
fix(web): fix repo description overflow and simplify install link
tlgimenes Apr 14, 2026
573d70f
fix(web): fix repo description overflow and simplify install link
tlgimenes Apr 14, 2026
e0ba8d6
fix(web): fix repo description overflow and simplify install link
tlgimenes Apr 14, 2026
b8eaac8
fix(web): fix repo description overflow and simplify install link
tlgimenes Apr 14, 2026
af7a248
refactor(github): remove GITHUB_LIST_ORG_REPOS tool
tlgimenes Apr 14, 2026
64acb2e
refactor(web): update githubOrgRepos query key to include search query
tlgimenes Apr 14, 2026
f698e38
feat(web): server-side repo search with useDeferredValue
tlgimenes Apr 14, 2026
eadec88
fix(web): fix owner parsing for GitHub MCP search_repositories response
tlgimenes Apr 14, 2026
08a19e8
fix(web): include url and installationId in githubRepo save mutation
tlgimenes Apr 14, 2026
cc7af58
fix(sdk): add connectionId to GithubRepoSchema to prevent Zod stripping
tlgimenes Apr 14, 2026
d60ff5d
fix(vm): fix clone/install race condition and setup tab filtering
tlgimenes Apr 14, 2026
19b4f70
fix(vm): use selected runtime instead of detected for VM spec and PATH
tlgimenes Apr 14, 2026
67d047f
refactor(vm): remove detected field from runtime metadata
tlgimenes Apr 14, 2026
7f8bcf0
refactor: replace RuntimeType with PackageManager in shared defaults
tlgimenes Apr 15, 2026
bed8fdb
refactor(vm): update VmMetadata and resolveRuntimeConfig for PackageM…
tlgimenes Apr 15, 2026
c7cdd97
refactor(vm): rewrite daemon with script discovery and generic proces…
tlgimenes Apr 15, 2026
8340d6a
refactor(web): store PackageManager directly in github repo picker
tlgimenes Apr 15, 2026
50afb44
refactor(web): simplify repository settings to runtime dropdown and port
tlgimenes Apr 15, 2026
b9158e1
refactor(web): rewrite useVmEvents for dynamic scripts and processes
tlgimenes Apr 15, 2026
525d106
refactor(web): progressive script tabs with daemon-driven discovery
tlgimenes Apr 15, 2026
5804fb1
chore: fix stale references and formatting after package manager refa…
tlgimenes Apr 15, 2026
8b8ce9f
fix(web): add missing usePreferences import and simplify settings title
tlgimenes Apr 15, 2026
35b4921
fix(web): remove unused setPreferences variable
tlgimenes Apr 15, 2026
f13590e
feat(vm): add detailed logging to VM_START and improve error UI
tlgimenes Apr 15, 2026
b8f67c4
feat(web): add useAutoInstallGitHub hook for inline registry install …
tlgimenes Apr 15, 2026
a255386
feat(web): replace AddConnectionDialog with inline auto-install in Gi…
tlgimenes Apr 15, 2026
e34c647
feat(web): add getActiveGithubRepo utility to detect stale GitHub con…
tlgimenes Apr 15, 2026
3c9e5ba
ai was too lazy to comit these
tlgimenes Apr 15, 2026
8e3a5f9
fix(web): prevent picker from rendering before OAuth completes
tlgimenes Apr 15, 2026
ce0fe44
fix(web): replace useQuery abuse with useState for runtime detection …
tlgimenes Apr 15, 2026
c5164eb
chore(web): remove debug console logs from GitHub repo picker
tlgimenes Apr 15, 2026
768fb98
chore(web): remove debug console logs from useAutoInstallGitHub hook
tlgimenes Apr 15, 2026
0d49ac7
chore(vm): clean up VM_START debug logs, add error logging
tlgimenes Apr 15, 2026
3d41a24
refactor(vm): extract daemon script into standalone module
tlgimenes Apr 15, 2026
e80c940
feat(vm): install ripgrep in Freestyle VM for grep/glob support
tlgimenes Apr 15, 2026
282d212
feat(decopilot): add VM file operation built-in tools
tlgimenes Apr 15, 2026
e67333f
feat(decopilot): wire VM file tools, replace sandbox when VM active
tlgimenes Apr 15, 2026
8ea924a
fix(decopilot): handle VM down gracefully, use server icon in header
tlgimenes Apr 15, 2026
0ff1fc6
fix(ui): open main view when toggling server panel
tlgimenes Apr 15, 2026
d051e72
fix(ui): close env panel when toggling main view off
tlgimenes Apr 15, 2026
59f278a
fix(vm): update test to expect install-ripgrep systemd service
tlgimenes Apr 15, 2026
64ec88c
refactor(preview): make EnvContent sole VM lifecycle owner
tlgimenes Apr 15, 2026
0f6d76d
fix(ui): make Start Server button always open env panel
tlgimenes Apr 15, 2026
27e1928
feat(ui): add "Add to chat" button for terminal text selection
tlgimenes Apr 15, 2026
0a5dfbc
fix(env): use predicate-based cache invalidation for VIRTUAL_MCP queries
tlgimenes Apr 15, 2026
f71c140
fix(preview): make empty state an overlay instead of early return
tlgimenes Apr 15, 2026
e10a901
refactor(vm-tools): drop vm_ prefix from tool variable names
tlgimenes Apr 15, 2026
2bd9c28
fix(env): use direct EventSource to fix tab replay on panel toggle
tlgimenes Apr 15, 2026
233767b
feat(vm): enable yarn via corepack on Freestyle VMs
tlgimenes Apr 16, 2026
09a56db
fix(vm-tools): add debug logging and handle isError in GitHub file fetch
tlgimenes Apr 16, 2026
2d4aec8
feat(vm): suppress corepack download prompt and refactor github repo …
tlgimenes Apr 16, 2026
adf53f1
fix(vm): enable corepack for all package managers, not just yarn
tlgimenes Apr 16, 2026
31e4c5d
fix(vm): restore terminal UI on panel toggle when VM is active
tlgimenes Apr 16, 2026
e7c5951
fix(github-repo-picker): read file content from resource block and fe…
tlgimenes Apr 16, 2026
daf75b3
fix(github-repo-picker): add debug logging for stuck detection state
tlgimenes Apr 16, 2026
18a6446
refactor(github-repo-picker): standalone mode — creates virtual MCP o…
tlgimenes Apr 16, 2026
3e41a54
feat: add Import from GitHub button, remove SiteEditorOnboardingModal…
tlgimenes Apr 16, 2026
dc1eca9
refactor: unify Create Agent behind a modal with Blank/GitHub options
tlgimenes Apr 16, 2026
106aab3
Revert "refactor: unify Create Agent behind a modal with Blank/GitHub…
tlgimenes Apr 16, 2026
b6fe13d
feat: add GitHub import buttons gated behind experimental_vibecode flag
tlgimenes Apr 16, 2026
b1cc5f1
feat(browse-agents): add + button for blank agent next to octocat in …
tlgimenes Apr 16, 2026
e5dcb45
feat(browse-agents): replace icon buttons with dropdown menu for agen…
tlgimenes Apr 16, 2026
2472169
fix(browse-agents): rename to Create agent with Users03 icon, use dec…
tlgimenes Apr 16, 2026
07fec23
fix(browse-agents): outline the + dropdown trigger button
tlgimenes Apr 16, 2026
c14d56c
fix: hide env/github button in header when agent has no github repo
tlgimenes Apr 16, 2026
c5b3782
feat: remove experimental_vibecode gate, ship GitHub import with Beta…
tlgimenes Apr 16, 2026
def7044
feat(agents-list): replace Create Agent button with dropdown menu
tlgimenes Apr 16, 2026
4d7933e
fix: remove Beta tag from Import from GitHub menu items
tlgimenes Apr 16, 2026
eff2fd3
fix(decopilot): surface real errors instead of masking them as JSON p…
tlgimenes Apr 16, 2026
d8a00eb
fix: remove Experimental VibeCode toggle from profile settings
tlgimenes Apr 16, 2026
445feb3
chore: purge experimental_vibecode from Preferences type and defaults
tlgimenes Apr 16, 2026
83fc4fe
fix(browse-agents): use ghost style for + dropdown trigger button
tlgimenes Apr 16, 2026
f8ab156
fix(browse-agents): use FolderPlus icon for dropdown trigger
tlgimenes Apr 16, 2026
4458d4c
fix(browse-agents): open dropdown to the right of the trigger button
tlgimenes Apr 16, 2026
7481fb5
fix: rename Create agent to Create from scratch in dropdown menus
tlgimenes Apr 16, 2026
cc6fab2
fix(collection-search): replace Input component with native input ele…
tlgimenes Apr 16, 2026
881226f
fix: address review bugs in GitHub repo picker and tool registry
tlgimenes Apr 16, 2026
89e6eab
refactor: extract shared GitHubIcon component
tlgimenes Apr 16, 2026
cb3d67d
refactor: extract shared CreateAgentDropdownContent component
tlgimenes Apr 16, 2026
0dfbb6b
fix: remove debug console.log from vm-tools daemonPost
tlgimenes Apr 16, 2026
19888e9
refactor: remove no-op PACKAGE_MANAGER_LABELS map
tlgimenes Apr 16, 2026
b16d20b
refactor: inject PM_CONFIG into daemon from shared runtime-defaults
tlgimenes Apr 16, 2026
b64841f
refactor: extract invalidateVirtualMcpQueries helper
tlgimenes Apr 16, 2026
9c448d6
feat(vm): run child processes as non-root user and shallow clone
tlgimenes Apr 16, 2026
53bdee0
fix(vm): chown /home/deco so child processes can write cache files
tlgimenes Apr 16, 2026
6f11167
fix(vm): mkdir /home/deco before chown in prepare-app-dir
tlgimenes Apr 16, 2026
a15d931
fix(vm): generate en_US.UTF-8 locale in VM setup
tlgimenes Apr 16, 2026
9ffae37
fix(vm): install locales package before running locale-gen
tlgimenes Apr 16, 2026
f56820b
fix: use null icons and shared query invalidation helper
tlgimenes Apr 16, 2026
f732a3b
fix(vm): set LANG and LC_ALL env vars for child processes
tlgimenes Apr 16, 2026
09c36d3
fix(vm): uncomment en_US.UTF-8 in locale.gen before generating
tlgimenes Apr 16, 2026
0ddc608
fix(vm): use regex to match variable whitespace in locale.gen
tlgimenes Apr 16, 2026
85cd021
fix(vm): use runCommands instead of users() for compatibility
tlgimenes Apr 16, 2026
82ed5f4
fix(vm): move user creation into prepare-app-dir service to fix boot …
tlgimenes Apr 16, 2026
af92213
fix(vm): update test for prepare-app-dir service and remove unused hook
tlgimenes Apr 16, 2026
b0eb69c
feat(vm): show retry page when upstream server is not ready
tlgimenes Apr 16, 2026
d2d8c1e
fix(vm): rename /_daemon/ routes to /_decopilot_vm/ to avoid API overlap
tlgimenes Apr 16, 2026
0347a4d
fix(vm): add error logging for non-OK daemon responses
tlgimenes Apr 16, 2026
07910e8
fix(vm): base64-encode daemon payloads to bypass Cloudflare WAF
tlgimenes Apr 16, 2026
60a7590
feat(preferences): add experimental_vibecode flag to gate GitHub import
tlgimenes Apr 16, 2026
1711cf3
fix(vm): improve daemon CORS, restart policy, terminal selection and …
tlgimenes Apr 16, 2026
90c03cc
feat(browse-agents): restore Site Editor template in Agent templates
tlgimenes Apr 16, 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
10 changes: 8 additions & 2 deletions apps/mesh/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,20 @@
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@freestyle-sh/with-bun": "^0.2.12",
"@freestyle-sh/with-deno": "^0.0.4",
"@freestyle-sh/with-nodejs": "^0.2.9",
"@inkjs/ui": "^2.0.0",
"@modelcontextprotocol/ext-apps": "^1.2.2",
"@openrouter/ai-sdk-provider": "^2.2.5",
"@opentelemetry/core": "^2.6.0",
"@tanstack/react-virtual": "^3.13.21",
"@xterm/addon-fit": "^0.11.0",
"@xterm/xterm": "^6.0.0",
"ai-sdk-provider-claude-code": "^3.4.4",
"ai-sdk-provider-codex-cli": "^1.1.0",
"embedded-postgres": "^18.3.0-beta.16",
"freestyle-sandboxes": "^0.1.46",
"ink": "^6.8.0",
"kysely": "^0.28.12",
"nats": "^2.29.3",
Expand All @@ -73,13 +79,13 @@
"@decocms/better-auth": "1.5.17",
"@decocms/bindings": "workspace:*",
"@decocms/mcp-utils": "workspace:*",
"@jitl/quickjs-wasmfile-release-sync": "0.31.0",
"@decocms/mesh-sdk": "workspace:*",
"@decocms/runtime": "workspace:*",
"@decocms/vite-plugin": "workspace:*",
"@electric-sql/pglite": "^0.3.15",
"@floating-ui/react": "^0.27.16",
"@hookform/resolvers": "^5.2.2",
"@jitl/quickjs-wasmfile-release-sync": "0.31.0",
"@modelcontextprotocol/sdk": "1.27.1",
"@monaco-editor/react": "^4.7.0",
"@opentelemetry/api": "^1.9.0",
Expand Down Expand Up @@ -136,14 +142,14 @@
"jose": "^6.0.11",
"kysely-pglite": "^0.6.1",
"lucide-react": "^0.468.0",
"react-resizable-panels": "^2.1.7",
"marked": "^15.0.6",
"mesh-plugin-workflows": "workspace:*",
"nanoid": "^5.1.6",
"pg": "^8.16.3",
"prettier": "^3.4.2",
"react-hook-form": "^7.66.0",
"react-markdown": "^10.1.0",
"react-resizable-panels": "^2.1.7",
"react-syntax-highlighter": "^15.6.1",
"recharts": "^3.6.0",
"rehype-raw": "^7.0.0",
Expand Down
27 changes: 21 additions & 6 deletions apps/mesh/src/api/routes/decopilot/built-in-tools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { createReadToolOutputTool } from "./read-tool-output";
import { createReadPromptTool } from "./prompts";
import { createReadResourceTool } from "./resources";
import { createSandboxTool, type VirtualClient } from "./sandbox";
import { createVmTools } from "./vm-tools";
import { createOpenInAgentTool } from "./open-in-agent";
import { createSubtaskTool } from "./subtask";
import { userAskTool } from "./user-ask";
Expand All @@ -33,6 +34,8 @@ export interface BuiltinToolParams {
isPlanMode?: boolean;
toolOutputMap: Map<string, string>;
passthroughClient: VirtualClient;
/** When set, VM file tools replace the sandbox tool */
activeVm?: { vmBaseUrl: string } | null;
}

/**
Expand All @@ -56,6 +59,7 @@ function buildAllTools(
isPlanMode = false,
toolOutputMap,
passthroughClient,
activeVm,
} = params;
const approvalOpts = { isPlanMode };
const tools: Record<string, unknown> = {
Expand All @@ -73,12 +77,6 @@ function buildAllTools(
read_tool_output: createReadToolOutputTool({
toolOutputMap,
}),
sandbox: createSandboxTool({
passthroughClient,
toolOutputMap,
needsApproval:
toolNeedsApproval(toolApprovalLevel, false, approvalOpts) !== false,
}),
read_resource: createReadResourceTool({
passthroughClient,
toolOutputMap,
Expand All @@ -99,6 +97,23 @@ function buildAllTools(
ctx,
),
};
// VM tools replace sandbox when a VM is active
if (activeVm) {
const vmTools = createVmTools({
vmBaseUrl: activeVm.vmBaseUrl,
toolOutputMap,
needsApproval:
toolNeedsApproval(toolApprovalLevel, false, approvalOpts) !== false,
});
Object.assign(tools, vmTools);
} else {
tools.sandbox = createSandboxTool({
passthroughClient,
toolOutputMap,
needsApproval:
toolNeedsApproval(toolApprovalLevel, false, approvalOpts) !== false,
});
}
// subtask requires a provider (LLM calls) — skip when provider is null (Claude Code)
if (provider) {
tools.subtask = createSubtaskTool(
Expand Down
272 changes: 272 additions & 0 deletions apps/mesh/src/api/routes/decopilot/built-in-tools/vm-tools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
/**
* VM File Tools
*
* Built-in decopilot tools that proxy to the in-VM daemon's file operation
* endpoints. Registered when a Virtual MCP has an active Freestyle VM,
* replacing the QuickJS sandbox tool.
*/

import { tool, zodSchema } from "ai";
import { z } from "zod";
import {
MAX_RESULT_TOKENS,
createOutputPreview,
estimateJsonTokens,
} from "./read-tool-output";

export interface VmToolsParams {
readonly vmBaseUrl: string;
readonly toolOutputMap: Map<string, string>;
readonly needsApproval: boolean;
}

async function daemonPost(
baseUrl: string,
endpoint: string,
body: Record<string, unknown>,
): Promise<unknown> {
const url = `${baseUrl}/_decopilot_vm/${endpoint}`;
const serialized = JSON.stringify(body);
// Base64-encode the payload to avoid Cloudflare WAF triggering on
// shell commands and other sensitive-looking content in the JSON body.
const encoded = btoa(
encodeURIComponent(serialized).replace(/%([0-9A-F]{2})/g, (_, p1) =>
String.fromCharCode(parseInt(p1, 16)),
),
);
let res: Response;
try {
res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "text/plain" },
body: encoded,
});
} catch {
throw new Error(
"The server is not running. Ask the user to start it by clicking the server button (left side of the header bar).",
);
}
const rawText = await res.text();
let json: unknown;
try {
json = JSON.parse(rawText);
} catch (e) {
console.error(
"[vm-tools:daemonPost] Failed to parse JSON response endpoint=%s status=%d rawText=%s",
endpoint,
res.status,
rawText.slice(0, 2000),
);
const statusHint =
res.status >= 500
? " (server error)"
: res.status === 0
? " (no response)"
: "";
throw new Error(
`Daemon ${endpoint} returned invalid JSON (HTTP ${res.status}${statusHint}): ${rawText.slice(0, 800)}`,
);
}
if (!res.ok) {
console.error(
"[vm-tools:daemonPost] Non-OK response endpoint=%s status=%d body=%s",
endpoint,
res.status,
rawText.slice(0, 2000),
);
throw new Error(
(json as { error?: string }).error ??
`Daemon ${endpoint} failed (${res.status})`,
);
}
return json;
}

function maybeTruncate(
result: unknown,
toolOutputMap: Map<string, string>,
): unknown {
let serialized: string;
try {
serialized =
typeof result === "string" ? result : JSON.stringify(result, null, 2);
} catch {
serialized = String(result);
}
const tokenCount = estimateJsonTokens(serialized);
if (tokenCount > MAX_RESULT_TOKENS) {
const toolCallId = `vm_${Date.now()}`;
toolOutputMap.set(toolCallId, serialized);
const preview = createOutputPreview(serialized);
return {
truncated: true,
message: `Output too large (${tokenCount} tokens). Use read_tool_output with tool_call_id "${toolCallId}" to extract specific data.`,
preview,
};
}
return result;
}

export function createVmTools(params: VmToolsParams) {
const { vmBaseUrl, toolOutputMap, needsApproval } = params;

const read = tool({
needsApproval: false,
description:
"Read a file from the VM's project directory. Returns content with line numbers. " +
"Use offset and limit for large files.",

inputSchema: zodSchema(
z.object({
path: z
.string()
.describe("File path relative to project root (e.g. 'src/index.ts')"),
offset: z
.number()
.optional()
.describe("Starting line number (1-based, default 1)"),
limit: z
.number()
.optional()
.describe("Max lines to return (default 2000)"),
}),
),
execute: async (input) => {
const result = await daemonPost(vmBaseUrl, "read", input);
return maybeTruncate(result, toolOutputMap);
},
});

const write = tool({
needsApproval,
description:
"Write content to a file in the VM's project directory. " +
"Creates parent directories if needed. Overwrites existing files entirely.",

inputSchema: zodSchema(
z.object({
path: z.string().describe("File path relative to project root"),
content: z.string().describe("The full file content to write"),
}),
),
execute: async (input) => {
return await daemonPost(vmBaseUrl, "write", input);
},
});

const edit = tool({
needsApproval,
description:
"Perform exact string replacement in a file in the VM. " +
"old_string must be unique in the file unless replace_all is true.",

inputSchema: zodSchema(
z.object({
path: z.string().describe("File path relative to project root"),
old_string: z.string().describe("The exact text to find and replace"),
new_string: z
.string()
.describe("The replacement text (must differ from old_string)"),
replace_all: z
.boolean()
.optional()
.describe("Replace all occurrences (default false)"),
}),
),
execute: async (input) => {
return await daemonPost(vmBaseUrl, "edit", input);
},
});

const grep = tool({
needsApproval: false,
description:
"Search file contents in the VM using ripgrep. " +
"Supports regex patterns, file type filtering via glob, and context lines.",

inputSchema: zodSchema(
z.object({
pattern: z.string().describe("Regex pattern to search for"),
path: z
.string()
.optional()
.describe("Directory or file to search in (default: project root)"),
glob: z
.string()
.optional()
.describe("Glob pattern to filter files (e.g. '*.ts', '*.{js,jsx}')"),
context: z
.number()
.optional()
.describe("Lines of context around matches"),
ignore_case: z.boolean().optional().describe("Case-insensitive search"),
output_mode: z
.enum(["content", "files", "count"])
.optional()
.describe("Output mode (default: 'files')"),
limit: z.number().optional().describe("Max result lines (default 250)"),
}),
),
execute: async (input) => {
console.log(
"[vm-tools:grep] inputType=%s input=%s",
typeof input,
JSON.stringify(input).slice(0, 500),
);
const result = await daemonPost(vmBaseUrl, "grep", input);
return maybeTruncate(result, toolOutputMap);
},
});

const glob = tool({
needsApproval: false,
description:
"Find files by name pattern in the VM's project directory. " +
"Uses ripgrep for gitignore-aware matching. Returns relative file paths.",

inputSchema: zodSchema(
z.object({
pattern: z
.string()
.describe(
"Glob pattern to match files (e.g. '**/*.ts', 'src/**/*.test.tsx')",
),
path: z
.string()
.optional()
.describe("Directory to search in (default: project root)"),
}),
),
execute: async (input) => {
const result = await daemonPost(vmBaseUrl, "glob", input);
return maybeTruncate(result, toolOutputMap);
},
});

const bashSchema = z.object({
command: z.string().describe("The bash command to execute"),
timeout: z
.number()
.optional()
.describe("Timeout in milliseconds (default 30000, max 120000)"),
});
const bash = tool({
needsApproval,
description:
"Execute a shell command in the VM's project directory. " +
"Working directory is the project root. Timeout default 30s, max 2min.",

inputSchema: zodSchema(bashSchema),
execute: async (input: z.infer<typeof bashSchema>) => {
console.log(
"[vm-tools:bash] inputType=%s input=%s",
typeof input,
JSON.stringify(input).slice(0, 500),
);
const result = await daemonPost(vmBaseUrl, "bash", input);
return maybeTruncate(result, toolOutputMap);
},
});

return { read, write, edit, grep, glob, bash };
}
Loading
Loading