mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-10 01:50:13 +01:00
fix(runner): require a managed AI connection for plugin Runner-task environments (#19341)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - A plugin can provide Runner execution through an environment driver that declares `supportsTasks: true`. Agent computers use this path. > - Core let an agent without a managed AI connection run on that path. The run then used the account that was installed on the plugin's execution host. > - That is not a supported credential source. When the host Runner did not match, the run failed three times, 30 seconds apart, and then blocked the task with a generic error. The error did not name the fix. > - The plugin cannot refuse these runs itself. `describe` has no connection data, and Core replaces plugin error text before the user sees it. > - This pull request makes a managed AI connection a requirement for every plugin Runner-task environment. Core refuses a run without one before it acquires a lease or calls the plugin. > - The benefit is one clear notice that tells the operator to choose an AI connection, and no wasted retries or plugin work. ## Linked Issues or Issue Description Refs #19326. That pull request makes a Runner revision mismatch retry. It noted that runs without a managed AI connection reach the Runner check on a different path, which still blocks after 3 attempts. This pull request removes that path for plugin Runner-task environments. **Problem or motivation** A `paperclip_runner` agent with no managed AI connection can run in a plugin environment that provides Runner tasks. The run uses the account installed on the execution host. If the host Runner does not match, the native session retries 3 times and then blocks the task with "Plugin-provided Runner execution operation unavailable". The operator cannot tell what to fix. **Proposed solution** Refuse these runs in Core before any lease, plugin call, secret resolution, or provider work. Use one stable reason, `ai_connection_required`, for run admission, the setup probe, and agent verification. Show a task notice that names the fix. **Alternatives considered** A refusal in the plugin. It cannot see the connection at `describe`, which runs first. Its error text is also replaced twice before the user sees it. A new structured plugin error code would still not cover `describe`. ## What Changed - Add `server/src/services/plugin-runner-ai-connection.ts`. It holds the `ai_connection_required` code and message, the probe result, and the manifest lookup for a Runner-task driver. The lookup moves here from `agent-runner-selection.ts`, so run admission and runner selection use the same rule. - `heartbeat/execution-configuration.ts`: refuse a new `paperclip_runner` run in a Runner-task environment when it has no managed AI connection. This also applies when `homeMode: "preconfigured"` drops the connection. The run fails as `configuration_incomplete` with reason `ai_connection_required` and an action URL to the agent's runtime settings. The check runs before observability, secrets, the managed runtime, the workspace, and the lease. A resumed native run keeps its admitted contract. - `recovery/stranded-notice.ts`: add an "AI connection required" task notice. - `run-failure-report.ts`: treat this pre-dispatch refusal as an owner action, not an unexpected failure. - `adapters/registry.ts`: the unmanaged probe for a Runner-task target now returns a failed `ai_connection_required` check. It calls no task operation. Managed probes still go through `testManagedEnvironment`. - `agent-harness-verification.ts` and `agent-lifecycle/application/failure.ts`: classify the check as `ai_connection_required` with a fixed message. Verification waits for the configuration to change instead of retrying. - Docs: `PLUGIN_RUNNER_EXECUTION.md` states the requirement. `PLUGIN_ENVIRONMENT_TASKS.md` no longer mentions installed accounts. `agent-config-ui.md` notes the requirement. - Tests: the "plugin-owned account" heartbeat test described the behavior that this change removes. It now checks the assembled heartbeat refusal: no plugin call, no native boundary, no adapter, no workspace files. ## Verification - `npx vitest run` in `server/` for these files. All tests passed: - `src/__tests__/heartbeat-execution-configuration.test.ts`. New cases: refused without a connection, refused for a preconfigured home, managed passes, resumed native input passes, non-task plugin driver passes. The refused cases also check that observability, secrets, and the managed runtime did not start. - `src/__tests__/heartbeat-plugin-environment.test.ts`. One test, "inherits the instance default environment across companies…", also fails on unmodified `master` in my environment. This change does not touch it, because its driver does not declare `supportsTasks`. - `src/adapters/registry.test.ts`, `src/__tests__/agent-harness-verification.test.ts`, `src/modules/agent-lifecycle/__tests__/diagnostics.test.ts`, `src/services/recovery/stranded-notice.test.ts`, and `src/services/__tests__/run-failure-report.test.ts`. - 17 more suites that use plugin Runner-task environments, with 705 tests: `plugin-runner-task.integration`, `plugin-warm-tasks.integration`, `task-creation-recovery.integration`, `native-startup-cleanup-recovery`, `environment-task-authority.integration`, `plugin-task-credential-writeback`, agent-lifecycle `lifecycle`, `setup`, and `environment-plugins`, `workspace-preparation`, `agent-runner-selection`, `agent-harness-verification-provider-api`, `agent-harness-verification-remote`, `plugin-environment-driver-seam`, `environment-task-runtime`, `agent-test-environment-routes`, and `adapter-registry`. - `pnpm typecheck` in `server/` reported no errors in the changed files. Its only errors came from sandbox-provider packages that my local install did not link. - Not run: `plugin-runner-probe.test.ts`, because it needs a Cargo build. This change does not modify `probePluginRunnerEnvironment`. Also not run: the full `pnpm test:run` and `pnpm build`. CI runs them. ## Risks - Behavior change: an agent in a plugin Runner-task environment with no managed AI connection now stops before dispatch. Before, it ran with the host's installed account. The agent's owner must choose an AI connection. This includes agents with `homeMode: "preconfigured"` in these environments. - Runs that were already admitted and resume from saved native input are not refused. They keep the earlier behavior until they finish. - The check reads the plugin manifest on each new run admission for plugin environments. This is the same lookup that runner selection already does. - This pull request and #19326 both edit `stranded-notice.ts` and `failure.ts`. The changes are additive, but whichever merges second needs a small rebase. ## Model Used - Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, in Claude Code with tool use (file edits, shell, test runs). Default context window, extended thinking on. ## 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 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bf10bc695a
commit
f9d366acdf
23 files changed
+357
-48
No files matched your search
@@ -177,8 +177,7 @@ change, reject submission and require new preparation and validation.
|
||||
Return `project_auth` with the same configuration ID and provider.
|
||||
Set `allowed: true` only after the checks pass.
|
||||
Core saves this result on the task lease. Core requires the exact configuration,
|
||||
provider, and project set before each submission. This also applies when the
|
||||
provider uses an installed account.
|
||||
provider, and project set before each submission.
|
||||
A new preparation or check removes the prior validation. A failed check does not
|
||||
authorize credential transfer. The dispatch update also checks that validation
|
||||
has not changed while Core waited for database work.
|
||||
@@ -268,9 +267,10 @@ after the probe and its descendants stop. A lost reply keeps the task available
|
||||
for `stop`, `status`, and `complete`. Core checks the profile and model before
|
||||
it accepts the account. Do not store the token in task metadata or logs.
|
||||
|
||||
For a native hello probe, select a saved AI account or use the installed account.
|
||||
Core rejects local environment overrides when no saved account is selected.
|
||||
This includes draft credentials. The probe uses the installed VM environment. Core does not test a different installed account in their place.
|
||||
A native hello probe requires a managed AI connection and an isolated Runner home.
|
||||
Without them, the probe fails the `ai_connection_required` check before Core
|
||||
acquires a lease or calls a task operation. See
|
||||
[Managed AI connection required](PLUGIN_RUNNER_EXECUTION.md#managed-ai-connection-required).
|
||||
Only Core can supply the selected account identity and local credential home.
|
||||
|
||||
## Fresh attempts
|
||||
|
||||
@@ -4,6 +4,23 @@ Core can run `paperclip_runner` tasks in a plugin environment.
|
||||
The plugin owns the execution host and its files.
|
||||
Core owns run identity, selected policy, assigned tools, and the PRP journal.
|
||||
|
||||
## Managed AI connection required
|
||||
|
||||
A task-capable environment runs only agents with a managed AI connection.
|
||||
Core does not use an account installed on the plugin's execution host.
|
||||
Before it acquires a lease or calls the plugin, Core fails a new run that has
|
||||
no managed AI connection. A `homeMode: "preconfigured"` Runner home does not use
|
||||
the agent's AI connection, so Core refuses it in the same way. The run fails as
|
||||
`configuration_incomplete` with reason `ai_connection_required`. The task is
|
||||
blocked with a notice that names the fix: choose an AI connection, or switch to
|
||||
an isolated Runner home. Agent verification applies the same rule before it
|
||||
resolves the probe target, so it acquires no lease. The agent Test route also
|
||||
checks before it resolves secrets or allocates a test target. A setup probe without a
|
||||
managed AI connection, or with a preconfigured home, fails the
|
||||
`ai_connection_required` check and calls no task operation. Verification then
|
||||
waits for the configuration to change.
|
||||
A resumed native run keeps the contract it was admitted under.
|
||||
|
||||
## Required hooks
|
||||
|
||||
Set `supportsTasks: true` on the environment driver.
|
||||
@@ -224,8 +241,7 @@ plugin runs without an explicit policy prefer warm execution. There is no
|
||||
provider-specific warm gate or additional setting. Existing runs retain their
|
||||
admitted lifecycle policy during restart recovery. The existing
|
||||
`runnerIdleTimeoutMs` controls bounded retention. Fresh warm admission requires
|
||||
a Core-managed credential identity before lease acquisition. Plugin-owned installed
|
||||
accounts continue per-turn until such an identity is available; the saved warm
|
||||
a Core-managed credential identity before lease acquisition. The saved warm
|
||||
preference does not bypass account ownership checks. Drivers without warm
|
||||
capability and setup probes remain ephemeral.
|
||||
|
||||
|
||||
Reference in new issue
Block a user