fix(opencode): flush embedded server telemetry
This commit is contained in:
parent
ceb4890ca3
commit
31d25c8f08
4 changed files with 60 additions and 26 deletions
|
|
@ -123,6 +123,18 @@ async function toolError(part: ToolPart) {
|
|||
}
|
||||
}
|
||||
|
||||
async function embeddedServer(auth?: string) {
|
||||
const { Server } = await import("@/server/server")
|
||||
const server = Server.Default()
|
||||
const fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
const request = new Request(input, init)
|
||||
const headers = new Headers(request.headers)
|
||||
if (auth) headers.set("Authorization", auth)
|
||||
return server.app.fetch(new Request(request, { headers }))
|
||||
}) as typeof globalThis.fetch
|
||||
return { fetch, dispose: server.dispose }
|
||||
}
|
||||
|
||||
export const RunCommand = effectCmd({
|
||||
command: "run [message..]",
|
||||
describe: "run opencode with a message",
|
||||
|
|
@ -902,19 +914,12 @@ export const RunCommand = effectCmd({
|
|||
if (interactive && !args.attach && !args.session && !args.continue) {
|
||||
const model = pick(args.model)
|
||||
const { runInteractiveLocalMode } = await import("./run/runtime")
|
||||
const fetchFn = (async (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
const { Server } = await import("@/server/server")
|
||||
const request = new Request(input, init)
|
||||
const headers = new Headers(request.headers)
|
||||
const auth = ServerAuth.header()
|
||||
if (auth) headers.set("Authorization", auth)
|
||||
return Server.Default().app.fetch(new Request(request, { headers }))
|
||||
}) as typeof globalThis.fetch
|
||||
const server = await embeddedServer(ServerAuth.header())
|
||||
|
||||
try {
|
||||
return await runInteractiveLocalMode({
|
||||
directory: directory ?? root,
|
||||
fetch: fetchFn,
|
||||
fetch: server.fetch,
|
||||
resolveAgent: localAgent,
|
||||
session,
|
||||
share,
|
||||
|
|
@ -932,6 +937,8 @@ export const RunCommand = effectCmd({
|
|||
})
|
||||
} catch (error) {
|
||||
dieInteractive(error)
|
||||
} finally {
|
||||
await server.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -940,20 +947,17 @@ export const RunCommand = effectCmd({
|
|||
return await execute(sdk)
|
||||
}
|
||||
|
||||
const fetchFn = (async (input: RequestInfo | URL, init?: RequestInit) => {
|
||||
const { Server } = await import("@/server/server")
|
||||
const request = new Request(input, init)
|
||||
const headers = new Headers(request.headers)
|
||||
const auth = ServerAuth.header()
|
||||
if (auth) headers.set("Authorization", auth)
|
||||
return Server.Default().app.fetch(new Request(request, { headers }))
|
||||
}) as typeof globalThis.fetch
|
||||
const sdk = createOpencodeClient({
|
||||
baseUrl: "http://opencode.internal",
|
||||
fetch: fetchFn,
|
||||
directory,
|
||||
})
|
||||
await execute(sdk)
|
||||
const server = await embeddedServer(ServerAuth.header())
|
||||
try {
|
||||
const sdk = createOpencodeClient({
|
||||
baseUrl: "http://opencode.internal",
|
||||
fetch: server.fetch,
|
||||
directory,
|
||||
})
|
||||
await execute(sdk)
|
||||
} finally {
|
||||
await server.dispose()
|
||||
}
|
||||
})
|
||||
}),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ export const rpc = {
|
|||
async shutdown() {
|
||||
await InstanceRuntime.disposeAllInstances()
|
||||
if (server) await server.stop(true)
|
||||
if (Server.Default.loaded()) await Server.Default().dispose()
|
||||
process.off("unhandledRejection", onUnhandledRejection)
|
||||
process.off("uncaughtException", onUncaughtException)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -54,14 +54,14 @@ class ListenerServerService extends Context.Service<ListenerServerService, Liste
|
|||
) {}
|
||||
|
||||
export const Default = lazy(() => {
|
||||
const handler = HttpApiApp.webHandler().handler
|
||||
const web = HttpApiApp.webHandler()
|
||||
const app: ServerApp = {
|
||||
fetch: (request: Request) => handler(request, HttpApiApp.context),
|
||||
fetch: (request: Request) => web.handler(request, HttpApiApp.context),
|
||||
request(input, init) {
|
||||
return app.fetch(input instanceof Request ? input : new Request(new URL(input, "http://localhost"), init))
|
||||
},
|
||||
}
|
||||
return { app }
|
||||
return { app, dispose: web.dispose }
|
||||
})
|
||||
|
||||
export async function openapi() {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,35 @@ describe("opencode run (non-interactive subprocess)", () => {
|
|||
60_000,
|
||||
)
|
||||
|
||||
cliIt.concurrent(
|
||||
"flushes server telemetry before exiting",
|
||||
({ llm, opencode }) =>
|
||||
Effect.gen(function* () {
|
||||
const requests: string[] = []
|
||||
const collector = yield* Effect.acquireRelease(
|
||||
Effect.sync(() =>
|
||||
Bun.serve({
|
||||
port: 0,
|
||||
fetch(request) {
|
||||
requests.push(new URL(request.url).pathname)
|
||||
return new Response(null, { status: 200 })
|
||||
},
|
||||
}),
|
||||
),
|
||||
(server) => Effect.sync(() => server.stop(true)),
|
||||
)
|
||||
yield* llm.text("telemetry response")
|
||||
|
||||
const result = yield* opencode.run("say hi", {
|
||||
env: { OTEL_EXPORTER_OTLP_ENDPOINT: collector.url.toString().replace(/\/$/, "") },
|
||||
})
|
||||
|
||||
opencode.expectExit(result, 0)
|
||||
expect(requests).toContain("/v1/traces")
|
||||
}),
|
||||
60_000,
|
||||
)
|
||||
|
||||
cliIt.concurrent(
|
||||
"prints each completed text part in order around a tool continuation",
|
||||
({ llm, opencode }) =>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue