paperclip/server/src/services
Devin Foley ad0bb57350
Fix exe.dev sandbox installs for gemini/opencode local adapters (#5737)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies, including
running adapter CLIs inside remote sandboxes
> - The QA matrix in PAPA-316 spins up local-runtime adapters
(claude/gemini/opencode) against both SSH and the new exe.dev sandbox
provider, and "Test" exercises the same install + probe path the real
runtime uses
> - On exe.dev the QA matrix failed at three different points:
SSH/sandbox secret refs would not resolve, gemini-local could not find
npm, and opencode-local installed a binary that was not on the
probe-shell PATH
> - These are all environment-shape issues the runtime should handle,
not regressions in any individual adapter, so they need to be fixed in
the shared install/resolve layer before the matrix can pass
> - This pull request wires the environment id through to secret-ref
resolution, bootstraps npm from a portable Node tarball when the sandbox
image lacks Node, and symlinks the opencode binary into a directory that
non-login shells see
> - The benefit is that the QA matrix passes end-to-end on exe.dev, and
any future sandbox provider that ships without Node or relies on rc-file
PATH wiring gets the same fixes for free

## What Changed

- `server/src/services/environment-execution-target.ts`: pass the
environment `id` into `resolveEnvironmentDriverConfigForRuntime` for
both the sandbox and SSH branches, so `privateKeySecretRef` /
sandbox-provider secret refs (e.g. exe.dev `apiKey`) can resolve against
the secret store at runtime instead of throwing `Runtime secret
resolution requires an environment id`.
- `packages/adapter-utils/src/sandbox-install-command.ts`: extend
`buildSandboxNpmInstallCommand` with an `ENSURE_NPM_PREAMBLE` that, when
`npm` is missing, downloads a portable Node v22 tarball into
`$HOME/.local` and sets `PAPERCLIP_NPM_BOOTSTRAPPED=1` so the install
step skips sudo (sudo's `secure_path` would lose the freshly-installed
`npm` in `$HOME/.local/bin`). Distro-packaged Node from apt-get is
intentionally avoided because it tends to be too old to parse modern JS
syntax used by `@google/gemini-cli`.
- `packages/adapters/gemini-local/src/index.ts`: switch the hardcoded
`npm install -g @google/gemini-cli` to `buildSandboxNpmInstallCommand`,
so gemini-local picks up the same sudo-aware + npm-bootstrap behavior as
the other local adapters.
- `packages/adapters/opencode-local/src/index.ts`: append a step to the
install command that symlinks `$HOME/.opencode/bin/opencode` into
`$HOME/.local/bin`. The upstream installer only adds `~/.opencode/bin`
to PATH via `~/.bashrc`, which non-login `sh -c` probe invocations do
not source.
- `packages/adapter-utils/src/sandbox-install-command.test.ts`: cover
the new preamble plus the unchanged root/sudo/user-prefix branches.

## Verification

- `cd packages/adapter-utils && npm test -- sandbox-install-command`
(passes; new "bootstraps npm from a portable Node tarball when missing"
case is included).
- Manual: ran the in-app `Test` action against the QA matrix dev
instance for `QA exe.dev Claude`, `QA exe.dev Gemini`, and `QA exe.dev
OpenCode` — all three now report `status=pass` including the hello
probe. `QA SSH Claude` also passes; without the environment-id fix, SSH
resolution threw before the wrapper / install fixes could run.
- Suggested reviewer check: re-run the matrix on a fresh exe.dev
environment and confirm the install step no longer hits `npm: command
not found` for gemini and the opencode probe no longer hits `opencode:
command not found`.

## Risks

- Low/medium. The npm bootstrap pins Node `v22.11.0` from
`nodejs.org/dist`; if that URL becomes unreachable the install will fail
with a clear `curl` error rather than corrupting state. The bootstrap
path is only taken when `npm` is genuinely missing, so existing sandbox
images that ship with Node are unaffected.
- The opencode symlink uses `ln -sf` into `$HOME/.local/bin`, which is
created with `mkdir -p`; idempotent on re-install.
- The `id` change is a strict additive: callers previously got
`undefined` and only the secret-ref code paths actually read it. No
behavior change for environments without secret refs.

## Model Used

- Claude (Anthropic), `claude-opus-4-7`, with extended thinking and tool
use enabled. Iterated through the Paperclip QA matrix harness; no other
model assisted.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots (n/a — runtime/install path only)
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-05-11 14:28:22 -07:00
..
recovery fix: harden release registry verification against npm lag (#4816) 2026-05-09 22:18:12 -07:00
access.ts [codex] Add access cleanup and user profile page (#4088) 2026-04-20 06:10:20 -05:00
activity-log.ts [codex] Add plugin orchestration host APIs (#4114) 2026-04-20 08:52:51 -05:00
activity.ts Add sandbox environment support (#4415) 2026-04-24 12:15:53 -07:00
adapter-plugin-store.ts [codex] Add runtime lifecycle recovery and live issue visibility (#4419) 2026-04-24 15:50:32 -05:00
agent-instructions.ts chore: mark bootstrapPromptTemplate as deprecated 2026-03-26 11:12:25 -05:00
agent-permissions.ts Implement agent hiring, approval workflows, config revisions, LLM reflection, and sidebar badges 2026-02-19 13:02:41 -06:00
agent-start-lock.ts [codex] Add runtime lifecycle recovery and live issue visibility (#4419) 2026-04-24 15:50:32 -05:00
agents.ts Add SSH environment support (#4358) 2026-04-23 19:15:22 -07:00
approvals.ts Add username log censor setting 2026-03-20 08:50:00 -05:00
assets.ts refactor: rename packages to @paperclipai and CLI binary to paperclipai 2026-03-03 08:45:26 -06:00
board-auth.ts feat: implement multi-user access and invite flows (#3784) 2026-04-17 09:44:19 -05:00
budgets.ts Sync/master post pap1497 followups 2026 04 15 (#3779) 2026-04-15 21:13:56 -05:00
companies.ts [codex] Split backend control-plane QoL slice (#4700) 2026-04-28 16:46:45 -05:00
company-export-readme.ts fix: link Agent Company to agentcompanies.io in export README 2026-03-20 08:06:04 -05:00
company-member-roles.ts feat: implement multi-user access and invite flows (#3784) 2026-04-17 09:44:19 -05:00
company-portability.ts Harden control-plane safety and issue identifiers (#5292) 2026-05-06 07:49:47 -05:00
company-search-rate-limit.ts Add full company search page (#5293) 2026-05-06 06:32:37 -05:00
company-search.ts Add full company search page (#5293) 2026-05-06 06:32:37 -05:00
company-skills.ts [codex] Reject stale company skill refreshes (#4601) 2026-04-27 13:19:38 -05:00
costs.ts Improve operator workflow QoL (#5291) 2026-05-06 06:30:44 -05:00
cron.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
dashboard.ts [codex] Harden heartbeat scheduling and runtime controls (#4223) 2026-04-21 12:24:11 -05:00
default-agent-instructions.ts Add default agent instructions bundle 2026-03-20 07:42:36 -05:00
documents.ts [codex] Add run liveness continuations (#4083) 2026-04-20 06:01:49 -05:00
environment-config.ts Add secrets provider vaults and remote import (#5429) 2026-05-09 18:22:17 -05:00
environment-execution-target.ts Fix exe.dev sandbox installs for gemini/opencode local adapters (#5737) 2026-05-11 14:28:22 -07:00
environment-probe.ts Add sandbox environment support (#4415) 2026-04-24 12:15:53 -07:00
environment-run-orchestrator.ts Add sandbox callback bridge for remote environment API access (#4801) 2026-04-29 16:37:34 -07:00
environment-runtime.ts Add Cloudflare sandbox provider plugin (#5687) 2026-05-11 07:33:13 -07:00
environments.ts Add sandbox environment support (#4415) 2026-04-24 12:15:53 -07:00
execution-workspace-policy.ts Add SSH environment support (#4358) 2026-04-23 19:15:22 -07:00
execution-workspaces.ts Add SSH environment support (#4358) 2026-04-23 19:15:22 -07:00
feedback-redaction.ts Add feedback voting and thumbs capture flow 2026-04-02 09:11:49 -05:00
feedback-share-client.ts Restore feedback trace export fixes 2026-04-03 15:59:42 -05:00
feedback.ts Add recovery handoff system notices (#5289) 2026-05-06 06:05:58 -05:00
finance.ts Sync/master post pap1497 followups 2026 04 15 (#3779) 2026-04-15 21:13:56 -05:00
github-fetch.ts fix: harden GHE URL detection and extract shared GitHub helpers 2026-04-01 21:05:48 +00:00
goals.ts Improve onboarding defaults and issue goal fallback 2026-03-12 08:50:31 -05:00
heartbeat-run-summary.ts [codex] Add run liveness continuations (#4083) 2026-04-20 06:01:49 -05:00
heartbeat-stop-metadata.test.ts [codex] Retry max-turn exhausted heartbeats (#5096) 2026-05-03 11:30:48 -05:00
heartbeat-stop-metadata.ts [codex] Retry max-turn exhausted heartbeats (#5096) 2026-05-03 11:30:48 -05:00
heartbeat.ts fix: harden release registry verification against npm lag (#4816) 2026-05-09 22:18:12 -07:00
hire-hook.ts fix(adapters): honor paused overrides and isolate UI parser state 2026-04-04 14:04:33 -05:00
inbox-dismissals.ts Persist non-issue inbox dismissals 2026-04-09 06:16:05 -05:00
index.ts Add full company search page (#5293) 2026-05-06 06:32:37 -05:00
instance-settings.ts Revert "Add experimental newest-first issue thread" (#5460) 2026-05-07 16:50:31 -07:00
invite-grants.ts feat: implement multi-user access and invite flows (#3784) 2026-04-17 09:44:19 -05:00
issue-approvals.ts refactor: rename packages to @paperclipai and CLI binary to paperclipai 2026-03-03 08:45:26 -06:00
issue-assignment-wakeup.ts fix: close remaining routine merge blockers 2026-03-20 16:40:27 -05:00
issue-continuation-summary.ts fix: harden release registry verification against npm lag (#4816) 2026-05-09 22:18:12 -07:00
issue-execution-policy.ts [codex] Add issue monitor liveness controls (#4988) 2026-05-03 08:58:53 -05:00
issue-goal-fallback.ts Seed onboarding project and issue goal context 2026-03-24 11:48:59 -05:00
issue-liveness.ts [codex] Add runtime lifecycle recovery and live issue visibility (#4419) 2026-04-24 15:50:32 -05:00
issue-references.ts Add first-class issue references (#4214) 2026-04-21 10:02:52 -05:00
issue-thread-interactions.test.ts [codex] Add structured issue-thread interactions (#4244) 2026-04-21 20:15:11 -05:00
issue-thread-interactions.ts Add planning mode for issue work (#5353) 2026-05-06 07:01:28 -05:00
issue-tree-control.ts [codex] Split backend control-plane QoL slice (#4700) 2026-04-28 16:46:45 -05:00
issues.ts Guard assigned backlog liveness (#5428) 2026-05-07 12:25:26 -05:00
json-schema-secret-refs.ts Generalize sandbox provider core for plugin-only providers (#4449) 2026-04-24 18:03:41 -07:00
live-events.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
local-service-supervisor.ts fix: harden heartbeat and adapter runtime workflows 2026-04-10 22:26:21 -05:00
plugin-capability-validator.ts Expand plugin host surface (#5205) 2026-05-05 07:42:57 -05:00
plugin-config-validator.ts Refactor secret-ref format registration to use a UI hint for Paperclip secret UUIDs 2026-03-14 15:43:56 -07:00
plugin-database.ts Expand plugin host surface (#5205) 2026-05-05 07:42:57 -05:00
plugin-dev-watcher.ts Tighten plugin dev file watching 2026-03-14 12:07:04 -05:00
plugin-environment-driver.ts Add Cloudflare sandbox provider plugin (#5687) 2026-05-11 07:33:13 -07:00
plugin-event-bus.ts Simplify plugin runtime and cleanup lifecycle 2026-03-13 16:58:29 -05:00
plugin-host-service-cleanup.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
plugin-host-services.ts [codex] Add LLM Wiki plugin host support (#5597) 2026-05-10 07:34:12 -05:00
plugin-job-coordinator.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
plugin-job-scheduler.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
plugin-job-store.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
plugin-lifecycle.ts Simplify plugin runtime and cleanup lifecycle 2026-03-13 16:58:29 -05:00
plugin-loader.ts Expand plugin host surface (#5205) 2026-05-05 07:42:57 -05:00
plugin-local-folders.ts [codex] Add LLM Wiki plugin host support (#5597) 2026-05-10 07:34:12 -05:00
plugin-log-retention.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
plugin-managed-agents.ts [codex] Add LLM Wiki plugin host support (#5597) 2026-05-10 07:34:12 -05:00
plugin-managed-routines.ts Expand plugin host surface (#5205) 2026-05-05 07:42:57 -05:00
plugin-managed-skills.ts [codex] Add LLM Wiki plugin host support (#5597) 2026-05-10 07:34:12 -05:00
plugin-manifest-validator.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
plugin-registry.ts Expand plugin host surface (#5205) 2026-05-05 07:42:57 -05:00
plugin-runtime-sandbox.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
plugin-secrets-handler.ts Add secrets provider vaults and remote import (#5429) 2026-05-09 18:22:17 -05:00
plugin-state-store.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
plugin-stream-bus.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
plugin-tool-dispatcher.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
plugin-tool-registry.ts Add plugin framework and settings UI 2026-03-13 16:22:34 -05:00
plugin-worker-manager.ts Stabilize runtime probes and Codex env tests (#5445) 2026-05-07 14:52:31 -07:00
productivity-review.ts Add recovery handoff system notices (#5289) 2026-05-06 06:05:58 -05:00
project-workspace-runtime-config.ts [codex] Respect manual workspace runtime controls (#4125) 2026-04-20 10:39:37 -05:00
projects.ts Expand plugin host surface (#5205) 2026-05-05 07:42:57 -05:00
quota-windows.ts feat(costs): add billing, quota, and budget control plane 2026-03-16 15:11:01 -05:00
routines.ts Add secrets provider vaults and remote import (#5429) 2026-05-09 18:22:17 -05:00
run-continuations.ts [codex] Add runtime lifecycle recovery and live issue visibility (#4419) 2026-04-24 15:50:32 -05:00
run-liveness.ts [codex] Add runtime lifecycle recovery and live issue visibility (#4419) 2026-04-24 15:50:32 -05:00
run-log-store.ts [codex] Add runtime lifecycle recovery and live issue visibility (#4419) 2026-04-24 15:50:32 -05:00
sandbox-provider-runtime.ts Generalize sandbox provider core for plugin-only providers (#4449) 2026-04-24 18:03:41 -07:00
secrets.ts Add secrets provider vaults and remote import (#5429) 2026-05-09 18:22:17 -05:00
sidebar-badges.ts Persist non-issue inbox dismissals 2026-04-09 06:16:05 -05:00
sidebar-preferences.ts [codex] Improve workspace runtime and navigation ergonomics (#3680) 2026-04-14 12:57:11 -05:00
work-products.ts Address remaining Greptile workspace review 2026-03-17 10:12:44 -05:00
workspace-operation-log-store.ts Add workspace operation tracking and fix project properties JSX 2026-03-17 09:36:35 -05:00
workspace-operations.ts [codex] Improve agent runtime recovery and governance (#4086) 2026-04-20 06:19:48 -05:00
workspace-realization.ts Add sandbox environment support (#4415) 2026-04-24 12:15:53 -07:00
workspace-runtime-read-model.ts Fix workspace runtime state reconciliation 2026-04-04 17:48:54 -05:00
workspace-runtime.ts Add planning mode for issue work (#5353) 2026-05-06 07:01:28 -05:00