feat(simulation): control arbitrary tool lifecycles (#37816)
This commit is contained in:
parent
925c2423de
commit
6d32bc9cb0
13 changed files with 1567 additions and 80 deletions
|
|
@ -33,6 +33,35 @@ test("encodes every simulated provider event as OpenAI SSE", async () => {
|
|||
)
|
||||
})
|
||||
|
||||
test("encodes provider-neutral partial tool input as OpenAI deltas", async () => {
|
||||
const provider: SimulatedProvider.Interface = {
|
||||
stream: () =>
|
||||
Stream.make(
|
||||
{ type: "toolInputStart", index: 0, id: "call_lookup", name: "lookup" },
|
||||
{ type: "toolInputDelta", index: 0, text: '{"query":' },
|
||||
{ type: "toolInputDelta", index: 0, text: '"OpenCode"}' },
|
||||
{ type: "finish", reason: "tool-calls" },
|
||||
),
|
||||
}
|
||||
const url = new URL(DEFAULT_BASE_URL + PATH)
|
||||
const request = HttpClientRequest.post(url).pipe(HttpClientRequest.bodyJsonUnsafe({ model: "gpt-5" }))
|
||||
const matched = SimulationOpenAI.route(provider).match(request, url)
|
||||
if (!matched) throw new Error("The simulated OpenAI route did not match")
|
||||
|
||||
const body = await Effect.runPromise(matched.pipe(Effect.flatMap((response) => response.text)))
|
||||
|
||||
expect(body).toBe(
|
||||
[
|
||||
'data: {"choices":[{"delta":{"tool_calls":[{"index":0,"id":"call_lookup","function":{"name":"lookup","arguments":""}}]}}]}',
|
||||
'data: {"choices":[{"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\\"query\\":"}}]}}]}',
|
||||
'data: {"choices":[{"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\\"OpenCode\\"}"}}]}}]}',
|
||||
'data: {"choices":[{"delta":{},"finish_reason":"tool_calls"}]}',
|
||||
"data: [DONE]",
|
||||
"",
|
||||
].join("\n\n"),
|
||||
)
|
||||
})
|
||||
|
||||
test("rejects malformed intercepted OpenAI JSON as an HTTP client error", async () => {
|
||||
const provider: SimulatedProvider.Interface = { stream: () => Stream.empty }
|
||||
const url = new URL(DEFAULT_BASE_URL + PATH)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue