Files
stack/packages/plugins/tests/proxy-harness.test.mjs
jason.woltje 39eadf8ba8 Row 332 R2 (#1830): hermetic pi launches in cli tests, pi bundle default, review F2 and F3
The cli tests that launch pi deleted only the session login names, so pi's
preflight passed or refused by whatever provider keys the host exported. A
shared helper now deletes every credential pi's preflight reads and gives pi
launches one made-up key. The refusal itself is unchanged.

pi bundle() takes a default argument again, so a call with none returns the
non-proxy bundle, as before P3. pi.bundle leaves out a launch.models entry
whose provider has no proxy route instead of failing every pi launch (F2);
malformed proxy entries still refuse. The invalid session proxy context
BundleError gets the code invalid-proxy-context. New tests cover F2, the code,
and the three proxy account branches in the launcher (F3).
2026-11-02 15:22:17 -06:00

77 lines
3.7 KiB
JavaScript

// P3: run real harness exports through the plug-in loader, with made-up session keys only.
import test from 'node:test';
import assert from 'node:assert/strict';
import { chmodSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { createLoader } from '../src/loader.mjs';
import { sessionEnv } from '../../seat/src/session.mjs';
async function harness(name) {
const loader = createLoader({ log() {} });
const result = await loader.load({ harness: [name] });
assert.deepEqual(result.refused, []);
return loader.modules('harness')[0];
}
function scratch(t) {
const root = mkdtempSync(join(tmpdir(), 'p332-'));
t.after(() => rmSync(root, { recursive: true, force: true }));
return root;
}
const policy = { tools: [], typed: [] };
const session = { model: 'claude-fixture', thinking: 'low' };
test('P3 Claude env receives the session proxy URL and key, without another agent or host credential', async () => {
const claude = await harness('claude-code');
const host = { CLAUDE_CODE_OAUTH_TOKEN: 'fx332-host', OPENAI_API_KEY: 'fx332-upstream' };
for (const [run, key] of [['r332a', 'fx332-agent-a'], ['r332b', 'fx332-agent-b']]) {
const proxy = { baseUrl: 'http://127.0.0.1:12345', key };
const env = { ...sessionEnv(host, run, proxy), ...claude.env({ files: {}, policy, session, proxy }) };
assert.equal(env.ANTHROPIC_BASE_URL, 'http://127.0.0.1:12345');
assert.equal(env.ANTHROPIC_AUTH_TOKEN, key);
assert.equal(Object.hasOwn(env, 'CLAUDE_CODE_OAUTH_TOKEN'), false);
assert.equal(Object.hasOwn(env, 'OPENAI_API_KEY'), false);
const other = run === 'r332a' ? 'fx332-agent-b' : 'fx332-agent-a';
assert.ok(!Object.values(env).includes(other));
}
});
test('P3 Claude preflight accepts a proxy key without a host provider credential', async t => {
const claude = await harness('claude-code');
const root = scratch(t), binary = join(root, 'claude');
writeFileSync(binary, '#!/bin/sh\nexit 0\n');
chmodSync(binary, 0o700);
assert.equal(claude.preflight({ env: { MOSAIC_CLAUDE_BIN: binary }, proxy: {
baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a',
} }), null);
});
test('P3 pi refuses no-session-credential with no provider key', async () => {
const pi = await harness('pi');
assert.equal(pi.preflight({ env: {} })?.code, 'no-session-credential');
});
test('P3 pi refuses no-session-credential with only a Claude OAuth token', async () => {
const pi = await harness('pi');
assert.equal(pi.preflight({ env: { CLAUDE_CODE_OAUTH_TOKEN: 'fx332-oauth' } })?.code, 'no-session-credential');
});
test('P3 pi accepts its own provider key or a session proxy key', async () => {
const pi = await harness('pi');
for (const name of ['ANTHROPIC_API_KEY', 'OPENAI_API_KEY', 'OPENROUTER_API_KEY', 'ZAI_API_KEY']) {
assert.equal(pi.preflight({ env: { [name]: 'fx332-own' } }), null, name);
}
assert.equal(pi.preflight({ env: {}, proxy: { baseUrl: 'http://127.0.0.1:12345', key: 'fx332-agent-a' } }), null);
});
// Row 332 R2 (#1830): callers that only want pi's bundle sources call bundle() with no argument,
// as they could before P3 (packages/cli/tests/stack-copy.test.mjs). It returns the non-proxy bundle.
test('row 332 R2 pi bundle() with no argument returns the non-proxy bundle it returned before P3', async () => {
const pi = await harness('pi');
const base = pi.bundle();
assert.deepEqual(base.files, {});
assert.deepEqual(base.digests, []);
assert.deepEqual(Object.keys(base.sources).sort(), ['piExtension', 'unslopCheck', 'unslopExtension', 'unslopLists']);
assert.deepEqual(pi.bundle({ dir: '/nonexistent/bundle', models: {} }), base, 'same as a call with no proxy context');
});