refactor(core): move v1 schemas into core (#30473)

This commit is contained in:
Dax
2026-06-02 22:42:13 -04:00
committed by GitHub
parent 0543fd29c8
commit 83452558f7
129 changed files with 1578 additions and 1227 deletions

View File

@@ -1,6 +1,6 @@
import { PermissionLegacy } from "@opencode-ai/core/permission/legacy"
import { PermissionV1 } from "@opencode-ai/core/v1/permission"
import { EOL } from "os"
import { SessionLegacy } from "@opencode-ai/core/session/legacy"
import { SessionV1 } from "@opencode-ai/core/v1/session"
import { basename } from "path"
import { Cause, Effect } from "effect"
import { Agent } from "../../../agent/agent"
@@ -150,7 +150,7 @@ const createToolContext = Effect.fn("Cli.debug.agent.createToolContext")(functio
)
})
const now = Date.now()
const message: SessionLegacy.Assistant = {
const message: SessionV1.Assistant = {
id: messageID,
sessionID: session.id,
role: "assistant",
@@ -179,12 +179,12 @@ const createToolContext = Effect.fn("Cli.debug.agent.createToolContext")(functio
abort: new AbortController().signal,
messages: [],
metadata: () => Effect.void,
ask(req: Omit<PermissionLegacy.Request, "id" | "sessionID" | "tool">) {
ask(req: Omit<PermissionV1.Request, "id" | "sessionID" | "tool">) {
return Effect.sync(() => {
for (const pattern of req.patterns) {
const rule = Permission.evaluate(req.permission, pattern, ruleset)
if (rule.action === "deny") {
throw new PermissionLegacy.DeniedError({ ruleset })
throw new PermissionV1.DeniedError({ ruleset })
}
}
})

View File

@@ -1,5 +1,5 @@
import { Session } from "@/session/session"
import { SessionLegacy } from "@opencode-ai/core/session/legacy"
import { SessionV1 } from "@opencode-ai/core/v1/session"
import { MessageV2 } from "../../session/message-v2"
import { SessionID } from "../../session/schema"
import { effectCmd, fail } from "../effect-cmd"
@@ -32,7 +32,7 @@ function diff(kind: string, diffs: { file?: string; patch?: string }[] | undefin
}))
}
function source(part: SessionLegacy.FilePart) {
function source(part: SessionV1.FilePart) {
if (!part.source) return part.source
if (part.source.type === "symbol") {
return {
@@ -57,7 +57,7 @@ function source(part: SessionLegacy.FilePart) {
}
}
function filepart(part: SessionLegacy.FilePart): SessionLegacy.FilePart {
function filepart(part: SessionV1.FilePart): SessionV1.FilePart {
return {
...part,
url: redact("file-url", part.id, part.url),
@@ -66,7 +66,7 @@ function filepart(part: SessionLegacy.FilePart): SessionLegacy.FilePart {
}
}
function part(part: SessionLegacy.Part): SessionLegacy.Part {
function part(part: SessionV1.Part): SessionV1.Part {
switch (part.type) {
case "text":
return {
@@ -160,7 +160,7 @@ function part(part: SessionLegacy.Part): SessionLegacy.Part {
const partFn = part
function sanitize(data: { info: Session.Info; messages: SessionLegacy.WithParts[] }) {
function sanitize(data: { info: Session.Info; messages: SessionV1.WithParts[] }) {
return {
info: {
...data.info,

View File

@@ -1,4 +1,4 @@
import type { SessionLegacy } from "@opencode-ai/core/session/legacy"
import type { SessionV1 } from "@opencode-ai/core/v1/session"
export { parseGitHubRemote } from "@/util/repository"
@@ -7,7 +7,7 @@ export { parseGitHubRemote } from "@/util/repository"
* Returns null for non-text responses (signals summary needed).
* Throws only for truly empty responses.
*/
export function extractResponseText(parts: SessionLegacy.Part[]): string | null {
export function extractResponseText(parts: SessionV1.Part[]): string | null {
const textPart = parts.findLast((p) => p.type === "text")
if (textPart) return textPart.text

View File

@@ -1,5 +1,5 @@
import type { Session as SDKSession, Message, Part } from "@opencode-ai/sdk/v2"
import { SessionLegacy } from "@opencode-ai/core/session/legacy"
import { SessionV1 } from "@opencode-ai/core/v1/session"
import { Session } from "@/session/session"
import { MessageV2 } from "../../session/message-v2"
import { CliError, effectCmd } from "../effect-cmd"
@@ -13,8 +13,8 @@ import { FSUtil } from "@opencode-ai/core/fs-util"
import { Effect, Schema } from "effect"
import type { InstanceContext } from "@/project/instance-context"
const decodeMessageInfo = Schema.decodeUnknownSync(SessionLegacy.Info)
const decodePart = Schema.decodeUnknownSync(SessionLegacy.Part)
const decodeMessageInfo = Schema.decodeUnknownSync(SessionV1.Info)
const decodePart = Schema.decodeUnknownSync(SessionV1.Part)
/** Discriminated union returned by the ShareNext API (GET /api/shares/:id/data) */
export type ShareData =
@@ -188,7 +188,7 @@ const runImport = Effect.fn("Cli.import.body")(function* (file: string, ctx: Ins
.pipe(Effect.orDie)
for (const msg of exportData.messages) {
const msgInfo = decodeMessageInfo(msg.info) as SessionLegacy.Info
const msgInfo = decodeMessageInfo(msg.info) as SessionV1.Info
const { id, sessionID: _, ...msgData } = msgInfo
yield* db
.insert(MessageTable)
@@ -203,7 +203,7 @@ const runImport = Effect.fn("Cli.import.body")(function* (file: string, ctx: Ins
.pipe(Effect.orDie)
for (const part of msg.parts) {
const partInfo = decodePart(part) as SessionLegacy.Part
const partInfo = decodePart(part) as SessionV1.Part
const { id: partId, sessionID: _s, messageID, ...partData } = partInfo
yield* db
.insert(PartTable)

View File

@@ -1,4 +1,5 @@
import { cmd } from "./cmd"
import { ConfigV1 } from "@opencode-ai/core/v1/config/config"
import { effectCmd } from "../effect-cmd"
import { Cause } from "effect"
import { Client } from "@modelcontextprotocol/sdk/client/index.js"
@@ -10,7 +11,7 @@ import { MCP } from "../../mcp"
import { McpAuth } from "../../mcp/auth"
import { McpOAuthProvider } from "../../mcp/oauth-provider"
import { Config } from "@/config/config"
import { ConfigMCP } from "../../config/mcp"
import { ConfigMCPV1 } from "@opencode-ai/core/v1/config/mcp"
import { InstanceRef } from "@/effect/instance-ref"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import path from "path"
@@ -43,9 +44,9 @@ function getAuthStatusText(status: MCP.AuthStatus): string {
}
}
type McpEntry = NonNullable<Config.Info["mcp"]>[string]
type McpEntry = NonNullable<ConfigV1.Info["mcp"]>[string]
type McpConfigured = ConfigMCP.Info
type McpConfigured = ConfigMCPV1.Info
function isMcpConfigured(config: McpEntry): config is McpConfigured {
return typeof config === "object" && config !== null && "type" in config
}
@@ -55,11 +56,11 @@ function isMcpRemote(config: McpEntry): config is McpRemote {
return isMcpConfigured(config) && config.type === "remote"
}
function configuredServers(config: Config.Info) {
function configuredServers(config: ConfigV1.Info) {
return Object.entries(config.mcp ?? {}).filter((entry): entry is [string, McpConfigured] => isMcpConfigured(entry[1]))
}
function oauthServers(config: Config.Info) {
function oauthServers(config: ConfigV1.Info) {
return configuredServers(config).filter(
(entry): entry is [string, McpRemote] => isMcpRemote(entry[1]) && entry[1].oauth !== false,
)
@@ -418,7 +419,7 @@ async function resolveConfigPath(baseDir: string, global = false) {
return candidates[0]
}
async function addMcpToConfig(name: string, mcpConfig: ConfigMCP.Info, configPath: string) {
async function addMcpToConfig(name: string, mcpConfig: ConfigMCPV1.Info, configPath: string) {
let text = "{}"
if (await Filesystem.exists(configPath)) {
text = await Filesystem.readText(configPath)
@@ -507,7 +508,7 @@ export const McpAddCommand = effectCmd({
})
if (prompts.isCancel(command)) throw new UI.CancelledError()
const mcpConfig: ConfigMCP.Info = {
const mcpConfig: ConfigMCPV1.Info = {
type: "local",
command: command.split(" "),
}
@@ -537,7 +538,7 @@ export const McpAddCommand = effectCmd({
})
if (prompts.isCancel(useOAuth)) throw new UI.CancelledError()
let mcpConfig: ConfigMCP.Info
let mcpConfig: ConfigMCPV1.Info
if (useOAuth) {
const hasClientId = await prompts.confirm({

View File

@@ -1,4 +1,4 @@
import type { PermissionLegacy } from "@opencode-ai/core/permission/legacy"
import type { PermissionV1 } from "@opencode-ai/core/v1/permission"
// CLI entry point for `opencode run`.
//
// Handles three modes:
@@ -362,7 +362,7 @@ export const RunCommand = effectCmd({
process.exit(1)
}
const rules: PermissionLegacy.Ruleset = args.interactive
const rules: PermissionV1.Ruleset = args.interactive
? []
: [
{

View File

@@ -1,4 +1,4 @@
import { ConfigPlugin } from "@/config/plugin"
import { ConfigPluginV1 } from "@opencode-ai/core/v1/config/plugin"
import { TuiKeybind } from "./keybind"
import { Schema } from "effect"
import { isRecord } from "@/util/record"
@@ -74,7 +74,7 @@ export const TuiInfo = Schema.Struct({
$schema: Schema.optional(Schema.String),
theme: Schema.optional(Schema.String),
keybinds: Schema.optional(TuiKeybind.KeybindOverrides),
plugin: Schema.optional(Schema.Array(ConfigPlugin.Spec)),
plugin: Schema.optional(Schema.Array(ConfigPluginV1.Spec)),
plugin_enabled: Schema.optional(Schema.Record(Schema.String, Schema.Boolean)),
leader_timeout: Schema.optional(KeymapLeaderTimeout),
attention: Schema.optional(Attention),

View File

@@ -29,7 +29,7 @@ import { useExit } from "./exit"
import { useArgs } from "./args"
import { batch, onMount } from "solid-js"
import * as Log from "@opencode-ai/core/util/log"
import { emptyConsoleState, type ConsoleState } from "@/config/console-state"
import { emptyConsoleState, type ConsoleState } from "@opencode-ai/core/v1/config/console-state"
import path from "path"
import { useKV } from "./kv"
import { aggregateFailures } from "./aggregate-failures"

View File

@@ -39,6 +39,7 @@ import { internalTuiPlugins, type InternalTuiPlugin } from "./internal"
import { setupSlots, Slot as View } from "./slots"
import type { HostPluginApi, HostSlots } from "./slots"
import { ConfigPlugin } from "@/config/plugin"
import { ConfigPluginV1 } from "@opencode-ai/core/v1/config/plugin"
import { createCommandShim } from "./command-shim"
import { RuntimeFlags } from "@/effect/runtime-flags"
import { Effect } from "effect"
@@ -46,7 +47,7 @@ import { Effect } from "effect"
ensureRuntimePluginSupport({ additional: keymapRuntimeModules })
type PluginLoad = {
options: ConfigPlugin.Options | undefined
options: ConfigPluginV1.Options | undefined
spec: string
target: string
retry: boolean
@@ -995,7 +996,7 @@ async function installPluginBySpec(
const tui = manifest.targets.find((item) => item.kind === "tui")
if (tui) {
const file = patch.items.find((item) => item.kind === "tui")?.file
const next = tui.opts ? ([spec, tui.opts] as ConfigPlugin.Spec) : spec
const next = tui.opts ? ([spec, tui.opts] as ConfigPluginV1.Spec) : spec
state.pending.set(spec, {
spec: next,
scope: global ? "global" : "local",

View File

@@ -1,4 +1,5 @@
import type { Argv, InferredOptionTypes } from "yargs"
import { ConfigV1 } from "@opencode-ai/core/v1/config/config"
import type { Config } from "@/config/config"
import { Effect } from "effect"
@@ -42,7 +43,7 @@ export const resolveNetworkOptions = Effect.fn("Cli.resolveNetworkOptions")(func
return resolveNetworkOptionsNoConfig(args, config)
})
export function resolveNetworkOptionsNoConfig(args: NetworkOptions, config?: Config.Info) {
export function resolveNetworkOptionsNoConfig(args: NetworkOptions, config?: ConfigV1.Info) {
const portExplicitlySet = process.argv.includes("--port")
const hostnameExplicitlySet = process.argv.includes("--hostname")
const mdnsExplicitlySet = process.argv.includes("--mdns")