mirror of
https://github.com/stablyai/orca.git
synced 2026-11-02 18:17:36 +00:00
Co-authored-by: Luchong <lu740528977@gmail.com> Co-authored-by: GuanBear <guanbear@users.noreply.github.com>
472 lines
17 KiB
TypeScript
472 lines
17 KiB
TypeScript
import {
|
|
cpSync,
|
|
mkdirSync,
|
|
mkdtempSync,
|
|
readFileSync,
|
|
readdirSync,
|
|
rmSync,
|
|
writeFileSync
|
|
} from 'node:fs'
|
|
import { buildSync } from 'esbuild'
|
|
import { runProcess } from '@orca/process-host'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { readZcodeV2PlanCredential, type ZcodeCredentialHost } from './zcode-v2-plan-credentials'
|
|
import { readZcodeUsageCredentials } from '../rate-limits/zcode-usage-credentials'
|
|
import { fetchZcodeRateLimits } from '../rate-limits/zcode-usage-fetcher'
|
|
|
|
let dir: string
|
|
let host: ZcodeCredentialHost
|
|
const fixtureRoot = join(import.meta.dirname, 'fixtures', 'v2-upstream')
|
|
function install(name = 'zai') {
|
|
cpSync(join(fixtureRoot, name), join(dir, '.zcode', 'v2'), { recursive: true })
|
|
}
|
|
function legacy() {
|
|
mkdirSync(join(dir, '.zcode', 'cli'), { recursive: true })
|
|
writeFileSync(
|
|
join(dir, '.zcode', 'cli', 'config.json'),
|
|
JSON.stringify({
|
|
model: 'legacy/GLM',
|
|
provider: {
|
|
legacy: { options: { apiKey: 'synthetic-legacy-key', baseURL: 'https://open.bigmodel.cn' } }
|
|
}
|
|
})
|
|
)
|
|
}
|
|
function quota() {
|
|
return new Response(
|
|
JSON.stringify({
|
|
success: true,
|
|
data: { limits: [{ type: 'TOKENS_LIMIT', unit: 3, number: 5, percentage: 12 }] }
|
|
})
|
|
)
|
|
}
|
|
beforeEach(() => {
|
|
dir = mkdtempSync(join(tmpdir(), 'orca-zcode-v2-'))
|
|
host = {
|
|
home: dir,
|
|
platform: 'linux',
|
|
username: 'synthetic-user',
|
|
env: { ZCODE_DATA_BASE_DIR: dir, ZCODE_CREDENTIAL_SECRET: 'synthetic-secret' }
|
|
}
|
|
vi.stubGlobal(
|
|
'fetch',
|
|
vi.fn(async () => quota())
|
|
)
|
|
})
|
|
afterEach(() => {
|
|
vi.unstubAllGlobals()
|
|
rmSync(dir, { recursive: true, force: true })
|
|
})
|
|
|
|
describe('upstream-written ZCode v2 stores', () => {
|
|
it.each(['zai', 'bigmodel'])(
|
|
'reads selected %s plan, exact encoded identity key and site without writing',
|
|
async (name) => {
|
|
install(name)
|
|
const before = readFileSync(join(dir, '.zcode', 'v2', 'credentials.json'))
|
|
expect(readZcodeV2PlanCredential(host)).toMatchObject({
|
|
status: 'ok',
|
|
apiKey: `synthetic-${name}-key`,
|
|
baseUrl: name === 'zai' ? 'https://api.z.ai' : 'https://open.bigmodel.cn'
|
|
})
|
|
const result = await fetchZcodeRateLimits({ credentialHost: host })
|
|
expect(result.status).toBe('ok')
|
|
const call = vi.mocked(fetch).mock.calls[0]
|
|
expect(String(call[0])).toContain(name === 'zai' ? 'api.z.ai' : 'open.bigmodel.cn')
|
|
expect(new Headers(call[1]?.headers).get('Authorization')).toBe(`synthetic-${name}-key`)
|
|
expect(JSON.stringify(result)).not.toContain(`synthetic-${name}-key`)
|
|
expect(JSON.stringify(result)).not.toContain('synthetic account')
|
|
expect(readFileSync(join(dir, '.zcode', 'v2', 'credentials.json'))).toEqual(before)
|
|
expect(readdirSync(join(dir, '.zcode', 'v2')).sort()).toEqual([
|
|
'credentials.json',
|
|
'provider_config.json'
|
|
])
|
|
}
|
|
)
|
|
|
|
it('prefers migrated credentials over a stale legacy account', () => {
|
|
legacy()
|
|
install()
|
|
const result = readZcodeUsageCredentials({ credentialHost: host })
|
|
expect(result).toMatchObject({ status: 'ok', credentials: { apiKey: 'synthetic-zai-key' } })
|
|
})
|
|
|
|
it('keeps legacy support when no personal v2 file exists', () => {
|
|
legacy()
|
|
expect(readZcodeUsageCredentials({ credentialHost: host })).toMatchObject({
|
|
status: 'ok',
|
|
credentials: { apiKey: 'synthetic-legacy-key' }
|
|
})
|
|
})
|
|
|
|
it.each([
|
|
'unsupported',
|
|
'missing-selection',
|
|
'future-schema',
|
|
'invalid-json',
|
|
'bad-ciphertext',
|
|
'missing-key'
|
|
])('never substitutes legacy credentials for %s v2 state', async (kind) => {
|
|
legacy()
|
|
install()
|
|
const path = join(dir, '.zcode', 'v2', 'provider_config.json')
|
|
if (kind === 'unsupported') {
|
|
writeFileSync(
|
|
path,
|
|
JSON.stringify({
|
|
schemaVersion: 1,
|
|
config: {
|
|
defaultModelSelection: { providerId: 'account:zai-team-coding-plan', modelId: 'GLM' }
|
|
}
|
|
})
|
|
)
|
|
}
|
|
if (kind === 'missing-selection') {
|
|
writeFileSync(path, JSON.stringify({ schemaVersion: 1, config: {} }))
|
|
}
|
|
if (kind === 'future-schema') {
|
|
writeFileSync(path, JSON.stringify({ schemaVersion: 2, config: {} }))
|
|
}
|
|
if (kind === 'invalid-json') {
|
|
writeFileSync(path, 'not-json')
|
|
}
|
|
if (kind === 'bad-ciphertext') {
|
|
writeFileSync(
|
|
join(dir, '.zcode', 'v2', 'credentials.json'),
|
|
JSON.stringify({
|
|
'account-provider:account:zai-individual-coding-plan:identity': 'enc:v1:broken'
|
|
})
|
|
)
|
|
}
|
|
if (kind === 'missing-key') {
|
|
writeFileSync(join(dir, '.zcode', 'v2', 'credentials.json'), '{}')
|
|
}
|
|
const result = await fetchZcodeRateLimits({ credentialHost: host })
|
|
expect(['unavailable', 'error']).toContain(result.status)
|
|
expect(result.session).toBeNull()
|
|
expect(fetch).not.toHaveBeenCalled()
|
|
expect(JSON.stringify(result)).not.toContain('synthetic-legacy-key')
|
|
})
|
|
|
|
it('honors custom secret and does not decrypt another host secret', () => {
|
|
install()
|
|
expect(readZcodeV2PlanCredential(host).status).toBe('ok')
|
|
expect(
|
|
readZcodeV2PlanCredential({
|
|
...host,
|
|
env: { ...host.env, ZCODE_CREDENTIAL_SECRET: 'wrong-secret' }
|
|
})
|
|
).toEqual({ status: 'error' })
|
|
})
|
|
|
|
it('honors the upstream personal config override independently of the credential directory', () => {
|
|
install()
|
|
const selected = join(dir, 'selected.json')
|
|
cpSync(join(dir, '.zcode', 'v2', 'provider_config.json'), selected)
|
|
writeFileSync(join(dir, '.zcode', 'v2', 'provider_config.json'), 'invalid-default')
|
|
expect(
|
|
readZcodeV2PlanCredential({
|
|
...host,
|
|
env: { ...host.env, ZCODE_PERSONAL_PROVIDER_CONFIG_FILE: '~/selected.json' }
|
|
})
|
|
).toMatchObject({ status: 'ok', configPath: selected })
|
|
})
|
|
|
|
it('accepts upstream plaintext compatibility and rejects header injection without a request', async () => {
|
|
install()
|
|
const path = join(dir, '.zcode', 'v2', 'credentials.json')
|
|
const identityKey = 'account-provider:account:zai-individual-coding-plan:identity'
|
|
const apiKey =
|
|
'account-provider:coding-plan:account:zai-individual-coding-plan:account:synthetic:api-key'
|
|
writeFileSync(
|
|
path,
|
|
JSON.stringify({ [identityKey]: 'synthetic', [apiKey]: 'synthetic-plain-key' })
|
|
)
|
|
expect(readZcodeV2PlanCredential(host)).toMatchObject({
|
|
status: 'ok',
|
|
apiKey: 'synthetic-plain-key'
|
|
})
|
|
writeFileSync(
|
|
path,
|
|
JSON.stringify({ [identityKey]: 'synthetic', [apiKey]: 'key\r\nInjected: value' })
|
|
)
|
|
expect((await fetchZcodeRateLimits({ credentialHost: host })).status).toBe('error')
|
|
expect(fetch).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('uses execution-host identity, not data-directory identity, for the fallback cipher', () => {
|
|
install('fallback-host')
|
|
const fallback = { ...host, home: '/synthetic/home', env: { ZCODE_DATA_BASE_DIR: dir } }
|
|
expect(readZcodeV2PlanCredential(fallback)).toMatchObject({
|
|
status: 'ok',
|
|
apiKey: 'synthetic-fallback-host-key'
|
|
})
|
|
for (const changed of [
|
|
{ home: '/other/home' },
|
|
{ platform: 'win32' },
|
|
{ username: 'other-user' }
|
|
]) {
|
|
expect(readZcodeV2PlanCredential({ ...fallback, ...changed })).toEqual({ status: 'error' })
|
|
}
|
|
})
|
|
|
|
it('does not borrow credentials from another execution host', () => {
|
|
install()
|
|
const other = join(dir, 'other-host')
|
|
mkdirSync(other)
|
|
expect(
|
|
readZcodeV2PlanCredential({
|
|
...host,
|
|
home: other,
|
|
env: { ZCODE_DATA_BASE_DIR: other, ZCODE_CREDENTIAL_SECRET: 'synthetic-secret' }
|
|
})
|
|
).toEqual({ status: 'absent' })
|
|
})
|
|
|
|
it('preserves the protected Orca key priority even if v2 is corrupt', async () => {
|
|
install()
|
|
writeFileSync(join(dir, '.zcode', 'v2', 'credentials.json'), 'broken')
|
|
const result = await fetchZcodeRateLimits({
|
|
credentialHost: host,
|
|
planCredential: { apiKey: 'synthetic-orca-key', baseUrl: 'https://open.bigmodel.cn' }
|
|
})
|
|
expect(result.status).toBe('ok')
|
|
expect(result.usageMetadata?.credentialSource).toBe('orca-plan')
|
|
})
|
|
|
|
it.each(['site', 'account', 'corrupt', 'network-error'])(
|
|
'drops an in-flight quota when %s changes',
|
|
async (change) => {
|
|
install()
|
|
vi.mocked(fetch).mockImplementationOnce(async () => {
|
|
if (change === 'site') {
|
|
install('bigmodel')
|
|
} else if (change === 'account') {
|
|
install('zai-other')
|
|
} else {
|
|
writeFileSync(join(dir, '.zcode', 'v2', 'credentials.json'), 'broken')
|
|
}
|
|
if (change === 'network-error') {
|
|
throw new Error('Synthetic transport failure')
|
|
}
|
|
return quota()
|
|
})
|
|
const result = await fetchZcodeRateLimits({ credentialHost: host })
|
|
expect(result.status).toBe('unavailable')
|
|
expect(result.session).toBeNull()
|
|
}
|
|
)
|
|
})
|
|
|
|
describe('external v2 file boundaries', () => {
|
|
it.each(['provider_config.json', 'credentials.json'])(
|
|
'refuses oversized %s without legacy fallback',
|
|
(name) => {
|
|
install()
|
|
legacy()
|
|
const path = join(dir, '.zcode', 'v2', name)
|
|
const record = JSON.parse(readFileSync(path, 'utf8'))
|
|
record['unrelated'] = 'x'.repeat(4 * 1024 * 1024)
|
|
writeFileSync(path, JSON.stringify(record))
|
|
expect(readZcodeUsageCredentials({ credentialHost: host }).status).toBe('error')
|
|
}
|
|
)
|
|
|
|
it.each(['provider_config.json', 'credentials.json'])('refuses a directory at %s', (name) => {
|
|
install()
|
|
const path = join(dir, '.zcode', 'v2', name)
|
|
rmSync(path)
|
|
mkdirSync(path)
|
|
expect(readZcodeV2PlanCredential(host).status).toBe('error')
|
|
})
|
|
|
|
it.skipIf(process.platform === 'win32').each([
|
|
{ name: 'provider_config.json', replace: false },
|
|
{ name: 'credentials.json', replace: false },
|
|
{ name: 'provider_config.json', replace: true },
|
|
{ name: 'credentials.json', replace: true }
|
|
])(
|
|
'settles FIFO $name with replacement $replace in a timeout-fenced child',
|
|
async ({ name, replace }) => {
|
|
install()
|
|
const path = join(dir, '.zcode', 'v2', name)
|
|
const fifoPath = replace ? join(dir, 'replacement.fifo') : path
|
|
if (!replace) {
|
|
rmSync(path)
|
|
}
|
|
expect((await runProcess({ program: 'mkfifo', args: [fifoPath] })).code).toBe(0)
|
|
const bundle = buildSync({
|
|
entryPoints: [join(import.meta.dirname, 'zcode-v2-plan-credentials.ts')],
|
|
bundle: true,
|
|
platform: 'node',
|
|
format: 'cjs',
|
|
write: false
|
|
}).outputFiles[0]!.text
|
|
const setup = replace
|
|
? `const fs=require('node:fs'),originalStat=fs.statSync;fs.statSync=(path,...args)=>{const evidence=originalStat(path,...args);if(path===${JSON.stringify(path)})fs.renameSync(${JSON.stringify(fifoPath)},path);return evidence};`
|
|
: ''
|
|
const script = join(dir, 'read.cjs')
|
|
writeFileSync(
|
|
script,
|
|
`${bundle}\n${setup}\nconsole.log(module.exports.readZcodeV2PlanCredential(${JSON.stringify(host)}).status)`
|
|
)
|
|
const result = await runProcess({
|
|
program: process.execPath,
|
|
args: [script],
|
|
timeoutMs: 2000
|
|
})
|
|
expect(result.timedOut).toBe(false)
|
|
expect(result.code).toBe(0)
|
|
expect(result.stdout.trim()).toBe('error')
|
|
}
|
|
)
|
|
|
|
it.each([
|
|
{ options: { reasoningLevel: 42 } },
|
|
{ options: { reasoningLevel: '' } },
|
|
{ options: { reasoningLevel: ' ' } },
|
|
{ options: { extra: true } },
|
|
{ extra: true },
|
|
{ options: null }
|
|
])('rejects upstream-invalid selection %j without legacy fallback', (changed) => {
|
|
install()
|
|
legacy()
|
|
const path = join(dir, '.zcode', 'v2', 'provider_config.json')
|
|
const config = JSON.parse(readFileSync(path, 'utf8'))
|
|
Object.assign(config.config.defaultModelSelection, changed)
|
|
writeFileSync(path, JSON.stringify(config))
|
|
expect(readZcodeUsageCredentials({ credentialHost: host }).status).toBe('error')
|
|
})
|
|
|
|
it('accepts a valid optional reasoning level', () => {
|
|
install()
|
|
const path = join(dir, '.zcode', 'v2', 'provider_config.json')
|
|
const config = JSON.parse(readFileSync(path, 'utf8'))
|
|
config.config.defaultModelSelection.options = { reasoningLevel: ' high ' }
|
|
writeFileSync(path, JSON.stringify(config))
|
|
expect(readZcodeV2PlanCredential(host).status).toBe('ok')
|
|
})
|
|
|
|
it.each([
|
|
{ providerConfigRules: null },
|
|
{ providerConfigRules: { providerRules: 42 } },
|
|
{ providerConfigRules: { providerRules: [], unknown: true } },
|
|
{ modelConfigRules: null },
|
|
{ modelConfigRules: { providerModelRules: 42, manualProviderModelRules: [] } },
|
|
{ modelConfigRules: { providerModelRules: [], manualProviderModelRules: [null] } },
|
|
{ modelConfigRules: { providerModelRules: [{}], manualProviderModelRules: [] } }
|
|
])('rejects upstream-invalid rule containers %j without legacy fallback', (changed) => {
|
|
install()
|
|
legacy()
|
|
const path = join(dir, '.zcode', 'v2', 'provider_config.json')
|
|
const config = JSON.parse(readFileSync(path, 'utf8'))
|
|
Object.assign(config.config, changed)
|
|
writeFileSync(path, JSON.stringify(config))
|
|
expect(readZcodeUsageCredentials({ credentialHost: host }).status).toBe('error')
|
|
})
|
|
|
|
it('accepts a valid selected-provider empty personal rule and smart model rule', () => {
|
|
install('bigmodel')
|
|
const path = join(dir, '.zcode', 'v2', 'provider_config.json')
|
|
const config = JSON.parse(readFileSync(path, 'utf8'))
|
|
const selection = config.config.defaultModelSelection
|
|
config.config.providerConfigRules.providerRules = [
|
|
{ providerId: selection.providerId, config: {} }
|
|
]
|
|
config.config.modelConfigRules.providerModelRules = [{ ...selection, config: {} }]
|
|
writeFileSync(path, JSON.stringify(config))
|
|
expect(readZcodeV2PlanCredential(host)).toMatchObject({
|
|
status: 'ok',
|
|
baseUrl: 'https://open.bigmodel.cn'
|
|
})
|
|
})
|
|
|
|
it.each([
|
|
{ access: { type: 'api-key', apiKey: 'synthetic-personal-key' } },
|
|
{ access: null },
|
|
{ api: { type: 'bad-api-type', baseUrl: 'invalid-url' } },
|
|
{ api: { baseUrl: 'https://valid.example' } },
|
|
{ visibility: 'hidden' }
|
|
])(
|
|
'refuses unvalidated provider config %j without reading the vault or querying quota',
|
|
async (personal) => {
|
|
install('bigmodel')
|
|
legacy()
|
|
const path = join(dir, '.zcode', 'v2', 'provider_config.json')
|
|
const config = JSON.parse(readFileSync(path, 'utf8'))
|
|
config.config.providerConfigRules.providerRules = [
|
|
{ providerId: config.config.defaultModelSelection.providerId, config: personal }
|
|
]
|
|
writeFileSync(path, JSON.stringify(config))
|
|
rmSync(join(dir, '.zcode', 'v2', 'credentials.json'))
|
|
expect(readZcodeUsageCredentials({ credentialHost: host }).status).toBe('unavailable')
|
|
expect((await fetchZcodeRateLimits({ credentialHost: host })).status).toBe('unavailable')
|
|
expect(fetch).not.toHaveBeenCalled()
|
|
expect(readFileSync(path, 'utf8')).toBe(JSON.stringify(config))
|
|
expect(
|
|
(
|
|
await fetchZcodeRateLimits({
|
|
credentialHost: host,
|
|
planCredential: {
|
|
apiKey: 'synthetic-orca-key',
|
|
baseUrl: 'https://api.z.ai'
|
|
}
|
|
})
|
|
).status
|
|
).toBe('ok')
|
|
}
|
|
)
|
|
|
|
it.each(['duplicate-provider', 'malformed-model', 'valid-unsupported-model', 'manual-model'])(
|
|
'cannot establish selected credentials from %s rules',
|
|
(kind) => {
|
|
install('bigmodel')
|
|
legacy()
|
|
const path = join(dir, '.zcode', 'v2', 'provider_config.json')
|
|
const config = JSON.parse(readFileSync(path, 'utf8'))
|
|
const selection = config.config.defaultModelSelection
|
|
if (kind === 'duplicate-provider') {
|
|
config.config.providerConfigRules.providerRules = Array.from({ length: 2 }, () => ({
|
|
providerId: selection.providerId,
|
|
config: {}
|
|
}))
|
|
} else {
|
|
const group = kind === 'manual-model' ? 'manualProviderModelRules' : 'providerModelRules'
|
|
config.config.modelConfigRules[group] = [
|
|
{
|
|
...selection,
|
|
config:
|
|
kind === 'manual-model'
|
|
? {}
|
|
: {
|
|
optionSpecs: {
|
|
reasoningLevel: { values: kind === 'malformed-model' ? 42 : ['high'] }
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
writeFileSync(path, JSON.stringify(config))
|
|
expect(readZcodeUsageCredentials({ credentialHost: host }).status).toBe(
|
|
kind === 'duplicate-provider' ? 'error' : 'unavailable'
|
|
)
|
|
}
|
|
)
|
|
})
|
|
|
|
it('leaves encrypted CLI files unchanged across repeated account reads', () => {
|
|
install()
|
|
const root = join(dir, '.zcode', 'v2')
|
|
const before = new Map(readdirSync(root).map((name) => [name, readFileSync(join(root, name))]))
|
|
expect(before.get('credentials.json')?.toString()).toContain('enc:v1:')
|
|
for (let index = 0; index < 25; index++) {
|
|
expect(readZcodeV2PlanCredential(host).status).toBe('ok')
|
|
}
|
|
expect(readdirSync(root)).toEqual([...before.keys()])
|
|
for (const [name, bytes] of before) {
|
|
expect(readFileSync(join(root, name))).toEqual(bytes)
|
|
}
|
|
})
|