mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-21 10:16:03 +00:00
fix(core): drop legacy config filename (#34645)
Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Aiden Cline
opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com>
parent
6387f955cf
commit
a4b6047e64
@@ -139,7 +139,7 @@ export const layer = Layer.effect(
|
|||||||
const global = yield* Global.Service
|
const global = yield* Global.Service
|
||||||
const location = yield* Location.Service
|
const location = yield* Location.Service
|
||||||
const policy = yield* Policy.Service
|
const policy = yield* Policy.Service
|
||||||
const names = ["config.json", "opencode.json", "opencode.jsonc"]
|
const names = ["opencode.json", "opencode.jsonc"]
|
||||||
const decodeOptions = { errors: "all", onExcessProperty: "ignore", propertyOrder: "original" } as const
|
const decodeOptions = { errors: "all", onExcessProperty: "ignore", propertyOrder: "original" } as const
|
||||||
const decodeInfo = Schema.decodeUnknownOption(Info, decodeOptions)
|
const decodeInfo = Schema.decodeUnknownOption(Info, decodeOptions)
|
||||||
const decodeV1Info = Schema.decodeUnknownOption(ConfigV1.Info, decodeOptions)
|
const decodeV1Info = Schema.decodeUnknownOption(ConfigV1.Info, decodeOptions)
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ describe("Config", () => {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.live("loads JSON and JSONC files from lowest to highest priority", () =>
|
it.live("loads opencode JSON and JSONC files from lowest to highest priority", () =>
|
||||||
Effect.acquireRelease(
|
Effect.acquireRelease(
|
||||||
Effect.promise(() => tmpdir()),
|
Effect.promise(() => tmpdir()),
|
||||||
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
|
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
|
||||||
@@ -170,13 +170,9 @@ describe("Config", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* Effect.promise(() =>
|
yield* Effect.promise(() =>
|
||||||
Promise.all([
|
Promise.all([
|
||||||
fs.writeFile(
|
|
||||||
path.join(tmp.path, "config.json"),
|
|
||||||
JSON.stringify({ $schema: "base", providers: { base: provider } }),
|
|
||||||
),
|
|
||||||
fs.writeFile(
|
fs.writeFile(
|
||||||
path.join(tmp.path, "opencode.json"),
|
path.join(tmp.path, "opencode.json"),
|
||||||
JSON.stringify({ $schema: "middle", providers: { middle: provider } }),
|
JSON.stringify({ $schema: "base", providers: { base: provider } }),
|
||||||
),
|
),
|
||||||
fs.writeFile(
|
fs.writeFile(
|
||||||
path.join(tmp.path, "opencode.jsonc"),
|
path.join(tmp.path, "opencode.jsonc"),
|
||||||
@@ -192,12 +188,12 @@ describe("Config", () => {
|
|||||||
const config = yield* Config.Service
|
const config = yield* Config.Service
|
||||||
const documents = (yield* config.entries()).filter((entry) => entry.type === "document")
|
const documents = (yield* config.entries()).filter((entry) => entry.type === "document")
|
||||||
|
|
||||||
expect(documents).toHaveLength(3)
|
expect(documents).toHaveLength(2)
|
||||||
expect(documents.map((document) => document.type)).toEqual(["document", "document", "document"])
|
expect(documents.map((document) => document.type)).toEqual(["document", "document"])
|
||||||
expect(documents.map((document) => document.info.$schema)).toEqual(["base", "middle", "last"])
|
expect(documents.map((document) => document.info.$schema)).toEqual(["base", "last"])
|
||||||
expect(documents[0]).toBeInstanceOf(Config.Document)
|
expect(documents[0]).toBeInstanceOf(Config.Document)
|
||||||
expect(documents[0]?.path).toBe(path.join(tmp.path, "config.json"))
|
expect(documents[0]?.path).toBe(path.join(tmp.path, "opencode.json"))
|
||||||
expect(documents[2]?.info.providers?.last).toBeInstanceOf(ConfigProvider.Info)
|
expect(documents[1]?.info.providers?.last).toBeInstanceOf(ConfigProvider.Info)
|
||||||
|
|
||||||
yield* Effect.promise(() =>
|
yield* Effect.promise(() =>
|
||||||
fs.writeFile(path.join(tmp.path, "opencode.jsonc"), JSON.stringify({ $schema: "changed" })),
|
fs.writeFile(path.join(tmp.path, "opencode.jsonc"), JSON.stringify({ $schema: "changed" })),
|
||||||
@@ -206,7 +202,29 @@ describe("Config", () => {
|
|||||||
(yield* config.entries())
|
(yield* config.entries())
|
||||||
.filter((entry) => entry.type === "document")
|
.filter((entry) => entry.type === "document")
|
||||||
.map((document) => document.info.$schema),
|
.map((document) => document.info.$schema),
|
||||||
).toEqual(["base", "middle", "last"])
|
).toEqual(["base", "last"])
|
||||||
|
}).pipe(Effect.provide(testLayer(tmp.path)))
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
it.live("does not load legacy config.json files", () =>
|
||||||
|
Effect.acquireRelease(
|
||||||
|
Effect.promise(() => tmpdir()),
|
||||||
|
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
|
||||||
|
).pipe(
|
||||||
|
Effect.flatMap((tmp) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
yield* Effect.promise(() =>
|
||||||
|
fs.writeFile(path.join(tmp.path, "config.json"), JSON.stringify({ $schema: "legacy" })),
|
||||||
|
)
|
||||||
|
|
||||||
|
return yield* Effect.gen(function* () {
|
||||||
|
const config = yield* Config.Service
|
||||||
|
const documents = (yield* config.entries()).filter((entry) => entry.type === "document")
|
||||||
|
|
||||||
|
expect(documents).toHaveLength(0)
|
||||||
}).pipe(Effect.provide(testLayer(tmp.path)))
|
}).pipe(Effect.provide(testLayer(tmp.path)))
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
@@ -648,7 +666,7 @@ describe("Config", () => {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
it.live("ignores invalid files while loading valid config values", () =>
|
it.live("ignores an invalid file while loading valid config values", () =>
|
||||||
Effect.acquireRelease(
|
Effect.acquireRelease(
|
||||||
Effect.promise(() => tmpdir()),
|
Effect.promise(() => tmpdir()),
|
||||||
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
|
(tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
|
||||||
@@ -657,9 +675,8 @@ describe("Config", () => {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
yield* Effect.promise(() =>
|
yield* Effect.promise(() =>
|
||||||
Promise.all([
|
Promise.all([
|
||||||
fs.writeFile(path.join(tmp.path, "config.json"), JSON.stringify({ $schema: "base" })),
|
fs.writeFile(path.join(tmp.path, "opencode.json"), JSON.stringify({ $schema: "base" })),
|
||||||
fs.writeFile(path.join(tmp.path, "opencode.json"), "{ invalid"),
|
fs.writeFile(path.join(tmp.path, "opencode.jsonc"), "{ invalid"),
|
||||||
fs.writeFile(path.join(tmp.path, "opencode.jsonc"), JSON.stringify({ providers: { invalid: true } })),
|
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
return yield* Effect.gen(function* () {
|
return yield* Effect.gen(function* () {
|
||||||
@@ -728,7 +745,7 @@ describe("Config", () => {
|
|||||||
fs.writeFile(path.join(global, "opencode.json"), JSON.stringify({ $schema: "global" })),
|
fs.writeFile(path.join(global, "opencode.json"), JSON.stringify({ $schema: "global" })),
|
||||||
fs.writeFile(path.join(root, "opencode.json"), JSON.stringify({ $schema: "root" })),
|
fs.writeFile(path.join(root, "opencode.json"), JSON.stringify({ $schema: "root" })),
|
||||||
fs.writeFile(path.join(parent, "opencode.jsonc"), JSON.stringify({ $schema: "parent" })),
|
fs.writeFile(path.join(parent, "opencode.jsonc"), JSON.stringify({ $schema: "parent" })),
|
||||||
fs.writeFile(path.join(directory, "config.json"), JSON.stringify({ $schema: "directory" })),
|
fs.writeFile(path.join(directory, "opencode.json"), JSON.stringify({ $schema: "directory" })),
|
||||||
fs.writeFile(path.join(root, ".opencode", "opencode.json"), JSON.stringify({ $schema: "root-dot" })),
|
fs.writeFile(path.join(root, ".opencode", "opencode.json"), JSON.stringify({ $schema: "root-dot" })),
|
||||||
fs.writeFile(
|
fs.writeFile(
|
||||||
path.join(directory, ".opencode", "opencode.jsonc"),
|
path.join(directory, ".opencode", "opencode.jsonc"),
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ describe("ConfigExternalPlugin", () => {
|
|||||||
const location = yield* Location.Service
|
const location = yield* Location.Service
|
||||||
const npm = yield* Npm.Service
|
const npm = yield* Npm.Service
|
||||||
const host = yield* PluginHost.make(plugins)
|
const host = yield* PluginHost.make(plugins)
|
||||||
const document = path.join(import.meta.dir, "config.json")
|
const document = path.join(import.meta.dir, "opencode.json")
|
||||||
|
|
||||||
yield* ConfigExternalPlugin.Plugin.effect(host).pipe(
|
yield* ConfigExternalPlugin.Plugin.effect(host).pipe(
|
||||||
Effect.provideService(PluginV2.Service, plugins),
|
Effect.provideService(PluginV2.Service, plugins),
|
||||||
@@ -82,7 +82,7 @@ describe("ConfigExternalPlugin", () => {
|
|||||||
Effect.succeed([
|
Effect.succeed([
|
||||||
new Config.Document({
|
new Config.Document({
|
||||||
type: "document",
|
type: "document",
|
||||||
path: path.join(import.meta.dir, "config.json"),
|
path: path.join(import.meta.dir, "opencode.json"),
|
||||||
info: decode({
|
info: decode({
|
||||||
plugins: [
|
plugins: [
|
||||||
{
|
{
|
||||||
@@ -125,7 +125,7 @@ describe("ConfigExternalPlugin", () => {
|
|||||||
Effect.succeed([
|
Effect.succeed([
|
||||||
new Config.Document({
|
new Config.Document({
|
||||||
type: "document",
|
type: "document",
|
||||||
path: path.join(import.meta.dir, "config.json"),
|
path: path.join(import.meta.dir, "opencode.json"),
|
||||||
info: decode({
|
info: decode({
|
||||||
plugins: [
|
plugins: [
|
||||||
"../plugin/fixtures/missing-plugin.ts",
|
"../plugin/fixtures/missing-plugin.ts",
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ This document breaks the legacy configuration schema into small review groups. W
|
|||||||
|
|
||||||
Use one v2 config schema for now. Some fields, such as `autoupdate`, are intended for global/user configuration, but there is not yet enough benefit to enforce that with separate global and location schemas. Revisit this if more scope-sensitive fields survive the review.
|
Use one v2 config schema for now. Some fields, such as `autoupdate`, are intended for global/user configuration, but there is not yet enough benefit to enforce that with separate global and location schemas. Revisit this if more scope-sensitive fields survive the review.
|
||||||
|
|
||||||
|
V2 core discovers config documents named `opencode.json` or `opencode.jsonc` in the global config directory, ancestor project directories, and `.opencode` config directories. The legacy `config.json` filename is not supported in V2.
|
||||||
|
|
||||||
## Group 1: File Metadata
|
## Group 1: File Metadata
|
||||||
|
|
||||||
Small fields describing the config file itself rather than application behavior.
|
Small fields describing the config file itself rather than application behavior.
|
||||||
|
|||||||
Reference in New Issue
Block a user