Compare commits

..

1 Commits

Author SHA1 Message Date
usrnk1 c97eb2d6fc feat(desktop): preserve session model selection 2026-06-30 14:16:10 +02:00
199 changed files with 116414 additions and 186834 deletions
+32 -36
View File
@@ -29,7 +29,7 @@
},
"packages/app": {
"name": "@opencode-ai/app",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@dnd-kit/abstract": "0.5.0",
"@dnd-kit/dom": "0.5.0",
@@ -92,7 +92,7 @@
},
"packages/cli": {
"name": "@opencode-ai/cli",
"version": "1.17.12",
"version": "1.17.11",
"bin": {
"lildax": "./bin/lildax.cjs",
},
@@ -140,7 +140,7 @@
},
"packages/console/app": {
"name": "@opencode-ai/console-app",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@cloudflare/vite-plugin": "1.15.2",
"@ibm/plex": "6.4.1",
@@ -176,7 +176,7 @@
},
"packages/console/core": {
"name": "@opencode-ai/console-core",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@aws-sdk/client-sts": "3.782.0",
"@jsx-email/render": "1.1.1",
@@ -203,7 +203,7 @@
},
"packages/console/function": {
"name": "@opencode-ai/console-function",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@ai-sdk/anthropic": "3.0.82",
"@ai-sdk/openai": "3.0.48",
@@ -225,7 +225,7 @@
},
"packages/console/mail": {
"name": "@opencode-ai/console-mail",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@jsx-email/all": "2.2.3",
"@jsx-email/cli": "1.4.3",
@@ -249,7 +249,7 @@
},
"packages/console/support": {
"name": "@opencode-ai/console-support",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@cloudflare/vite-plugin": "1.15.2",
"@opencode-ai/console-core": "workspace:*",
@@ -269,7 +269,7 @@
},
"packages/core": {
"name": "@opencode-ai/core",
"version": "1.17.12",
"version": "1.17.11",
"bin": {
"opencode": "./bin/opencode",
},
@@ -334,7 +334,7 @@
"npm-package-arg": "13.0.2",
"semver": "^7.6.3",
"turndown": "7.2.0",
"venice-ai-sdk-provider": "2.1.1",
"venice-ai-sdk-provider": "2.0.2",
"which": "6.0.1",
"xdg-basedir": "5.1.0",
"zod": "catalog:",
@@ -363,7 +363,7 @@
},
"packages/desktop": {
"name": "@opencode-ai/desktop",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@zip.js/zip.js": "2.7.62",
"effect": "catalog:",
@@ -417,7 +417,7 @@
},
"packages/effect-drizzle-sqlite": {
"name": "@opencode-ai/effect-drizzle-sqlite",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"drizzle-orm": "catalog:",
"effect": "catalog:",
@@ -431,7 +431,7 @@
},
"packages/effect-sqlite-node": {
"name": "@opencode-ai/effect-sqlite-node",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"effect": "catalog:",
},
@@ -443,7 +443,7 @@
},
"packages/enterprise": {
"name": "@opencode-ai/enterprise",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@hono/standard-validator": "catalog:",
"@opencode-ai/core": "workspace:*",
@@ -475,7 +475,7 @@
},
"packages/function": {
"name": "@opencode-ai/function",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@octokit/auth-app": "8.0.1",
"@octokit/rest": "catalog:",
@@ -491,7 +491,7 @@
},
"packages/http-recorder": {
"name": "@opencode-ai/http-recorder",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@effect/platform-node": "4.0.0-beta.83",
"@effect/platform-node-shared": "4.0.0-beta.83",
@@ -522,7 +522,7 @@
},
"packages/llm": {
"name": "@opencode-ai/llm",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@opencode-ai/schema": "workspace:*",
"@smithy/eventstream-codec": "4.2.14",
@@ -541,7 +541,7 @@
},
"packages/opencode": {
"name": "opencode",
"version": "1.17.12",
"version": "1.17.11",
"bin": {
"opencode": "./bin/opencode",
},
@@ -637,7 +637,7 @@
"tree-sitter-powershell": "0.25.10",
"turndown": "7.2.0",
"ulid": "catalog:",
"venice-ai-sdk-provider": "2.1.1",
"venice-ai-sdk-provider": "2.0.2",
"vscode-jsonrpc": "8.2.1",
"web-tree-sitter": "0.25.10",
"ws": "8.21.0",
@@ -671,7 +671,7 @@
},
"packages/plugin": {
"name": "@opencode-ai/plugin",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@ai-sdk/provider": "3.0.8",
"@opencode-ai/sdk": "workspace:*",
@@ -747,7 +747,7 @@
},
"packages/sdk/js": {
"name": "@opencode-ai/sdk",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"cross-spawn": "catalog:",
},
@@ -762,7 +762,7 @@
},
"packages/server": {
"name": "@opencode-ai/server",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@opencode-ai/core": "workspace:*",
"@opencode-ai/protocol": "workspace:*",
@@ -777,7 +777,7 @@
},
"packages/session-ui": {
"name": "@opencode-ai/session-ui",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@kobalte/core": "catalog:",
"@opencode-ai/core": "workspace:*",
@@ -821,7 +821,7 @@
},
"packages/slack": {
"name": "@opencode-ai/slack",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@opencode-ai/sdk": "workspace:*",
"@slack/bolt": "^3.17.1",
@@ -834,7 +834,7 @@
},
"packages/stats/app": {
"name": "@opencode-ai/stats-app",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@ibm/plex": "6.4.1",
"@opencode-ai/stats-core": "workspace:*",
@@ -867,7 +867,7 @@
},
"packages/stats/core": {
"name": "@opencode-ai/stats-core",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@aws-sdk/client-athena": "3.933.0",
"@planetscale/database": "1.19.0",
@@ -886,7 +886,7 @@
},
"packages/stats/server": {
"name": "@opencode-ai/stats-server",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@aws-sdk/client-firehose": "3.933.0",
"@effect/platform-node": "catalog:",
@@ -927,7 +927,7 @@
},
"packages/tui": {
"name": "@opencode-ai/tui",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@opencode-ai/core": "workspace:*",
"@opencode-ai/plugin": "workspace:*",
@@ -954,7 +954,7 @@
},
"packages/ui": {
"name": "@opencode-ai/ui",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@kobalte/core": "catalog:",
"@pierre/diffs": "catalog:",
@@ -1005,7 +1005,7 @@
},
"packages/web": {
"name": "@opencode-ai/web",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@astrojs/cloudflare": "12.6.3",
"@astrojs/markdown-remark": "6.3.1",
@@ -5429,7 +5429,7 @@
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
"venice-ai-sdk-provider": ["venice-ai-sdk-provider@2.1.1", "", { "dependencies": { "@ai-sdk/openai-compatible": "^2.0.51", "@ai-sdk/provider": "^3.0.10", "@ai-sdk/provider-utils": "^4.0.30" }, "peerDependencies": { "ai": "^6.0.90" } }, "sha512-w3OHkuzzKZ3r2TOxER6myBYzZJNoDqol+DUHu3NnfBN/GETnUVxecZJab0CHQQ8GZc0jjzpFymepjcLDPS4SQg=="],
"venice-ai-sdk-provider": ["venice-ai-sdk-provider@2.0.2", "", { "dependencies": { "@ai-sdk/openai-compatible": "^2.0.47", "@ai-sdk/provider": "^3.0.10", "@ai-sdk/provider-utils": "^4.0.27" }, "peerDependencies": { "ai": "^6.0.90" } }, "sha512-aoa05nI3BTK5aGbjBflq+Gfln2AHAkwNbWuGGvCzUIsOfp5Y3iPD4O4PUGDAEiWVJWbjpPn0KfDa0H/HebwsaA=="],
"verror": ["verror@1.10.1", "", { "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg=="],
@@ -6449,11 +6449,11 @@
"unzipper/fs-extra": ["fs-extra@11.3.5", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg=="],
"venice-ai-sdk-provider/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.53", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.32" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-SoPSkrL5cbNQnAljRsJ7pOzJ2FmWgnhC0lfFOda873ycCdFJL1A+h3Ib7mX2spcv3XnNaO13y/45/0RyqNWlIQ=="],
"venice-ai-sdk-provider/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.47", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Enm5UlL0zUCrW3792opk5h7hRWxZOZzDe6eQYVFqX9LUOGGCe1h8MZWAGim765nwzgnjlpeYOsuzZmLtRsTPlg=="],
"venice-ai-sdk-provider/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="],
"venice-ai-sdk-provider/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.32", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Kwj499fTcN9bP/AfGoPU7JWIXeP6VZqKI6omsH062c9E2G4gdjeJczkz4z/tYSkzYjLE2AI3DtZbMfs6D7vn2Q=="],
"venice-ai-sdk-provider/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="],
"verror/core-util-is": ["core-util-is@1.0.2", "", {}, "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="],
@@ -7073,10 +7073,6 @@
"unzipper/fs-extra/jsonfile": ["jsonfile@6.2.1", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q=="],
"venice-ai-sdk-provider/@ai-sdk/openai-compatible/@ai-sdk/provider": ["@ai-sdk/provider@3.0.12", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-sj9DWTJ2Ze0WR9qsiOPqoqzNx3OxL6iMxHImbhvoe9qOspekbzxNDMiJ4TIGfYHYh9w4OmBjz3prvqhzTi96+Q=="],
"venice-ai-sdk-provider/@ai-sdk/provider-utils/@ai-sdk/provider": ["@ai-sdk/provider@3.0.12", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-sj9DWTJ2Ze0WR9qsiOPqoqzNx3OxL6iMxHImbhvoe9qOspekbzxNDMiJ4TIGfYHYh9w4OmBjz3prvqhzTi96+Q=="],
"venice-ai-sdk-provider/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
"vitest/@vitest/expect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
+4 -4
View File
@@ -1,8 +1,8 @@
{
"nodeModules": {
"x86_64-linux": "sha256-Ulflihjr8JDRVyNxSchoqaey6z/12256zs1FOiw+4vo=",
"aarch64-linux": "sha256-wP6p30a9f7s3tua5qbIq/10OHdbJb8xUni5KxE3F+/k=",
"aarch64-darwin": "sha256-7+4skFiJ+tLSjNG6WR53bT/IektA5B7gEcWLYpkK4z8=",
"x86_64-darwin": "sha256-NL945zD4J6HomH5SF0XIO8ZFCbIh2MTsJFtTyuxm2Q0="
"x86_64-linux": "sha256-JXQ9PAqqRlJtHa8T3ZxqdRRyxC+0ip+2wSnehvKXUbI=",
"aarch64-linux": "sha256-nI+RaxDXmAcjhSjCtIvyi292xBEg0E5NXaoyGrJE69s=",
"aarch64-darwin": "sha256-UleKpm7Khf3kibm4BqZJ9bmu0N2kOjNd77g1Bd2tmfw=",
"x86_64-darwin": "sha256-V4AQH868dOfVhEj1mKTnZlhpZwFqBYsHS28Tx9VXHkE="
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/app",
"version": "1.17.12",
"version": "1.17.11",
"description": "",
"type": "module",
"exports": {
@@ -59,6 +59,7 @@ const ModelList: Component<{
class="w-full"
placement="right-start"
gutter={12}
openDelay={0}
value={<ModelTooltip model={item} latest={item.latest} free={isFree(item.provider.id, item.cost)} />}
>
{node}
@@ -37,7 +37,7 @@ export const PromptContextItems: Component<ContextItemsProps> = (props) => {
</span>
}
placement="top"
openDelay={800}
openDelay={2000}
>
<div
classList={{
@@ -92,17 +92,11 @@ export function PromptWorkspaceSelector(props: {
</MenuV2.Content>
</MenuV2.Portal>
</MenuV2>
<Show when={props.branch}>
{(branch) => (
<>
<span class="hidden select-none opacity-50 sm:inline mx-1">/</span>
<div class="flex h-7 min-w-0 max-w-[220px] items-center gap-1.5 px-2 text-[13px] font-[440] leading-5 tracking-[-0.04px]">
<Icon name="branch" size="small" class="shrink-0 text-v2-icon-icon-muted" />
<span class="min-w-0 truncate">{branch()}</span>
</div>
</>
)}
</Show>
<span class="hidden select-none opacity-50 sm:inline mx-1">/</span>
<div class="flex h-7 min-w-0 max-w-[220px] items-center gap-1.5 px-2 text-[13px] font-[440] leading-5 tracking-[-0.04px]">
<Icon name="branch" size="small" class="shrink-0 text-v2-icon-icon-muted" />
<span class="min-w-0 truncate">{props.branch || "main"}</span>
</div>
</>
)
}
@@ -541,7 +541,6 @@ function SessionHeaderV2Actions(props: { state: SessionHeaderV2ActionsState }) {
</Show>
<Show when={props.state.reviewVisible}>
<TooltipV2
class="shrink-0"
placement="bottom"
value={
<>
+3 -3
View File
@@ -572,7 +572,7 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
placement="bottom"
title={language.t("command.session.new")}
keybind={command.keybind("session.new")}
openDelay={800}
openDelay={2000}
>
<Button
variant="ghost"
@@ -602,7 +602,7 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
>
<Show when={hasProjects() && nav()}>
<div class="flex items-center gap-0 transition-transform">
<Tooltip placement="bottom" value={language.t("common.goBack")} openDelay={800}>
<Tooltip placement="bottom" value={language.t("common.goBack")} openDelay={2000}>
<Button
variant="ghost"
icon="chevron-left"
@@ -612,7 +612,7 @@ export function Titlebar(props: { update?: TitlebarUpdate }) {
aria-label={language.t("common.goBack")}
/>
</Tooltip>
<Tooltip placement="bottom" value={language.t("common.goForward")} openDelay={800}>
<Tooltip placement="bottom" value={language.t("common.goForward")} openDelay={2000}>
<Button
variant="ghost"
icon="chevron-right"
+35 -18
View File
@@ -1,6 +1,6 @@
import { createSimpleContext } from "@opencode-ai/ui/context"
import { base64Encode } from "@opencode-ai/core/util/encode"
import { useParams } from "@solidjs/router"
import { useParams, useSearchParams } from "@solidjs/router"
import { batch, createEffect, createMemo, startTransition } from "solid-js"
import { createStore } from "solid-js/store"
import { useModels } from "@/context/models"
@@ -18,10 +18,12 @@ type State = {
agent?: string
model?: ModelKey
variant?: string | null
source?: "manual" | "message"
}
type Saved = {
session: Record<string, State | undefined>
draft?: State
}
const WORKSPACE_KEY = "__workspace__"
@@ -37,11 +39,13 @@ const migrate = (value: unknown) => {
pick?: Record<string, State | undefined>
}
if (item.session && typeof item.session === "object") return { session: item.session }
const draft = "draft" in item && item.draft && typeof item.draft === "object" ? (item.draft as State) : undefined
if (item.session && typeof item.session === "object") return { session: item.session, draft }
if (!item.pick || typeof item.pick !== "object") return { session: {} }
return {
session: Object.fromEntries(Object.entries(item.pick).filter(([key]) => key !== WORKSPACE_KEY)),
draft,
}
}
@@ -57,6 +61,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
name: "Local",
init: () => {
const params = useParams()
const [search] = useSearchParams<{ draftId?: string }>()
const sdk = useSDK()
const sync = useSync()
const serverSDK = useServerSDK()
@@ -64,12 +69,15 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
const models = useModels()
const id = createMemo(() => params.id || undefined)
const draftID = createMemo(() => search.draftId || undefined)
const list = createMemo(() => sync().data.agent.filter((item) => item.mode !== "subagent" && !item.hidden))
const connected = createMemo(() => new Set(providers.connected().map((item) => item.id)))
const [saved, setSaved] = persisted(
{
...Persist.serverWorkspace(serverSDK().scope, sdk().directory, "model-selection", ["model-selection.v1"]),
...(draftID()
? Persist.draft(draftID()!, "model-selection")
: Persist.serverWorkspace(serverSDK().scope, sdk().directory, "model-selection", ["model-selection.v1"])),
migrate,
},
createStore<Saved>({
@@ -124,7 +132,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
const scope = createMemo<State | undefined>(() => {
const session = id()
if (!session) return store.draft ?? store.promoting
if (!session) return saved.draft ?? store.draft ?? store.promoting
return saved.session[session] ?? handoff.get(handoffKey(serverSDK().scope, sdk().directory, session))
})
@@ -178,6 +186,19 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
const fallback = createMemo<ModelKey | undefined>(() => configuredModel() ?? recentModel() ?? defaultModel())
const save = (state: State) => {
const session = id()
if (session) {
setSaved("session", session, state)
return
}
if (draftID()) {
setSaved("draft", state)
return
}
setStore("draft", state)
}
const agent = {
list,
current() {
@@ -203,13 +224,9 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
agent: item.name,
model: item.model ?? prev?.model,
variant: item.variant ?? prev?.variant,
source: "manual",
} satisfies State
const session = id()
if (session) {
setSaved("session", session, next)
return
}
setStore("draft", next)
save(next)
})
},
move(direction: 1 | -1) {
@@ -263,14 +280,10 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
const state = {
...(scope() ?? { agent: agent.current()?.name }),
...next,
source: "manual",
} satisfies State
const session = id()
if (session) {
setSaved("session", session, state)
return
}
setStore("draft", state)
save(state)
}
const recent = createMemo(() => models.recent.list().map(models.find).filter(Boolean))
@@ -377,10 +390,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
session: {
reset() {
setStore({ draft: undefined, promoting: undefined })
if (draftID()) setSaved("draft", undefined)
},
promote(dir: string, session: string) {
const next = clone(snapshot())
if (!next) return
next.source = "manual"
const key = handoffKey(serverSDK().scope, dir, session)
handoff.set(key, next)
@@ -391,17 +406,19 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
setStore("promoting", next)
setStore("draft", undefined)
},
restore(msg: { sessionID: string; agent: string; model: ModelKey }) {
restore(msg: { id?: string; sessionID: string; agent: string; model: ModelKey }) {
const session = id()
if (!session) return
if (msg.sessionID !== session) return
if (saved.session[session] !== undefined) return
const current = saved.session[session]
if (current?.source === "manual") return
if (handoff.has(handoffKey(serverSDK().scope, sdk().directory, session))) return
setSaved("session", session, {
agent: msg.agent,
model: msg.model,
variant: msg.model?.variant ?? null,
source: "message",
})
},
},
+1 -4
View File
@@ -276,10 +276,7 @@ export const ErrorPage: Component<ErrorPageProps> = (props) => {
}
return (
<div
class="relative flex-1 h-screen w-screen min-h-0 flex flex-col items-center justify-center bg-background-base font-sans"
data-tauri-drag-region
>
<div class="relative flex-1 h-screen w-screen min-h-0 flex flex-col items-center justify-center bg-background-base font-sans">
<div class="w-2/3 max-w-3xl flex flex-col items-center justify-center gap-8">
<Logo class="w-58.5 opacity-12 shrink-0" />
<div class="flex flex-col items-center gap-2 text-center">
+9 -3
View File
@@ -1006,8 +1006,8 @@ function HomeSessionLeading(props: {
<Show when={hasOpenTab()}>
<span
aria-hidden="true"
class="pointer-events-none absolute top-1/2 h-3 w-0.5 -translate-y-1/2 rounded-[2px] bg-v2-background-bg-layer-04"
style={{ right: "calc(100% + 4px)" }}
class="pointer-events-none absolute top-1/2 h-[7px] w-[3px] -translate-y-1/2 rounded-[2px] bg-v2-background-bg-layer-04"
style={{ right: "calc(100% + 5px)" }}
/>
</Show>
<SessionTabAvatar
@@ -1163,7 +1163,13 @@ function HomeSessionSearch(props: {
</div>
</div>
</Show>
<label class="relative z-20 flex h-9 w-full items-center gap-2 rounded-[6px] bg-v2-background-bg-layer-02/60 py-1 pl-3 pr-2 text-v2-icon-icon-muted transition-[background-color,box-shadow] duration-[120ms] ease-in-out hover:bg-v2-background-bg-layer-02">
<label
class="relative z-20 flex h-9 w-full items-center gap-2 rounded-[6px] bg-v2-background-bg-layer-02 py-1 pl-3 pr-2 text-v2-icon-icon-muted transition-[background-color,box-shadow] duration-[120ms] ease-in-out"
classList={{
"focus-within:shadow-[0_0_0_0.5px_var(--v2-border-border-focus),var(--v2-elevation-raised)]": !props.open,
"shadow-[0_0_0_0.5px_var(--v2-border-border-focus)]": props.open,
}}
>
<IconV2 name="magnifying-glass" />
<input
ref={input}
@@ -736,9 +736,8 @@ export function MessageTimeline(props: {
if (!sessionID() || parentID()) return
setTitle({ editing: true, draft: titleLabel() ?? "" })
requestAnimationFrame(() => {
if (!titleRef) return
titleRef.focus()
titleRef.select()
titleRef?.focus()
titleRef?.select()
})
}
@@ -1370,7 +1369,7 @@ export function MessageTimeline(props: {
"pr-3": !settings.general.newLayoutDesigns(),
}}
>
<div class="flex items-center min-w-0 flex-1 w-full">
<div class="flex items-center min-w-0 grow-1">
<Show when={parentID()}>
<button
type="button"
@@ -1414,9 +1413,9 @@ export function MessageTimeline(props: {
value={title.draft}
disabled={titleMutation.isPending}
classList={{
"text-14-medium text-text-strong block": true,
"w-full flex-1 grow-1 min-w-0 pl-1 -ml-1 rounded-[6px]": !settings.general.newLayoutDesigns(),
"field-sizing-content self-start rounded-[6px] px-2 py-1 ":
"text-14-medium text-text-strong grow-1 min-w-0 pl-1 ml-1": true,
"grow-1 min-w-0 pl-1 -ml-1 rounded-[6px]": !settings.general.newLayoutDesigns(),
"rounded-[6px] -ml-2 px-2 py-1 h-6 leading-4 focus:shadow-none focus:outline focus:outline-1 focus:outline-offset-[-1px] focus:outline-v2-border-border-focus":
settings.general.newLayoutDesigns(),
}}
style={{
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/cli",
"version": "1.17.12",
"version": "1.17.11",
"type": "module",
"license": "MIT",
"bin": {
+2 -3
View File
@@ -1,7 +1,5 @@
import { NodeHttpServer } from "@effect/platform-node"
import { Credential } from "@opencode-ai/core/credential"
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
import { PermissionSaved } from "@opencode-ai/core/permission/saved"
import { Context, Layer, Option } from "effect"
import * as Effect from "effect/Effect"
@@ -40,7 +38,8 @@ function bind(hostname: string, port: number, password: string) {
return Layer.build(
HttpRouter.serve(createRoutes(password), { disableListenLog: true, disableLogger: true }).pipe(
Layer.provideMerge(NodeHttpServer.layer(() => createServer(), { port, host: hostname })),
Layer.provide(AppNodeBuilder.build(LayerNode.group([Credential.node, PermissionSaved.node]))),
Layer.provide(Credential.defaultLayer),
Layer.provide(PermissionSaved.defaultLayer),
),
).pipe(Effect.map((context) => Context.get(context, HttpServer.HttpServer).address))
}
+1 -1
View File
@@ -25,7 +25,7 @@ const Handlers = Runtime.handlers(Commands, {
})
Runtime.run(Commands, Handlers, { version: "local" }).pipe(
Effect.provide(Daemon.layer),
Effect.provide(Daemon.defaultLayer),
Effect.provide(NodeServices.layer),
Effect.scoped,
NodeRuntime.runMain,
+2
View File
@@ -189,4 +189,6 @@ export const layer = Layer.effect(
}),
)
export const defaultLayer = layer
export * as Daemon from "./daemon"
+1 -2
View File
@@ -1,7 +1,6 @@
import { run } from "@opencode-ai/tui"
import { TuiConfig } from "@opencode-ai/tui/config"
import { Effect } from "effect"
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
import { Global } from "@opencode-ai/core/global"
export function runTui(transport: { url: string; headers: RequestInit["headers"] }) {
@@ -15,7 +14,7 @@ export function runTui(transport: { url: string; headers: RequestInit["headers"]
async start() {},
async dispose() {},
},
}).pipe(Effect.provide(AppNodeBuilder.build(Global.node)))
}).pipe(Effect.provide(Global.defaultLayer))
}
const legacyDefaults: Record<string, unknown> = {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-app",
"version": "1.17.12",
"version": "1.17.11",
"type": "module",
"license": "MIT",
"scripts": {
+1
View File
@@ -248,6 +248,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "الاستثناءات التالية",
"go.title": "OpenCode Go | نماذج برمجة منخفضة التكلفة للجميع",
"go.banner.text": "MiniMax M3: حد استخدام أكبر 3 مرات لفترة محدودة",
"go.meta.description":
"يبدأ Go من $5 للشهر الأول، ثم $10/شهر، مع حدود طلب سخية لمدة 5 ساعات لـ GLM-5.2 وGLM-5.1 وKimi K2.7 Code وKimi K2.6 وMiMo-V2.5-Pro وMiMo-V2.5 وQwen3.7 Max وQwen3.7 Plus وQwen3.6 Plus وMiniMax M2.7 وMiniMax M3 وDeepSeek V4 Pro وDeepSeek V4 Flash.",
"go.hero.title": "نماذج برمجة منخفضة التكلفة للجميع",
+1
View File
@@ -252,6 +252,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "seguintes exceções",
"go.title": "OpenCode Go | Modelos de codificação de baixo custo para todos",
"go.banner.text": "MiniMax M3 tem limite de uso 3x maior por tempo limitado",
"go.meta.description":
"O Go começa em $5 no primeiro mês, depois $10/mês, com limites generosos de solicitação de 5 horas para GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro e DeepSeek V4 Flash.",
"go.hero.title": "Modelos de codificação de baixo custo para todos",
+1
View File
@@ -250,6 +250,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "følgende undtagelser",
"go.title": "OpenCode Go | Kodningsmodeller til lav pris for alle",
"go.banner.text": "MiniMax M3 får tredoblet brugsgrænse i en begrænset periode",
"go.meta.description":
"Go starter ved $5 for den første måned, derefter $10/måned, med generøse 5-timers anmodningsgrænser for GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro og DeepSeek V4 Flash.",
"go.hero.title": "Kodningsmodeller til lav pris for alle",
+1
View File
@@ -252,6 +252,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "folgenden Ausnahmen",
"go.title": "OpenCode Go | Kostengünstige Coding-Modelle für alle",
"go.banner.text": "MiniMax M3 erhält für begrenzte Zeit 3x Nutzungslimits",
"go.meta.description":
"Go beginnt bei $5 für den ersten Monat, danach $10/Monat, mit großzügigen 5-Stunden-Anfragelimits für GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro und DeepSeek V4 Flash.",
"go.hero.title": "Kostengünstige Coding-Modelle für alle",
+1
View File
@@ -248,6 +248,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "following exceptions",
"go.title": "OpenCode Go | Low cost coding models for everyone",
"go.banner.text": "MiniMax M3 gets 3× usage limits for a limited time",
"go.meta.description":
"Go starts at $5 for your first month, then $10/month, with generous 5-hour request limits for GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro, and DeepSeek V4 Flash.",
"go.hero.title": "Low cost coding models for everyone",
+1
View File
@@ -253,6 +253,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "siguientes excepciones",
"go.title": "OpenCode Go | Modelos de programación de bajo coste para todos",
"go.banner.text": "MiniMax M3 tiene límites de uso 3x mayores por tiempo limitado",
"go.meta.description":
"Go comienza en $5 el primer mes, luego 10 $/mes, con generosos límites de solicitudes de 5 horas para GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro y DeepSeek V4 Flash.",
"go.hero.title": "Modelos de programación de bajo coste para todos",
+1
View File
@@ -254,6 +254,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "exceptions suivantes",
"go.title": "OpenCode Go | Modèles de code à faible coût pour tous",
"go.banner.text": "MiniMax M3 bénéficie de limites dutilisation 3x supérieures pour une durée limitée",
"go.meta.description":
"Go commence à $5 pour le premier mois, puis 10 $/mois, avec des limites de requêtes généreuses sur 5 heures pour GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro et DeepSeek V4 Flash.",
"go.hero.title": "Modèles de code à faible coût pour tous",
+1
View File
@@ -250,6 +250,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "seguenti eccezioni",
"go.title": "OpenCode Go | Modelli di coding a basso costo per tutti",
"go.banner.text": "MiniMax M3 offre limiti di utilizzo 3x superiori per un periodo limitato",
"go.meta.description":
"Go inizia a $5 per il primo mese, poi $10/mese, con generosi limiti di richiesta di 5 ore per GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro e DeepSeek V4 Flash.",
"go.hero.title": "Modelli di coding a basso costo per tutti",
+1
View File
@@ -249,6 +249,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "以下の例外",
"go.title": "OpenCode Go | すべての人のための低価格なコーディングモデル",
"go.banner.text": "MiniMax M3の利用上限が期間限定で3倍に",
"go.meta.description":
"Goは最初の月$5、その後$10/月で、GLM-5.2、GLM-5.1、Kimi K2.7 Code、Kimi K2.6、MiMo-V2.5-Pro、MiMo-V2.5、Qwen3.7 Max、Qwen3.7 Plus、Qwen3.6 Plus、MiniMax M2.7、MiniMax M3、DeepSeek V4 Pro、DeepSeek V4 Flashに対して5時間のゆとりあるリクエスト上限があります。",
"go.hero.title": "すべての人のための低価格なコーディングモデル",
+1
View File
@@ -246,6 +246,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "다음 예외",
"go.title": "OpenCode Go | 모두를 위한 저비용 코딩 모델",
"go.banner.text": "MiniMax M3 사용 한도가 한시적으로 3배 확대됩니다",
"go.meta.description":
"Go는 첫 달 $5, 이후 $10/월로 시작하며, GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro, DeepSeek V4 Flash에 대해 넉넉한 5시간 요청 한도를 제공합니다.",
"go.hero.title": "모두를 위한 저비용 코딩 모델",
+1
View File
@@ -250,6 +250,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "følgende unntak",
"go.title": "OpenCode Go | Rimelige kodemodeller for alle",
"go.banner.text": "MiniMax M3 får 3x bruksgrense i en begrenset periode",
"go.meta.description":
"Go starter på $5 for den første måneden, deretter $10/måned, med sjenerøse 5-timers forespørselsgrenser for GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro og DeepSeek V4 Flash.",
"go.hero.title": "Rimelige kodemodeller for alle",
+1
View File
@@ -251,6 +251,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "następującymi wyjątkami",
"go.title": "OpenCode Go | Niskokosztowe modele do kodowania dla każdego",
"go.banner.text": "MiniMax M3 oferuje 3x wyższe limity użycia przez ograniczony czas",
"go.meta.description":
"Go zaczyna się od $5 za pierwszy miesiąc, potem $10/miesiąc, z hojnymi 5-godzinnymi limitami zapytań dla GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro i DeepSeek V4 Flash.",
"go.hero.title": "Niskokosztowe modele do kodowania dla każdego",
+1
View File
@@ -254,6 +254,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "следующими исключениями",
"go.title": "OpenCode Go | Недорогие модели для кодинга для всех",
"go.banner.text": "MiniMax M3 получает 3x лимиты использования на ограниченное время",
"go.meta.description":
"Go начинается с $5 за первый месяц, затем $10/месяц, с щедрыми лимитами запросов за 5 часов для GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro и DeepSeek V4 Flash.",
"go.hero.title": "Недорогие модели для кодинга для всех",
+1
View File
@@ -249,6 +249,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "ข้อยกเว้นดังนี้",
"go.title": "OpenCode Go | โมเดลเขียนโค้ดราคาประหยัดสำหรับทุกคน",
"go.banner.text": "MiniMax M3 เพิ่มโควตาการใช้งานเป็น 3 เท่าในช่วงเวลาจำกัด",
"go.meta.description":
"Go เริ่มต้นที่ $5 สำหรับเดือนแรก จากนั้น $10/เดือน พร้อมขีดจำกัดคำขอ 5 ชั่วโมงที่เอื้อเฟื้อสำหรับ GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro และ DeepSeek V4 Flash",
"go.hero.title": "โมเดลเขียนโค้ดราคาประหยัดสำหรับทุกคน",
+1
View File
@@ -252,6 +252,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "aşağıdaki istisnalar",
"go.title": "OpenCode Go | Herkes için düşük maliyetli kodlama modelleri",
"go.banner.text": "MiniMax M3 sınırlı bir süre için 3x kullanım limiti sunuyor",
"go.meta.description":
"Go ilk ay $5, sonrasında ayda 10$ fiyatıyla başlar; GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro ve DeepSeek V4 Flash için cömert 5 saatlik istek limitleri sunar.",
"go.hero.title": "Herkes için düşük maliyetli kodlama modelleri",
+1
View File
@@ -251,6 +251,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "такими винятками",
"go.title": "OpenCode Go | Недорогі моделі кодування для всіх",
"go.banner.text": "MiniMax M3 отримує 3x ліміти використання протягом обмеженого часу",
"go.meta.description":
"Go починається від $5 за перший місяць, потім $10/місяць, з generous 5-годинними лімітами запитів для GLM-5.2, GLM-5.1, Kimi K2.7 Code, Kimi K2.6, MiMo-V2.5-Pro, MiMo-V2.5, Qwen3.7 Max, Qwen3.7 Plus, Qwen3.6 Plus, MiniMax M2.7, MiniMax M3, DeepSeek V4 Pro та DeepSeek V4 Flash.",
"go.hero.title": "Недорогі моделі кодування для всіх",
+1
View File
@@ -240,6 +240,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "以下例外情况除外",
"go.title": "OpenCode Go | 人人可用的低成本编程模型",
"go.banner.text": "MiniMax M3 限时享受 3 倍使用额度",
"go.meta.description":
"Go 首月 $5,之后 $10/月,提供对 GLM-5.2、GLM-5.1、Kimi K2.7 Code、Kimi K2.6、MiMo-V2.5-Pro、MiMo-V2.5、Qwen3.7 Max、Qwen3.7 Plus、Qwen3.6 Plus、MiniMax M2.7、MiniMax M3、DeepSeek V4 Pro 和 DeepSeek V4 Flash 的 5 小时充裕请求额度。",
"go.hero.title": "人人可用的低成本编程模型",
+1
View File
@@ -240,6 +240,7 @@ export const dict = {
"zen.privacy.exceptionsLink": "以下例外情況",
"go.title": "OpenCode Go | 低成本全民編碼模型",
"go.banner.text": "MiniMax M3 限時享有 3 倍使用額度",
"go.meta.description":
"Go 首月 $5,之後 $10/月,提供對 GLM-5.2、GLM-5.1、Kimi K2.7 Code、Kimi K2.6、MiMo-V2.5-Pro、MiMo-V2.5、Qwen3.7 Max、Qwen3.7 Plus、Qwen3.6 Plus、MiniMax M2.7、MiniMax M3、DeepSeek V4 Pro 和 DeepSeek V4 Flash 的 5 小時充裕請求額度。",
"go.hero.title": "低成本全民編碼模型",
@@ -327,6 +327,37 @@ body {
}
}
[data-component="desktop-app-banner"] {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 32px;
[data-slot="badge"] {
background: var(--color-background-strong);
color: var(--color-text-inverted);
font-weight: 500;
padding: 4px 8px;
line-height: 1;
flex-shrink: 0;
}
[data-slot="content"] {
display: flex;
align-items: center;
gap: 1ch;
}
[data-slot="text"] {
color: var(--color-text-strong);
line-height: 1.4;
@media (max-width: 30.625rem) {
display: none;
}
}
}
[data-slot="hero-copy"] {
img {
margin-bottom: 24px;
@@ -632,6 +663,10 @@ body {
fill: var(--color-text-strong);
}
[data-bar][data-kind="promo"] {
fill: color-mix(in srgb, var(--bar-go) 50%, transparent);
}
[data-val] {
fill: var(--color-text-strong);
font-size: 13px;
+23 -5
View File
@@ -64,10 +64,10 @@ function LimitsGraph(props: { href: string }) {
{ id: "glm-5.2", name: "GLM-5.2", req: 880, d: "100ms" },
{ id: "qwen3.7-max", name: "Qwen3.7 Max", req: 950, d: "110ms" },
{ id: "kimi-k2.7-code", name: "Kimi K2.7 Code", req: 1150, d: "150ms" },
{ id: "minimax-m3", name: "MiniMax M3", req: 3200, d: "210ms" },
{ id: "mimo-v2.5-pro", name: "MiMo-V2.5-Pro", req: 3250, d: "240ms" },
{ id: "deepseek-v4-pro", name: "DeepSeek V4 Pro", req: 3450, d: "270ms" },
{ id: "qwen3.7-plus", name: "Qwen3.7 Plus", req: 4300, d: "300ms" },
{ id: "mimo-v2.5-pro", name: "MiMo-V2.5-Pro", req: 3250, d: "210ms" },
{ id: "deepseek-v4-pro", name: "DeepSeek V4 Pro", req: 3450, d: "240ms" },
{ id: "qwen3.7-plus", name: "Qwen3.7 Plus", req: 4300, d: "250ms" },
{ id: "minimax-m3", name: "MiniMax M3 (3x usage)", req: 9600, baseReq: 3200, d: "280ms" },
{ id: "mimo-v2.5", name: "MiMo-V2.5", req: 30100, d: "340ms" },
{ id: "deepseek-v4-flash", name: "DeepSeek V4 Flash", req: 31650, d: "340ms" },
]
@@ -157,12 +157,24 @@ function LimitsGraph(props: { href: string }) {
<rect
x={left}
y={gy(i()) - bh / 2}
width={Math.max(0, x(ratio(m.req)) - left)}
width={Math.max(0, x(ratio(m.baseReq ?? m.req)) - left)}
height={bh}
data-bar
data-kind="go"
data-model={m.id}
data-segment={m.baseReq ? "base" : undefined}
/>
{m.baseReq && (
<rect
x={x(ratio(m.baseReq)) + 2}
y={gy(i()) - bh / 2}
width={Math.max(0, x(ratio(m.req)) - x(ratio(m.baseReq)) - 2)}
height={bh}
data-bar
data-kind="promo"
data-model={m.id}
/>
)}
</g>
)}
</For>
@@ -252,6 +264,12 @@ export default function Home() {
<div data-component="content">
<section data-component="hero">
<div data-component="desktop-app-banner">
<span data-slot="badge">{i18n.t("home.banner.badge")}</span>
<div data-slot="content">
<span data-slot="text">{i18n.t("go.banner.text")}</span>
</div>
</div>
<div data-slot="hero-copy">
<img data-slot="zen logo light" src={goLogoLight} alt="" />
<img data-slot="zen logo dark" src={goLogoDark} alt="" />
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/console-core",
"version": "1.17.12",
"version": "1.17.11",
"private": true,
"type": "module",
"license": "MIT",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-function",
"version": "1.17.12",
"version": "1.17.11",
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"type": "module",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-mail",
"version": "1.17.12",
"version": "1.17.11",
"dependencies": {
"@jsx-email/all": "2.2.3",
"@jsx-email/cli": "1.4.3",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@opencode-ai/console-support",
"version": "1.17.12",
"version": "1.17.11",
"type": "module",
"license": "MIT",
"scripts": {
+2 -2
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://json.schemastore.org/package.json",
"version": "1.17.12",
"version": "1.17.11",
"name": "@opencode-ai/core",
"type": "module",
"license": "MIT",
@@ -121,7 +121,7 @@
"npm-package-arg": "13.0.2",
"semver": "^7.6.3",
"turndown": "7.2.0",
"venice-ai-sdk-provider": "2.1.1",
"venice-ai-sdk-provider": "2.0.2",
"which": "6.0.1",
"xdg-basedir": "5.1.0",
"zod": "catalog:"
+1 -1
View File
@@ -42,7 +42,7 @@ export interface Interface extends State.Transformable<Draft> {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Agent") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const state = State.create<Data, Draft>({
+2
View File
@@ -233,3 +233,5 @@ export const locationLayer = Layer.effect(
)
export const node = makeLocationNode({ service: Service, layer: locationLayer, deps: [] })
export const defaultLayer = locationLayer
+3 -1
View File
@@ -360,6 +360,8 @@ export const make = Effect.gen(function* () {
return Service.of({ list, get, start, extend, wait, waitForPromotion, promote, cancel })
})
const layer = Layer.effect(Service, make)
export const layer = Layer.effect(Service, make)
export const defaultLayer = layer
export const node = makeGlobalNode({ service: Service, layer, deps: [] })
+1 -1
View File
@@ -61,7 +61,7 @@ export interface Interface extends State.Transformable<Draft> {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Catalog") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const events = yield* EventV2.Service
+1 -1
View File
@@ -26,7 +26,7 @@ export interface Interface extends State.Transformable<Draft> {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Command") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.sync(() => {
const state = State.create<Data, Draft>({
+2 -2
View File
@@ -132,14 +132,14 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Config") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* FSUtil.Service
const global = yield* Global.Service
const location = yield* Location.Service
const policy = yield* Policy.Service
const names = ["opencode.json", "opencode.jsonc"]
const names = ["config.json", "opencode.json", "opencode.jsonc"]
const decodeOptions = { errors: "all", onExcessProperty: "ignore", propertyOrder: "original" } as const
const decodeInfo = Schema.decodeUnknownOption(Info, decodeOptions)
const decodeV1Info = Schema.decodeUnknownOption(ConfigV1.Info, decodeOptions)
@@ -66,7 +66,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/ControlPlaneMoveSession") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const git = yield* Git.Service
@@ -141,6 +141,13 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(
Layer.provide(Git.defaultLayer),
Layer.provide(EventV2.defaultLayer),
Layer.provide(ProjectV2.defaultLayer),
Layer.provide(SessionStore.defaultLayer),
)
export const node = makeGlobalNode({
service: Service,
layer,
+3 -1
View File
@@ -48,7 +48,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Credential") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const { db } = yield* Database.Service
@@ -135,4 +135,6 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(Layer.provide(Database.defaultLayer))
export const node = makeGlobalNode({ service: Service, layer, deps: [Database.node] })
+2 -1
View File
@@ -497,11 +497,12 @@ export const make = Effect.gen(function* () {
return makeSpawner(spawnCommand)
})
const layer: Layer.Layer<ChildProcessSpawner, never, FileSystem.FileSystem | Path.Path> = Layer.effect(
export const layer: Layer.Layer<ChildProcessSpawner, never, FileSystem.FileSystem | Path.Path> = Layer.effect(
ChildProcessSpawner,
make,
)
export const defaultLayer = layer.pipe(Layer.provide(NodeFileSystem.layer), Layer.provide(NodePath.layer))
export const node = makeGlobalNode({ service: ChildProcessSpawner, layer, deps: [filesystem, path] })
export * as CrossSpawnSpawner from "./cross-spawn-spawner"
+7 -1
View File
@@ -19,7 +19,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/storage/Database") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const db = yield* makeDatabase
@@ -54,4 +54,10 @@ export function path() {
return join(Global.Path.data, `opencode-${InstallationChannel.replace(/[^a-zA-Z0-9._-]/g, "-")}.db`)
}
export const defaultLayer = Layer.unwrap(
Effect.gen(function* () {
return layerFromPath(path())
}),
).pipe(Layer.provide(Global.defaultLayer))
export const node = makeGlobalNode({ service: Service, layer: layerFromPath(path()), deps: [] })
+3 -1
View File
@@ -634,5 +634,7 @@ export const layerWith = (options?: LayerOptions) =>
}),
)
const layer = layerWith()
export const layer = layerWith()
export const node = makeGlobalNode({ service: Service, layer: layer, deps: [Database.node] })
export const defaultLayer = layer.pipe(Layer.provide(Database.defaultLayer))
+1 -1
View File
@@ -71,7 +71,7 @@ export class Service extends Context.Service<Service, Interface>()("@opencode/v2
* write under the same process-local lock so cooperating OpenCode mutations do
* not overwrite changes made from the same stale content.
*/
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* FSUtil.Service
+4
View File
@@ -111,6 +111,10 @@ const baseLayer = Layer.effect(
}),
)
export const layer = baseLayer.pipe(Layer.provide(FileSystemSearch.locationLayer), Layer.provide(FSUtil.defaultLayer))
export const locationLayer = layer
export const node = makeLocationNode({
service: Service,
layer: baseLayer,
+3 -1
View File
@@ -54,7 +54,7 @@ export interface Interface {}
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/FileWatcher") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
if (yield* Flag.OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER) return Service.of({})
@@ -133,6 +133,8 @@ const layer = Layer.effect(
),
)
export const locationLayer = layer.pipe(Layer.provide(Config.locationLayer), Layer.provide(Git.defaultLayer))
export const node = makeLocationNode({
service: Service,
layer,
+2 -1
View File
@@ -49,7 +49,7 @@ export namespace FSUtil {
export const use = serviceUse(Service)
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem
@@ -200,6 +200,7 @@ export namespace FSUtil {
}),
)
export const defaultLayer = layer.pipe(Layer.provide(NodeFileSystem.layer))
export const node = makeGlobalNode({ service: Service, layer: layer, deps: [filesystem] })
// Pure helpers that don't need Effect (path manipulation, sync operations)
+2 -1
View File
@@ -172,7 +172,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/GitV2") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* FSUtil.Service
@@ -943,6 +943,7 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(Layer.provide(FSUtil.defaultLayer), Layer.provide(AppProcess.defaultLayer))
export const node = makeGlobalNode({ service: Service, layer: layer, deps: [FSUtil.node, AppProcess.node] })
interface Result {
@@ -86,7 +86,7 @@ export async function convertToOpenAIResponsesInput({
: {
image_url: `data:${mediaType};base64,${convertToBase64(part.data)}`,
}),
detail: part.providerOptions?.copilot?.imageDetail,
detail: part.providerOptions?.openai?.imageDetail,
}
} else if (part.mediaType === "application/pdf") {
if (part.data instanceof URL) {
@@ -127,7 +127,7 @@ export async function convertToOpenAIResponsesInput({
input.push({
role: "assistant",
content: [{ type: "output_text", text: part.text }],
id: (part.providerOptions?.copilot?.itemId as string) ?? undefined,
id: (part.providerOptions?.openai?.itemId as string) ?? undefined,
})
break
}
@@ -143,7 +143,7 @@ export async function convertToOpenAIResponsesInput({
input.push({
type: "local_shell_call",
call_id: part.toolCallId,
id: (part.providerOptions?.copilot?.itemId as string) ?? undefined,
id: (part.providerOptions?.openai?.itemId as string) ?? undefined,
action: {
type: "exec",
command: parsedInput.action.command,
@@ -162,7 +162,7 @@ export async function convertToOpenAIResponsesInput({
call_id: part.toolCallId,
name: part.toolName,
arguments: JSON.stringify(part.input),
id: (part.providerOptions?.copilot?.itemId as string) ?? undefined,
id: (part.providerOptions?.openai?.itemId as string) ?? undefined,
})
break
}
@@ -275,7 +275,7 @@ export async function convertToOpenAIResponsesInput({
const output = part.output
if (output.type === "execution-denied") {
const approvalId = (output.providerOptions?.copilot as { approvalId?: string } | undefined)?.approvalId
const approvalId = (output.providerOptions?.openai as { approvalId?: string } | undefined)?.approvalId
if (approvalId) {
continue
@@ -525,7 +525,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
type: "reasoning" as const,
text: summary.text,
providerMetadata: {
copilot: {
openai: {
itemId: part.id,
reasoningEncryptedContent: part.encrypted_content ?? null,
},
@@ -563,7 +563,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
toolName: "local_shell",
input: JSON.stringify({ action: part.action } satisfies z.infer<typeof localShellInputSchema>),
providerMetadata: {
copilot: {
openai: {
itemId: part.id,
},
},
@@ -574,7 +574,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
case "message": {
for (const contentPart of part.content) {
if (options.providerOptions?.copilot?.logprobs && contentPart.logprobs) {
if (options.providerOptions?.openai?.logprobs && contentPart.logprobs) {
logprobs.push(contentPart.logprobs)
}
@@ -582,7 +582,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
type: "text",
text: contentPart.text,
providerMetadata: {
copilot: {
openai: {
itemId: part.id,
},
},
@@ -622,7 +622,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
toolName: part.name,
input: part.arguments,
providerMetadata: {
copilot: {
openai: {
itemId: part.id,
},
},
@@ -724,15 +724,15 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
}
const providerMetadata: SharedV3ProviderMetadata = {
copilot: { responseId: response.id },
openai: { responseId: response.id },
}
if (logprobs.length > 0) {
providerMetadata.copilot.logprobs = logprobs
providerMetadata.openai.logprobs = logprobs
}
if (typeof response.service_tier === "string") {
providerMetadata.copilot.serviceTier = response.service_tier
providerMetadata.openai.serviceTier = response.service_tier
}
return {
@@ -954,7 +954,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
type: "text-start",
id: value.item.id,
providerMetadata: {
copilot: {
openai: {
itemId: value.item.id,
},
},
@@ -971,7 +971,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
type: "reasoning-start",
id: `${value.item.id}:0`,
providerMetadata: {
copilot: {
openai: {
itemId: value.item.id,
reasoningEncryptedContent: value.item.encrypted_content ?? null,
},
@@ -994,7 +994,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
toolName: value.item.name,
input: value.item.arguments,
providerMetadata: {
copilot: {
openai: {
itemId: value.item.id,
},
},
@@ -1103,7 +1103,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
},
} satisfies z.infer<typeof localShellInputSchema>),
providerMetadata: {
copilot: { itemId: value.item.id },
openai: { itemId: value.item.id },
},
})
} else if (value.item.type === "message") {
@@ -1122,7 +1122,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
type: "reasoning-end",
id: `${activeReasoningPart.canonicalId}:${summaryIndex}`,
providerMetadata: {
copilot: {
openai: {
itemId: activeReasoningPart.canonicalId,
reasoningEncryptedContent: value.item.encrypted_content ?? null,
},
@@ -1209,7 +1209,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
type: "text-start",
id: currentTextId,
providerMetadata: {
copilot: { itemId: value.item_id },
openai: { itemId: value.item_id },
},
})
}
@@ -1220,7 +1220,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
delta: value.delta,
})
if (options.providerOptions?.copilot?.logprobs && value.logprobs) {
if (options.providerOptions?.openai?.logprobs && value.logprobs) {
logprobs.push(value.logprobs)
}
} else if (isResponseReasoningSummaryPartAddedChunk(value)) {
@@ -1235,7 +1235,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
type: "reasoning-start",
id: `${activeItem.canonicalId}:${value.summary_index}`,
providerMetadata: {
copilot: {
openai: {
itemId: activeItem.canonicalId,
reasoningEncryptedContent: activeItem.encryptedContent ?? null,
},
@@ -1252,7 +1252,7 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
id: `${activeItem.canonicalId}:${value.summary_index}`,
delta: value.delta,
providerMetadata: {
copilot: {
openai: {
itemId: activeItem.canonicalId,
},
},
@@ -1306,17 +1306,17 @@ export class OpenAIResponsesLanguageModel implements LanguageModelV3 {
}
const providerMetadata: SharedV3ProviderMetadata = {
copilot: {
openai: {
responseId,
},
}
if (logprobs.length > 0) {
providerMetadata.copilot.logprobs = logprobs
providerMetadata.openai.logprobs = logprobs
}
if (serviceTier !== undefined) {
providerMetadata.copilot.serviceTier = serviceTier
providerMetadata.openai.serviceTier = serviceTier
}
controller.enqueue({
+2 -1
View File
@@ -71,11 +71,12 @@ export function make(input: Partial<Interface> = {}): Interface {
}
}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.sync(() => Service.of(make())),
)
export const defaultLayer = layer
export const node = makeGlobalNode({ service: Service, layer: layer, deps: [] })
export const layerWith = (input: Partial<Interface>) =>
+1 -1
View File
@@ -44,7 +44,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/Image") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const config = yield* Config.Service
+1 -1
View File
@@ -19,7 +19,7 @@ class File extends Schema.Class<File>("InstructionContext.File")({
const Files = Schema.Array(File)
const key = SystemContext.Key.make("core/instructions")
const layer = Layer.effectDiscard(
export const layer = Layer.effectDiscard(
Effect.gen(function* () {
const fs = yield* FSUtil.Service
const global = yield* Global.Service
+1 -1
View File
@@ -76,7 +76,7 @@ interface ResolvedPath {
const slash = (value: string) => value.replaceAll("\\", "/")
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* FSUtil.Service
+1 -1
View File
@@ -16,7 +16,7 @@ export class Service extends Context.Service<Service, Interface>()("@opencode/Lo
export const node = LayerNode.unbound(Service, tags.values.location)
const layer = (ref: Ref) =>
export const layer = (ref: Ref) =>
Layer.effect(
Service,
Effect.gen(function* () {
+6 -28
View File
@@ -44,32 +44,6 @@ const Cost = Schema.Struct({
),
})
const ReasoningEffortValue = Schema.Union([Schema.Null, Schema.String])
export const KnownReasoningOption = Schema.Union([
Schema.Struct({
type: Schema.Literal("effort"),
values: Schema.Array(ReasoningEffortValue),
}),
Schema.Struct({
type: Schema.Literal("toggle"),
}),
Schema.Struct({
type: Schema.Literal("budget_tokens"),
min: Schema.optional(Schema.Finite),
max: Schema.optional(Schema.Finite),
}),
])
export type KnownReasoningOption = typeof KnownReasoningOption.Type
export const ReasoningOption = Schema.Union([
KnownReasoningOption,
Schema.Struct({
type: Schema.String,
}),
])
export type ReasoningOption = typeof ReasoningOption.Type
export const Model = Schema.Struct({
id: Schema.String,
name: Schema.String,
@@ -77,7 +51,6 @@ export const Model = Schema.Struct({
release_date: Schema.String,
attachment: Schema.Boolean,
reasoning: Schema.Boolean,
reasoning_options: Schema.optional(Schema.Array(ReasoningOption)),
temperature: Schema.Boolean,
tool_call: Schema.Boolean,
interleaved: Schema.optional(
@@ -147,7 +120,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/ModelsDev") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* FSUtil.Service
@@ -266,6 +239,11 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(
Layer.provide(FetchHttpClient.layer),
Layer.provide(FSUtil.defaultLayer),
Layer.provide(EventV2.defaultLayer),
)
export const node = makeGlobalNode({ service: Service, layer: layer, deps: [FSUtil.node, EventV2.node, httpClient] })
export * as ModelsDev from "./models-dev"
+8 -3
View File
@@ -9,7 +9,6 @@ import { Global } from "./global"
import { EffectFlock } from "./util/effect-flock"
import { makeGlobalNode } from "./effect/app-node"
import { filesystem } from "./effect/app-node-platform"
import { LayerNode } from "./effect/layer-node"
import { makeRuntime } from "./effect/runtime"
import { NpmConfig } from "./npm-config"
@@ -69,7 +68,7 @@ interface ArboristTree {
edgesOut: Map<string, { to?: ArboristNode }>
}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const afs = yield* FSUtil.Service
@@ -248,13 +247,19 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(
Layer.provide(EffectFlock.layer),
Layer.provide(FSUtil.layer),
Layer.provide(Global.layer),
Layer.provide(NodeFileSystem.layer),
)
export const node = makeGlobalNode({
service: Service,
layer: layer,
deps: [FSUtil.node, Global.node, filesystem, EffectFlock.node],
})
const { runPromise } = makeRuntime(Service, LayerNode.compile(node))
const { runPromise } = makeRuntime(Service, defaultLayer)
export async function install(...args: Parameters<Interface["install"]>) {
return runPromise((svc) => svc.install(...args))
+1 -1
View File
@@ -106,7 +106,7 @@ interface Pending {
readonly deferred: Deferred.Deferred<void, RejectedError | CorrectedError>
}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
EffectRuntime.gen(function* () {
const events = yield* EventV2.Service
+3 -1
View File
@@ -34,7 +34,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/PermissionSaved") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const { db } = yield* Database.Service
@@ -76,4 +76,6 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(Layer.provide(Database.defaultLayer))
export const node = makeGlobalNode({ service: Service, layer, deps: [Database.node] })
+2 -1
View File
@@ -28,7 +28,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Plugin") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const events = yield* EventV2.Service
@@ -149,6 +149,7 @@ export const locationLayer = layer.pipe(
Layer.provideMerge(CommandV2.locationLayer),
Layer.provideMerge(Integration.locationLayer),
Layer.provideMerge(Reference.locationLayer),
Layer.provideMerge(SkillV2.locationLayer),
)
export const node = makeLocationNode({
+2
View File
@@ -125,7 +125,9 @@ const layer = Layer.effectDiscard(
)
export const locationLayer = layer.pipe(
Layer.provideMerge(PluginV2.locationLayer),
Layer.provideMerge(Config.locationLayer),
Layer.provideMerge(FileSystem.locationLayer),
Layer.provideMerge(FetchHttpClient.layer),
)
+1 -1
View File
@@ -22,7 +22,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Policy") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
EffectRuntime.gen(function* () {
let statements: Info[] = []
+2 -1
View File
@@ -136,7 +136,7 @@ export const collectStream = (stream: Stream.Stream<Uint8Array, PlatformError>,
},
).pipe(Effect.map((x) => ({ buffer: Buffer.concat(x.chunks), truncated: x.truncated })))
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const spawner = yield* ChildProcessSpawner
@@ -256,6 +256,7 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(Layer.provide(CrossSpawnSpawner.defaultLayer))
export const node = makeGlobalNode({ service: Service, layer: layer, deps: [CrossSpawnSpawner.node] })
export * as AppProcess from "./process"
+6 -1
View File
@@ -51,7 +51,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/ProjectV2") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* FSUtil.Service
@@ -129,6 +129,11 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(
Layer.provide(FSUtil.defaultLayer),
Layer.provide(Git.defaultLayer),
Layer.provideMerge(ProjectDirectories.defaultLayer),
)
export const node = makeGlobalNode({
service: Service,
layer: layer,
+1 -1
View File
@@ -125,7 +125,7 @@ export const refreshAfterBoot = Effect.gen(function* () {
)
})
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* FSUtil.Service
+2 -1
View File
@@ -57,7 +57,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/ProjectDirectories") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const db = (yield* Database.Service).db
@@ -155,4 +155,5 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(Layer.provide(Database.defaultLayer))
export const node = makeGlobalNode({ service: Service, layer: layer, deps: [Database.node] })
+1 -1
View File
@@ -89,7 +89,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Pty") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const events = yield* EventV2.Service
+2 -1
View File
@@ -51,6 +51,7 @@ export const make = (ttl: Duration.Input = DEFAULT_TTL) =>
})
})
const layer = Layer.effect(Service, make())
export const layer = Layer.effect(Service, make())
export const defaultLayer = layer
export const node = makeGlobalNode({ service: Service, layer: layer, deps: [] })
+1 -1
View File
@@ -72,7 +72,7 @@ interface Pending {
* layer once per embedded Location so replies cannot settle another Location's
* deferred request.
*/
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const events = yield* EventV2.Service
+1 -1
View File
@@ -40,7 +40,7 @@ export interface Interface extends State.Transformable<Draft> {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Reference") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const global = yield* Global.Service
+1 -1
View File
@@ -31,7 +31,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/ReferenceGuidance") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const references = yield* Reference.Service
+8 -1
View File
@@ -121,7 +121,7 @@ export const validateBranch = Effect.fn("RepositoryCache.validateBranch")(functi
})
})
const layer: Layer.Layer<Service, never, FSUtil.Service | Git.Service | EffectFlock.Service | Global.Service> =
export const layer: Layer.Layer<Service, never, FSUtil.Service | Git.Service | EffectFlock.Service | Global.Service> =
Layer.effect(
Service,
Effect.gen(function* () {
@@ -223,6 +223,13 @@ const layer: Layer.Layer<Service, never, FSUtil.Service | Git.Service | EffectFl
}),
)
export const defaultLayer: Layer.Layer<Service> = layer.pipe(
Layer.provide(EffectFlock.defaultLayer),
Layer.provide(FSUtil.defaultLayer),
Layer.provide(Git.defaultLayer),
Layer.provide(Global.defaultLayer),
)
export const node = makeGlobalNode({
service: Service,
layer,
+2 -1
View File
@@ -89,7 +89,7 @@ const failure = (message: string, cause?: unknown) => new Error({ message, cause
const isInvalidPattern = (stderr: string) =>
stderr.includes("regex parse error") || stderr.includes("error parsing regex")
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const process = yield* AppProcess.Service
@@ -278,4 +278,5 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(Layer.provide(Layer.merge(RipgrepBinary.defaultLayer, AppProcess.defaultLayer)))
export const node = makeGlobalNode({ service: Service, layer: layer, deps: [RipgrepBinary.node, AppProcess.node] })
+7 -1
View File
@@ -28,7 +28,7 @@ export namespace RipgrepBinary {
export class Service extends Context.Service<Service, Interface>()("@opencode/RipgrepBinary") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* FSUtil.Service
@@ -124,6 +124,12 @@ export namespace RipgrepBinary {
}),
)
export const defaultLayer = layer.pipe(
Layer.provide(FetchHttpClient.layer),
Layer.provide(FSUtil.defaultLayer),
Layer.provide(CrossSpawnSpawner.defaultLayer),
)
export const node = makeGlobalNode({
service: Service,
layer: layer,
+10 -1
View File
@@ -181,7 +181,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Session") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const database = yield* Database.Service
@@ -457,6 +457,15 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(
Layer.provide(SessionStore.defaultLayer),
Layer.provide(SessionProjector.defaultLayer),
Layer.provide(EventV2.defaultLayer),
Layer.provide(Database.defaultLayer),
Layer.provide(ProjectV2.defaultLayer),
Layer.orDie,
)
const resolvePrompt = (input: PromptInput.Prompt) =>
Prompt.make({
text: input.text,
+3 -1
View File
@@ -8,7 +8,7 @@ import { SessionStore } from "../store"
import { SessionExecution } from "../execution"
/** Current-process routing for implicit-local Locations. Future remote placement belongs here. */
const layer = Layer.effect(
export const layer = Layer.effect(
SessionExecution.Service,
Effect.gen(function* () {
const store = yield* SessionStore.Service
@@ -37,6 +37,8 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(Layer.provide(SessionStore.defaultLayer))
export const node = makeGlobalNode({
service: SessionExecution.Service,
layer,
+2 -1
View File
@@ -208,7 +208,7 @@ function insertMessage(db: DatabaseService, event: SessionEvent.Event, message:
.pipe(Effect.orDie)
}
const layer = Layer.effectDiscard(
export const layer = Layer.effectDiscard(
Effect.gen(function* () {
const events = yield* EventV2.Service
const { db } = yield* Database.Service
@@ -455,4 +455,5 @@ const layer = Layer.effectDiscard(
}),
)
export const defaultLayer = layer.pipe(Layer.provide(EventV2.defaultLayer), Layer.provide(Database.defaultLayer))
export const node = makeGlobalNode({ name: "session-projector", layer, deps: [EventV2.node, Database.node] })
+3 -1
View File
@@ -89,7 +89,7 @@ import { llmClient } from "../../effect/app-node-platform"
* explicit loop starts the next provider turn after local settlement. Configured agent step limits bound the loop.
*/
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const events = yield* EventV2.Service
@@ -406,6 +406,8 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer
export const node = makeLocationNode({
service: Service,
layer,
+3 -1
View File
@@ -25,7 +25,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/SessionStore") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const { db } = yield* Database.Service
@@ -60,4 +60,6 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(Layer.provide(Database.defaultLayer))
export const node = makeGlobalNode({ service: Service, layer, deps: [Database.node] })
+3 -1
View File
@@ -23,7 +23,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/SessionTodo") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const { db } = yield* Database.Service
@@ -75,4 +75,6 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(Layer.provide(EventV2.defaultLayer), Layer.provide(Database.defaultLayer))
export const node = makeLocationNode({ service: Service, layer, deps: [EventV2.node, Database.node] })
+3 -1
View File
@@ -53,7 +53,7 @@ export interface Interface extends State.Transformable<Draft> {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Skill") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const discovery = yield* SkillDiscovery.Service
@@ -129,4 +129,6 @@ const layer = Layer.effect(
}),
)
export const locationLayer = layer.pipe(Layer.provide(SkillDiscovery.defaultLayer))
export const node = makeLocationNode({ service: Service, layer, deps: [SkillDiscovery.node, FSUtil.node] })
+7 -1
View File
@@ -68,7 +68,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/SkillDiscovery") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* FSUtil.Service
@@ -210,4 +210,10 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(
Layer.provide(FetchHttpClient.layer),
Layer.provide(FSUtil.defaultLayer),
Layer.provide(Global.defaultLayer),
)
export const node = makeGlobalNode({ service: Service, layer, deps: [httpClient, FSUtil.node, Global.node] })
+1 -1
View File
@@ -37,7 +37,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/SkillGuidance") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const skills = yield* SkillV2.Service
+1 -1
View File
@@ -83,7 +83,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Snapshot") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const config = yield* Config.Service
+7 -1
View File
@@ -43,8 +43,14 @@ const builtIns = Layer.effectDiscard(
}),
)
export const layer = Layer.mergeAll(builtIns, InstructionContext.layer).pipe(
Layer.provideMerge(SystemContextRegistry.layer),
)
export const locationLayer = layer
export const node = makeLocationNode({
name: "system-context-builtins",
layer: builtIns,
layer,
deps: [Location.node, SystemContextRegistry.node, InstructionContext.node, FSUtil.node, Global.node],
})
+1 -1
View File
@@ -16,7 +16,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/SystemContextRegistry") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const entries = yield* Ref.make<ReadonlyArray<Entry>>([])
+6 -6
View File
@@ -109,7 +109,7 @@ const lineCount = (text: string) => {
return count
}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const fs = yield* FSUtil.Service
@@ -192,6 +192,8 @@ const layer = Layer.effect(
}),
)
export const defaultLayer = layer.pipe(Layer.provide(FSUtil.defaultLayer), Layer.provide(Global.defaultLayer))
export const node = makeLocationNode({ service: Service, layer, deps: [FSUtil.node, Global.node, Config.node] })
export const nodeWithoutConfig = makeLocationNode({ service: Service, layer, deps: [FSUtil.node, Global.node] })
@@ -204,8 +206,6 @@ export const cleanupLayer = Layer.effectDiscard(
}),
)
export const cleanupNode = makeGlobalNode({
name: "tool-output-cleanup",
layer: Layer.merge(layer, cleanupLayer.pipe(Layer.provide(layer))),
deps: [FSUtil.node, Global.node],
})
export const defaultCleanupLayer = Layer.merge(defaultLayer, cleanupLayer.pipe(Layer.provide(defaultLayer)))
export const cleanupNode = makeGlobalNode({ name: "tool-output-cleanup", layer: defaultCleanupLayer, deps: [] })
+1 -1
View File
@@ -27,7 +27,7 @@ export interface Interface {
export class Service extends Context.Service<Service, Interface>()("@opencode/ApplicationTools") {}
const layer = Layer.effect(
export const layer = Layer.effect(
Service,
Effect.gen(function* () {
const state = State.create<Data, Draft>({
+1 -1
View File
@@ -56,7 +56,7 @@ type Prepared =
readonly after: string
})
const layer = Layer.effectDiscard(
export const layer = Layer.effectDiscard(
Effect.gen(function* () {
const tools = yield* Tools.Service
const mutation = yield* LocationMutation.Service

Some files were not shown because too many files have changed in this diff Show More