@tickernelz/paperclip-pro-adapter-utils 2026.929.2 → 2026.929.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1365,6 +1365,49 @@ describe("shared ACPX engine runtime behavior", () => {
1365
1365
  expect(authStat.isSymbolicLink()).toBe(true);
1366
1366
  expect(path.resolve(path.dirname(managedAuth), await fs.readlink(managedAuth))).toBe(sourceAuth);
1367
1367
  });
1368
+ it.each(["OPENAI_API_KEY", "CODEX_API_KEY"])("uses isolated API-key auth instead of the host ChatGPT login for %s", async (keyName) => {
1369
+ const root = await makeTempRoot();
1370
+ const sourceCodexHome = path.join(root, "source-codex-home");
1371
+ const paperclipHome = path.join(root, "paperclip-home");
1372
+ await fs.mkdir(sourceCodexHome, { recursive: true });
1373
+ const sourceAuth = path.join(sourceCodexHome, "auth.json");
1374
+ await fs.writeFile(sourceAuth, JSON.stringify({ tokens: "host-login" }), "utf8");
1375
+ const managedHome = path.join(paperclipHome, "instances", "test-instance", "companies", "company-1", "acp-engine", "agents", "agent-1", "codex-home");
1376
+ await fs.mkdir(managedHome, { recursive: true });
1377
+ const managedAuth = path.join(managedHome, "auth.json");
1378
+ if (process.platform === "win32") {
1379
+ await fs.writeFile(managedAuth, JSON.stringify({ tokens: "stale-login" }), "utf8");
1380
+ }
1381
+ else {
1382
+ await fs.symlink(sourceAuth, managedAuth);
1383
+ }
1384
+ vi.stubEnv("CODEX_HOME", sourceCodexHome);
1385
+ vi.stubEnv("PAPERCLIP_HOME", paperclipHome);
1386
+ vi.stubEnv("PAPERCLIP_INSTANCE_ID", "test-instance");
1387
+ vi.stubEnv("OPENAI_API_KEY", "");
1388
+ vi.stubEnv("CODEX_API_KEY", "");
1389
+ try {
1390
+ const { sessionInputs } = await runExecutor({
1391
+ agent: "codex",
1392
+ stateDir: path.join(root, "state"),
1393
+ env: { [keyName]: "sk-acp-test-key" },
1394
+ paperclipRuntimeSkills: [],
1395
+ paperclipSkillSync: { desiredSkills: [] },
1396
+ });
1397
+ const sessionEnv = sessionInputs[0].sessionOptions.env;
1398
+ expect(sessionEnv.CODEX_HOME).toBe(managedHome);
1399
+ expect(sessionEnv.DEFAULT_AUTH_REQUEST).toBe(JSON.stringify({ methodId: "api-key" }));
1400
+ expect((await fs.lstat(managedAuth)).isSymbolicLink()).toBe(false);
1401
+ expect(JSON.parse(await fs.readFile(managedAuth, "utf8"))).toEqual({ OPENAI_API_KEY: "sk-acp-test-key" });
1402
+ expect(await fs.readFile(sourceAuth, "utf8")).toBe(JSON.stringify({ tokens: "host-login" }));
1403
+ if (process.platform !== "win32") {
1404
+ expect((await fs.stat(managedAuth)).mode & 0o777).toBe(0o600);
1405
+ }
1406
+ }
1407
+ finally {
1408
+ vi.unstubAllEnvs();
1409
+ }
1410
+ });
1368
1411
  it("sets GROK_HOME for a Grok run from the company Grok home, and leaves CODEX_HOME unchanged for a Codex run", async () => {
1369
1412
  const root = await makeTempRoot();
1370
1413
  const paperclipHome = path.join(root, "paperclip-home");
@@ -2636,6 +2679,35 @@ describe("ACPX engine remote sandbox staging seam (PR 1: workspace + cwd)", () =
2636
2679
  // And session/new is created on the in-sandbox workspace cwd.
2637
2680
  expect(sessionInputs[0]?.cwd).toBe(remoteCwd);
2638
2681
  });
2682
+ it.skipIf(process.platform === "win32")("never seeds a remote Codex run from a host API key", async () => {
2683
+ const { root, stateDir, localCwd, executionTarget } = await setupRemoteSandbox();
2684
+ const sourceCodexHome = path.join(root, "source-codex-home");
2685
+ const paperclipHome = path.join(root, "paperclip-home");
2686
+ await fs.mkdir(sourceCodexHome, { recursive: true });
2687
+ const sourceAuth = path.join(sourceCodexHome, "auth.json");
2688
+ await fs.writeFile(sourceAuth, JSON.stringify({ tokens: "host-login" }), "utf8");
2689
+ vi.stubEnv("CODEX_HOME", sourceCodexHome);
2690
+ vi.stubEnv("PAPERCLIP_HOME", paperclipHome);
2691
+ vi.stubEnv("PAPERCLIP_INSTANCE_ID", "test-instance");
2692
+ vi.stubEnv("OPENAI_API_KEY", "sk-host-only-key");
2693
+ try {
2694
+ await runExecutor({
2695
+ agent: "codex",
2696
+ stateDir,
2697
+ cwd: localCwd,
2698
+ paperclipRuntimeSkills: [],
2699
+ paperclipSkillSync: { desiredSkills: [] },
2700
+ }, { authToken: "real-run-jwt", executionTarget });
2701
+ }
2702
+ finally {
2703
+ vi.unstubAllEnvs();
2704
+ }
2705
+ const instanceRoot = path.join(paperclipHome, "instances", "test-instance", "companies", "company-1");
2706
+ const subscriptionAuth = path.join(instanceRoot, "codex-home", "auth.json");
2707
+ expect((await fs.lstat(subscriptionAuth)).isSymbolicLink()).toBe(true);
2708
+ await expect(fs.readFile(path.join(instanceRoot, "acp-engine", "agents", "agent-1", "codex-home", "auth.json"), "utf8")).rejects.toMatchObject({ code: "ENOENT" });
2709
+ expect(await fs.readFile(sourceAuth, "utf8")).toBe(JSON.stringify({ tokens: "host-login" }));
2710
+ });
2639
2711
  it("hands the merged paperclip env to the process-session launch when the setups overlap", async () => {
2640
2712
  const { stateDir, localCwd, remoteCwd, executionTarget } = await setupRemoteSandbox();
2641
2713
  // Decode the process-session LAUNCH payload (the base64 command blob) — the