|
|
@@ -413,260 +413,261 @@ export const layer = Layer.effect(
|
|
|
}
|
|
|
})
|
|
|
|
|
|
- const loadInstanceState = Effect.fn("Config.loadInstanceState")(function* (ctx: InstanceContext) {
|
|
|
- const auth = yield* authSvc.all().pipe(Effect.orDie)
|
|
|
-
|
|
|
- let result: Info = {}
|
|
|
- const consoleManagedProviders = new Set<string>()
|
|
|
- let activeOrgName: string | undefined
|
|
|
-
|
|
|
- const pluginScopeForSource = Effect.fnUntraced(function* (source: string) {
|
|
|
- if (source.startsWith("http://") || source.startsWith("https://")) return "global"
|
|
|
- if (source === "OPENCODE_CONFIG_CONTENT") return "local"
|
|
|
- if (yield* InstanceRef.use((ctx) => Effect.succeed(Instance.containsPath(source, ctx)))) return "local"
|
|
|
- return "global"
|
|
|
- })
|
|
|
+ const loadInstanceState = Effect.fn("Config.loadInstanceState")(
|
|
|
+ function* (ctx: InstanceContext) {
|
|
|
+ const auth = yield* authSvc.all().pipe(Effect.orDie)
|
|
|
+
|
|
|
+ let result: Info = {}
|
|
|
+ const consoleManagedProviders = new Set<string>()
|
|
|
+ let activeOrgName: string | undefined
|
|
|
+
|
|
|
+ const pluginScopeForSource = Effect.fnUntraced(function* (source: string) {
|
|
|
+ if (source.startsWith("http://") || source.startsWith("https://")) return "global"
|
|
|
+ if (source === "OPENCODE_CONFIG_CONTENT") return "local"
|
|
|
+ if (yield* InstanceRef.use((ctx) => Effect.succeed(Instance.containsPath(source, ctx)))) return "local"
|
|
|
+ return "global"
|
|
|
+ })
|
|
|
|
|
|
- const mergePluginOrigins = Effect.fnUntraced(function* (
|
|
|
- source: string,
|
|
|
- // mergePluginOrigins receives raw Specs from one config source, before provenance for this merge step
|
|
|
- // is attached.
|
|
|
- list: ConfigPlugin.Spec[] | undefined,
|
|
|
- // Scope can be inferred from the source path, but some callers already know whether the config should
|
|
|
- // behave as global or local and can pass that explicitly.
|
|
|
- kind?: ConfigPlugin.Scope,
|
|
|
- ) {
|
|
|
- if (!list?.length) return
|
|
|
- const hit = kind ?? (yield* pluginScopeForSource(source))
|
|
|
- // Merge newly seen plugin origins with previously collected ones, then dedupe by plugin identity while
|
|
|
- // keeping the winning source/scope metadata for downstream installs, writes, and diagnostics.
|
|
|
- const plugins = ConfigPlugin.deduplicatePluginOrigins([
|
|
|
- ...(result.plugin_origins ?? []),
|
|
|
- ...list.map((spec) => ({ spec, source, scope: hit })),
|
|
|
- ])
|
|
|
- result.plugin = plugins.map((item) => item.spec)
|
|
|
- result.plugin_origins = plugins
|
|
|
- })
|
|
|
+ const mergePluginOrigins = Effect.fnUntraced(function* (
|
|
|
+ source: string,
|
|
|
+ // mergePluginOrigins receives raw Specs from one config source, before provenance for this merge step
|
|
|
+ // is attached.
|
|
|
+ list: ConfigPlugin.Spec[] | undefined,
|
|
|
+ // Scope can be inferred from the source path, but some callers already know whether the config should
|
|
|
+ // behave as global or local and can pass that explicitly.
|
|
|
+ kind?: ConfigPlugin.Scope,
|
|
|
+ ) {
|
|
|
+ if (!list?.length) return
|
|
|
+ const hit = kind ?? (yield* pluginScopeForSource(source))
|
|
|
+ // Merge newly seen plugin origins with previously collected ones, then dedupe by plugin identity while
|
|
|
+ // keeping the winning source/scope metadata for downstream installs, writes, and diagnostics.
|
|
|
+ const plugins = ConfigPlugin.deduplicatePluginOrigins([
|
|
|
+ ...(result.plugin_origins ?? []),
|
|
|
+ ...list.map((spec) => ({ spec, source, scope: hit })),
|
|
|
+ ])
|
|
|
+ result.plugin = plugins.map((item) => item.spec)
|
|
|
+ result.plugin_origins = plugins
|
|
|
+ })
|
|
|
|
|
|
- const merge = (source: string, next: Info, kind?: ConfigPlugin.Scope) => {
|
|
|
- result = mergeConfigConcatArrays(result, next)
|
|
|
- return mergePluginOrigins(source, next.plugin, kind)
|
|
|
- }
|
|
|
+ const merge = (source: string, next: Info, kind?: ConfigPlugin.Scope) => {
|
|
|
+ result = mergeConfigConcatArrays(result, next)
|
|
|
+ return mergePluginOrigins(source, next.plugin, kind)
|
|
|
+ }
|
|
|
|
|
|
- for (const [key, value] of Object.entries(auth)) {
|
|
|
- if (value.type === "wellknown") {
|
|
|
- const url = key.replace(/\/+$/, "")
|
|
|
- process.env[value.key] = value.token
|
|
|
- log.debug("fetching remote config", { url: `${url}/.well-known/opencode` })
|
|
|
- const response = yield* Effect.promise(() => fetch(`${url}/.well-known/opencode`))
|
|
|
- if (!response.ok) {
|
|
|
- throw new Error(`failed to fetch remote config from ${url}: ${response.status}`)
|
|
|
+ for (const [key, value] of Object.entries(auth)) {
|
|
|
+ if (value.type === "wellknown") {
|
|
|
+ const url = key.replace(/\/+$/, "")
|
|
|
+ process.env[value.key] = value.token
|
|
|
+ log.debug("fetching remote config", { url: `${url}/.well-known/opencode` })
|
|
|
+ const response = yield* Effect.promise(() => fetch(`${url}/.well-known/opencode`))
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error(`failed to fetch remote config from ${url}: ${response.status}`)
|
|
|
+ }
|
|
|
+ const wellknown = (yield* Effect.promise(() => response.json())) as { config?: Record<string, unknown> }
|
|
|
+ const remoteConfig = wellknown.config ?? {}
|
|
|
+ if (!remoteConfig.$schema) remoteConfig.$schema = "https://opencode.ai/config.json"
|
|
|
+ const source = `${url}/.well-known/opencode`
|
|
|
+ const next = yield* loadConfig(JSON.stringify(remoteConfig), {
|
|
|
+ dir: path.dirname(source),
|
|
|
+ source,
|
|
|
+ })
|
|
|
+ yield* merge(source, next, "global")
|
|
|
+ log.debug("loaded remote config from well-known", { url })
|
|
|
}
|
|
|
- const wellknown = (yield* Effect.promise(() => response.json())) as { config?: Record<string, unknown> }
|
|
|
- const remoteConfig = wellknown.config ?? {}
|
|
|
- if (!remoteConfig.$schema) remoteConfig.$schema = "https://opencode.ai/config.json"
|
|
|
- const source = `${url}/.well-known/opencode`
|
|
|
- const next = yield* loadConfig(JSON.stringify(remoteConfig), {
|
|
|
- dir: path.dirname(source),
|
|
|
- source,
|
|
|
- })
|
|
|
- yield* merge(source, next, "global")
|
|
|
- log.debug("loaded remote config from well-known", { url })
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- const global = yield* getGlobal()
|
|
|
- yield* merge(Global.Path.config, global, "global")
|
|
|
|
|
|
- if (Flag.OPENCODE_CONFIG) {
|
|
|
- yield* merge(Flag.OPENCODE_CONFIG, yield* loadFile(Flag.OPENCODE_CONFIG))
|
|
|
- log.debug("loaded custom config", { path: Flag.OPENCODE_CONFIG })
|
|
|
- }
|
|
|
+ const global = yield* getGlobal()
|
|
|
+ yield* merge(Global.Path.config, global, "global")
|
|
|
|
|
|
- if (!Flag.OPENCODE_DISABLE_PROJECT_CONFIG) {
|
|
|
- for (const file of yield* Effect.promise(() =>
|
|
|
- ConfigPaths.projectFiles("opencode", ctx.directory, ctx.worktree),
|
|
|
- )) {
|
|
|
- yield* merge(file, yield* loadFile(file), "local")
|
|
|
+ if (Flag.OPENCODE_CONFIG) {
|
|
|
+ yield* merge(Flag.OPENCODE_CONFIG, yield* loadFile(Flag.OPENCODE_CONFIG))
|
|
|
+ log.debug("loaded custom config", { path: Flag.OPENCODE_CONFIG })
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- result.agent = result.agent || {}
|
|
|
- result.mode = result.mode || {}
|
|
|
- result.plugin = result.plugin || []
|
|
|
+ if (!Flag.OPENCODE_DISABLE_PROJECT_CONFIG) {
|
|
|
+ for (const file of yield* ConfigPaths.files("opencode", ctx.directory, ctx.worktree).pipe(Effect.orDie)) {
|
|
|
+ yield* merge(file, yield* loadFile(file), "local")
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- const directories = yield* Effect.promise(() => ConfigPaths.directories(ctx.directory, ctx.worktree))
|
|
|
+ result.agent = result.agent || {}
|
|
|
+ result.mode = result.mode || {}
|
|
|
+ result.plugin = result.plugin || []
|
|
|
|
|
|
- if (Flag.OPENCODE_CONFIG_DIR) {
|
|
|
- log.debug("loading config from OPENCODE_CONFIG_DIR", { path: Flag.OPENCODE_CONFIG_DIR })
|
|
|
- }
|
|
|
+ const directories = yield* ConfigPaths.directories(ctx.directory, ctx.worktree)
|
|
|
|
|
|
- const deps: Fiber.Fiber<void, never>[] = []
|
|
|
+ if (Flag.OPENCODE_CONFIG_DIR) {
|
|
|
+ log.debug("loading config from OPENCODE_CONFIG_DIR", { path: Flag.OPENCODE_CONFIG_DIR })
|
|
|
+ }
|
|
|
|
|
|
- for (const dir of directories) {
|
|
|
- if (dir.endsWith(".opencode") || dir === Flag.OPENCODE_CONFIG_DIR) {
|
|
|
- for (const file of ["opencode.json", "opencode.jsonc"]) {
|
|
|
- const source = path.join(dir, file)
|
|
|
- log.debug(`loading config from ${source}`)
|
|
|
- yield* merge(source, yield* loadFile(source))
|
|
|
- result.agent ??= {}
|
|
|
- result.mode ??= {}
|
|
|
- result.plugin ??= []
|
|
|
+ const deps: Fiber.Fiber<void, never>[] = []
|
|
|
+
|
|
|
+ for (const dir of directories) {
|
|
|
+ if (dir.endsWith(".opencode") || dir === Flag.OPENCODE_CONFIG_DIR) {
|
|
|
+ for (const file of ["opencode.json", "opencode.jsonc"]) {
|
|
|
+ const source = path.join(dir, file)
|
|
|
+ log.debug(`loading config from ${source}`)
|
|
|
+ yield* merge(source, yield* loadFile(source))
|
|
|
+ result.agent ??= {}
|
|
|
+ result.mode ??= {}
|
|
|
+ result.plugin ??= []
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- yield* ensureGitignore(dir).pipe(Effect.orDie)
|
|
|
+ yield* ensureGitignore(dir).pipe(Effect.orDie)
|
|
|
+
|
|
|
+ const dep = yield* npmSvc
|
|
|
+ .install(dir, {
|
|
|
+ add: ["@opencode-ai/plugin" + (InstallationLocal ? "" : "@" + InstallationVersion)],
|
|
|
+ })
|
|
|
+ .pipe(
|
|
|
+ Effect.exit,
|
|
|
+ Effect.tap((exit) =>
|
|
|
+ Exit.isFailure(exit)
|
|
|
+ ? Effect.sync(() => {
|
|
|
+ log.warn("background dependency install failed", { dir, error: String(exit.cause) })
|
|
|
+ })
|
|
|
+ : Effect.void,
|
|
|
+ ),
|
|
|
+ Effect.asVoid,
|
|
|
+ Effect.forkDetach,
|
|
|
+ )
|
|
|
+ deps.push(dep)
|
|
|
+
|
|
|
+ result.command = mergeDeep(result.command ?? {}, yield* Effect.promise(() => ConfigCommand.load(dir)))
|
|
|
+ result.agent = mergeDeep(result.agent ?? {}, yield* Effect.promise(() => ConfigAgent.load(dir)))
|
|
|
+ result.agent = mergeDeep(result.agent ?? {}, yield* Effect.promise(() => ConfigAgent.loadMode(dir)))
|
|
|
+ // Auto-discovered plugins under `.opencode/plugin(s)` are already local files, so ConfigPlugin.load
|
|
|
+ // returns normalized Specs and we only need to attach origin metadata here.
|
|
|
+ const list = yield* Effect.promise(() => ConfigPlugin.load(dir))
|
|
|
+ yield* mergePluginOrigins(dir, list)
|
|
|
+ }
|
|
|
|
|
|
- const dep = yield* npmSvc
|
|
|
- .install(dir, {
|
|
|
- add: ["@opencode-ai/plugin" + (InstallationLocal ? "" : "@" + InstallationVersion)],
|
|
|
+ if (process.env.OPENCODE_CONFIG_CONTENT) {
|
|
|
+ const source = "OPENCODE_CONFIG_CONTENT"
|
|
|
+ const next = yield* loadConfig(process.env.OPENCODE_CONFIG_CONTENT, {
|
|
|
+ dir: ctx.directory,
|
|
|
+ source,
|
|
|
})
|
|
|
- .pipe(
|
|
|
- Effect.exit,
|
|
|
- Effect.tap((exit) =>
|
|
|
- Exit.isFailure(exit)
|
|
|
- ? Effect.sync(() => {
|
|
|
- log.warn("background dependency install failed", { dir, error: String(exit.cause) })
|
|
|
- })
|
|
|
- : Effect.void,
|
|
|
- ),
|
|
|
- Effect.asVoid,
|
|
|
- Effect.forkDetach,
|
|
|
- )
|
|
|
- deps.push(dep)
|
|
|
-
|
|
|
- result.command = mergeDeep(result.command ?? {}, yield* Effect.promise(() => ConfigCommand.load(dir)))
|
|
|
- result.agent = mergeDeep(result.agent ?? {}, yield* Effect.promise(() => ConfigAgent.load(dir)))
|
|
|
- result.agent = mergeDeep(result.agent ?? {}, yield* Effect.promise(() => ConfigAgent.loadMode(dir)))
|
|
|
- // Auto-discovered plugins under `.opencode/plugin(s)` are already local files, so ConfigPlugin.load
|
|
|
- // returns normalized Specs and we only need to attach origin metadata here.
|
|
|
- const list = yield* Effect.promise(() => ConfigPlugin.load(dir))
|
|
|
- yield* mergePluginOrigins(dir, list)
|
|
|
- }
|
|
|
+ yield* merge(source, next, "local")
|
|
|
+ log.debug("loaded custom config from OPENCODE_CONFIG_CONTENT")
|
|
|
+ }
|
|
|
|
|
|
- if (process.env.OPENCODE_CONFIG_CONTENT) {
|
|
|
- const source = "OPENCODE_CONFIG_CONTENT"
|
|
|
- const next = yield* loadConfig(process.env.OPENCODE_CONFIG_CONTENT, {
|
|
|
- dir: ctx.directory,
|
|
|
- source,
|
|
|
- })
|
|
|
- yield* merge(source, next, "local")
|
|
|
- log.debug("loaded custom config from OPENCODE_CONFIG_CONTENT")
|
|
|
- }
|
|
|
+ const activeAccount = Option.getOrUndefined(
|
|
|
+ yield* accountSvc.active().pipe(Effect.catch(() => Effect.succeed(Option.none()))),
|
|
|
+ )
|
|
|
+ if (activeAccount?.active_org_id) {
|
|
|
+ const accountID = activeAccount.id
|
|
|
+ const orgID = activeAccount.active_org_id
|
|
|
+ const url = activeAccount.url
|
|
|
+ yield* Effect.gen(function* () {
|
|
|
+ const [configOpt, tokenOpt] = yield* Effect.all(
|
|
|
+ [accountSvc.config(accountID, orgID), accountSvc.token(accountID)],
|
|
|
+ { concurrency: 2 },
|
|
|
+ )
|
|
|
+ if (Option.isSome(tokenOpt)) {
|
|
|
+ process.env["OPENCODE_CONSOLE_TOKEN"] = tokenOpt.value
|
|
|
+ yield* env.set("OPENCODE_CONSOLE_TOKEN", tokenOpt.value)
|
|
|
+ }
|
|
|
|
|
|
- const activeAccount = Option.getOrUndefined(
|
|
|
- yield* accountSvc.active().pipe(Effect.catch(() => Effect.succeed(Option.none()))),
|
|
|
- )
|
|
|
- if (activeAccount?.active_org_id) {
|
|
|
- const accountID = activeAccount.id
|
|
|
- const orgID = activeAccount.active_org_id
|
|
|
- const url = activeAccount.url
|
|
|
- yield* Effect.gen(function* () {
|
|
|
- const [configOpt, tokenOpt] = yield* Effect.all(
|
|
|
- [accountSvc.config(accountID, orgID), accountSvc.token(accountID)],
|
|
|
- { concurrency: 2 },
|
|
|
+ if (Option.isSome(configOpt)) {
|
|
|
+ const source = `${url}/api/config`
|
|
|
+ const next = yield* loadConfig(JSON.stringify(configOpt.value), {
|
|
|
+ dir: path.dirname(source),
|
|
|
+ source,
|
|
|
+ })
|
|
|
+ for (const providerID of Object.keys(next.provider ?? {})) {
|
|
|
+ consoleManagedProviders.add(providerID)
|
|
|
+ }
|
|
|
+ yield* merge(source, next, "global")
|
|
|
+ }
|
|
|
+ }).pipe(
|
|
|
+ Effect.withSpan("Config.loadActiveOrgConfig"),
|
|
|
+ Effect.catch((err) => {
|
|
|
+ log.debug("failed to fetch remote account config", {
|
|
|
+ error: err instanceof Error ? err.message : String(err),
|
|
|
+ })
|
|
|
+ return Effect.void
|
|
|
+ }),
|
|
|
)
|
|
|
- if (Option.isSome(tokenOpt)) {
|
|
|
- process.env["OPENCODE_CONSOLE_TOKEN"] = tokenOpt.value
|
|
|
- yield* env.set("OPENCODE_CONSOLE_TOKEN", tokenOpt.value)
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- if (Option.isSome(configOpt)) {
|
|
|
- const source = `${url}/api/config`
|
|
|
- const next = yield* loadConfig(JSON.stringify(configOpt.value), {
|
|
|
- dir: path.dirname(source),
|
|
|
- source,
|
|
|
- })
|
|
|
- for (const providerID of Object.keys(next.provider ?? {})) {
|
|
|
- consoleManagedProviders.add(providerID)
|
|
|
- }
|
|
|
- yield* merge(source, next, "global")
|
|
|
+ const managedDir = ConfigManaged.managedConfigDir()
|
|
|
+ if (existsSync(managedDir)) {
|
|
|
+ for (const file of ["opencode.json", "opencode.jsonc"]) {
|
|
|
+ const source = path.join(managedDir, file)
|
|
|
+ yield* merge(source, yield* loadFile(source), "global")
|
|
|
}
|
|
|
- }).pipe(
|
|
|
- Effect.withSpan("Config.loadActiveOrgConfig"),
|
|
|
- Effect.catch((err) => {
|
|
|
- log.debug("failed to fetch remote account config", {
|
|
|
- error: err instanceof Error ? err.message : String(err),
|
|
|
- })
|
|
|
- return Effect.void
|
|
|
- }),
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- const managedDir = ConfigManaged.managedConfigDir()
|
|
|
- if (existsSync(managedDir)) {
|
|
|
- for (const file of ["opencode.json", "opencode.jsonc"]) {
|
|
|
- const source = path.join(managedDir, file)
|
|
|
- yield* merge(source, yield* loadFile(source), "global")
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- // macOS managed preferences (.mobileconfig deployed via MDM) override everything
|
|
|
- const managed = yield* Effect.promise(() => ConfigManaged.readManagedPreferences())
|
|
|
- if (managed) {
|
|
|
- result = mergeConfigConcatArrays(
|
|
|
- result,
|
|
|
- yield* loadConfig(managed.text, {
|
|
|
- dir: path.dirname(managed.source),
|
|
|
- source: managed.source,
|
|
|
- }),
|
|
|
- )
|
|
|
- }
|
|
|
+ // macOS managed preferences (.mobileconfig deployed via MDM) override everything
|
|
|
+ const managed = yield* Effect.promise(() => ConfigManaged.readManagedPreferences())
|
|
|
+ if (managed) {
|
|
|
+ result = mergeConfigConcatArrays(
|
|
|
+ result,
|
|
|
+ yield* loadConfig(managed.text, {
|
|
|
+ dir: path.dirname(managed.source),
|
|
|
+ source: managed.source,
|
|
|
+ }),
|
|
|
+ )
|
|
|
+ }
|
|
|
|
|
|
- for (const [name, mode] of Object.entries(result.mode ?? {})) {
|
|
|
- result.agent = mergeDeep(result.agent ?? {}, {
|
|
|
- [name]: {
|
|
|
- ...mode,
|
|
|
- mode: "primary" as const,
|
|
|
- },
|
|
|
- })
|
|
|
- }
|
|
|
+ for (const [name, mode] of Object.entries(result.mode ?? {})) {
|
|
|
+ result.agent = mergeDeep(result.agent ?? {}, {
|
|
|
+ [name]: {
|
|
|
+ ...mode,
|
|
|
+ mode: "primary" as const,
|
|
|
+ },
|
|
|
+ })
|
|
|
+ }
|
|
|
|
|
|
- if (Flag.OPENCODE_PERMISSION) {
|
|
|
- result.permission = mergeDeep(result.permission ?? {}, JSON.parse(Flag.OPENCODE_PERMISSION))
|
|
|
- }
|
|
|
+ if (Flag.OPENCODE_PERMISSION) {
|
|
|
+ result.permission = mergeDeep(result.permission ?? {}, JSON.parse(Flag.OPENCODE_PERMISSION))
|
|
|
+ }
|
|
|
|
|
|
- if (result.tools) {
|
|
|
- const perms: Record<string, ConfigPermission.Action> = {}
|
|
|
- for (const [tool, enabled] of Object.entries(result.tools)) {
|
|
|
- const action: ConfigPermission.Action = enabled ? "allow" : "deny"
|
|
|
- if (tool === "write" || tool === "edit" || tool === "patch" || tool === "multiedit") {
|
|
|
- perms.edit = action
|
|
|
- continue
|
|
|
+ if (result.tools) {
|
|
|
+ const perms: Record<string, ConfigPermission.Action> = {}
|
|
|
+ for (const [tool, enabled] of Object.entries(result.tools)) {
|
|
|
+ const action: ConfigPermission.Action = enabled ? "allow" : "deny"
|
|
|
+ if (tool === "write" || tool === "edit" || tool === "patch" || tool === "multiedit") {
|
|
|
+ perms.edit = action
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ perms[tool] = action
|
|
|
}
|
|
|
- perms[tool] = action
|
|
|
+ result.permission = mergeDeep(perms, result.permission ?? {})
|
|
|
}
|
|
|
- result.permission = mergeDeep(perms, result.permission ?? {})
|
|
|
- }
|
|
|
|
|
|
- if (!result.username) result.username = os.userInfo().username
|
|
|
+ if (!result.username) result.username = os.userInfo().username
|
|
|
|
|
|
- if (result.autoshare === true && !result.share) {
|
|
|
- result.share = "auto"
|
|
|
- }
|
|
|
+ if (result.autoshare === true && !result.share) {
|
|
|
+ result.share = "auto"
|
|
|
+ }
|
|
|
|
|
|
- if (Flag.OPENCODE_DISABLE_AUTOCOMPACT) {
|
|
|
- result.compaction = { ...result.compaction, auto: false }
|
|
|
- }
|
|
|
- if (Flag.OPENCODE_DISABLE_PRUNE) {
|
|
|
- result.compaction = { ...result.compaction, prune: false }
|
|
|
- }
|
|
|
+ if (Flag.OPENCODE_DISABLE_AUTOCOMPACT) {
|
|
|
+ result.compaction = { ...result.compaction, auto: false }
|
|
|
+ }
|
|
|
+ if (Flag.OPENCODE_DISABLE_PRUNE) {
|
|
|
+ result.compaction = { ...result.compaction, prune: false }
|
|
|
+ }
|
|
|
|
|
|
- return {
|
|
|
- config: result,
|
|
|
- directories,
|
|
|
- deps,
|
|
|
- consoleState: {
|
|
|
- consoleManagedProviders: Array.from(consoleManagedProviders),
|
|
|
- activeOrgName,
|
|
|
- switchableOrgCount: 0,
|
|
|
- },
|
|
|
- }
|
|
|
- })
|
|
|
+ return {
|
|
|
+ config: result,
|
|
|
+ directories,
|
|
|
+ deps,
|
|
|
+ consoleState: {
|
|
|
+ consoleManagedProviders: Array.from(consoleManagedProviders),
|
|
|
+ activeOrgName,
|
|
|
+ switchableOrgCount: 0,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ },
|
|
|
+ Effect.provideService(AppFileSystem.Service, fs),
|
|
|
+ )
|
|
|
|
|
|
const state = yield* InstanceState.make<State>(
|
|
|
Effect.fn("Config.state")(function* (ctx) {
|
|
|
- return yield* loadInstanceState(ctx)
|
|
|
+ return yield* loadInstanceState(ctx).pipe(Effect.orDie)
|
|
|
}),
|
|
|
)
|
|
|
|