fix(llm): keep request generations coherent
This commit is contained in:
@@ -25,8 +25,10 @@ async function harness(baseURL: string, overrides: Record<string, unknown> = {})
|
||||
|
||||
/** Direct adapter over the real profile resolver, with literal-key resolution. */
|
||||
function adapterOf(providers: Record<string, LlmPiAi.PiAiProviderProfile>): PiAiAdapter {
|
||||
const compositionProfiles = resolveProfiles(providers)
|
||||
return new PiAiAdapter({
|
||||
profiles: () => resolveProfiles(providers),
|
||||
profiles: () => compositionProfiles,
|
||||
compositionProfiles,
|
||||
resolveApiKey: (_provider, profile) => Promise.resolve(profile.apiKey),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ afterEach(async () => {
|
||||
while (cleanups.length > 0) await cleanups.pop()!()
|
||||
await closeMockServers()
|
||||
vi.unstubAllEnvs()
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
async function home(): Promise<string> {
|
||||
@@ -97,4 +98,45 @@ describe('request-level dynamic profiles', () => {
|
||||
jitterRatio: 0.2,
|
||||
})
|
||||
})
|
||||
|
||||
it('cannot mix earlier capability facts with a later settings connection', async () => {
|
||||
const dir = await home()
|
||||
const first = await mockServer([{ events: textEvents }])
|
||||
const second = await mockServer([{ events: textEvents }])
|
||||
const ctx = await boot(dir, {
|
||||
providers: {
|
||||
deepseek: {
|
||||
apiKey: 'first-key',
|
||||
baseURL: first.url,
|
||||
reasoning: 'off',
|
||||
},
|
||||
},
|
||||
})
|
||||
const resolveModel = vi.spyOn(LlmPiAi.PiAiAdapter.prototype, 'resolveModel')
|
||||
resolveModel.mockImplementation(async function (
|
||||
this: LlmPiAi.PiAiAdapter,
|
||||
provider,
|
||||
model,
|
||||
signal,
|
||||
) {
|
||||
resolveModel.mockRestore()
|
||||
const resolved = await this.resolveModel(provider, model, signal)
|
||||
// Land a complete settings generation after capability resolution but
|
||||
// before stream dispatch. Its changed reasoning default rejects it whole.
|
||||
await ctx.settings.update(NS, {
|
||||
providers: {
|
||||
deepseek: {
|
||||
apiKey: 'second-key',
|
||||
baseURL: second.url,
|
||||
reasoning: 'max',
|
||||
},
|
||||
},
|
||||
})
|
||||
return resolved
|
||||
})
|
||||
|
||||
await assemble(ctx, { provider: 'deepseek', model: 'deepseek-v4-flash', messages: [] })
|
||||
expect(second.requests).toHaveLength(0)
|
||||
expect(first.headers[0]?.authorization).toBe('Bearer first-key')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -22,8 +22,10 @@ describe('pi-ai SDK retry boundary', () => {
|
||||
throw failure
|
||||
},
|
||||
})
|
||||
const compositionProfiles = resolveProfiles({ openai: { apiKey: 'test-key' } })
|
||||
const adapter = new PiAiAdapter({
|
||||
profiles: () => resolveProfiles({ openai: { apiKey: 'test-key' } }),
|
||||
profiles: () => compositionProfiles,
|
||||
compositionProfiles,
|
||||
resolveApiKey: () => Promise.resolve('test-key'),
|
||||
})
|
||||
const drain = async (): Promise<void> => {
|
||||
|
||||
Reference in New Issue
Block a user