Commit Graph
5 Commits
Author SHA1 Message Date
DottaandPaperclip 380040082e fix(adapters): preserve conversation policy across provider paths
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-11 17:41:19 -05:00
DottaandPaperclip ebaeba40ee feat: simplify agent onboarding and configuration (#13011)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Operators create agents and configure their runtimes in the board
UI.
> - The old creation flow presents several choices and a large form
before an agent can start.
> - The existing onboarding controls already provide clear provider
connection steps.
> - This pull request uses those controls in a new-agent wizard and
organizes the full configuration pages.
> - Operators can connect, test, save, and assign a first task while
keeping the existing configuration tools.

## Linked Issues or Issue Description

Related: #10974. That earlier open PR also reorganizes agent
configuration. This PR follows the reviewed Storybook designs for agent
creation and the current configuration tabs.

**What existing behavior does this improve?**

Agent creation, provider connection, runtime tests, and full agent
configuration.

**Current behavior**

The creation dialog leads to a large manual configuration form. Provider
login controls differ from onboarding. Environment variables and secret
access appear in separate places.

**Proposed behavior**

Choose a name and adapter. Connect Claude or Codex through the existing
onboarding controls. Configure and test the runtime, save the agent, and
open a task dialog with that agent assigned. Use the same design on the
existing configuration tabs.

**Reason and benefit**

The first setup asks for fewer decisions. The full editor keeps
instructions, skills, runtime controls, secret access, permissions,
keys, and revisions available in clear sections.

**Breaking changes**

The board creation and configuration layouts change. The
test-environment API adds an optional, allowlisted `testCredentials`
field for one-shot probes. Database contracts stay the same. Native ACPX
tests now reject unsupported local platforms before a CLI login can mask
the runtime restriction.

## What Changed

- Added a new-agent wizard with numbered steps, adapter branding,
provider connections, editable model choices, runtime tests, and
confirmation.
- Added Codex app-server, Claude ACPX, and OpenCode runner choices.
- Stored API credentials through existing secret APIs and persisted
references in agent configuration. New setup keys are isolated from
credentials used by existing agents.
- Preserved external-agent invitations beside the wizard, including
optional messages, one-time prompts, and clipboard fallback.
- Added OpenRouter provider and secret bindings for Pi and OpenCode.
- Added adapter-specific prerequisite fields for Cursor, Gemini, Kimi,
and Hermes. Cursor Cloud keys are saved as new organization secrets.
- Fixed Cursor Cloud repository field mapping, omitted empty remote
environment values, and added useful model and repository error
messages.
- Preserved complete MCP assignments when multiple valid profiles
contain more than 250 tools in total. Generated profiles retain exact
tool selectors.
- Added service branding and deployment-aware adapter choices. Cloud
setup offers Claude, Codex, and OpenCode; local native runners require
the experimental setting.
- Made the agent list responsive at intermediate widths.
- Applied the reviewed design to the real agent configuration pages.
Kept the instruction editor, skills, and existing mutations.
- Combined secret access and environment variables under one Save and
Discard action.
- Added interactive Storybook screens for setup, configuration,
confirmation, authentication, and test results.
- Fixed Pi provider-error parsing and thinking-effort persistence.
Native ACPX validates Linux x64 on the actual local, SSH, or sandbox
target.
- Redacted the complete transient probe-credential field from HTTP error
logs, including rejected provider names.

## Verification

- Current head `df0292fe6` has a fresh Greptile 5/5 review with no
unresolved findings. All 31 executed CI checks passed, including the
aggregate verification gate and all browser E2E shards. Storybook visual
regression is skipped by its workflow; the local Storybook build passed.

- Browser tests completed real assigned tasks with direct Codex, Claude,
OpenCode, Pi, and native Codex.
- Verified external-agent invitation generation and automatic prompt
copying in the live browser.
- Pi and OpenCode used an existing OpenRouter secret. Browser checks
covered save and reload, instruction edits, skill selection,
environment-variable Save and Discard, and assigned task creation.
- Invalid Claude API credentials remained on the connection step with an
error. A live Pi/OpenRouter invalid-key probe returned a provider
failure and left the user-secret inventory unchanged (zero entries
before and after).
- Full workspace typecheck and build passed after rebasing onto current
master. After review fixes, server and UI typechecks, token gates, and
the full build passed again. Storybook built successfully.
- All 5,542 local UI tests passed. The Cursor Cloud and Pi adapter
regressions passed all 24 tests. Review regressions passed 69 server
tests and all 18 agent-list tests.
- The local full test command ran 6,971 general server tests
successfully. Editing review fixes during that long run caused nine
tests to use stale modules; fresh isolated runs passed. An unrelated
embedded-Postgres fixture hit the host shared-memory limit; its 15
affected tests passed when the fixture groups ran separately.
- Local workspace groups passed after rerunning 18 CLI tests
sequentially to avoid host database limits and parallel-load timeouts.
The local full command stopped at the general server phase, so
serialized server verification comes from the five passing CI shards.
- Browser testing at 390px confirmed that the agent action menu opens
and the page has no horizontal overflow. CI browser E2E shards passed.
- Review the `Onboarding / New agent` and `Agents / Configuration
refresh` Storybook groups. In the real app, create an agent, run its
connection test, save it, assign a task, and reload its configuration.

## Risks

- This changes the main agent setup and configuration UI. Regression
tests cover routing, persistence, secret bindings, and form actions.
- Native Claude ACPX requires Linux x64. Direct Claude works on macOS.
Remote checks execute a bounded platform probe and reject unsupported or
unverified targets.
- A native OpenCode task reached the provider context limit because of
its tool payload. Its provider connection test passed. Direct OpenCode
completed a task. This existing native execution limit is not fixed
here.
- Claude and Codex connection keys use the existing user-secret store.
Other runtime setup keys use distinct organization secrets. Existing
credentials are never rotated. Probes do not store entered keys. Failed
agent creation removes newly staged credentials.
- Cursor Cloud has not completed a live task. Its authenticated account
still needs GitHub repository access. The live run passed MCP
provisioning, remote environment validation, and explicit Auto model
selection before the repository prerequisite blocked execution.
- Generated runtime MCP profiles can exceed the public profile-edit
request limit. They still contain exact catalog selectors and preserve
permission boundaries.
- No database migration, dependency, lockfile, or workflow changes are
included.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, repository tools, shell
execution, and browser automation. The runtime did not expose the exact
model ID or context window size.

## 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-09-08 14:22:32 -05:00
DottaandPaperclip b3343dbd64 feat(connections): add self-serve intent runtime (#12345)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents need a governed way to request app connections during issue
work.
> - The catalog now describes the available providers and setup methods.
> - A request must become a durable, company-scoped intent before an
operator acts on it.
> - This pull request adds that intent runtime across server, agent,
CLI, and shared contracts.
> - The benefit is a safe bridge from agent need to operator-approved
setup.

## Linked Issues or Issue Description

Refs #11965

This is stack 7 of 11. It depends on stack 6 and replaces another
reviewable part of #11965.

## What Changed

- Add connection intent types, validation, service logic, and routes.
- Add agent runtime tools and CLI support for connection requests.
- Add issue-thread interaction support for connection intents.
- Add runtime, route, adapter, and contract tests.
- Hold the final resolved-continuation row lock through asynchronous
adapter preparation until an actual process spawn, so parking or
reassignment cannot cross that boundary.
- Report Hermes Gateway's first remote run request through the shared
dispatch hook so the resolved-intent lock is released at the true
dispatch boundary.
- Revalidate the addressed user's live non-viewer membership and
connection-management authority for every intent mutation, including
OAuth completion.

## Verification

- `pnpm --filter @paperclipai/server typecheck`
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/tool-access-service.test.ts`
- Result: 176 tests passed.
- `pnpm build`
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/heartbeat-stale-queue-invalidation.test.ts` (32 passed;
includes non-process dispatch lock-release coverage)
- `pnpm exec vitest run --project @paperclipai/server
server/src/__tests__/connection-intents-service.test.ts -t
"addressed-user mutation"` (1 passed)
- `pnpm exec vitest run --project @paperclipai/server
server/src/__tests__/tool-access-service.test.ts -t "binds OAuth
callback completion to the initiating board session"` (1 passed)
- `pnpm --filter @paperclipai/hermes-paperclip-adapter test --
src/gateway/server/execute.test.ts` (23 passed; includes dispatch-hook
ordering and exactly-once coverage)
- `pnpm --filter @paperclipai/hermes-paperclip-adapter typecheck`

## Risks

- A malformed intent could create an unusable operator request.
- Validators and company checks reject invalid or cross-company
requests.
- The final continuation gate holds the issue row lock through adapter
preparation until process or remote dispatch; later operator changes use
the normal active-run interruption path.
- The change does not add a database migration.

> I checked `ROADMAP.md`. This stack continues the existing app
connection work from #11965 and does not duplicate another planned item.

## Model Used

OpenAI Codex, GPT-5. The runtime model ID and context window were not
exposed. The model used reasoning, tool use, and code execution.

## 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 linked the public source pull request with `Refs #`
- [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-08-29 12:08:34 -05:00
93ff6a8771 fix(cursor-cloud): drop unreachable Paperclip API callback for remote… (#8546)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents run via per-adapter execute paths; the `cursor_cloud` adapter
runs the agent in Cursor's cloud (remote), orchestrated server-side via
the Cursor Agent SDK
> - Local adapters receive a run-scoped Paperclip JWT
(`supportsLocalAgentJwt=true`) injected as `PAPERCLIP_API_KEY` so the
agent can call the Paperclip API; `cursor_cloud` is intentionally
`supportsLocalAgentJwt=false` (no JWT minted for a remote worker)
> - But `buildPaperclipEnv` always sets `PAPERCLIP_API_URL` (defaulting
to the local runtime host), so the remote cloud worker is handed a
callback URL it can neither reach nor authenticate against
> - Any agent-initiated Paperclip API call from the cloud worker
therefore fails with a 401 (or is unreachable), producing log noise and
confusing failures
> - This pull request drops the callback wiring when there is no usable
key, so cloud-side Paperclip tools degrade to a clean no-op
> - The benefit is no spurious 401s from remote cloud runs, with run
results unaffected (delivered server-side via the Cursor Agent SDK)

## Linked Issues or Issue Description

No existing public issue — describing the bug inline (per
`.github/ISSUE_TEMPLATE/bug_report.yml`):

**What happened**

`cursor_cloud` runs emit 401s when the remote cloud agent attempts
Paperclip API calls. Root cause: `buildPaperclipEnv`
(`packages/adapter-utils/src/server-utils.ts`) always sets
`PAPERCLIP_API_URL` (local runtime default), while `cursor_cloud` has
`supportsLocalAgentJwt=false`, so no `PAPERCLIP_API_KEY` is minted — URL
present, key absent → 401 / unreachable from `buildWakeEnv` in
`packages/adapters/cursor-cloud/src/server/execute.ts`.

**Expected behavior**

A remote cloud worker that is not issued a run JWT should not attempt
(and fail) Paperclip API callbacks.

**Steps to reproduce**

1. Configure a `cursor_cloud` agent (runs in Cursor's cloud;
`supportsLocalAgentJwt=false`).
2. Trigger a run that causes the cloud agent to make a Paperclip API
call.
3. Observe a 401 (or unreachable) because `PAPERCLIP_API_URL` points at
an unreachable local runtime and no key is present.

**Paperclip version**

Reproduced on current `master` (cutover base `e68188c43`).

**Deployment mode**

Self-hosted control plane, `cursor_cloud` adapter (remote execution in
Cursor's cloud).

**Related PRs (searched; none duplicate this fix):**

- #8197 — `claude_local` opt-out of the sandbox *bridge* for
direct-reachable remote SSH targets. Related family, but the opposite
situation: that path keeps the callback because the remote is reachable
**and** has a run token. `cursor_cloud` has neither, so here the
callback is removed.
- #8130, #4794, #8025 — `PAPERCLIP_API_URL`/loopback injection for
**local** agents (distinct from the remote cloud worker case).
- #401 — alternative agent-auth scheme (run-ID header when no bearer
token); different approach, not overlapping with this targeted fix.

## What Changed

- `packages/adapters/cursor-cloud/src/server/execute.ts`: in
`buildWakeEnv`, when there is no usable `PAPERCLIP_API_KEY`, delete
`PAPERCLIP_API_URL` and `PAPERCLIP_API_BRIDGE_MODE` so the remote worker
performs no Paperclip API callbacks. Informational `PAPERCLIP_*` vars
(run id, agent id, company id, task, wake reason) still flow. When a key
*is* present (operator-provided), the URL is retained.
- `packages/adapters/cursor-cloud/src/server/execute.test.ts`: new test
asserting no callback vars are injected when no run JWT is present;
positive assertion that the URL is retained when a key is present.

## Verification

- `pnpm exec vitest run
packages/adapters/cursor-cloud/src/server/execute.test.ts` → **5/5
pass**.
- `pnpm --filter @paperclipai/adapter-cursor-cloud typecheck` →
**green**.
- Confirmed result delivery does not depend on this callback:
`execute()` reads results server-side via `Agent.getRun()` and
`run.wait()`.

## Risks

- **Low risk.** Only affects the env handed to remote `cursor_cloud`
workers. No schema/migration/behavioral change to result delivery (which
is server-side). When an operator explicitly provides
`PAPERCLIP_API_KEY`, the callback URL is retained, preserving
intentional callback setups.

## Model Used

- **Claude Opus 4.8** (Anthropic), extended/high reasoning mode, via the
Cursor agent with tool use + code execution. Diagnosis grounded in the
adapter/runtime code.

## 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 (none found)
- [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 references)
- [x] My branch name describes the change
(`fix/cursor-cloud-skip-unreachable-callback`) 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
- [ ] I have updated relevant documentation to reflect my changes (N/A —
no documented behavior changes)
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green (pending CI run)
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(pending review)
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Sebastian Heyneman <sebastian@joinnova.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 14:02:16 -07:00
Devin FoleyandPaperclip 534aee66ae Add cursor_cloud adapter for Cursor SDK + Cloud Agents API v1 (#5664)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies
> - There are many adapter types, one per agent-runtime product (Claude,
Codex, OpenCode, Cursor local CLI, etc.)
> - Cursor shipped a public TypeScript SDK on 2026-04-29 that exposes
Cursor's full hosted-agent platform (cloud VMs, harness, MCP, skills,
hooks)
> - Paperclip had no first-class adapter for this — agents that wanted
to use Cursor's managed cloud runtime had to fall back to the local CLI
adapter, which loses the cloud session, streaming, and durable run model
> - This PR adds a new `cursor_cloud` adapter built directly on
`@cursor/sdk`, with Paperclip's heartbeat mapped to Cursor's
durable-agent + per-run model
> - The benefit is that any Paperclip agent can now drive a Cursor cloud
agent across heartbeats with native session reuse, streaming, and
cancellation, while Paperclip remains the source of truth for issue/task
state

## What Changed

- New built-in adapter package `packages/adapters/cursor-cloud` (15
files, ~1.7k LOC) backed by `@cursor/sdk` ^1.0.12
- `src/server/execute.ts` — SDK-first lifecycle: `Agent.create` /
`Agent.resume` / `Agent.getRun` / `agent.send` / `run.stream` /
`run.wait`, with session reuse keyed on the (runtime env type, env name,
repo set) tuple
- `src/server/session.ts` — codec for `cursorAgentId` + `latestRunId` +
repo metadata, persisted in `runtime.sessionParams`
- `src/server/test.ts` — environment probe via `Cursor.me()` and
optional model validation via `Cursor.models.list()`
- `src/ui/parse-stdout.ts` + `src/cli/format-event.ts` — normalize
Cursor SDK message types (`status`, `thinking`, `assistant`, `user`,
`tool_call`, `tool_result`, `result`) into Paperclip transcript events
for the UI and CLI
- Registrations: `packages/shared/src/constants.ts`,
`packages/adapter-utils/src/session-compaction.ts`,
`server/src/adapters/{registry,builtin-adapter-types}.ts`,
`ui/src/adapters/{registry,adapter-display-registry}.ts` +
`ui/src/adapters/cursor-cloud/index.ts`, `cli/src/adapters/registry.ts`,
plus workspace deps in `cli`/`server`/`ui` `package.json`
- `ui/src/components/AgentConfigForm.tsx` — hide local-Cursor
`mode`/thinking-effort field for `cursor_cloud` (different config
surface)
- 11 vitest tests covering execute paths (fresh create, matching-resume,
active-run reattach, non-finished result), session codec round-trip,
transcript parsing, and config building

## Verification

Reviewer steps:

```bash
pnpm install
pnpm --filter @paperclipai/adapter-cursor-cloud typecheck   # → clean
pnpm vitest run packages/adapters/cursor-cloud              # → 11/11 passing
```

End-to-end check against a real Cursor cloud agent (requires
`CURSOR_API_KEY` and Cursor GitHub-app install on the target repo):

1. Create a `cursor_cloud` agent in Paperclip with `repoUrl` set to the
test repo, `repoStartingRef: main`, and `env.CURSOR_API_KEY` set
2. Trigger a heartbeat → adapter calls `Agent.create({ cloud: { env: {
type: "cloud" }, repos: [...] } })`, streams events, terminates on
`finished`
3. Trigger a second heartbeat → adapter calls `Agent.resume` or
`agent.send` follow-up depending on prior-run state, reusing
`cursorAgentId`
4. The Paperclip UI/CLI transcript reflects Cursor `status` / `thinking`
/ `assistant` events as they stream
5. Cancellation from Paperclip maps to `run.cancel()` or Cloud API v1
`cancelRun` for cross-heartbeat cancellation

A direct-SDK smoke run against a real repo (devinfoley/my_test_project @
main) confirmed: `Cursor.me()` ok → `Agent.create` → `agent.send` →
`run.stream()` (30 events) → terminal status `finished` in ~11s.

## Risks

- **New adapter, additive only.** No existing adapter or registry is
replaced; current `cursor` local-CLI adapter is untouched. Default
behavior of any existing agent is unchanged.
- **External dependency on `@cursor/sdk`.** Cursor's SDK is v1.0.x and
may evolve. Mocked unit tests cover the public surface used here; if the
SDK breaks compatibility we update the adapter independently.
- **Cost/budget.** `cursor_cloud` runs on Cursor's billed cloud VMs;
operators must understand they are spending money outside Paperclip's
budget controls when they enable this adapter. Same shape as other
API-billed adapters.
- **No webhook support in V1.** The SDK already provides
stream/wait/cancel/reattach, so V1 does not require a public callback
URL. If a future use case needs out-of-band wakes, we add a Cloud API v1
webhook bridge as a separate change. This is called out in the issue
plan document.
- **Lockfile.** Per repo policy, `pnpm-lock.yaml` is intentionally not
in this PR — CI's lockfile workflow will update it on merge given the
manifest changes.

## Model Used

- Provider: Anthropic Claude (via Claude Code / Paperclip `claude_local`
adapter)
- Model: `claude-opus-4-7` (Claude Opus 4.7), knowledge cutoff January
2026
- Mode: standard tool-use with extended reasoning
- Context: ~200k token window
- Capabilities used: code generation, multi-file edits, shell/test
execution, GitHub PR workflow

## 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 (11/11 in
`packages/adapters/cursor-cloud`)
- [x] I have added or updated tests where applicable (4 new test files,
11 cases)
- [ ] If this change affects the UI, I have included before/after
screenshots (the only UI change is hiding the local-Cursor mode field on
the `cursor_cloud` adapter — happy to attach a screenshot if the
reviewer wants one)
- [x] I have updated relevant documentation to reflect my changes (issue
plan document supersedes the pre-SDK design; tracked in PAPA-203)
- [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-10 17:21:04 -07:00