Commit Graph

7 Commits

Author SHA1 Message Date
Nicky Leach 38d8f37172
fix(build): enforce Node 24 across Paperclip (#11792)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip runs across the CLI, server, adapters, plugins, CI, and
container images.
> - These surfaces declared different Node.js versions from 20 through
24.
> - A newer `@types/node` major can expose APIs that the supported
runtime does not provide.
> - Node.js 20 is no longer a suitable project baseline, and Node.js 24
is the current LTS line.
> - This pull request sets Node.js 24.11.0 as one repository-wide
baseline, adds a drift check, and gives users actionable startup
guidance when their runtime is too old.
> - The benefit is one clear runtime contract for development, release,
installation, and published packages.

## Linked Issues or Issue Description

Refs #2734

Refs #11727

Refs #739

## What Changed

- Require Node.js 24.11.0 or newer in all 42 package manifests and
runtime checks.
- Use Node.js 24 in GitHub Actions, Docker images, smoke images, sandbox
setup, portable installs, and esbuild targets.
- Align every direct `@types/node` declaration on `^24.0.0`.
- Prevent Dependabot from opening major `@types/node` upgrades without a
matching runtime decision.
- Add `.nvmrc` and a CI policy check for Node version drift.
- Update ACP version gates, tests, and user documentation for the new
minimum.
- Print a non-blocking warning on CLI and server startup when Node is
unsupported, with remediation through a version manager or the
documented downloaded `install.sh` workflow.
- Deduplicate that warning when `paperclipai run` boots the CLI and
server in the same process.

## Verification

- `node scripts/check-node-version-policy.mjs`
- `node --check scripts/check-node-version-policy.mjs`
- `node --check cli/esbuild.config.mjs`
- `node --check scripts/generate-npm-package-json.mjs`
- `bash -n scripts/install.sh scripts/test-install-sh-docker.sh
scripts/e2e-install-lifecycle.sh`
- Parsed all 42 package manifests and confirmed `engines.node` is
`>=24.11.0`.
- `git diff --check`
- `vitest run
packages/adapter-utils/src/sandbox-install-command.test.ts` passed with
3 tests.
- `vitest run cli/src/node-version.test.ts` passed with 4 tests.
- Directly exercised the shared warning helper for unsupported-version
messaging and same-process deduplication.
- The focused exe.dev suite could not resolve the locally unbuilt plugin
SDK from this isolated worktree. A full offline workspace install was
also blocked because the package-manager signature verifier requires
registry access. The full suite was not run locally; draft CI performs a
clean install and evaluates the wider impact.

## Risks

- This is a breaking runtime change for users, plugins, and deployments
that still use Node.js 20 or 22.
- Published workspace packages will now produce an engine warning or
failure in strict package managers on older Node.js releases.
- Node.js 24 can reveal dependency, native module, Playwright, or agent
CLI compatibility issues in CI.
- The bootstrap installer now installs Node.js 24 when the current
runtime is older than 24.11.0.
- The portable sandbox fallback is pinned to Node.js 24.11.0 and depends
on that upstream tarball remaining available.
- Unsupported runtimes continue booting after a warning, so a later
incompatibility can still fail at its point of use.
- The CLI and server share the warning policy through the published
`@paperclipai/shared` package; packaging checks must keep that subpath
export available.
- This PR does not commit `pnpm-lock.yaml` because repository policy
assigns lockfile generation to CI.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex based on GPT-5. The exact deployment ID and context
window are not exposed in this session. Reasoning, repository tools,
shell execution, and GitHub tools were enabled.

## 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 searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-21 10:17:52 -07:00
Devin Foley 75acc4650f
feat(sandbox-providers): pre-fill environment form with default sizing and image values (#11004)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent runs execute inside sandbox environments. Sandbox provider
plugins (Daytona, Modal, exe.dev, and others) declare a JSON-Schema
`configSchema`. The Environment configuration form renders from that
schema.
> - The sizing and image fields open empty. Users must guess working
values. The Modal form cannot submit at all until the user types an app
name and an image by hand.
> - The form renderer already pre-fills every field that declares a
JSON-Schema `default`. The manifests do not use this mechanism for
sizing or image fields.
> - This pull request adds optional `default` values to the Daytona,
Modal, and exe.dev manifest schemas.
> - The benefit is a form that opens with known-good values. Users can
create a working environment without provider research.

## Linked Issues or Issue Description

**Current behavior**

The Environment configuration form opens with empty sizing and image
fields for the Daytona, Modal, and exe.dev sandbox providers. Users must
find working values in provider documentation. Modal declares `appName`
and `image` as required with no default, so the form blocks submission
until the user invents both values.

**Proposed behavior**

The provider manifests declare JSON-Schema `default` values. The
existing form renderer pre-fills them:

- Daytona: CPU `4`, memory `4` GiB, disk `10` GiB, image
`daytonaio/sandbox:0.8.0`
- exe.dev: CPU `4`, memory `4GB`, disk `20GB`
- Modal: app name `paperclip`, image `node:22`

Secret-ref fields (API keys, tokens) get no defaults on purpose. The
form persists a raw string in a secret-ref field as a company secret on
save. A placeholder default would become a stored secret with a bogus
value. Each plugin test suite now guards this invariant.

**Reason and benefit**

New users can create a working sandbox environment without guessing. The
defaults stay optional: users can clear or change every value, and the
schema marks no new field as required. The Modal image default `node:22`
satisfies the sandbox runtime contract in `SANDBOX-REQUIREMENTS.md`
(`node`, `sh`, and `tar` on PATH).

**Subsystem affected**

Sandbox provider plugins (`packages/plugins/sandbox-providers/*`):
environment driver `configSchema` manifests.

**Breaking changes**

None. Defaults only seed the create-mode form. Saved environments keep
their stored config. E2B, Novita, Cloudflare, and Kubernetes manifests
do not change: E2B and Novita already default to their base templates,
and the Cloudflare bridge and Kubernetes cluster fields have no sensible
universal value.

## What Changed

- Add `default` values for `cpu`, `memory`, `disk`, and `image` in the
Daytona manifest. Trim the memory description to match.
- Add `default` values for `cpu`, `memory`, and `disk` in the exe.dev
manifest.
- Add `default` values for `appName` and `image` in the Modal manifest.
Extend the image description with the runtime-contract rationale.
- Add manifest tests in all three plugins: defaults match expected
values, defaults satisfy their own schema constraints, and no secret-ref
field declares a default.
- Bump plugin versions: daytona and modal `0.1.0` → `0.1.1`, exe-dev
`0.1.1` → `0.1.2`.

## Verification

- Run `pnpm test` in `packages/plugins/sandbox-providers/daytona`,
`.../modal`, and `.../exe-dev`. The new `* manifest form defaults`
suites pass.
- Run `./node_modules/.bin/tsc --noEmit` in each of the three packages.
Typecheck passes.
- Manual: rebuild the plugins (`pnpm build` in each package), let the
plugin dev-watcher refresh the manifest, then open Environments → New
environment. The Daytona form shows CPU 4, Memory 4, Disk 10, and image
`daytonaio/sandbox:0.8.0`. The Modal form shows `paperclip` and
`node:22`. The API key fields stay empty.
- Verified live on a local instance: the served `configSchema` in the
plugin registry carries the new defaults, and existing environments are
unchanged.

## Risks

- Low risk. The change touches only manifest schema metadata and tests.
No runtime code path changes.
- New environments created with untouched forms now request 4 CPU / 4
GiB / 10 GiB from Daytona instead of provider minimums. This can raise
cost per sandbox for users who previously saved empty fields.
- The Daytona image default pins `daytonaio/sandbox:0.8.0`. The default
needs a manual bump when Daytona ships new sandbox images.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- Claude Fable 5 (Anthropic, model ID `claude-fable-5`), via the Claude
Code CLI, with extended thinking and tool use.

## 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 searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-08-06 12:04:33 -07:00
Nicky Leach d6e235cbcf
perf(sandbox-providers): drop nvm sourcing from exec wrappers (#10443)
## Thinking Path

> - Paperclip keeps agent work on a controlled execution plane.
> - Sandbox exec wrappers run on the hot path for agent commands.
> - The current change removes the explicit `nvm.sh` load step from
those wrappers.
> - The sandbox image already restores PATH through profile startup.
> - This pull request keeps profile sourcing where the wrapper still
needs it and drops only the `nvm.sh` load step.
> - The result is a smaller command path with the same node and agent
CLI resolution.

## Linked Issues or Issue Description

No public GitHub issue exists for this change.

Problem:
The sandbox exec wrappers spent extra time sourcing `nvm.sh` before each
command.
The sandbox image already restores PATH in
`/etc/profile.d/00-restore-env.sh`, so that explicit `nvm.sh` work was
redundant.

Proposed solution:
Remove the `nvm.sh` source step from all six wrappers.
Keep the profile sourcing that the provider still needs for PATH setup.

Alternatives considered:
Keep the existing shell setup and accept the launch cost.
That keeps the current behavior, but it leaves the hot path slower than
needed.

Roadmap alignment:
This change keeps the sandbox command path small and predictable.
It does not change the adapter contract or the node resolution rules.

## What Changed

- Removed `nvm.sh` sourcing from all six sandbox exec wrappers.
- Kept profile sourcing where the provider still needs it for PATH
setup.
- Switched Modal to a non-login shell because the script now sources
profiles itself.
- Updated wrapper tests to assert that built commands do not source
`nvm.sh`.

## Verification

- Local TypeScript typecheck passed in each changed package.
- Focused provider tests passed for Daytona, E2B, Modal, exe-dev,
Cloudflare bridge, and adapter-utils.
- One Daytona test failure is pre-existing and unrelated to this change.

## Risks

- This change alters shell startup for sandbox exec paths.
- A provider that depends on implicit shell setup may need a follow-up.
- The current tests cover command shape, but they do not cover every
runtime shell path.

## Model Used

OpenAI Codex, GPT-5, tool use.

## 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 searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-29 12:40:16 -07:00
Devin Foley 547463d3a2
refactor(environments): make execution environments instance-scoped (#8375)
## Thinking Path

> - Paperclip is the control plane for AI-agent companies, so execution
environment selection has to stay inspectable and predictable across
companies, agents, and runs.
> - The environment subsystem decides where an agent heartbeat actually
runs and how remote sandbox state is realized and restored.
> - That subsystem previously mixed company-scoped environment catalogs
with issue-level environment stamping, so a reassigned issue could keep
executing in the previous assignee's sandbox.
> - That behavior breaks the control-plane contract: changing the
assignee should change the executing agent/environment path unless there
is an explicit current override.
> - Fixing it cleanly required more than a narrow patch; the environment
model had to move to instance scope with a single inherited default and
per-agent override semantics.
> - This pull request rewires the schema, server/API surface, runtime
resolution, and UI around that model, then adds regression coverage for
cross-company inheritance and per-agent isolation.
> - The benefit is that environment choice now follows the approved
instance/agent configuration path instead of stale issue state, while
shared environments only need to be configured once per instance.

## Linked Issues or Issue Description

- No directly matching public GitHub issue or PR was found while
searching for this refactor.

### What happened?

Reassigning work between agents with different execution environments
could keep running in the previous sandbox because environment choice
was stamped onto the issue and outranked the current assignee. The same
subsystem also forced environment catalogs to be duplicated per company
even though the underlying execution environments were instance-wide
resources.

### Expected behavior

Execution should resolve through the current instance and agent
configuration path, with one instance-scoped environment catalog, one
instance default, optional per-agent override, and no stale issue-level
environment authority surviving reassignment.

### Steps to reproduce

1. Configure two agents to use different execution environments.
2. Assign an issue to the first agent so the issue records execution
state in that environment.
3. Reassign the same issue to the second agent and run another
heartbeat.
4. Observe that the pre-fix runtime can still sync or execute in the
original sandbox instead of the second agent's environment.

### Paperclip version or commit

Current `master` before this PR.

### Deployment mode

Self-hosted server.

### Installation method

Built from source (`pnpm dev` / `pnpm build`).

### Agent adapter(s) involved

- Claude Code
- Not adapter-specific (core bug in environment authority / resolution)

### Database mode

External Postgres.

### Access context

Both board reassignment and agent heartbeats were involved.

## What Changed

- Moved environments and their default selection contract to instance
scope in DB/shared types, including the migration that dedupes legacy
per-company environments and seeds the instance local default.
- Reworked environment CRUD/auth flows to use instance-scoped APIs and
added route/service coverage for instance-level environment management.
- Changed runtime resolution to prefer `agent default -> instance
default -> built-in local`, removed issue-level environment stamping
from the active execution path, and isolated sandbox/plugin leases by
`(executionWorkspaceId, agentId)`.
- Added environment env-var runtime precedence so environment-provided
values act as the baseline for agent execution.
- Moved the environment UI into instance settings and updated agent
configuration surfaces to reflect inherit/override behavior.
- Added regression coverage for instance-default inheritance across
companies and for the new runtime resolution behavior.
- Fixed a rebase-only duplicate `enableTaskWatchdogs` flag regression in
instance settings types/validators/services so the branch typechecks
cleanly on current `master`.
- Updated stale server tests so CI matches the shipped instance-scoped
environment contract.

## Verification

- `git diff --check`
- `pnpm --filter @paperclipai/shared typecheck`
- `pnpm --filter @paperclipai/db typecheck`
- `pnpm exec vitest run
server/src/__tests__/environment-runtime-driver-contract.test.ts
server/src/__tests__/agent-permissions-routes.test.ts
server/src/__tests__/environment-routes.test.ts
server/src/__tests__/environment-instance-routes.test.ts
server/src/__tests__/execution-workspace-policy.test.ts
server/src/__tests__/heartbeat-plugin-environment.test.ts
server/src/__tests__/instance-settings-routes.test.ts`

## Risks

- The migration changes environment scope and dedupes existing rows, so
installs with unusual legacy environment combinations should be reviewed
carefully during upgrade.
- Remote execution behavior now depends on instance-default inheritance
semantics instead of issue-level stamping, so any remaining code paths
that still assume issue-scoped environment authority would surface as
follow-up bugs.
- This PR includes both server/runtime behavior and UI relocation, so
reviewers should watch for authorization edge cases around instance
settings and environment management.

> I checked [`ROADMAP.md`](ROADMAP.md). This work fits the existing
Cloud / Sandbox agents direction as a bug-fix/refactor to current
behavior, not a new parallel product surface.

## Model Used

- OpenAI Codex coding agent in this Paperclip/Codex session; GPT-5-class
tool-using model with code execution and shell access. The exact backend
model ID is not exposed to the session runtime.

## 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 searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [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
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-06-20 09:42:53 -07:00
Devin Foley 93291df5c8
fix(plugins): move dev SDK linking out of plugin postinstall scripts (#8255)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Sandbox-provider plugins (cloudflare, daytona, e2b, exe-dev,
kubernetes, modal, novita) and `plugin-workspace-diff` are published as
standalone npm packages, but during local dev they need the in-repo
`@paperclipai/plugin-sdk` symlinked in
> - Each of these plugins shipped a `postinstall` lifecycle script that
traversed *out* of its own package directory (`node
../../../../scripts/link-plugin-dev-sdk.mjs`) to do that linking
> - The publishable manifest is built by a `prepack` whitelist that
drops the `scripts` field, so npm consumers don't see the postinstall
today — but that safety property depends entirely on `prepack` running
on every publish. A publish that skips lifecycle scripts would ship a
tarball whose postinstall escapes its package directory at consumer
install time
> - This pull request removes the escape-the-package-dir lifecycle
script from every plugin source manifest and moves the dev linking to a
single root-level postinstall that iterates the excluded plugin
directories itself
> - The benefit is that plugin tarballs can no longer carry an
install-time script that reaches outside their own directory, regardless
of whether `prepack` runs

## Linked Issues or Issue Description

This is a follow-up hardening change flagged during review of the Novita
sandbox provider PR (#7595).

**Problem (security):** Excluded plugin packages each carried
`"postinstall": "node ../../../../scripts/link-plugin-dev-sdk.mjs"`. The
relative path traverses outside the package root. Today the published
manifest is sanitized by a `prepack` whitelist that drops `scripts`, so
consumers are unaffected in the normal publish path. The risk is that
this is a defense-in-depth gap: if a publish ever skips lifecycle
scripts (e.g. `npm publish --ignore-scripts` is *not* used, or a tool
publishes the raw manifest), the tarball would ship a postinstall that
runs out-of-tree code at the consumer's install time.

## What Changed

- Added a single root `package.json` `postinstall`: `node
scripts/link-plugin-dev-sdk.mjs`.
- Rewrote `scripts/link-plugin-dev-sdk.mjs` to iterate the excluded
plugin directories itself (`packages/plugins/sandbox-providers/*` + the
orchestration smoke example) instead of relying on each plugin to invoke
it from its own cwd. Preserves both prior behaviors: leave a real
installed SDK dir alone, and skip when already correctly symlinked
(idempotent).
- Removed `scripts.postinstall` from all 7 sandbox-provider plugins
(cloudflare, daytona, e2b, exe-dev, kubernetes, modal, novita).
- Removed `scripts.postinstall` from `plugin-workspace-diff` (a pnpm
workspace member — pnpm already links the SDK, so the script was a no-op
there).

## Verification

- `node scripts/link-plugin-dev-sdk.mjs` from repo root: links the SDK
into the excluded plugins and reports skipped (already-linked) dirs;
re-running is idempotent.
- `grep -r "link-plugin-dev-sdk" packages/plugins/*/package.json
packages/plugins/sandbox-providers/*/package.json` returns no matches —
no plugin source manifest references the linker any longer.
- All affected `package.json` files re-validated as parseable JSON.

## Risks

Low risk. Dev-only tooling: the linker only runs at the repo root during
local install and only touches `node_modules/@paperclipai/plugin-sdk`
symlinks inside excluded plugin dirs. No change to published plugin
behavior or runtime code. Worst case if the root postinstall failed to
run, local dev of an excluded plugin would not find the SDK symlink —
easily re-run manually.

## Model Used

Claude Opus (claude-opus-4-8), extended reasoning, with tool use / code
execution in an agentic coding harness.

## 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 searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues OR (b) described the
issue in-PR following the relevant issue template
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable (added
`scripts/link-plugin-dev-sdk.test.js`, wired into
`test:release-registry`)
- [ ] If this change affects the UI, I have included before/after
screenshots (N/A — no UI change)
- [ ] I have updated relevant documentation to reflect my changes (N/A)
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-06-18 07:45:53 -07:00
Devin Foley 20aea356cc
refactor(deps-dev): bump vitest from 3.2.4 to 4.1.8 (#7581)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies
> - Test infrastructure across server, ui, packages/* runs on Vitest
> - Dependabot opened a narrow bump (3.2.4 → 3.2.6), but the wider
workspace is on 3.2.4 and the major-version bridge to v4 needs a
coordinated change set across configs and tests
> - Staying on 3.x indefinitely leaves us behind on Vitest 4 (perf,
pool, and config improvements) and forces repeated patch-only dependabot
churn
> - This pull request upgrades Vitest to 4.1.8 across the workspace,
updates `server/vitest.config.ts` and `scripts/run-vitest-stable.mjs`
for the new API, and adjusts two UI tests for the new assertion
semantics
> - The benefit is a single, coherent Vitest 4 upgrade that supersedes
#7570 and gets us on the supported major line

## What Changed

- Bump `vitest` from `3.2.4` to `4.1.8` across root, `server`, `ui`, and
all `packages/*` (including plugin examples and sandbox providers)
- Update `server/vitest.config.ts` for Vitest 4 config surface
- Update `scripts/run-vitest-stable.mjs` to match the new runner
behavior
- Adjust `ui/src/components/CommentThread.test.tsx` and
`ui/src/components/MarkdownEditor.test.tsx` for Vitest 4 matcher/timing
semantics
- Refresh `pnpm-lock.yaml`

## Verification

- `pnpm install` resolves cleanly with the new lockfile
- `pnpm -w -r test` (server, ui, packages) runs under Vitest 4.1.8

## Risks

- Major-version Vitest bump: behavioral changes in pools, fake timers,
and matcher strictness can surface flake. Test config and the two UI
tests were updated to match v4 semantics; broader test runs should be
watched on CI before merge.
- Supersedes dependabot PR #7570 (3.2.4 → 3.2.6); that PR should be
closed.

## Model Used

- Claude (Anthropic) — `claude-opus-4-7`, extended thinking, tool use
enabled

## 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
- [ ] I have run tests locally and they pass
- [ ] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [ ] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge

Closes #7570
2026-06-05 21:11:32 -07:00
Devin Foley 4b1e92a588
feat(plugins): add Modal sandbox provider plugin (#6245)
## Thinking Path

> - Paperclip orchestrates AI agents through company-scoped
control-plane workflows and extensible runtime integrations.
> - Sandbox providers are part of that extension surface because they
let agents execute isolated work without baking each provider into the
core server.
> - Modal already offers managed sandboxes with filesystem, process,
timeout, and networking controls that map onto Paperclip's sandbox
provider contract.
> - The repo did not have a Modal provider plugin, so teams wanting
Modal-backed sandboxes had no first-party integration path.
> - This pull request adds a standalone
`packages/plugins/sandbox-providers/modal` plugin that implements the
provider contract, worker entrypoint, docs, and tests.
> - The benefit is that Modal can now be installed as a provider plugin
without expanding the core control-plane surface area.

## What Changed

- Added a new `packages/plugins/sandbox-providers/modal` package with
the plugin manifest, worker entrypoint, and exported plugin surface.
- Implemented Modal-backed sandbox lifecycle support for creation,
command execution, file operations, networking options, termination, and
metadata translation.
- Added focused Vitest coverage for config validation, env handling,
lifecycle flows, networking behavior, and error mapping.
- Documented installation, configuration, and usage requirements in the
plugin README.
- Removed misleading `MODAL_TOKEN_*` fallback behavior so authentication
relies on supported Modal credentials only.

## Verification

- `pnpm -r typecheck`
- `pnpm test:run`
- `pnpm build`
- `cd packages/plugins/sandbox-providers/modal && pnpm test`

## Risks

- Low to medium risk: this is isolated to a new plugin package, but
runtime behavior still depends on live Modal account credentials and
service-side sandbox semantics.
- Modal's current docs target a newer Node baseline than the repo
default, so the first live install should confirm credential loading and
sandbox startup behavior in a real Modal workspace.
- No UI or schema changes are included in this PR.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex via Paperclip `codex_local` agent (GPT-5-class Codex
coding model; exact backend model ID is not exposed by the runtime),
with tool use, shell execution, and code-editing capabilities enabled.

## 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
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [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-18 08:36:34 -07:00