mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 02:26:12 +02:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agent runtime settings can bind organization secrets to an adapter environment > - Paperclip redacts plain environment values when it returns a saved agent to the UI > - A saved-agent test sent the redacted `CODEX_HOME` value back to the server > - Codex ACP also received the API key without an ACP API-key authentication request > - This pull request restores saved environment values for tests and selects API-key authentication for Codex ACP runs > - The benefit is that Codex agents can test and run with an organization-scoped OpenAI API key ## Linked Issues or Issue Description **What happened?** Testing a saved Codex agent sent `***REDACTED***` as `CODEX_HOME`. Secret normalization rejected that placeholder. Remote Codex ACP runs received `OPENAI_API_KEY`, but session creation stopped with `Authentication required`. **Expected behavior** Paperclip must use the saved `CODEX_HOME` value when it tests an existing agent. Codex ACP must select API-key authentication when `OPENAI_API_KEY` is available. **Steps to reproduce** 1. Create an organization-scoped secret named `OPENAI_API_KEY`. 2. Give a Codex agent access to the secret. 3. Save the agent runtime settings. 4. Test the saved agent again. 5. Run the agent in a remote sandbox through ACP. **Paperclip version or commit** Reproduced on master before commit `68c17709d7c051a804a416263e2e08920f1dfcb1`. **Deployment mode** Self-hosted server with a remote sandbox environment. **Installation method** Built from source. **Agent adapter(s) involved** Codex. ## What Changed - Send the saved agent ID with adapter environment tests. - Restore redacted plain environment values from the saved agent before test-time secret resolution. - Select the Codex ACP `api-key` authentication method when `OPENAI_API_KEY` is present. - Add focused regression coverage for saved-agent tests and remote ACP launch configuration. ## Verification - `pnpm --filter @paperclipai/adapter-utils exec vitest run src/acpx-engine/execute.test.ts` - `pnpm --filter @paperclipai/server exec vitest run src/__tests__/agent-adapter-validation-routes.test.ts` - `pnpm --filter @paperclipai/ui exec vitest run src/lib/test-agent-setup.test.ts` - `pnpm -r typecheck` - `pnpm test:run` - `pnpm build` - `git diff --check` ## Risks - Low risk. The test route reads saved configuration only when the request supplies a compatible agent ID and the caller can update that agent. - The Codex ACP change applies only when `OPENAI_API_KEY` exists and no explicit `DEFAULT_AUTH_REQUEST` exists. - There are no schema migrations or telemetry changes. > 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 with `gpt-5`. The context-window size is not exposed in this runtime. The model used reasoning, repository search, file editing, command execution, and test 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 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>
82 lines
2.3 KiB
TypeScript
82 lines
2.3 KiB
TypeScript
import { beforeEach, expect, it, vi } from "vitest";
|
|
import { testAgentSetup } from "./test-agent-setup";
|
|
const testEnvironment = vi.hoisted(() => vi.fn());
|
|
vi.mock("../api/agents", () => ({ agentsApi: { testEnvironment } }));
|
|
const input = {
|
|
companyId: "company-1",
|
|
agentId: "agent-1",
|
|
adapterType: "paperclip_runner",
|
|
providerAdapter: "claude_local",
|
|
environmentId: "sandbox-1",
|
|
adapterConfig: {
|
|
provider: "acpx",
|
|
acpxAgent: "claude",
|
|
env: {
|
|
ANTHROPIC_API_KEY: {
|
|
type: "user_secret_ref",
|
|
key: "ANTHROPIC_API_KEY",
|
|
version: "latest",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
const ready = {
|
|
adapterType: "paperclip_runner",
|
|
status: "pass",
|
|
testedAt: "now",
|
|
checks: [{ code: "runtime", level: "info", message: "Ready" }],
|
|
};
|
|
beforeEach(() => testEnvironment.mockReset());
|
|
it("does not report a connection when runtime readiness passes but provider authentication fails", async () => {
|
|
testEnvironment
|
|
.mockResolvedValueOnce(ready)
|
|
.mockResolvedValueOnce({
|
|
...ready,
|
|
adapterType: "claude_local",
|
|
status: "fail",
|
|
checks: [
|
|
{
|
|
code: "claude_hello_probe_failed",
|
|
level: "error",
|
|
message: "Invalid API key",
|
|
},
|
|
],
|
|
});
|
|
const result = await testAgentSetup(input);
|
|
expect(result.status).toBe("fail");
|
|
expect(result.adapterType).toBe("paperclip_runner");
|
|
expect(testEnvironment).toHaveBeenLastCalledWith(
|
|
"company-1",
|
|
"claude_local",
|
|
{
|
|
agentId: "agent-1",
|
|
environmentId: "sandbox-1",
|
|
adapterConfig: { ...input.adapterConfig, engine: "cli" },
|
|
},
|
|
);
|
|
expect(result.checks.map((check) => check.code)).toEqual([
|
|
"runtime",
|
|
"claude_hello_probe_failed",
|
|
]);
|
|
});
|
|
it("does not repeat a completed model probe", async () => {
|
|
testEnvironment.mockResolvedValue({
|
|
...ready,
|
|
checks: [
|
|
{ code: "codex_hello_probe_passed", level: "info", message: "Hello" },
|
|
],
|
|
});
|
|
await testAgentSetup({
|
|
...input,
|
|
adapterType: "codex_local",
|
|
providerAdapter: "codex_local",
|
|
});
|
|
expect(testEnvironment).toHaveBeenCalledTimes(1);
|
|
});
|
|
it("preserves runtime warnings after a successful provider request", async () => {
|
|
testEnvironment
|
|
.mockResolvedValueOnce({ ...ready, status: "warn" })
|
|
.mockResolvedValueOnce(ready);
|
|
expect((await testAgentSetup(input)).status).toBe("warn");
|
|
});
|