cleanup(agent-loop): simplify request construction
This commit is contained in:
@@ -535,25 +535,19 @@ export class ReactLoopAgent implements Agent {
|
|||||||
): Promise<{ request: GenerateOptions; preparedCall?: PreparedLlmCall }> {
|
): Promise<{ request: GenerateOptions; preparedCall?: PreparedLlmCall }> {
|
||||||
const { session } = this
|
const { session } = this
|
||||||
|
|
||||||
const loggedConfig = session.requestHeader()?.config
|
|
||||||
const initialProvider = this.options.provider ?? ''
|
|
||||||
const initialModel = this.options.model ?? ''
|
|
||||||
const initialConfig: LlmCallConfig = {
|
|
||||||
provider: initialProvider,
|
|
||||||
model: initialModel,
|
|
||||||
...loggedConfig?.provider === initialProvider
|
|
||||||
&& loggedConfig.model === initialModel
|
|
||||||
&& loggedConfig.reasoningEffort !== undefined
|
|
||||||
? { reasoningEffort: loggedConfig.reasoningEffort }
|
|
||||||
: {},
|
|
||||||
}
|
|
||||||
// A loop instance starts from its declared route, restoring only an opaque
|
// A loop instance starts from its declared route, restoring only an opaque
|
||||||
// effort owned by that exact model. Later steps fold the config it logged.
|
// effort owned by that exact model. Later steps fold the config it logged.
|
||||||
const seedConfig: LlmCallConfig = deepFreeze(structuredClone(
|
const persistedConfig = session.requestHeader()?.config
|
||||||
|
const route = { provider: this.options.provider ?? '', model: this.options.model ?? '' }
|
||||||
|
const reasoningEffort = persistedConfig?.provider === route.provider
|
||||||
|
&& persistedConfig.model === route.model
|
||||||
|
? persistedConfig.reasoningEffort
|
||||||
|
: undefined
|
||||||
|
const seedConfig = deepFreeze(structuredClone(
|
||||||
this.requestHeaderLogged
|
this.requestHeaderLogged
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- a logged instance anchor guarantees the fold
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- the instance logged the header it now folds
|
||||||
? session.requestHeader()!.config
|
? persistedConfig!
|
||||||
: initialConfig,
|
: { ...route, ...reasoningEffort === undefined ? {} : { reasoningEffort } },
|
||||||
))
|
))
|
||||||
const proposedConfig = await this.loopCtx.waterfall(
|
const proposedConfig = await this.loopCtx.waterfall(
|
||||||
agentCarrier(this), 'agent/request', this, turn, step, signal,
|
agentCarrier(this), 'agent/request', this, turn, step, signal,
|
||||||
@@ -590,17 +584,10 @@ export class ReactLoopAgent implements Agent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const request = markAgentLoopRequest(deepFreeze({
|
const request = markAgentLoopRequest(deepFreeze({
|
||||||
provider: header.config.provider,
|
...header.config,
|
||||||
model: header.config.model,
|
|
||||||
...header.config.reasoningEffort !== undefined
|
|
||||||
? { reasoningEffort: header.config.reasoningEffort }
|
|
||||||
: {},
|
|
||||||
messages: boundaryMessages,
|
messages: boundaryMessages,
|
||||||
...header.system !== undefined ? { system: header.system } : {},
|
...header.system !== undefined ? { system: header.system } : {},
|
||||||
...header.tools !== undefined ? { tools: header.tools } : {},
|
...header.tools !== undefined ? { tools: header.tools } : {},
|
||||||
...header.config.temperature !== undefined ? { temperature: header.config.temperature } : {},
|
|
||||||
...header.config.maxTokens !== undefined ? { maxTokens: header.config.maxTokens } : {},
|
|
||||||
...header.config.stop !== undefined ? { stop: header.config.stop } : {},
|
|
||||||
sessionId: session.id,
|
sessionId: session.id,
|
||||||
signal,
|
signal,
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -136,20 +136,26 @@ describe('request stability across the loop', () => {
|
|||||||
])
|
])
|
||||||
expect(headers.map(event => event.data.reason)).toEqual(['initial', 'change'])
|
expect(headers.map(event => event.data.reason)).toEqual(['initial', 'change'])
|
||||||
|
|
||||||
const resumedAdapter = new MockAdapter([textResponse('three')], reasoning)
|
for (const [model, effort] of [
|
||||||
const resumedCtx = await harness(resumedAdapter)
|
['mock', ReasoningEffortId('max')],
|
||||||
const resumedHandle = await resumedCtx.agents.create({
|
['replacement', ReasoningEffortId('high')],
|
||||||
sessionId: SessionId('effort-resumed'),
|
] as const) {
|
||||||
seed: structuredClone(agent.session.events),
|
const resumedAdapter = new MockAdapter([textResponse('resumed')], reasoning)
|
||||||
agentOptions: { provider: 'mock', model: 'mock' },
|
const resumedCtx = await harness(resumedAdapter)
|
||||||
})
|
const resumedHandle = await resumedCtx.agents.create({
|
||||||
send(resumedHandle.agent, 'third')
|
sessionId: SessionId(`effort-${model}`),
|
||||||
await waitForIdle(resumedCtx, resumedHandle.agent)
|
seed: structuredClone(agent.session.events),
|
||||||
|
agentOptions: { provider: 'mock', model },
|
||||||
|
})
|
||||||
|
send(resumedHandle.agent, 'resumed')
|
||||||
|
await waitForIdle(resumedCtx, resumedHandle.agent)
|
||||||
|
|
||||||
expect(resumedAdapter.requests[0]?.reasoningEffort).toBe(ReasoningEffortId('max'))
|
expect(resumedAdapter.requests[0]?.model).toBe(model)
|
||||||
const resumedHeaders = resumedHandle.agent.session.events.filter(event => event.type === 'request/header')
|
expect(resumedAdapter.requests[0]?.reasoningEffort).toBe(effort)
|
||||||
expect(resumedHeaders.at(-1)?.data.header.config.reasoningEffort).toBe(ReasoningEffortId('max'))
|
const resumedHeaders = resumedHandle.agent.session.events.filter(event => event.type === 'request/header')
|
||||||
expect(resumedHeaders.at(-1)?.data.reason).toBe('resume')
|
expect(resumedHeaders.at(-1)?.data.header.config.reasoningEffort).toBe(effort)
|
||||||
|
expect(resumedHeaders.at(-1)?.data.reason).toBe('resume')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('keeps exact-model resolution, request logging, and dispatch on one adapter registration', async () => {
|
it('keeps exact-model resolution, request logging, and dispatch on one adapter registration', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user