Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 4.1.8 to 4.1.10. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vitest-dev/vitest/releases">vitest's releases</a>.</em></p> <blockquote> <h2>v4.1.10</h2> <h3> 🐞 Bug Fixes</h3> <ul> <li><strong>browser</strong>: Check fs access in builtin commands [backport to v4] - by <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a>, <strong>Hiroshi Ogawa</strong> and <strong>OpenCode (claude-opus-4-8)</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10680">vitest-dev/vitest#10680</a> <a href="https://github.com/vitest-dev/vitest/commit/5c18dd267"><!-- raw HTML omitted -->(5c18d)<!-- raw HTML omitted --></a></li> <li><strong>vm</strong>: Fix external module resolve error with deps optimizer query for encoded URI [backport to v4] - by <a href="https://github.com/SveLil"><code>@SveLil</code></a> and <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10661">vitest-dev/vitest#10661</a> <a href="https://github.com/vitest-dev/vitest/commit/bae52b511"><!-- raw HTML omitted -->(bae52)<!-- raw HTML omitted --></a></li> </ul> <h5> <a href="https://github.com/vitest-dev/vitest/compare/v4.1.9...v4.1.10">View changes on GitHub</a></h5> <h2>v4.1.9</h2> <h3>🐞 Bug Fixes</h3> <ul> <li>Fix <code>importOriginal</code> with optimizer and query import [backport to v4] - by <strong>Hiroshi Ogawa</strong>, <strong>David Harris</strong>, <strong>Codex</strong>and <strong>Vladimir</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10546">vitest-dev/vitest#10546</a> <a href="https://github.com/vitest-dev/vitest/commit/a5180190c"><!-- raw HTML omitted -->(a5180)<!-- raw HTML omitted --></a></li> <li><strong>browser</strong>: <ul> <li>Wait for orchestrator readiness before resolving browser sessions [backport to v4] - by <strong>Vladimir</strong> and <strong>Séamus O'Connor</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10555">vitest-dev/vitest#10555</a> <a href="https://github.com/vitest-dev/vitest/commit/7fb29651a"><!-- raw HTML omitted -->(7fb29)<!-- raw HTML omitted --></a></li> <li>Wait for iframe tester readiness before preparing [backport to v4] - by <strong>Vladimir</strong> and <strong>Séamus O'Connor</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10497">vitest-dev/vitest#10497</a> and <a href="https://redirect.github.com/vitest-dev/vitest/issues/10556">vitest-dev/vitest#10556</a> <a href="https://github.com/vitest-dev/vitest/commit/fbc626c40"><!-- raw HTML omitted -->(fbc62)<!-- raw HTML omitted --></a></li> </ul> </li> <li><strong>mocker</strong>: <ul> <li>Hoist vi.mock() for vite-plus/test imports [backport to v4] - by <strong>Hiroshi Ogawa</strong>, <strong>LongYinan</strong>, <strong>Claude Opus 4.8</strong> and <strong>Vladimir</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10548">vitest-dev/vitest#10548</a> <a href="https://github.com/vitest-dev/vitest/commit/2c9559c02"><!-- raw HTML omitted -->(2c955)<!-- raw HTML omitted --></a></li> </ul> </li> <li><strong>pool</strong>: <ul> <li>Prevent test run hang on worker crash [backport to v4] - by <strong>Ari Perkkiö</strong> and <strong>Jattioui Ismail</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10543">vitest-dev/vitest#10543</a> and <a href="https://redirect.github.com/vitest-dev/vitest/issues/10564">vitest-dev/vitest#10564</a> <a href="https://github.com/vitest-dev/vitest/commit/934b0f587"><!-- raw HTML omitted -->(934b0)<!-- raw HTML omitted --></a></li> </ul> </li> </ul> <h5><a href="https://github.com/vitest-dev/vitest/compare/v4.1.8...v4.1.9">View changes on GitHub</a></h5> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="db616d227b"><code>db616d2</code></a> chore: release v4.1.10 (<a href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/10718">#10718</a>)</li> <li><a href="bae52b5112"><code>bae52b5</code></a> fix(vm): fix external module resolve error with deps optimizer query for enco...</li> <li><a href="a7a61e78c7"><code>a7a61e7</code></a> chore: release v4.1.9 (<a href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/10598">#10598</a>)</li> <li><a href="934b0f587c"><code>934b0f5</code></a> fix(pool): prevent test run hang on worker crash (<a href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/10543">#10543</a>) [backport to v4] (#...</li> <li><a href="7fb29651af"><code>7fb2965</code></a> fix(browser): wait for orchestrator readiness before resolving browser sessio...</li> <li><a href="a5180190c1"><code>a518019</code></a> fix: fix <code>importOriginal</code> with optimizer and query import [backport to v4] (#...</li> <li>See full diff in <a href="https://github.com/vitest-dev/vitest/commits/v4.1.10/packages/vitest">compare view</a></li> </ul> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
Paperclip Runtime Plugin
Drives a Paperclip agent (an "employee" in a Paperclip company) via the wakeup + heartbeat-run API. Each Fusion prompt becomes a Paperclip task, not a chat completion.
Mental model — read this first
Paperclip is a control plane for AI labor. Agents are long-lived employees with budgets, chains of command, and approval gates; Paperclip itself does not run models — it dispatches work to adapters (claude_local, codex_local, openclaw, http, …) which run the actual LLM call inside their own heartbeat.
This plugin proxies a Fusion conversation through one of those Paperclip agents:
- (Optionally) creates a Paperclip issue with the prompt as its body, assigned to your chosen agent.
- Calls
POST /api/agents/{id}/wakeupwithpayload: { prompt, fusionSessionId, issueId }and an idempotency key. - Streams
GET /api/heartbeat-runs/{runId}/events, forwardingheartbeat.run.logchunks to the chat UI. - On terminal status (
succeeded | failed | cancelled | timed_out), reads the issue's final state and the agent's closing comment.
Implications:
- Latency is task-shaped (seconds to minutes), not chat-shaped.
- Governance applies: budget caps, approval requirements, audit log all come from Paperclip.
- A single Paperclip agent can be proxied from many Fusion sessions concurrently.
Prerequisites
A running Paperclip server you can reach. For local development:
npm install -g paperclipai
paperclipai onboard # interactive setup
paperclipai run # starts the server (default: http://localhost:3100)
Verify the server is up:
curl http://localhost:3100/api/health
Connection modes
The dashboard settings card lets you pick API or CLI mode:
API mode (default)
Paste an apiUrl and an agent apiKey. Get a key from the Paperclip UI's agent detail page → "Create API Key" (the full value is shown once). For local-trusted deployments, the key may be omitted.
CLI mode
Auto-derive the apiUrl from the local paperclipai install. The plugin reads ~/.paperclip/instances/default/config.json and uses that host:port as the apiUrl. No token needs to be pasted into Fusion. For non-local-trusted deployments, you can still set an override apiKey.
CLI key bootstrap
For authenticated Paperclip deployments (e.g. paperclip-dev or any non-local_trusted instance), a bearer token is required. The dashboard offers a one-click "✨ Mint API key via paperclipai" button that appears in CLI mode when:
- A connection has been attempted but
available === false(typically "API key rejected"), AND - The user has already selected an agent in the agent picker.
The button calls POST /api/providers/paperclip/cli-mint-key on the Fusion backend, which spawns:
paperclipai agent local-cli <agentRef> --json --no-install-skills --key-name fusion-runtime
On success the returned apiKey is written into the API key field and a save-prompt toast is shown. On failure (e.g. CLI not authenticated) the toast shows the error and instructs the user to run paperclipai onboard.
Requirement: The local paperclipai CLI must be authenticated (~/.paperclip/context.json must have a valid profile). Run paperclipai onboard to authenticate if the mint fails.
Conversation modes
Independent of transport, the mode setting controls how prompts map to Paperclip issues:
| Mode | Behavior |
|---|---|
rolling-issue (default) |
Creates one Paperclip issue per Fusion session; subsequent prompts add comments. Closest to chat. |
issue-per-prompt |
Each prompt creates a new top-level issue. Maximally explicit; clutters the board. |
wakeup-only |
No issue side-effects; the prompt is delivered via the wakeup payload only. Requires the agent's prompt template to handle payload-driven wakes. |
Settings
| Key | Env var | Default | Notes |
|---|---|---|---|
transport |
PAPERCLIP_TRANSPORT |
api |
api or cli. |
apiUrl |
PAPERCLIP_API_URL |
http://localhost:3100 |
API mode only. |
apiKey |
PAPERCLIP_API_KEY |
(none) | API mode (and as a CLI-mode override). |
cliBinaryPath |
PAPERCLIPAI_BIN |
paperclipai |
CLI mode only. |
cliConfigPath |
PAPERCLIP_CLI_CONFIG |
~/.paperclip/instances/default/config.json |
CLI mode only. |
agentId |
PAPERCLIP_AGENT_ID |
auto-derived from /api/agents/me |
The Paperclip agent this Fusion runtime proxies. |
companyId |
PAPERCLIP_COMPANY_ID |
auto-derived from /api/agents/me |
The Paperclip company. |
mode |
PAPERCLIP_RUNTIME_MODE |
rolling-issue |
One of the conversation modes above. |
parentIssueId |
PAPERCLIP_PARENT_ISSUE_ID |
(none) | Optional issue scoping. |
projectId |
PAPERCLIP_PROJECT_ID |
(none) | Optional. |
goalId |
PAPERCLIP_GOAL_ID |
(none) | Optional. |
runTimeoutMs |
PAPERCLIP_RUN_TIMEOUT_MS |
600000 |
Local cap before Fusion stops polling. The run continues server-side. |
pollIntervalMs |
PAPERCLIP_POLL_INTERVAL_MS |
500 |
Initial poll interval. |
pollIntervalMaxMs |
PAPERCLIP_POLL_INTERVAL_MAX_MS |
2000 |
Max poll interval after exponential backoff. |
Settings precedence: plugin settings → env var → default.
Public API
import {
PaperclipRuntimeAdapter,
// REST helpers
agentsMe,
listCompanies,
listCompanyAgents,
// Probes
probePaperclipConnection,
discoverPaperclipCliConfig,
// CLI key minting
mintAgentApiKeyViaCli,
// Types
type PaperclipAgentSummary,
type PaperclipCompanySummary,
type PaperclipConnectionStatus,
type PaperclipCliDiscoveryResult,
type MintCliKeyOptions,
type MintedApiKey,
} from "@fusion-plugin-examples/paperclip-runtime";
probePaperclipConnection({ apiUrl, apiKey?, timeoutMs? })→{ available, identity?, reason? }. Powers the dashboard's "✓ Connected as " badge.listCompanyAgents(apiUrl, apiKey, companyId)→ list of agents in a company. Drives the agent picker.discoverPaperclipCliConfig({ configPath? })→{ ok, apiUrl, deploymentMode? }from the localpaperclipaiconfig. Drives CLI-mode auth discovery.mintAgentApiKeyViaCli(opts: MintCliKeyOptions)→Promise<MintedApiKey>. Spawnspaperclipai agent local-cli <agentRef> --json --no-install-skillsto mint a fresh agent API key. Throws on ENOENT, non-zero exit, or malformed JSON; includes a hint to runpaperclipai onboardon auth failures.
Endpoints used (Paperclip side)
| Method | Path | Purpose |
|---|---|---|
GET |
/api/agents/me |
Identity + auto-derive agentId/companyId. |
GET |
/api/companies |
Company list (board access). |
GET |
/api/companies/{companyId}/agents |
Agent list (agent-key sees its own company). |
POST |
/api/companies/{companyId}/issues |
Issue creation (issue-per-prompt / rolling-issue modes). |
POST |
/api/agents/{agentId}/wakeup |
Trigger a heartbeat run with the Fusion prompt as payload. |
GET |
/api/heartbeat-runs/{runId}/events |
Streaming run log + status. |
GET |
/api/issues/{issueId} |
Final issue state. |
GET |
/api/issues/{issueId}/comments |
Final comment fallback. |
The adapter does not call /api/issues/{id}/checkout — checkout is the agent's job during its own heartbeat. The adapter does not call the legacy /api/agents/{id}/heartbeat/invoke.
Limitations
- Latency. Heartbeat runs can take minutes; not a chat-completion drop-in.
- Single-agent identity per connection. A Paperclip agent API key is scoped to one agent in one company. To proxy several agents, configure several Fusion connections.
- Run-events schema is partially inferred. The events endpoint payload shape is documented but not formally schema'd; the client accepts both bare-array and
{ events: [...] }envelopes defensively.
Metadata
- Plugin ID:
fusion-plugin-paperclip-runtime - Runtime ID:
paperclip - Package:
@fusion-plugin-examples/paperclip-runtime
Development
pnpm --filter @fusion-plugin-examples/paperclip-runtime test # 46 tests
pnpm --filter @fusion-plugin-examples/paperclip-runtime build