From 02981844b88aed33f06f1527da6c58d137975069 Mon Sep 17 00:00:00 2001 From: opencode Date: Mon, 27 Jul 2026 07:32:46 +0000 Subject: [PATCH 1/2] release: v1.18.7 --- bun.lock | 56 ++++++++++----------- packages/app/package.json | 2 +- packages/cli/package.json | 2 +- packages/codemode/package.json | 2 +- packages/console/app/package.json | 2 +- packages/console/core/package.json | 2 +- packages/console/function/package.json | 2 +- packages/console/mail/package.json | 2 +- packages/console/support/package.json | 2 +- packages/core/package.json | 2 +- packages/desktop/package.json | 2 +- packages/effect-drizzle-sqlite/package.json | 2 +- packages/effect-sqlite-node/package.json | 2 +- packages/enterprise/package.json | 2 +- packages/function/package.json | 2 +- packages/http-recorder/package.json | 2 +- packages/llm/package.json | 2 +- packages/opencode/package.json | 2 +- packages/plugin/package.json | 2 +- packages/sdk/js/package.json | 2 +- packages/server/package.json | 2 +- packages/session-ui/package.json | 2 +- packages/slack/package.json | 2 +- packages/stats/app/package.json | 2 +- packages/stats/core/package.json | 2 +- packages/stats/server/package.json | 2 +- packages/tui/package.json | 2 +- packages/ui/package.json | 2 +- packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- 30 files changed, 57 insertions(+), 57 deletions(-) diff --git a/bun.lock b/bun.lock index 4f969c2f1e9f..396e8a599d61 100644 --- a/bun.lock +++ b/bun.lock @@ -29,7 +29,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@corvu/drawer": "catalog:", "@dnd-kit/abstract": "0.5.0", @@ -96,7 +96,7 @@ }, "packages/cli": { "name": "@opencode-ai/cli", - "version": "1.18.6", + "version": "1.18.7", "bin": { "lildax": "./bin/lildax.cjs", }, @@ -144,7 +144,7 @@ }, "packages/codemode": { "name": "@opencode-ai/codemode", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "acorn": "8.15.0", "effect": "catalog:", @@ -158,7 +158,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -194,7 +194,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -221,7 +221,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@ai-sdk/anthropic": "3.0.82", "@ai-sdk/openai": "3.0.48", @@ -243,7 +243,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -267,7 +267,7 @@ }, "packages/console/support": { "name": "@opencode-ai/console-support", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@opencode-ai/console-core": "workspace:*", @@ -287,7 +287,7 @@ }, "packages/core": { "name": "@opencode-ai/core", - "version": "1.18.6", + "version": "1.18.7", "bin": { "opencode": "./bin/opencode", }, @@ -381,7 +381,7 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@zip.js/zip.js": "2.7.62", "effect": "catalog:", @@ -435,7 +435,7 @@ }, "packages/effect-drizzle-sqlite": { "name": "@opencode-ai/effect-drizzle-sqlite", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "drizzle-orm": "catalog:", "effect": "catalog:", @@ -449,7 +449,7 @@ }, "packages/effect-sqlite-node": { "name": "@opencode-ai/effect-sqlite-node", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "effect": "catalog:", }, @@ -461,7 +461,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@hono/standard-validator": "catalog:", "@opencode-ai/core": "workspace:*", @@ -493,7 +493,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -509,7 +509,7 @@ }, "packages/http-recorder": { "name": "@opencode-ai/http-recorder", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@effect/platform-node": "4.0.0-beta.83", "@effect/platform-node-shared": "4.0.0-beta.83", @@ -540,7 +540,7 @@ }, "packages/llm": { "name": "@opencode-ai/llm", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@opencode-ai/schema": "workspace:*", "@smithy/eventstream-codec": "4.2.14", @@ -559,7 +559,7 @@ }, "packages/opencode": { "name": "opencode", - "version": "1.18.6", + "version": "1.18.7", "bin": { "opencode": "./bin/opencode", }, @@ -690,7 +690,7 @@ }, "packages/plugin": { "name": "@opencode-ai/plugin", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@ai-sdk/provider": "3.0.8", "@opencode-ai/sdk": "workspace:*", @@ -766,7 +766,7 @@ }, "packages/sdk/js": { "name": "@opencode-ai/sdk", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "cross-spawn": "catalog:", }, @@ -781,7 +781,7 @@ }, "packages/server": { "name": "@opencode-ai/server", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@opencode-ai/core": "workspace:*", "@opencode-ai/protocol": "workspace:*", @@ -796,7 +796,7 @@ }, "packages/session-ui": { "name": "@opencode-ai/session-ui", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@kobalte/core": "catalog:", "@opencode-ai/client": "file:../app/vendor/opencode-ai-client-1.17.13-v2.tgz", @@ -841,7 +841,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@opencode-ai/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -854,7 +854,7 @@ }, "packages/stats/app": { "name": "@opencode-ai/stats-app", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@ibm/plex": "6.4.1", "@kobalte/core": "catalog:", @@ -888,7 +888,7 @@ }, "packages/stats/core": { "name": "@opencode-ai/stats-core", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@aws-sdk/client-athena": "3.933.0", "@planetscale/database": "1.19.0", @@ -907,7 +907,7 @@ }, "packages/stats/server": { "name": "@opencode-ai/stats-server", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@aws-sdk/client-firehose": "3.933.0", "@effect/platform-node": "catalog:", @@ -949,7 +949,7 @@ }, "packages/tui": { "name": "@opencode-ai/tui", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@opencode-ai/core": "workspace:*", "@opencode-ai/plugin": "workspace:*", @@ -976,7 +976,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@kobalte/core": "catalog:", "@pierre/diffs": "catalog:", @@ -1027,7 +1027,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", diff --git a/packages/app/package.json b/packages/app/package.json index d2219740b12d..8341a2b26884 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "1.18.6", + "version": "1.18.7", "description": "", "type": "module", "exports": { diff --git a/packages/cli/package.json b/packages/cli/package.json index d8886470a091..c93fa6625533 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/cli", - "version": "1.18.6", + "version": "1.18.7", "type": "module", "license": "MIT", "bin": { diff --git a/packages/codemode/package.json b/packages/codemode/package.json index a57dad613028..acdaca0ec552 100644 --- a/packages/codemode/package.json +++ b/packages/codemode/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/codemode", - "version": "1.18.6", + "version": "1.18.7", "description": "Effect-native confined code execution over schema-described tools", "private": true, "type": "module", diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 0ccae42dbfc8..dc2a03a1c5af 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.18.6", + "version": "1.18.7", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 4e7f7658510c..140c32ecb4cc 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.18.6", + "version": "1.18.7", "private": true, "type": "module", "license": "MIT", diff --git a/packages/console/function/package.json b/packages/console/function/package.json index edb98fa95eae..9101f0ea4635 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.18.6", + "version": "1.18.7", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index 26b7745a9ab9..939824a4db0f 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.18.6", + "version": "1.18.7", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/console/support/package.json b/packages/console/support/package.json index ee4bd72911ee..a6c4d2ec7807 100644 --- a/packages/console/support/package.json +++ b/packages/console/support/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-support", - "version": "1.18.6", + "version": "1.18.7", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/core/package.json b/packages/core/package.json index b297ac569aaf..c91df0d23909 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.18.6", + "version": "1.18.7", "name": "@opencode-ai/core", "type": "module", "license": "MIT", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index fc7d278bedfd..4ac36046a1ab 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,7 +1,7 @@ { "name": "@opencode-ai/desktop", "private": true, - "version": "1.18.6", + "version": "1.18.7", "type": "module", "license": "MIT", "homepage": "https://opencode.ai", diff --git a/packages/effect-drizzle-sqlite/package.json b/packages/effect-drizzle-sqlite/package.json index 84c6cda13131..341291dd265d 100644 --- a/packages/effect-drizzle-sqlite/package.json +++ b/packages/effect-drizzle-sqlite/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.18.6", + "version": "1.18.7", "name": "@opencode-ai/effect-drizzle-sqlite", "type": "module", "license": "MIT", diff --git a/packages/effect-sqlite-node/package.json b/packages/effect-sqlite-node/package.json index fd915ebd3baf..d14decf085b0 100644 --- a/packages/effect-sqlite-node/package.json +++ b/packages/effect-sqlite-node/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.18.6", + "version": "1.18.7", "name": "@opencode-ai/effect-sqlite-node", "type": "module", "license": "MIT", diff --git a/packages/enterprise/package.json b/packages/enterprise/package.json index f338cde8fc9b..7c20f5e29938 100644 --- a/packages/enterprise/package.json +++ b/packages/enterprise/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/enterprise", - "version": "1.18.6", + "version": "1.18.7", "private": true, "type": "module", "license": "MIT", diff --git a/packages/function/package.json b/packages/function/package.json index 117632f768e6..1c1bcf83ecc2 100644 --- a/packages/function/package.json +++ b/packages/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/function", - "version": "1.18.6", + "version": "1.18.7", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/http-recorder/package.json b/packages/http-recorder/package.json index 40e0dd80c7f3..980c2b24a945 100644 --- a/packages/http-recorder/package.json +++ b/packages/http-recorder/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.18.6", + "version": "1.18.7", "name": "@opencode-ai/http-recorder", "description": "Record and replay Effect HTTP client traffic with deterministic cassettes", "type": "module", diff --git a/packages/llm/package.json b/packages/llm/package.json index 100aa8552681..cd62b1eb1331 100644 --- a/packages/llm/package.json +++ b/packages/llm/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.18.6", + "version": "1.18.7", "name": "@opencode-ai/llm", "type": "module", "license": "MIT", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 380bef3358b6..1cd15b7b720f 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.18.6", + "version": "1.18.7", "name": "opencode", "type": "module", "license": "MIT", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index ab795d5327c5..058803a25214 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/plugin", - "version": "1.18.6", + "version": "1.18.7", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/sdk/js/package.json b/packages/sdk/js/package.json index 9859ba179855..422f5ac849b9 100644 --- a/packages/sdk/js/package.json +++ b/packages/sdk/js/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/sdk", - "version": "1.18.6", + "version": "1.18.7", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/server/package.json b/packages/server/package.json index 80504ced29d9..d4ffebe4fdfd 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/server", - "version": "1.18.6", + "version": "1.18.7", "private": true, "type": "module", "license": "MIT", diff --git a/packages/session-ui/package.json b/packages/session-ui/package.json index 2d4bc6c65d3b..fe07ed5e452d 100644 --- a/packages/session-ui/package.json +++ b/packages/session-ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/session-ui", - "version": "1.18.6", + "version": "1.18.7", "private": true, "type": "module", "license": "MIT", diff --git a/packages/slack/package.json b/packages/slack/package.json index 33e8109358fb..85d1ede18462 100644 --- a/packages/slack/package.json +++ b/packages/slack/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/slack", - "version": "1.18.6", + "version": "1.18.7", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/stats/app/package.json b/packages/stats/app/package.json index d070a6a96e07..c32ac327d7bc 100644 --- a/packages/stats/app/package.json +++ b/packages/stats/app/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/stats-app", - "version": "1.18.6", + "version": "1.18.7", "private": true, "type": "module", "license": "MIT", diff --git a/packages/stats/core/package.json b/packages/stats/core/package.json index 09493362f924..d1e74ec3d8b0 100644 --- a/packages/stats/core/package.json +++ b/packages/stats/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/stats-core", - "version": "1.18.6", + "version": "1.18.7", "private": true, "type": "module", "license": "MIT", diff --git a/packages/stats/server/package.json b/packages/stats/server/package.json index 1d1607612a89..8f2f05e5c335 100644 --- a/packages/stats/server/package.json +++ b/packages/stats/server/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/stats-server", - "version": "1.18.6", + "version": "1.18.7", "private": true, "type": "module", "license": "MIT", diff --git a/packages/tui/package.json b/packages/tui/package.json index f86400885bcd..4f9850eba8e6 100644 --- a/packages/tui/package.json +++ b/packages/tui/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/tui", - "version": "1.18.6", + "version": "1.18.7", "private": true, "type": "module", "license": "MIT", diff --git a/packages/ui/package.json b/packages/ui/package.json index 3174e2113a91..d5022aeb48eb 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/ui", - "version": "1.18.6", + "version": "1.18.7", "type": "module", "license": "MIT", "repository": { diff --git a/packages/web/package.json b/packages/web/package.json index 0ac92292d5fd..1966ee63fb83 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -2,7 +2,7 @@ "name": "@opencode-ai/web", "type": "module", "license": "MIT", - "version": "1.18.6", + "version": "1.18.7", "scripts": { "dev": "astro dev", "dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev", diff --git a/sdks/vscode/package.json b/sdks/vscode/package.json index 55684f7ab38c..6a53c96c5b66 100644 --- a/sdks/vscode/package.json +++ b/sdks/vscode/package.json @@ -2,7 +2,7 @@ "name": "opencode", "displayName": "opencode", "description": "opencode for VS Code", - "version": "1.18.6", + "version": "1.18.7", "publisher": "sst-dev", "repository": { "type": "git", From f9e5527ee978f85a6e907339ba8db38accd80d82 Mon Sep 17 00:00:00 2001 From: Sami Jawhar Date: Mon, 27 Apr 2026 02:25:49 +0000 Subject: [PATCH 2/2] fix(session): preserve agent and model on async prompt When a prompt comes in without explicit agent/model fields (the common case for prompt_async), createUserMessage was falling back to the config's default agent and that agent's default model. This caused the session to silently switch agents/models mid-conversation. Fix: read the most recent user message in the session and prefer its agent and model as the fallback before going to defaults. Both fields fall through together because the user's previous choice was a coherent pairing. Replaces the dropped fix/prompt-async-agent-preserve branch with a minimal version. Loop continuation guard and 30-min timeout from the original branch are intentionally omitted; can be added later if needed. --- packages/opencode/src/session/prompt.ts | 35 +++- packages/opencode/test/session/prompt.test.ts | 169 ++++++++++++++++++ 2 files changed, 200 insertions(+), 4 deletions(-) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index eb116f6b960f..f1389fb7a226 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -633,7 +633,20 @@ const layer = Layer.effect( }) const createUserMessage = Effect.fn("SessionPrompt.createUserMessage")(function* (input: PromptInput) { - const agentName = input.agent + // The session row is the durable record of the session's current agent and + // model (written back below via setAgentModel), so injected prompts that omit + // agent/model (envoy, pty notifications, prompt_async) stick to whatever the + // session is currently using instead of reverting to configured defaults. + // It also survives compaction, which can empty the message-based lookup below. + const current = yield* sessions.get(input.sessionID).pipe(Effect.orDie) + const prev = + input.agent || current.agent + ? undefined + : (yield* MessageV2.filterCompactedEffect(input.sessionID).pipe(Effect.provideService(Database.Service, database))).findLast( + (m): m is SessionV1.WithParts & { info: SessionV1.User } => + m.info.role === "user" && !!m.info.agent, + ) + const agentName = input.agent ?? current.agent ?? prev?.info.agent const ag = agentName ? yield* agents.get(agentName) : yield* agents.defaultInfo() if (!ag) { const available = (yield* agents.list()).filter((a) => !a.hidden).map((a) => a.name) @@ -643,7 +656,20 @@ const layer = Layer.effect( throw error } - const model = input.model ?? ag.model ?? (yield* currentModel(input.sessionID)) + // Only a genuine agent switch may reset the model to the agent's configured + // default; an explicit agent equal to the session's current one (e.g. a pty + // exit notification echoing its spawn-time agent) keeps the current model. + const switched = !!current.agent && ag.name !== current.agent + const sessionModel = + !switched && current.model + ? { + providerID: ProviderV2.ID.make(current.model.providerID), + modelID: ModelV2.ID.make(current.model.id), + variant: current.model.variant === "default" ? undefined : current.model.variant, + } + : undefined + const model = + input.model ?? sessionModel ?? prev?.info.model ?? ag.model ?? (yield* currentModel(input.sessionID)) const same = ag.model && model.providerID === ag.model.providerID && model.modelID === ag.model.modelID const full = !input.variant && ag.variant && same @@ -651,7 +677,9 @@ const layer = Layer.effect( .getModel(model.providerID, model.modelID) .pipe(Effect.catchIf(Provider.ModelNotFoundError.isInstance, () => Effect.succeed(undefined))) : undefined - const variant = input.variant ?? (ag.variant && full?.variants?.[ag.variant] ? ag.variant : undefined) + const modelVariant = model === sessionModel ? sessionModel.variant : model === prev?.info.model ? prev.info.model.variant : undefined + const variant = + input.variant ?? modelVariant ?? (ag.variant && full?.variants?.[ag.variant] ? ag.variant : undefined) const info: SessionV1.User = { id: input.messageID ?? MessageID.ascending(), @@ -669,7 +697,6 @@ const layer = Layer.effect( format: input.format, } - const current = yield* sessions.get(input.sessionID).pipe(Effect.orDie) if ( current.agent !== info.agent || current.model?.providerID !== info.model.providerID || diff --git a/packages/opencode/test/session/prompt.test.ts b/packages/opencode/test/session/prompt.test.ts index 491ad06aaf47..876b65b58191 100644 --- a/packages/opencode/test/session/prompt.test.ts +++ b/packages/opencode/test/session/prompt.test.ts @@ -2244,6 +2244,173 @@ it.instance("records aborted errors when prompt is cancelled mid-stream", () => // Agent variant +noLLMServer.instance( + "prompt without agent and model preserves current session agent and model", + () => + Effect.gen(function* () { + const prompt = yield* SessionPrompt.Service + const sessions = yield* Session.Service + const session = yield* sessions.create({}) + + yield* prompt.prompt({ + sessionID: session.id, + agent: "build", + model: ref, + noReply: true, + parts: [{ type: "text", text: "hello" }], + }) + + const next = yield* prompt.prompt({ + sessionID: session.id, + noReply: true, + parts: [{ type: "text", text: "hello again" }], + }) + if (next.info.role !== "user") throw new Error("expected user message") + expect(next.info.agent).toBe("build") + expect(next.info.model).toEqual(ref) + + yield* sessions.remove(session.id) + }), + { + config: { + ...cfg, + default_agent: "plan", + }, + }, +) + +noLLMServer.instance( + "explicit agent without model keeps the session's current model", + () => + Effect.gen(function* () { + const prompt = yield* SessionPrompt.Service + const sessions = yield* Session.Service + const session = yield* sessions.create({}) + + yield* prompt.prompt({ + sessionID: session.id, + agent: "build", + model: { providerID: ProviderV2.ID.make("opencode"), modelID: ModelV2.ID.make("kimi-k2.5-free") }, + noReply: true, + parts: [{ type: "text", text: "hello" }], + }) + + // pty/envoy-style injection: echoes the agent captured at spawn time but + // omits the model. Must NOT revert to the agent's configured model. + const next = yield* prompt.prompt({ + sessionID: session.id, + agent: "build", + noReply: true, + parts: [{ type: "text", text: "notification" }], + }) + if (next.info.role !== "user") throw new Error("expected user message") + expect(next.info.agent).toBe("build") + expect(next.info.model.providerID).toBe(ProviderV2.ID.make("opencode")) + expect(next.info.model.modelID).toBe(ModelV2.ID.make("kimi-k2.5-free")) + + yield* sessions.remove(session.id) + }), + { + config: { + ...cfg, + agent: { + build: { + model: "test/test-model", + }, + }, + }, + }, +) + +noLLMServer.instance( + "explicit agent switch without model uses the new agent's model", + () => + Effect.gen(function* () { + const prompt = yield* SessionPrompt.Service + const sessions = yield* Session.Service + const session = yield* sessions.create({}) + + yield* prompt.prompt({ + sessionID: session.id, + agent: "build", + model: { providerID: ProviderV2.ID.make("opencode"), modelID: ModelV2.ID.make("kimi-k2.5-free") }, + noReply: true, + parts: [{ type: "text", text: "hello" }], + }) + + const next = yield* prompt.prompt({ + sessionID: session.id, + agent: "plan", + noReply: true, + parts: [{ type: "text", text: "switch" }], + }) + if (next.info.role !== "user") throw new Error("expected user message") + expect(next.info.agent).toBe("plan") + expect(next.info.model.providerID).toBe(ProviderV2.ID.make("test")) + expect(next.info.model.modelID).toBe(ModelV2.ID.make("test-model")) + + yield* sessions.remove(session.id) + }), + { + config: { + ...cfg, + agent: { + plan: { + model: "test/test-model", + }, + }, + }, + }, +) + +noLLMServer.instance( + "prompt without agent, model, and variant preserves the current variant", + () => + Effect.gen(function* () { + const prompt = yield* SessionPrompt.Service + const sessions = yield* Session.Service + const session = yield* sessions.create({}) + + yield* prompt.prompt({ + sessionID: session.id, + agent: "build", + model: ref, + variant: "xhigh", + noReply: true, + parts: [{ type: "text", text: "hello" }], + }) + + const next = yield* prompt.prompt({ + sessionID: session.id, + noReply: true, + parts: [{ type: "text", text: "hello again" }], + }) + if (next.info.role !== "user") throw new Error("expected user message") + expect(next.info.agent).toBe("build") + expect(next.info.model).toEqual({ ...ref, variant: "xhigh" }) + + yield* sessions.remove(session.id) + }), + { + config: { + ...cfg, + provider: { + ...cfg.provider, + test: { + ...cfg.provider.test, + models: { + "test-model": { + ...cfg.provider.test.models["test-model"], + variants: { xhigh: {}, high: {} }, + }, + }, + }, + }, + default_agent: "plan", + }, + }, +) + noLLMServer.instance( "applies agent variant only when using agent model", () => @@ -2265,6 +2432,7 @@ noLLMServer.instance( const match = yield* prompt.prompt({ sessionID: session.id, agent: "build", + model: ref, noReply: true, parts: [{ type: "text", text: "hello again" }], }) @@ -2313,6 +2481,7 @@ noLLMServer.instance( }, ) + // Agent / command resolution errors noLLMServer.instance(