mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-10 11:39:45 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c9640058a8 |
@@ -29,7 +29,7 @@
|
|||||||
},
|
},
|
||||||
"packages/app": {
|
"packages/app": {
|
||||||
"name": "@opencode-ai/app",
|
"name": "@opencode-ai/app",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@corvu/drawer": "catalog:",
|
"@corvu/drawer": "catalog:",
|
||||||
"@dnd-kit/abstract": "0.5.0",
|
"@dnd-kit/abstract": "0.5.0",
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
},
|
},
|
||||||
"packages/cli": {
|
"packages/cli": {
|
||||||
"name": "@opencode-ai/cli",
|
"name": "@opencode-ai/cli",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"bin": {
|
"bin": {
|
||||||
"lildax": "./bin/lildax.cjs",
|
"lildax": "./bin/lildax.cjs",
|
||||||
},
|
},
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
},
|
},
|
||||||
"packages/codemode": {
|
"packages/codemode": {
|
||||||
"name": "@opencode-ai/codemode",
|
"name": "@opencode-ai/codemode",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"acorn": "8.15.0",
|
"acorn": "8.15.0",
|
||||||
"effect": "catalog:",
|
"effect": "catalog:",
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/app": {
|
"packages/console/app": {
|
||||||
"name": "@opencode-ai/console-app",
|
"name": "@opencode-ai/console-app",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cloudflare/vite-plugin": "1.15.2",
|
"@cloudflare/vite-plugin": "1.15.2",
|
||||||
"@ibm/plex": "6.4.1",
|
"@ibm/plex": "6.4.1",
|
||||||
@@ -194,7 +194,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/core": {
|
"packages/console/core": {
|
||||||
"name": "@opencode-ai/console-core",
|
"name": "@opencode-ai/console-core",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-sts": "3.782.0",
|
"@aws-sdk/client-sts": "3.782.0",
|
||||||
"@jsx-email/render": "1.1.1",
|
"@jsx-email/render": "1.1.1",
|
||||||
@@ -221,7 +221,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/function": {
|
"packages/console/function": {
|
||||||
"name": "@opencode-ai/console-function",
|
"name": "@opencode-ai/console-function",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/anthropic": "3.0.82",
|
"@ai-sdk/anthropic": "3.0.82",
|
||||||
"@ai-sdk/openai": "3.0.48",
|
"@ai-sdk/openai": "3.0.48",
|
||||||
@@ -243,7 +243,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/mail": {
|
"packages/console/mail": {
|
||||||
"name": "@opencode-ai/console-mail",
|
"name": "@opencode-ai/console-mail",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jsx-email/all": "2.2.3",
|
"@jsx-email/all": "2.2.3",
|
||||||
"@jsx-email/cli": "1.4.3",
|
"@jsx-email/cli": "1.4.3",
|
||||||
@@ -267,7 +267,7 @@
|
|||||||
},
|
},
|
||||||
"packages/console/support": {
|
"packages/console/support": {
|
||||||
"name": "@opencode-ai/console-support",
|
"name": "@opencode-ai/console-support",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cloudflare/vite-plugin": "1.15.2",
|
"@cloudflare/vite-plugin": "1.15.2",
|
||||||
"@opencode-ai/console-core": "workspace:*",
|
"@opencode-ai/console-core": "workspace:*",
|
||||||
@@ -287,7 +287,7 @@
|
|||||||
},
|
},
|
||||||
"packages/core": {
|
"packages/core": {
|
||||||
"name": "@opencode-ai/core",
|
"name": "@opencode-ai/core",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"bin": {
|
"bin": {
|
||||||
"opencode": "./bin/opencode",
|
"opencode": "./bin/opencode",
|
||||||
},
|
},
|
||||||
@@ -381,7 +381,7 @@
|
|||||||
},
|
},
|
||||||
"packages/desktop": {
|
"packages/desktop": {
|
||||||
"name": "@opencode-ai/desktop",
|
"name": "@opencode-ai/desktop",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@zip.js/zip.js": "2.7.62",
|
"@zip.js/zip.js": "2.7.62",
|
||||||
"drizzle-orm": "catalog:",
|
"drizzle-orm": "catalog:",
|
||||||
@@ -435,7 +435,7 @@
|
|||||||
},
|
},
|
||||||
"packages/effect-drizzle-sqlite": {
|
"packages/effect-drizzle-sqlite": {
|
||||||
"name": "@opencode-ai/effect-drizzle-sqlite",
|
"name": "@opencode-ai/effect-drizzle-sqlite",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"drizzle-orm": "catalog:",
|
"drizzle-orm": "catalog:",
|
||||||
"effect": "catalog:",
|
"effect": "catalog:",
|
||||||
@@ -449,7 +449,7 @@
|
|||||||
},
|
},
|
||||||
"packages/effect-sqlite-node": {
|
"packages/effect-sqlite-node": {
|
||||||
"name": "@opencode-ai/effect-sqlite-node",
|
"name": "@opencode-ai/effect-sqlite-node",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"effect": "catalog:",
|
"effect": "catalog:",
|
||||||
},
|
},
|
||||||
@@ -461,7 +461,7 @@
|
|||||||
},
|
},
|
||||||
"packages/enterprise": {
|
"packages/enterprise": {
|
||||||
"name": "@opencode-ai/enterprise",
|
"name": "@opencode-ai/enterprise",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hono/standard-validator": "catalog:",
|
"@hono/standard-validator": "catalog:",
|
||||||
"@opencode-ai/core": "workspace:*",
|
"@opencode-ai/core": "workspace:*",
|
||||||
@@ -493,7 +493,7 @@
|
|||||||
},
|
},
|
||||||
"packages/function": {
|
"packages/function": {
|
||||||
"name": "@opencode-ai/function",
|
"name": "@opencode-ai/function",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/auth-app": "8.0.1",
|
"@octokit/auth-app": "8.0.1",
|
||||||
"@octokit/rest": "catalog:",
|
"@octokit/rest": "catalog:",
|
||||||
@@ -509,7 +509,7 @@
|
|||||||
},
|
},
|
||||||
"packages/http-recorder": {
|
"packages/http-recorder": {
|
||||||
"name": "@opencode-ai/http-recorder",
|
"name": "@opencode-ai/http-recorder",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@effect/platform-node": "4.0.0-beta.83",
|
"@effect/platform-node": "4.0.0-beta.83",
|
||||||
"@effect/platform-node-shared": "4.0.0-beta.83",
|
"@effect/platform-node-shared": "4.0.0-beta.83",
|
||||||
@@ -540,7 +540,7 @@
|
|||||||
},
|
},
|
||||||
"packages/llm": {
|
"packages/llm": {
|
||||||
"name": "@opencode-ai/llm",
|
"name": "@opencode-ai/llm",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/schema": "workspace:*",
|
"@opencode-ai/schema": "workspace:*",
|
||||||
"@smithy/eventstream-codec": "4.2.14",
|
"@smithy/eventstream-codec": "4.2.14",
|
||||||
@@ -559,7 +559,7 @@
|
|||||||
},
|
},
|
||||||
"packages/opencode": {
|
"packages/opencode": {
|
||||||
"name": "opencode",
|
"name": "opencode",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"bin": {
|
"bin": {
|
||||||
"opencode": "./bin/opencode",
|
"opencode": "./bin/opencode",
|
||||||
},
|
},
|
||||||
@@ -690,7 +690,7 @@
|
|||||||
},
|
},
|
||||||
"packages/plugin": {
|
"packages/plugin": {
|
||||||
"name": "@opencode-ai/plugin",
|
"name": "@opencode-ai/plugin",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/provider": "3.0.8",
|
"@ai-sdk/provider": "3.0.8",
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
@@ -766,7 +766,7 @@
|
|||||||
},
|
},
|
||||||
"packages/sdk/js": {
|
"packages/sdk/js": {
|
||||||
"name": "@opencode-ai/sdk",
|
"name": "@opencode-ai/sdk",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cross-spawn": "catalog:",
|
"cross-spawn": "catalog:",
|
||||||
},
|
},
|
||||||
@@ -781,7 +781,7 @@
|
|||||||
},
|
},
|
||||||
"packages/server": {
|
"packages/server": {
|
||||||
"name": "@opencode-ai/server",
|
"name": "@opencode-ai/server",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/core": "workspace:*",
|
"@opencode-ai/core": "workspace:*",
|
||||||
"@opencode-ai/protocol": "workspace:*",
|
"@opencode-ai/protocol": "workspace:*",
|
||||||
@@ -796,7 +796,7 @@
|
|||||||
},
|
},
|
||||||
"packages/session-ui": {
|
"packages/session-ui": {
|
||||||
"name": "@opencode-ai/session-ui",
|
"name": "@opencode-ai/session-ui",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kobalte/core": "catalog:",
|
"@kobalte/core": "catalog:",
|
||||||
"@opencode-ai/client": "file:../app/vendor/opencode-ai-client-1.17.13-v2.tgz",
|
"@opencode-ai/client": "file:../app/vendor/opencode-ai-client-1.17.13-v2.tgz",
|
||||||
@@ -836,7 +836,7 @@
|
|||||||
},
|
},
|
||||||
"packages/slack": {
|
"packages/slack": {
|
||||||
"name": "@opencode-ai/slack",
|
"name": "@opencode-ai/slack",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/sdk": "workspace:*",
|
"@opencode-ai/sdk": "workspace:*",
|
||||||
"@slack/bolt": "^3.17.1",
|
"@slack/bolt": "^3.17.1",
|
||||||
@@ -849,7 +849,7 @@
|
|||||||
},
|
},
|
||||||
"packages/stats/app": {
|
"packages/stats/app": {
|
||||||
"name": "@opencode-ai/stats-app",
|
"name": "@opencode-ai/stats-app",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ibm/plex": "6.4.1",
|
"@ibm/plex": "6.4.1",
|
||||||
"@kobalte/core": "catalog:",
|
"@kobalte/core": "catalog:",
|
||||||
@@ -883,7 +883,7 @@
|
|||||||
},
|
},
|
||||||
"packages/stats/core": {
|
"packages/stats/core": {
|
||||||
"name": "@opencode-ai/stats-core",
|
"name": "@opencode-ai/stats-core",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-athena": "3.933.0",
|
"@aws-sdk/client-athena": "3.933.0",
|
||||||
"@planetscale/database": "1.19.0",
|
"@planetscale/database": "1.19.0",
|
||||||
@@ -902,7 +902,7 @@
|
|||||||
},
|
},
|
||||||
"packages/stats/server": {
|
"packages/stats/server": {
|
||||||
"name": "@opencode-ai/stats-server",
|
"name": "@opencode-ai/stats-server",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-firehose": "3.933.0",
|
"@aws-sdk/client-firehose": "3.933.0",
|
||||||
"@effect/platform-node": "catalog:",
|
"@effect/platform-node": "catalog:",
|
||||||
@@ -944,7 +944,7 @@
|
|||||||
},
|
},
|
||||||
"packages/tui": {
|
"packages/tui": {
|
||||||
"name": "@opencode-ai/tui",
|
"name": "@opencode-ai/tui",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@opencode-ai/core": "workspace:*",
|
"@opencode-ai/core": "workspace:*",
|
||||||
"@opencode-ai/plugin": "workspace:*",
|
"@opencode-ai/plugin": "workspace:*",
|
||||||
@@ -971,7 +971,7 @@
|
|||||||
},
|
},
|
||||||
"packages/ui": {
|
"packages/ui": {
|
||||||
"name": "@opencode-ai/ui",
|
"name": "@opencode-ai/ui",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kobalte/core": "catalog:",
|
"@kobalte/core": "catalog:",
|
||||||
"@pierre/diffs": "catalog:",
|
"@pierre/diffs": "catalog:",
|
||||||
@@ -1022,7 +1022,7 @@
|
|||||||
},
|
},
|
||||||
"packages/web": {
|
"packages/web": {
|
||||||
"name": "@opencode-ai/web",
|
"name": "@opencode-ai/web",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/cloudflare": "12.6.3",
|
"@astrojs/cloudflare": "12.6.3",
|
||||||
"@astrojs/markdown-remark": "6.3.1",
|
"@astrojs/markdown-remark": "6.3.1",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/app",
|
"name": "@opencode-ai/app",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ test("resolves directory autocomplete from the current browser root", async () =
|
|||||||
directories.push(input.location?.directory ?? "")
|
directories.push(input.location?.directory ?? "")
|
||||||
return Promise.resolve({ data: [] })
|
return Promise.resolve({ data: [] })
|
||||||
},
|
},
|
||||||
list: () => Promise.resolve({ data: [] }),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as unknown as Parameters<typeof createDirectorySearch>[0]["sdk"]
|
} as unknown as Parameters<typeof createDirectorySearch>[0]["sdk"]
|
||||||
@@ -153,67 +152,6 @@ test("resolves directory autocomplete from the current browser root", async () =
|
|||||||
expect(directories).toEqual(["/repo", "/repo/src"])
|
expect(directories).toEqual(["/repo", "/repo/src"])
|
||||||
})
|
})
|
||||||
|
|
||||||
test("keeps indexed directory results for servers that support empty search", async () => {
|
|
||||||
const sdk = {
|
|
||||||
api: {
|
|
||||||
file: {
|
|
||||||
find: () => Promise.resolve({ data: [{ path: "projects/", type: "directory" }] }),
|
|
||||||
list: () => Promise.reject(new Error("listing should not run when search returns results")),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as unknown as Parameters<typeof createDirectorySearch>[0]["sdk"]
|
|
||||||
const search = createDirectorySearch({ sdk, home: () => "/home/luke", base: () => "/home/luke" })
|
|
||||||
|
|
||||||
expect(await search("")).toEqual(["/home/luke/projects"])
|
|
||||||
})
|
|
||||||
|
|
||||||
test("lists the default directory when empty search is unsupported", async () => {
|
|
||||||
const calls: string[] = []
|
|
||||||
const directories = Array.from({ length: 60 }, (_, index) => ({
|
|
||||||
path: `project-${index}/`,
|
|
||||||
type: "directory" as const,
|
|
||||||
}))
|
|
||||||
const sdk = {
|
|
||||||
api: {
|
|
||||||
file: {
|
|
||||||
find: () => Promise.resolve({ data: [] }),
|
|
||||||
list: (input: { location?: { directory?: string } }) => {
|
|
||||||
calls.push(input.location?.directory ?? "")
|
|
||||||
return Promise.resolve({
|
|
||||||
data: [...directories, { path: "README.md", type: "file" }],
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as unknown as Parameters<typeof createDirectorySearch>[0]["sdk"]
|
|
||||||
const search = createDirectorySearch({ sdk, home: () => "/home/luke", base: () => "/home/luke" })
|
|
||||||
|
|
||||||
const results = await search("")
|
|
||||||
expect(results).toHaveLength(60)
|
|
||||||
expect(results.at(-1)).toBe("/home/luke/project-59")
|
|
||||||
expect(calls).toEqual(["/home/luke"])
|
|
||||||
})
|
|
||||||
|
|
||||||
test("matches the default directory listing when typed search is unsupported", async () => {
|
|
||||||
const sdk = {
|
|
||||||
api: {
|
|
||||||
file: {
|
|
||||||
find: () => Promise.resolve({ data: [] }),
|
|
||||||
list: () =>
|
|
||||||
Promise.resolve({
|
|
||||||
data: [
|
|
||||||
{ path: "Documents/", type: "directory" },
|
|
||||||
{ path: "Downloads/", type: "directory" },
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as unknown as Parameters<typeof createDirectorySearch>[0]["sdk"]
|
|
||||||
const search = createDirectorySearch({ sdk, home: () => "/home/luke", base: () => "/home/luke" })
|
|
||||||
|
|
||||||
expect(await search("documents")).toEqual(["/home/luke/Documents"])
|
|
||||||
})
|
|
||||||
|
|
||||||
test("searches from an absolute root without a default base", async () => {
|
test("searches from an absolute root without a default base", async () => {
|
||||||
const directories: string[] = []
|
const directories: string[] = []
|
||||||
const sdk = {
|
const sdk = {
|
||||||
|
|||||||
@@ -379,14 +379,7 @@ export function createDirectorySearch(args: { sdk: ServerSDK; base: () => string
|
|||||||
.then((result) => result.data.map((entry) => entry.path))
|
.then((result) => result.data.map((entry) => entry.path))
|
||||||
.catch(() => [])
|
.catch(() => [])
|
||||||
if (!active()) return []
|
if (!active()) return []
|
||||||
if (results.length) {
|
return results.map((path) => joinPickerPath(input.directory, path)).slice(0, 50)
|
||||||
return results.map((path) => joinPickerPath(input.directory, path)).slice(0, 50)
|
|
||||||
}
|
|
||||||
const fallback = query
|
|
||||||
? await match(input.directory, query, 50)
|
|
||||||
: (await directories(input.directory)).map((item) => item.absolute)
|
|
||||||
if (!active()) return []
|
|
||||||
return fallback
|
|
||||||
}
|
}
|
||||||
const segments = query.replace(/^\/+/, "").split("/")
|
const segments = query.replace(/^\/+/, "").split("/")
|
||||||
const head = segments.slice(0, -1).filter((part) => part && part !== ".")
|
const head = segments.slice(0, -1).filter((part) => part && part !== ".")
|
||||||
|
|||||||
@@ -103,7 +103,6 @@ describe("normalizeProviderList", () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(result.connected).toEqual(["openai"])
|
expect(result.connected).toEqual(["openai"])
|
||||||
expect(result.defaultModel).toEqual({ providerID: "openai", modelID: "gpt-5" })
|
|
||||||
expect(result.default).toEqual({ openai: "gpt-5" })
|
expect(result.default).toEqual({ openai: "gpt-5" })
|
||||||
expect(result.all.get("openai")?.models["gpt-old"]).toBeUndefined()
|
expect(result.all.get("openai")?.models["gpt-old"]).toBeUndefined()
|
||||||
expect(result.all.get("openai")?.models["gpt-5"]).toMatchObject({
|
expect(result.all.get("openai")?.models["gpt-5"]).toMatchObject({
|
||||||
@@ -114,10 +113,6 @@ describe("normalizeProviderList", () => {
|
|||||||
variants: { high: {} },
|
variants: { high: {} },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test("preserves an empty current default", () => {
|
|
||||||
expect(normalizeProviderList([] as ProviderListOutput["data"], [], null).defaultModel).toBeNull()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("directoryKey", () => {
|
describe("directoryKey", () => {
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ export function normalizeProviderList(
|
|||||||
return {
|
return {
|
||||||
all,
|
all,
|
||||||
connected: providers.map((provider) => provider.id),
|
connected: providers.map((provider) => provider.id),
|
||||||
defaultModel: defaultModel ? { providerID: defaultModel.providerID, modelID: defaultModel.id } : null,
|
|
||||||
default: Object.fromEntries(
|
default: Object.fromEntries(
|
||||||
providers.flatMap((provider) => {
|
providers.flatMap((provider) => {
|
||||||
const model =
|
const model =
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { createStore } from "solid-js/store"
|
|||||||
import { useModels } from "@/context/models"
|
import { useModels } from "@/context/models"
|
||||||
import { useSettings } from "@/context/settings"
|
import { useSettings } from "@/context/settings"
|
||||||
import { useProviders } from "@/hooks/use-providers"
|
import { useProviders } from "@/hooks/use-providers"
|
||||||
import { resolveDefaultModel } from "@/hooks/provider-catalog"
|
|
||||||
import { Persist, persisted } from "@/utils/persist"
|
import { Persist, persisted } from "@/utils/persist"
|
||||||
import { hasCustomAgent, resolveAgent } from "./local-agent"
|
import { hasCustomAgent, resolveAgent } from "./local-agent"
|
||||||
import { cycleModelVariant, getConfiguredAgentVariant, resolveModelVariant } from "./model-variant"
|
import { cycleModelVariant, getConfiguredAgentVariant, resolveModelVariant } from "./model-variant"
|
||||||
@@ -150,8 +149,10 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const configuredModel = () => {
|
const configuredModel = () => {
|
||||||
const model = resolveDefaultModel(providers.defaultModel(), sync().data.config.model)
|
const configured = sync().data.config.model
|
||||||
if (!model) return
|
if (!configured) return
|
||||||
|
const [providerID, modelID] = configured.split("/")
|
||||||
|
const model = { providerID, modelID }
|
||||||
if (validModel(model)) return model
|
if (validModel(model)) return model
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { expect, test } from "bun:test"
|
import { expect, test } from "bun:test"
|
||||||
import type { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
|
import type { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
|
||||||
import { resolveDefaultModel, selectProviderCatalog } from "./provider-catalog"
|
import { selectProviderCatalog } from "./provider-catalog"
|
||||||
|
|
||||||
const catalog = (id: string): NormalizedProviderListResponse => ({
|
const catalog = (id: string): NormalizedProviderListResponse => ({
|
||||||
all: new Map([[id, { id, name: id, source: "api", env: [], options: {}, models: {} }]]),
|
all: new Map([[id, { id, name: id, source: "api", env: [], options: {}, models: {} }]]),
|
||||||
@@ -57,21 +57,3 @@ test("falls back to the global catalog for route consumers", () => {
|
|||||||
}),
|
}),
|
||||||
).toBe(global)
|
).toBe(global)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("uses the current server default model", () => {
|
|
||||||
expect(resolveDefaultModel({ providerID: "openai", modelID: "gpt-5" }, "anthropic/claude")).toEqual({
|
|
||||||
providerID: "openai",
|
|
||||||
modelID: "gpt-5",
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test("does not use legacy config when the current server has no default", () => {
|
|
||||||
expect(resolveDefaultModel(null, "anthropic/claude")).toBeUndefined()
|
|
||||||
})
|
|
||||||
|
|
||||||
test("uses config for legacy servers", () => {
|
|
||||||
expect(resolveDefaultModel(undefined, "anthropic/claude")).toEqual({
|
|
||||||
providerID: "anthropic",
|
|
||||||
modelID: "claude",
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -25,13 +25,3 @@ export function selectProviderCatalog(input: ProviderCatalogInput) {
|
|||||||
if (input.explicit) return emptyProviderCatalog
|
if (input.explicit) return emptyProviderCatalog
|
||||||
return input.global
|
return input.global
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resolveDefaultModel(
|
|
||||||
current: NormalizedProviderListResponse["defaultModel"],
|
|
||||||
legacy: string | undefined,
|
|
||||||
) {
|
|
||||||
if (current !== undefined) return current ?? undefined
|
|
||||||
if (!legacy) return undefined
|
|
||||||
const [providerID, modelID] = legacy.split("/")
|
|
||||||
return { providerID, modelID }
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ export function useProviders(directory: Accessor<string | undefined>) {
|
|||||||
return {
|
return {
|
||||||
all: () => providers().all,
|
all: () => providers().all,
|
||||||
default: () => providers().default,
|
default: () => providers().default,
|
||||||
defaultModel: () => providers().defaultModel,
|
|
||||||
popular: () =>
|
popular: () =>
|
||||||
pipe(
|
pipe(
|
||||||
providers().all,
|
providers().all,
|
||||||
|
|||||||
@@ -583,7 +583,7 @@ export const dict = {
|
|||||||
"dialog.usageExceeded.dontShowAgain": "不再显示",
|
"dialog.usageExceeded.dontShowAgain": "不再显示",
|
||||||
|
|
||||||
"context.breakdown.title": "上下文细分",
|
"context.breakdown.title": "上下文细分",
|
||||||
"context.breakdown.note": "输入 token 的大致细分。“其他”包含工具定义和开销。",
|
"context.breakdown.note": "输入词元的大致细分。“其他”包含工具定义和开销。",
|
||||||
"context.breakdown.system": "系统",
|
"context.breakdown.system": "系统",
|
||||||
"context.breakdown.user": "用户",
|
"context.breakdown.user": "用户",
|
||||||
"context.breakdown.assistant": "助手",
|
"context.breakdown.assistant": "助手",
|
||||||
@@ -598,18 +598,18 @@ export const dict = {
|
|||||||
"context.stats.provider": "提供商",
|
"context.stats.provider": "提供商",
|
||||||
"context.stats.model": "模型",
|
"context.stats.model": "模型",
|
||||||
"context.stats.limit": "上下文限制",
|
"context.stats.limit": "上下文限制",
|
||||||
"context.stats.totalTokens": "总 token",
|
"context.stats.totalTokens": "词元总数",
|
||||||
"context.stats.usage": "使用率",
|
"context.stats.usage": "使用率",
|
||||||
"context.stats.inputTokens": "输入 token",
|
"context.stats.inputTokens": "输入词元",
|
||||||
"context.stats.outputTokens": "输出 token",
|
"context.stats.outputTokens": "输出词元",
|
||||||
"context.stats.reasoningTokens": "推理 token",
|
"context.stats.reasoningTokens": "推理词元",
|
||||||
"context.stats.cacheTokens": "缓存 token(读/写)",
|
"context.stats.cacheTokens": "缓存词元(读/写)",
|
||||||
"context.stats.userMessages": "用户消息",
|
"context.stats.userMessages": "用户消息",
|
||||||
"context.stats.assistantMessages": "助手消息",
|
"context.stats.assistantMessages": "助手消息",
|
||||||
"context.stats.totalCost": "总成本",
|
"context.stats.totalCost": "总成本",
|
||||||
"context.stats.sessionCreated": "创建时间",
|
"context.stats.sessionCreated": "创建时间",
|
||||||
"context.stats.lastActivity": "最后活动",
|
"context.stats.lastActivity": "最后活动",
|
||||||
"context.usage.tokens": "Token",
|
"context.usage.tokens": "词元数",
|
||||||
"context.usage.usage": "使用率",
|
"context.usage.usage": "使用率",
|
||||||
"context.usage.cost": "成本",
|
"context.usage.cost": "成本",
|
||||||
"context.usage.clickToView": "点击查看上下文",
|
"context.usage.clickToView": "点击查看上下文",
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { usePrompt } from "@/context/prompt"
|
|||||||
import { useSDK } from "@/context/sdk"
|
import { useSDK } from "@/context/sdk"
|
||||||
import { useSync } from "@/context/sync"
|
import { useSync } from "@/context/sync"
|
||||||
import { useProviders } from "@/hooks/use-providers"
|
import { useProviders } from "@/hooks/use-providers"
|
||||||
import { resolveDefaultModel } from "@/hooks/provider-catalog"
|
|
||||||
|
|
||||||
export function createPromptModelSelection(input: { agent: () => { model?: ModelKey; variant?: string } | undefined }) {
|
export function createPromptModelSelection(input: { agent: () => { model?: ModelKey; variant?: string } | undefined }) {
|
||||||
const sdk = useSDK()
|
const sdk = useSDK()
|
||||||
@@ -22,8 +21,10 @@ export function createPromptModelSelection(input: { agent: () => { model?: Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
const configured = () => {
|
const configured = () => {
|
||||||
const model = resolveDefaultModel(providers.defaultModel(), sync().data.config.model)
|
const value = sync().data.config.model
|
||||||
if (!model) return
|
if (!value) return
|
||||||
|
const [providerID, modelID] = value.split("/")
|
||||||
|
const model = { providerID, modelID }
|
||||||
if (valid(model)) return model
|
if (valid(model)) return model
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/cli",
|
"name": "@opencode-ai/cli",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/codemode",
|
"name": "@opencode-ai/codemode",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"description": "Effect-native confined code execution over schema-described tools",
|
"description": "Effect-native confined code execution over schema-described tools",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/console-app",
|
"name": "@opencode-ai/console-app",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/console-core",
|
"name": "@opencode-ai/console-core",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/console-function",
|
"name": "@opencode-ai/console-function",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/console-mail",
|
"name": "@opencode-ai/console-mail",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jsx-email/all": "2.2.3",
|
"@jsx-email/all": "2.2.3",
|
||||||
"@jsx-email/cli": "1.4.3",
|
"@jsx-email/cli": "1.4.3",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/console-support",
|
"name": "@opencode-ai/console-support",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"name": "@opencode-ai/core",
|
"name": "@opencode-ai/core",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1769,6 +1769,62 @@ describe("SessionRunnerLLM", () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
it.effect("replays interrupted provider-local tool call IDs uniquely", () =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
yield* setup
|
||||||
|
const session = yield* SessionV2.Service
|
||||||
|
yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Echo twice" }), resume: false })
|
||||||
|
|
||||||
|
requests.length = 0
|
||||||
|
executions.length = 0
|
||||||
|
const firstGate = yield* Deferred.make<void>()
|
||||||
|
const secondGate = yield* Deferred.make<void>()
|
||||||
|
toolExecutionGate = firstGate
|
||||||
|
responses = [
|
||||||
|
[
|
||||||
|
LLMEvent.stepStart({ index: 0 }),
|
||||||
|
LLMEvent.toolCall({ id: "tool_0", name: "echo", input: { text: "first" } }),
|
||||||
|
LLMEvent.stepFinish({ index: 0, reason: "tool-calls" }),
|
||||||
|
LLMEvent.finish({ reason: "tool-calls" }),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
LLMEvent.stepStart({ index: 0 }),
|
||||||
|
LLMEvent.toolCall({ id: "tool_0", name: "echo", input: { text: "second" } }),
|
||||||
|
LLMEvent.stepFinish({ index: 0, reason: "tool-calls" }),
|
||||||
|
LLMEvent.finish({ reason: "tool-calls" }),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
|
const run = yield* session.resume(sessionID).pipe(Effect.forkChild)
|
||||||
|
while (executions.length < 1) yield* Effect.yieldNow
|
||||||
|
toolExecutionGate = secondGate
|
||||||
|
yield* Deferred.succeed(firstGate, undefined)
|
||||||
|
while (executions.length < 2) yield* Effect.yieldNow
|
||||||
|
yield* session.interrupt(sessionID)
|
||||||
|
expect(yield* Fiber.await(run)).toMatchObject({ _tag: "Failure" })
|
||||||
|
toolExecutionGate = undefined
|
||||||
|
|
||||||
|
expect(yield* session.context(sessionID)).toMatchObject([
|
||||||
|
{ type: "user", text: "Echo twice" },
|
||||||
|
{ type: "assistant", content: [{ type: "tool", id: "tool_0", state: { status: "completed" } }] },
|
||||||
|
{ type: "assistant", content: [{ type: "tool", id: "tool_0", state: { status: "error" } }] },
|
||||||
|
])
|
||||||
|
|
||||||
|
requests.length = 0
|
||||||
|
responses = undefined
|
||||||
|
response = []
|
||||||
|
yield* session.resume(sessionID)
|
||||||
|
|
||||||
|
const callIDs = requests[0]!.messages.flatMap((message) =>
|
||||||
|
message.role === "assistant"
|
||||||
|
? message.content.filter((part) => part.type === "tool-call").map((part) => part.id)
|
||||||
|
: [],
|
||||||
|
)
|
||||||
|
expect(callIDs).toHaveLength(2)
|
||||||
|
expect(new Set(callIDs).size).toBe(callIDs.length)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
it.effect("joins concurrent resume calls into one active provider run", () =>
|
it.effect("joins concurrent resume calls into one active provider run", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* setup
|
yield* setup
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/desktop",
|
"name": "@opencode-ai/desktop",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "https://opencode.ai",
|
"homepage": "https://opencode.ai",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"name": "@opencode-ai/effect-drizzle-sqlite",
|
"name": "@opencode-ai/effect-drizzle-sqlite",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"name": "@opencode-ai/effect-sqlite-node",
|
"name": "@opencode-ai/effect-sqlite-node",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/enterprise",
|
"name": "@opencode-ai/enterprise",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/function",
|
"name": "@opencode-ai/function",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"name": "@opencode-ai/http-recorder",
|
"name": "@opencode-ai/http-recorder",
|
||||||
"description": "Record and replay Effect HTTP client traffic with deterministic cassettes",
|
"description": "Record and replay Effect HTTP client traffic with deterministic cassettes",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"name": "@opencode-ai/llm",
|
"name": "@opencode-ai/llm",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"name": "opencode",
|
"name": "opencode",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -37,11 +37,22 @@ export function schema<S extends EffectSchema.Decoder<unknown, never>>(
|
|||||||
data: unknown,
|
data: unknown,
|
||||||
source: string,
|
source: string,
|
||||||
): DeepMutable<S["Type"]> {
|
): DeepMutable<S["Type"]> {
|
||||||
const decoded = EffectSchema.decodeUnknownExit(schema)(data, {
|
const extra = topLevelExtraKeys(schema, data)
|
||||||
errors: "all",
|
if (extra.length) {
|
||||||
onExcessProperty: "ignore",
|
throw new InvalidError({
|
||||||
propertyOrder: "original",
|
path: source,
|
||||||
})
|
issues: [
|
||||||
|
{
|
||||||
|
code: "unrecognized_keys",
|
||||||
|
keys: extra,
|
||||||
|
path: [],
|
||||||
|
message: `Unrecognized key${extra.length === 1 ? "" : "s"}: ${extra.join(", ")}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const decoded = EffectSchema.decodeUnknownExit(schema)(data, { errors: "all", propertyOrder: "original" })
|
||||||
if (Exit.isSuccess(decoded)) return decoded.value as DeepMutable<S["Type"]>
|
if (Exit.isSuccess(decoded)) return decoded.value as DeepMutable<S["Type"]>
|
||||||
const error = Cause.squash(decoded.cause)
|
const error = Cause.squash(decoded.cause)
|
||||||
|
|
||||||
@@ -59,3 +70,10 @@ export function schema<S extends EffectSchema.Decoder<unknown, never>>(
|
|||||||
{ cause: error },
|
{ cause: error },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function topLevelExtraKeys(schema: EffectSchema.Top, data: unknown) {
|
||||||
|
if (typeof data !== "object" || data === null || Array.isArray(data)) return []
|
||||||
|
if (schema.ast._tag !== "Objects" || schema.ast.indexSignatures.length > 0) return []
|
||||||
|
const known = new Set(schema.ast.propertySignatures.map((item) => String(item.name)))
|
||||||
|
return Object.keys(data).filter((key) => !known.has(key))
|
||||||
|
}
|
||||||
|
|||||||
@@ -597,12 +597,12 @@ accountTokenIt.instance("resolves env templates in account config with account t
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.instance("validates config schema and throws on invalid values", () =>
|
it.instance("validates config schema and throws on invalid fields", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const test = yield* TestInstance
|
const test = yield* TestInstance
|
||||||
yield* writeConfigEffect(test.directory, {
|
yield* writeConfigEffect(test.directory, {
|
||||||
$schema: "https://opencode.ai/config.json",
|
$schema: "https://opencode.ai/config.json",
|
||||||
model: 42,
|
invalid_field: "should cause error",
|
||||||
})
|
})
|
||||||
const exit = yield* Config.use.get().pipe(Effect.exit)
|
const exit = yield* Config.use.get().pipe(Effect.exit)
|
||||||
expect(Exit.isFailure(exit)).toBe(true)
|
expect(Exit.isFailure(exit)).toBe(true)
|
||||||
@@ -1331,7 +1331,7 @@ it.instance("permission config preserves user key order", () =>
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
test("config parser preserves permission order while ignoring unknown top-level keys", () => {
|
test("config parser preserves permission order while rejecting unknown top-level keys", () => {
|
||||||
const config = ConfigParse.schema(
|
const config = ConfigParse.schema(
|
||||||
ConfigV1.Info,
|
ConfigV1.Info,
|
||||||
{
|
{
|
||||||
@@ -1340,13 +1340,18 @@ test("config parser preserves permission order while ignoring unknown top-level
|
|||||||
"*": "deny",
|
"*": "deny",
|
||||||
edit: "ask",
|
edit: "ask",
|
||||||
},
|
},
|
||||||
plugins: ["example"],
|
|
||||||
},
|
},
|
||||||
"test",
|
"test",
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(Object.keys(config.permission!)).toEqual(["bash", "*", "edit"])
|
expect(Object.keys(config.permission!)).toEqual(["bash", "*", "edit"])
|
||||||
expect(config).not.toHaveProperty("plugins")
|
try {
|
||||||
|
ConfigParse.schema(ConfigV1.Info, { invalid_field: true }, "test")
|
||||||
|
throw new Error("expected config parse to fail")
|
||||||
|
} catch (err) {
|
||||||
|
const error = err as { data?: { issues?: Array<{ code?: string; keys?: string[]; path?: string[] }> } }
|
||||||
|
expect(error.data?.issues?.[0]).toMatchObject({ code: "unrecognized_keys", keys: ["invalid_field"], path: [] })
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// MCP config merging tests
|
// MCP config merging tests
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/plugin",
|
"name": "@opencode-ai/plugin",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/sdk",
|
"name": "@opencode-ai/sdk",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/server",
|
"name": "@opencode-ai/server",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/session-ui",
|
"name": "@opencode-ai/session-ui",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -5,10 +5,6 @@ import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
|
|||||||
|
|
||||||
export type NormalizedProviderListResponse = {
|
export type NormalizedProviderListResponse = {
|
||||||
all: Map<string, Provider>
|
all: Map<string, Provider>
|
||||||
defaultModel?: {
|
|
||||||
providerID: string
|
|
||||||
modelID: string
|
|
||||||
} | null
|
|
||||||
default: {
|
default: {
|
||||||
[key: string]: string
|
[key: string]: string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/slack",
|
"name": "@opencode-ai/slack",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/stats-app",
|
"name": "@opencode-ai/stats-app",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/stats-core",
|
"name": "@opencode-ai/stats-core",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { Effect, Layer } from "effect"
|
|||||||
import * as Context from "effect/Context"
|
import * as Context from "effect/Context"
|
||||||
import { Resource } from "sst/resource"
|
import { Resource } from "sst/resource"
|
||||||
|
|
||||||
const ATHENA_MAX_POLL_ATTEMPTS = 900
|
const ATHENA_MAX_POLL_ATTEMPTS = 300
|
||||||
const ATHENA_PAGE_SIZE = 1000
|
const ATHENA_PAGE_SIZE = 1000
|
||||||
|
|
||||||
export type AthenaData = Record<string, string>
|
export type AthenaData = Record<string, string>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/stats-server",
|
"name": "@opencode-ai/stats-server",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -19,19 +19,9 @@ const daemon = Effect.gen(function* () {
|
|||||||
let lastFullDay = ""
|
let lastFullDay = ""
|
||||||
const pass = Effect.gen(function* () {
|
const pass = Effect.gen(function* () {
|
||||||
const today = new Date().toISOString().slice(0, 10)
|
const today = new Date().toISOString().slice(0, 10)
|
||||||
if (lastFullDay !== today) {
|
const full = lastFullDay !== today
|
||||||
const completed = yield* syncStats({ full: true }).pipe(
|
yield* syncStats({ full })
|
||||||
Effect.as(true),
|
if (full) lastFullDay = today
|
||||||
Effect.catchCause((cause) =>
|
|
||||||
Effect.logWarning(`full stats sync failed; falling back to incremental sync ${Cause.pretty(cause)}`).pipe(
|
|
||||||
Effect.as(false),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
lastFullDay = today
|
|
||||||
if (completed) return
|
|
||||||
}
|
|
||||||
yield* syncStats({ full: false })
|
|
||||||
}).pipe(
|
}).pipe(
|
||||||
Effect.catchCause((cause) =>
|
Effect.catchCause((cause) =>
|
||||||
Effect.logWarning(`stats sync failed ${JSON.stringify({ cause: Cause.pretty(cause) })}`),
|
Effect.logWarning(`stats sync failed ${JSON.stringify({ cause: Cause.pretty(cause) })}`),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package.json",
|
"$schema": "https://json.schemastore.org/package.json",
|
||||||
"name": "@opencode-ai/tui",
|
"name": "@opencode-ai/tui",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@opencode-ai/ui",
|
"name": "@opencode-ai/ui",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "@opencode-ai/web",
|
"name": "@opencode-ai/web",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "astro dev",
|
"dev": "astro dev",
|
||||||
"dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev",
|
"dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "opencode",
|
"name": "opencode",
|
||||||
"displayName": "opencode",
|
"displayName": "opencode",
|
||||||
"description": "opencode for VS Code",
|
"description": "opencode for VS Code",
|
||||||
"version": "1.18.16",
|
"version": "1.18.15",
|
||||||
"publisher": "sst-dev",
|
"publisher": "sst-dev",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
Reference in New Issue
Block a user