feat(backend): queue-time runtime/profile validation; job.runtime authoritative in worker
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
import { describe, expect, test, vi } from 'vitest';
|
||||
import { mkdtemp, readFile, rm, stat } from 'node:fs/promises';
|
||||
import { tmpdir } from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
||||
import { afterEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
import type { NormalizedAgentEvent } from '../../src/agent-events';
|
||||
import type { ExecStreamFn } from '../../src/runtime/agent-runtime';
|
||||
@@ -51,6 +55,69 @@ const makeWorkspace = (): AdapterWorkspace => ({
|
||||
runtime: 'claude',
|
||||
});
|
||||
|
||||
const makeOAuthWorkspace = (
|
||||
homeDir: string,
|
||||
authType: 'anthropic_oauth_json' | 'opencode_auth_json',
|
||||
): AdapterWorkspace => ({
|
||||
claim: {
|
||||
...claim,
|
||||
aiProviderProfile: {
|
||||
id: 'p',
|
||||
name: 'Anthropic',
|
||||
provider: 'anthropic',
|
||||
authType,
|
||||
secret: JSON.stringify({ access_token: 'oauth-token' }),
|
||||
model: 'claude-sonnet-4',
|
||||
reasoningEffort: 'medium',
|
||||
},
|
||||
} as unknown as Claim,
|
||||
workdir: homeDir,
|
||||
homeDir,
|
||||
username: 'tester',
|
||||
containerHome: '/home/tester',
|
||||
containerRepo: '/home/tester/Code/spoon',
|
||||
repoDir: path.join(homeDir, 'Code/spoon'),
|
||||
boxName: 'spoon-box-tester',
|
||||
redact: (value: string) => value,
|
||||
runtime: 'claude',
|
||||
});
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
afterEach(async () => {
|
||||
while (tempDirs.length) {
|
||||
const dir = tempDirs.pop();
|
||||
if (dir) await rm(dir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
describe('ClaudeCodeAdapter prepareAuth', () => {
|
||||
test('writes credentials.json for an anthropic_oauth_json profile', async () => {
|
||||
const { createClaudeAdapter } = await loadAdapter();
|
||||
const homeDir = await mkdtemp(path.join(tmpdir(), 'spoon-claude-oauth-'));
|
||||
tempDirs.push(homeDir);
|
||||
|
||||
const adapter = createClaudeAdapter();
|
||||
await adapter.prepareAuth(makeOAuthWorkspace(homeDir, 'anthropic_oauth_json'));
|
||||
|
||||
const credentialsPath = path.join(homeDir, '.claude', '.credentials.json');
|
||||
const contents = await readFile(credentialsPath, 'utf8');
|
||||
expect(contents).toContain('oauth-token');
|
||||
});
|
||||
|
||||
test('does not write credentials.json for an opencode_auth_json profile', async () => {
|
||||
const { createClaudeAdapter } = await loadAdapter();
|
||||
const homeDir = await mkdtemp(path.join(tmpdir(), 'spoon-claude-oauth-'));
|
||||
tempDirs.push(homeDir);
|
||||
|
||||
const adapter = createClaudeAdapter();
|
||||
await adapter.prepareAuth(makeOAuthWorkspace(homeDir, 'opencode_auth_json'));
|
||||
|
||||
const credentialsPath = path.join(homeDir, '.claude', '.credentials.json');
|
||||
await expect(stat(credentialsPath)).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ClaudeCodeAdapter', () => {
|
||||
test('streams normalized events and marks the turn via buildMarkedCommand', async () => {
|
||||
const { createClaudeAdapter } = await loadAdapter();
|
||||
|
||||
Reference in New Issue
Block a user