diff --git a/packages/core/src/flag/flag.ts b/packages/core/src/flag/flag.ts index f97c6953aa..1822d8f8da 100644 --- a/packages/core/src/flag/flag.ts +++ b/packages/core/src/flag/flag.ts @@ -20,7 +20,6 @@ export const Flag = { OTEL_EXPORTER_OTLP_ENDPOINT: process.env["OTEL_EXPORTER_OTLP_ENDPOINT"], OTEL_EXPORTER_OTLP_HEADERS: process.env["OTEL_EXPORTER_OTLP_HEADERS"], - OPENCODE_AUTO_SHARE: truthy("OPENCODE_AUTO_SHARE"), OPENCODE_AUTO_HEAP_SNAPSHOT: truthy("OPENCODE_AUTO_HEAP_SNAPSHOT"), OPENCODE_GIT_BASH_PATH: process.env["OPENCODE_GIT_BASH_PATH"], OPENCODE_CONFIG: process.env["OPENCODE_CONFIG"], diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts index 33dff2ab5d..9487d6d826 100644 --- a/packages/opencode/src/cli/cmd/run.ts +++ b/packages/opencode/src/cli/cmd/run.ts @@ -17,13 +17,13 @@ import { pathToFileURL } from "url" import { Effect } from "effect" import { UI } from "../ui" import { effectCmd } from "../effect-cmd" -import { Flag } from "@opencode-ai/core/flag/flag" import { ServerAuth } from "@/server/auth" import { EOL } from "os" import { Filesystem } from "@/util/filesystem" import { createOpencodeClient, type OpencodeClient, type ToolPart } from "@opencode-ai/sdk/v2" import { Agent } from "@/agent/agent" import { Permission } from "@/permission" +import { RuntimeFlags } from "@/effect/runtime-flags" import { FormatError, FormatUnknownError } from "../error" import { INTERACTIVE_INPUT_ERROR, resolveInteractiveStdin } from "./run/runtime.stdin" @@ -235,6 +235,7 @@ export const RunCommand = effectCmd({ }), handler: Effect.fn("Cli.run")(function* (args) { const agentSvc = yield* Agent.Service + const flags = yield* RuntimeFlags.Service yield* Effect.promise(async () => { const rawMessage = [...args.message, ...(args["--"] || [])].join(" ") const thinking = args.interactive ? (args.thinking ?? true) : (args.thinking ?? false) @@ -446,7 +447,7 @@ export const RunCommand = effectCmd({ async function share(sdk: OpencodeClient, sessionID: string) { const cfg = await sdk.config.get() if (!cfg.data) return - if (cfg.data.share !== "auto" && !Flag.OPENCODE_AUTO_SHARE && !args.share) return + if (cfg.data.share !== "auto" && !flags.autoShare && !args.share) return const res = await sdk.session.share({ sessionID }).catch((error) => { if (error instanceof Error && error.message.includes("disabled")) { UI.println(UI.Style.TEXT_DANGER_BOLD + "! " + error.message) diff --git a/packages/opencode/src/effect/app-runtime.ts b/packages/opencode/src/effect/app-runtime.ts index d5e9f529b8..ec0336785a 100644 --- a/packages/opencode/src/effect/app-runtime.ts +++ b/packages/opencode/src/effect/app-runtime.ts @@ -56,6 +56,7 @@ import { Npm } from "@opencode-ai/core/npm" import { memoMap } from "@opencode-ai/core/effect/memo-map" import { DataMigration } from "@/data-migration" import { BackgroundJob } from "@/background/job" +import { RuntimeFlags } from "@/effect/runtime-flags" export const AppLayer = Layer.mergeAll( Npm.defaultLayer, @@ -83,6 +84,7 @@ export const AppLayer = Layer.mergeAll( Session.defaultLayer, SessionStatus.defaultLayer, BackgroundJob.defaultLayer, + RuntimeFlags.defaultLayer, SessionRunState.defaultLayer, SessionProcessor.defaultLayer, SessionCompaction.defaultLayer, diff --git a/packages/opencode/src/effect/runtime-flags.ts b/packages/opencode/src/effect/runtime-flags.ts index 0c21b30e68..332568680a 100644 --- a/packages/opencode/src/effect/runtime-flags.ts +++ b/packages/opencode/src/effect/runtime-flags.ts @@ -12,6 +12,7 @@ const enabledByExperimental = (name: string) => Config.all({ experimental, enabled: bool(name) }).pipe(Config.map((flags) => flags.experimental || flags.enabled)) export class Service extends ConfigService.Service()("@opencode/RuntimeFlags", { + autoShare: bool("OPENCODE_AUTO_SHARE"), pure: bool("OPENCODE_PURE"), disableDefaultPlugins: bool("OPENCODE_DISABLE_DEFAULT_PLUGINS"), disableEmbeddedWebUi: bool("OPENCODE_DISABLE_EMBEDDED_WEB_UI"), diff --git a/packages/opencode/src/share/session.ts b/packages/opencode/src/share/session.ts index 7e4de204ed..47c944b4f4 100644 --- a/packages/opencode/src/share/session.ts +++ b/packages/opencode/src/share/session.ts @@ -3,7 +3,7 @@ import { SessionID } from "@/session/schema" import { SyncEvent } from "@/sync" import { Effect, Layer, Scope, Context } from "effect" import { Config } from "@/config/config" -import { Flag } from "@opencode-ai/core/flag/flag" +import { RuntimeFlags } from "@/effect/runtime-flags" import * as ShareNext from "./share-next" export interface Interface { @@ -22,6 +22,7 @@ export const layer = Layer.effect( const shareNext = yield* ShareNext.Service const scope = yield* Scope.Scope const sync = yield* SyncEvent.Service + const flags = yield* RuntimeFlags.Service const share = Effect.fn("SessionShare.share")(function* (sessionID: SessionID) { const conf = yield* cfg.get() @@ -40,7 +41,7 @@ export const layer = Layer.effect( const result = yield* session.create(input) if (result.parentID) return result const conf = yield* cfg.get() - if (!(Flag.OPENCODE_AUTO_SHARE || conf.share === "auto")) return result + if (!(flags.autoShare || conf.share === "auto")) return result yield* share(result.id).pipe(Effect.ignore, Effect.forkIn(scope)) return result }) @@ -54,6 +55,7 @@ export const defaultLayer = layer.pipe( Layer.provide(Session.defaultLayer), Layer.provide(Config.defaultLayer), Layer.provide(SyncEvent.defaultLayer), + Layer.provide(RuntimeFlags.defaultLayer), ) export * as SessionShare from "./session" diff --git a/packages/opencode/test/effect/runtime-flags.test.ts b/packages/opencode/test/effect/runtime-flags.test.ts index 79c33e6dbf..5167905b8e 100644 --- a/packages/opencode/test/effect/runtime-flags.test.ts +++ b/packages/opencode/test/effect/runtime-flags.test.ts @@ -9,6 +9,14 @@ const fromConfig = (input: Record) => const readFlags = RuntimeFlags.Service.useSync((flags) => flags) describe("RuntimeFlags", () => { + it.effect("defaultLayer defaults autoShare to false", () => + Effect.gen(function* () { + const flags = yield* readFlags.pipe(Effect.provide(fromConfig({}))) + + expect(flags.autoShare).toBe(false) + }), + ) + it.effect("defaultLayer parses plugin flags from the active ConfigProvider", () => Effect.gen(function* () { const flags = yield* readFlags.pipe( @@ -16,6 +24,7 @@ describe("RuntimeFlags", () => { fromConfig({ OPENCODE_PURE: "true", OPENCODE_DISABLE_DEFAULT_PLUGINS: "true", + OPENCODE_AUTO_SHARE: "true", OPENCODE_DISABLE_EMBEDDED_WEB_UI: "true", OPENCODE_EXPERIMENTAL: "true", OPENCODE_ENABLE_EXA: "true", @@ -28,6 +37,7 @@ describe("RuntimeFlags", () => { ) expect(flags.pure).toBe(true) + expect(flags.autoShare).toBe(true) expect(flags.disableDefaultPlugins).toBe(true) expect(flags.disableEmbeddedWebUi).toBe(true) expect(flags.enableExa).toBe(true) @@ -68,6 +78,7 @@ describe("RuntimeFlags", () => { ) expect(flags.pure).toBe(false) + expect(flags.autoShare).toBe(false) expect(flags.disableDefaultPlugins).toBe(true) expect(flags.disableEmbeddedWebUi).toBe(false) expect(flags.disableClaudeCodeSkills).toBe(false)