Compare commits

...
Author SHA1 Message Date
Filip 068393e3bd fix(server): apply agent model during session creation 2026-08-14 12:41:25 +00:00
2 changed files with 79 additions and 2 deletions
+15 -2
View File
@@ -1,4 +1,7 @@
import { Session } from "@opencode-ai/core/session"
import { Agent } from "@opencode-ai/core/agent"
import { LocationServiceMap } from "@opencode-ai/core/location-service-map"
import { PluginSupervisor } from "@opencode-ai/core/plugin/supervisor"
import { SessionTransfer } from "@opencode-ai/core/session/transfer"
import { InstructionEntry } from "@opencode-ai/core/session/instruction-entry"
import { DateTime, Effect, Stream } from "effect"
@@ -91,14 +94,24 @@ export const SessionHandler = HttpApiBuilder.group(Api, "server.session", (handl
.handle(
"session.create",
Effect.fn(function* (ctx) {
const location = ctx.payload.location ?? { directory: AbsolutePath.make(process.cwd()) }
const selectedAgent = ctx.payload.model ? undefined : ctx.payload.agent
const agentModel = selectedAgent
? yield* Effect.gen(function* () {
const plugins = yield* PluginSupervisor.Service
yield* plugins.flush
const agents = yield* Agent.Service
return (yield* agents.get(selectedAgent))?.model
}).pipe(Effect.provide(LocationServiceMap.Service.get(location)))
: undefined
return {
data: yield* session
.create({
id: ctx.payload.id,
title: ctx.payload.title,
agent: ctx.payload.agent,
model: ctx.payload.model,
location: ctx.payload.location ?? { directory: AbsolutePath.make(process.cwd()) },
model: ctx.payload.model ?? agentModel,
location,
})
.pipe(Effect.orDie),
}
+64
View File
@@ -0,0 +1,64 @@
import fs from "node:fs/promises"
import path from "node:path"
import { expect } from "bun:test"
import { Effect } from "effect"
import { HttpServer } from "effect/unstable/http"
import { tmpdir } from "../../core/test/fixture/tmpdir"
import { it } from "../../core/test/lib/effect"
import { ServerProcess } from "../src/process"
it.live("waits for plugin initialization before applying the selected agent model", () =>
Effect.acquireUseRelease(
Effect.promise(() => tmpdir("opencode-session-endpoint-")),
(tmp) =>
Effect.gen(function* () {
yield* Effect.promise(() =>
fs.writeFile(
path.join(tmp.path, "opencode.json"),
JSON.stringify({
agents: {
modelprobe: {
description: "Model resolution probe",
mode: "primary",
model: "opencode/nemotron-3.5-lightning-free",
},
},
}),
),
)
const server = yield* ServerProcess.start<never, never>({
hostname: "127.0.0.1",
port: 0,
password: "secret",
app: { version: "test-version" },
database: { path: ":memory:" },
config: { directory: tmp.path },
fs: { filewatcher: false },
})
const response = yield* Effect.promise(() =>
fetch(new URL("/api/session", HttpServer.formatAddress(server.address)), {
method: "POST",
headers: {
authorization: `Basic ${btoa("opencode:secret")}`,
"content-type": "application/json",
},
body: JSON.stringify({ agent: "modelprobe", location: { directory: tmp.path } }),
}),
)
expect(response.status).toBe(200)
const body: unknown = yield* Effect.promise(() => response.json())
if (!isRecord(body) || !isRecord(body["data"])) throw new Error("Expected a created session")
expect(body["data"]["model"]).toEqual({
providerID: "opencode",
id: "nemotron-3.5-lightning-free",
variant: "default",
})
}),
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
),
)
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value)
}