Dashboard › opencode › Distillation
0bea79df-485d-4a57-bea3-dd65b327b1ce["lore_tm_v1_kslYxP0oBBP6UiyQiVzkuXa-nWjBFuNrs02-cQCnF0o","lore_tm_v1_Rs38DfF41SzrVk9NiYJKgny04dDCyZUs6CZFk5N4LuY","lore_tm_v1_mtTWGCz10DFhhH0dOa6cmTzLBxZS3kreCV92es2S0Cc"]
bun typecheck from package directories such as packages/core; never run tsc directly.sdk composes Client, Core, and Server.import { foo as bar } from "..." or resolve as pathResolve. An aliased type import such as import type { Plugin as PluginDefinition } from "..." is permitted only as a last resort for a genuine name collision and remains strongly discouraged.import("...") references such as Schema.declare<import("@opencode/plugin/effect/plugin").Plugin["effect"]>.import * as Foo from "..." and import type * as Foo from "..."; namespace-style use should import the moduleβs exported namespace by name, such as import { Project } from "@opencode/core/project" followed by Project.ID.await import("./module").then((mod) => mod.value()) or (await import("./module")).value() should be avoided.bun run generate from packages/client after changing the public Protocol or Server HttpApi; generated client files must not be edited directly.v2; new branches and worktrees should default to v2, or origin/v2 if local v2 is unavailable, pull requests should target v2, and diffs should use v2/origin/v2 because local main may not exist..changeset files must not be added./home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/permission.ts (35 lines). It defines PermissionEvaluation, PermissionHooks, and PermissionAssertInput; PermissionDomain is Pick<PermissionApi, "list" | "get" | "reply"> plus assert: (input: PermissionAssertInput) => Promise<void> and hook: Hooks<PermissionHooks>.PermissionEvaluation contains sessionID: Session.ID, optional agent: Agent.ID, action: string, resources: ReadonlyArray<string>, optional metadata: Record<string, unknown>, optional source: Permission.Source, mutable effect: Permission.Effect, and optional mutable message: string. PermissionAssertInput adds optional save: ReadonlyArray<string> and otherwise carries the same request identity/action/resource metadata./home/byk/Code/opencode-v2-pilot/packages/plugin/src/effect/permission.ts (36 lines). It mirrors the Promise permission structures, but PermissionDomain is Pick<PermissionApi<unknown>, "list" | "get" | "reply"> plus assert: (input: PermissionAssertInput) => Effect.Effect<void, unknown> and hook: Hooks<PermissionHooks>./home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/adapter.ts (639 lines), which implements fromPromise(plugin: Plugin) to adapt Promise plugins into the existing Effect-only Core plugin runtime./home/byk/Code/opencode-v2-pilot/packages/plugin/src/promise/adapter.ts defines HostRegistration, Registration, PromiseContext, PromiseEvent, HostRpc, StreamAdapter, CompiledEndpoint, HostRpcCallContext, TypedFailure, ReturnedRpcError, and RuntimeSchema; compiled HTTP endpoints are cached in const compiledEndpoints = new WeakMap<object, CompiledEndpoint>().makeStreams() converts Stream.Stream<A, E> to AsyncIterable<A> using Stream.toAsyncIterableWith(stream, context). It tracks iterator close functions in a Set, closes every subscription through an Effect scope finalizer, supports optional AbortSignal, removes abort listeners on close, and closes iterators after completion or failure.rpcFromEffect(host, streams) adapts portable RPC clients and registrations. Client methods invoke local Effect methods via Effect.runPromiseWith(context) and pass optional abort signals; event APIs expose subscribe and on, with on combining signals through AbortSignal.any and returning an abort callback.Effect.tryPromise; ReturnedRpcError(type, message, data?) carries typed errors, hostRpcError() converts it through context.error(...), and non-ReturnedRpcError values pass through unchanged. Registration returns Promise-facing dispose() and events.emit(...).compileEndpoint(endpoint: HttpApiEndpoint.Top) rejects more than one payload or success schema with Unsupported API schema cardinality: ${endpoint.identifier}. It decodes params, type-converted query, headers, and payload; defaults success to HttpApiSchema.NoContent; unwraps a sole object property named data; and stores decode functions, an output encoder, and noContent in compiledEndpoints.fromPromise() dynamically imports ClientApi from @opencode/protocol/client and OpenCodeEvent from @opencode/protocol/groups/event through one Promise.all, then extracts endpoint groups for agent, command, experimental, generate, integration, mcp, model, plugin, permission, provider, reference, session, skill, vcs, websearch, and worktree.fromPromise() captures the plugin Effect scope and defines: register() to attach registrations to that scope and expose Promise disposal; run() using Effect.runPromiseWith(context); promiseExecutor() to bridge tool execution and progress; adaptApiMethod() to decode API input, invoke an Effect method, handle no-content output, and encode results; and transform() to adapt editor callbacks.app, location, options, agent, aisdk, catalog, command, event, experimental.terminal, generate, integration, mcp, permission, plugin, reference, rpc, skill, storage, tool, vcs, websearch, worktree, session, and shell.get/list; catalog provider list/get and model list/default; command list; experimental terminal read; generate text; integration list, get, key connect, OAuth connect/status/complete/cancel, and command connect/status/cancel; MCP list; permission list/get/reply; plugin list; reference list; skill list; VCS get/base/branches/status/diff; websearch providers/query; worktree list/create/remove/refresh; and session create/get/switchAgent/switchModel/prompt/generate/command/synthetic/interrupt/rename/move/wait/context.Schema.encodeUnknownEffect(OpenCodeEvent) before exposing it as PromiseEvent. Hook adapters for aisdk, permission, tool, session, and shell wrap callbacks with Effect.promise(() => Promise.resolve(callback(event))).host.permission.assert(input) and converts its typed Effect failure into a defect via Effect.die(new TypedFailure(error)), allowing tool execution to recognize the wrapped permission failure later.authorize results: "auto" authorization callbacks take no code, non-auto callbacks take code, and optional credential refresh is wrapped with Effect.promise.namespace, adapts added tools through executePromiseTool(), and on update reconstructs a Promise-facing Info, invokes the update callback, then writes back output, options, and an Effect execution wrapper.id, name, info, optional bound base, branches, status, and diff; each asynchronous operation is converted by attempt((signal) => ...). Websearch transform similarly adapts provider execute, and worktree transform adapts create, remove, and list.fromPromise() installs plugin setup using Effect.acquireRelease: acquisition resolves plugin.setup(context2), and release invokes the returned cleanup function if present, preserving scope-bound cleanup on plugin unload.attempt<A>() uses Effect.tryPromise({ try: evaluate, catch: (cause) => cause }). executePromiseTool() bridges progress with Effect.runPromise(context.progress(update)); a caught TypedFailure becomes new Tool.Error({ message, error }), deriving message in order from string feedback, Error.message, or String(error.error), while other failures become defects via Effect.die(error).