mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-14 03:56:55 +03:00
fix(core): send unchanged hooked requests without copying the body (#58449)
This commit is contained in:
committed by
GitHub
Unverified
parent
7b76b88cb3
commit
1e3d32167f
@@ -317,17 +317,20 @@ export const layer = Layer.effect(
|
||||
const http: StreamOptions["http"] = hasHttpHooks
|
||||
? (req, handler) =>
|
||||
Effect.gen(function* () {
|
||||
const before = yield* hooks.trigger("session", "http.request", {
|
||||
...scope,
|
||||
request: yield* HttpClientRequest.toWeb(req),
|
||||
})
|
||||
let sent = HttpClientRequest.fromWeb(before.request)
|
||||
if (before.request.body)
|
||||
sent = HttpClientRequest.bodyUint8Array(
|
||||
sent,
|
||||
new Uint8Array(yield* Effect.promise(() => before.request.clone().arrayBuffer())),
|
||||
before.request.headers.get("content-type") ?? undefined,
|
||||
)
|
||||
const request = yield* HttpClientRequest.toWeb(req)
|
||||
const before = yield* hooks.trigger("session", "http.request", { ...scope, request })
|
||||
// A hook that kept the request object cannot have replaced its body, so the original body is sent as is.
|
||||
// Reading it back would hold a second full copy of the request, screenshots included, for the whole call.
|
||||
const sent =
|
||||
before.request === request
|
||||
? HttpClientRequest.setBody(HttpClientRequest.fromWeb(request), req.body)
|
||||
: before.request.body
|
||||
? HttpClientRequest.bodyUint8Array(
|
||||
HttpClientRequest.fromWeb(before.request),
|
||||
new Uint8Array(yield* Effect.promise(() => before.request.clone().arrayBuffer())),
|
||||
before.request.headers.get("content-type") ?? undefined,
|
||||
)
|
||||
: HttpClientRequest.fromWeb(before.request)
|
||||
const res = yield* handler(sent)
|
||||
const after = yield* hooks.trigger("session", "http.response", {
|
||||
...scope,
|
||||
|
||||
@@ -80,6 +80,54 @@ describe("SessionModelRequest HTTP hooks", () => {
|
||||
}).pipe(Effect.provideService(SessionModelTransport.Service, transport)),
|
||||
)
|
||||
|
||||
it.effect("sends a kept request's original body and a replaced request's new body", () =>
|
||||
Effect.gen(function* () {
|
||||
const hooks = yield* PluginHooks.Service
|
||||
let replace = false
|
||||
yield* hooks.register("session", "http.request", (event) =>
|
||||
Effect.sync(() => {
|
||||
if (replace) {
|
||||
event.request = new Request(event.request.url, { method: "POST", body: '{"replaced":true}' })
|
||||
return
|
||||
}
|
||||
event.request.headers.set("x-plugin", "kept")
|
||||
}),
|
||||
)
|
||||
const requests = yield* SessionModelRequest.Service.pipe(Effect.provide(SessionModelRequest.layer))
|
||||
const prepared = yield* requests.primary({
|
||||
session,
|
||||
agent: Agent.ID.make("build"),
|
||||
model,
|
||||
system: [],
|
||||
messages: [],
|
||||
})
|
||||
const http = prepared.options.http
|
||||
if (!http) throw new Error("Expected HTTP middleware")
|
||||
const original = HttpClientRequest.post("https://example.test/v1/chat/completions").pipe(
|
||||
HttpClientRequest.bodyText('{"messages":[]}', "application/json"),
|
||||
)
|
||||
const send = () => {
|
||||
const sent: HttpClientRequest.HttpClientRequest[] = []
|
||||
return http(original, (request) =>
|
||||
Effect.sync(() => {
|
||||
sent.push(request)
|
||||
return HttpClientResponse.fromWeb(request, new Response("{}", { status: 200 }))
|
||||
}),
|
||||
).pipe(Effect.map(() => sent[0]!))
|
||||
}
|
||||
|
||||
const kept = yield* send()
|
||||
expect(kept.body).toBe(original.body)
|
||||
expect(kept.headers["x-plugin"]).toBe("kept")
|
||||
|
||||
replace = true
|
||||
const replaced = yield* send()
|
||||
expect(replaced.body._tag).toBe("Uint8Array")
|
||||
if (replaced.body._tag !== "Uint8Array") return
|
||||
expect(new TextDecoder().decode(replaced.body.body)).toBe('{"replaced":true}')
|
||||
}).pipe(Effect.provideService(SessionModelTransport.Service, transport)),
|
||||
)
|
||||
|
||||
it.effect("offers the WebSocket executor alongside HTTP hooks and routes the WebSocket hooks", () =>
|
||||
Effect.gen(function* () {
|
||||
const hooks = yield* PluginHooks.Service
|
||||
|
||||
Reference in New Issue
Block a user