49f20b6a30
Add an experimental, off-by-default `execute` tool that runs LLM-authored JavaScript with a `tools.<name>(args)` proxy over connected MCP tools. When OPENCODE_EXPERIMENTAL_CODE_MODE is enabled and MCP tools are present, the session exposes the single code-mode tool instead of registering each MCP tool directly; child calls route through the native permission path. Code mode is defined via the standard Tool.define/Tool.init machinery so it inherits arg decoding and output truncation from the shared wrapper. Tool results are reduced to structured content or text, and the program's return value is coerced to text without failing on shape. Note: execution currently uses an in-process AsyncFunction with no isolation or timeout; sandboxing is tracked as follow-up work.
81 lines
3.9 KiB
TypeScript
81 lines
3.9 KiB
TypeScript
import { Config, ConfigProvider, Context, Effect, Layer, Option } from "effect"
|
|
import { ConfigService } from "@/effect/config-service"
|
|
|
|
const bool = (name: string) => Config.boolean(name).pipe(Config.withDefault(false))
|
|
const positiveInteger = (name: string) =>
|
|
Config.number(name).pipe(
|
|
Config.map((value) => (Number.isInteger(value) && value > 0 ? value : undefined)),
|
|
Config.orElse(() => Config.succeed(undefined)),
|
|
)
|
|
const experimental = bool("OPENCODE_EXPERIMENTAL")
|
|
const enabledByExperimental = (name: string) =>
|
|
Config.all({ experimental, enabled: Config.boolean(name).pipe(Config.option) }).pipe(
|
|
Config.map((flags) => Option.getOrElse(flags.enabled, () => flags.experimental)),
|
|
)
|
|
|
|
export class Service extends ConfigService.Service<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"),
|
|
disableExternalSkills: bool("OPENCODE_DISABLE_EXTERNAL_SKILLS"),
|
|
disableLspDownload: bool("OPENCODE_DISABLE_LSP_DOWNLOAD"),
|
|
disableClaudeCodePrompt: Config.all({
|
|
broad: bool("OPENCODE_DISABLE_CLAUDE_CODE"),
|
|
direct: bool("OPENCODE_DISABLE_CLAUDE_CODE_PROMPT"),
|
|
}).pipe(Config.map((flags) => flags.broad || flags.direct)),
|
|
disableClaudeCodeSkills: Config.all({
|
|
broad: bool("OPENCODE_DISABLE_CLAUDE_CODE"),
|
|
direct: bool("OPENCODE_DISABLE_CLAUDE_CODE_SKILLS"),
|
|
}).pipe(Config.map((flags) => flags.broad || flags.direct)),
|
|
enableExa: Config.all({
|
|
experimental,
|
|
enabled: bool("OPENCODE_ENABLE_EXA"),
|
|
legacy: bool("OPENCODE_EXPERIMENTAL_EXA"),
|
|
}).pipe(Config.map((flags) => flags.experimental || flags.enabled || flags.legacy)),
|
|
enableParallel: Config.all({
|
|
enabled: bool("OPENCODE_ENABLE_PARALLEL"),
|
|
legacy: bool("OPENCODE_EXPERIMENTAL_PARALLEL"),
|
|
}).pipe(Config.map((flags) => flags.enabled || flags.legacy)),
|
|
enableExperimentalModels: bool("OPENCODE_ENABLE_EXPERIMENTAL_MODELS"),
|
|
enableQuestionTool: bool("OPENCODE_ENABLE_QUESTION_TOOL"),
|
|
experimentalReferences: enabledByExperimental("OPENCODE_EXPERIMENTAL_REFERENCES"),
|
|
experimentalBackgroundSubagents: enabledByExperimental("OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS"),
|
|
experimentalLspTy: bool("OPENCODE_EXPERIMENTAL_LSP_TY"),
|
|
experimentalLspTool: enabledByExperimental("OPENCODE_EXPERIMENTAL_LSP_TOOL"),
|
|
experimentalCodeMode: enabledByExperimental("OPENCODE_EXPERIMENTAL_CODE_MODE"),
|
|
experimentalOxfmt: enabledByExperimental("OPENCODE_EXPERIMENTAL_OXFMT"),
|
|
experimentalPlanMode: enabledByExperimental("OPENCODE_EXPERIMENTAL_PLAN_MODE"),
|
|
experimentalEventSystem: enabledByExperimental("OPENCODE_EXPERIMENTAL_EVENT_SYSTEM"),
|
|
experimentalWorkspaces: enabledByExperimental("OPENCODE_EXPERIMENTAL_WORKSPACES"),
|
|
experimentalIconDiscovery: enabledByExperimental("OPENCODE_EXPERIMENTAL_ICON_DISCOVERY"),
|
|
outputTokenMax: positiveInteger("OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX"),
|
|
bashDefaultTimeoutMs: positiveInteger("OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS"),
|
|
experimentalNativeLlm: bool("OPENCODE_EXPERIMENTAL_NATIVE_LLM"),
|
|
experimentalWebSockets: bool("OPENCODE_EXPERIMENTAL_WEBSOCKETS"),
|
|
client: Config.string("OPENCODE_CLIENT").pipe(Config.withDefault("cli")),
|
|
}) {}
|
|
|
|
export type Info = Context.Service.Shape<typeof Service>
|
|
|
|
const emptyConfigLayer = Service.defaultLayer.pipe(
|
|
Layer.provide(ConfigProvider.layer(ConfigProvider.fromUnknown({}))),
|
|
Layer.orDie,
|
|
)
|
|
|
|
export const layer = (overrides: Partial<Info> = {}) =>
|
|
Layer.effect(
|
|
Service,
|
|
Effect.gen(function* () {
|
|
const flags = yield* Service
|
|
return Service.of({ ...flags, ...overrides })
|
|
}),
|
|
).pipe(Layer.provide(emptyConfigLayer))
|
|
|
|
export const defaultLayer = Service.defaultLayer.pipe(Layer.orDie)
|
|
|
|
export const node = LayerNode.make({ service: Service, layer: defaultLayer, deps: [] })
|
|
|
|
export * as RuntimeFlags from "./runtime-flags"
|
|
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|