mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-15 00:52:35 +00:00
Drop unused opencode Zod statics (#26935)
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import path from "path"
|
||||
import { Effect, Layer, Record, Result, Schema, Context } from "effect"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { NonNegativeInt } from "@opencode-ai/core/schema"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { AppFileSystem } from "@opencode-ai/core/filesystem"
|
||||
@@ -32,9 +31,8 @@ export class WellKnown extends Schema.Class<WellKnown>("WellKnownAuth")({
|
||||
token: Schema.String,
|
||||
}) {}
|
||||
|
||||
const _Info = Schema.Union([Oauth, Api, WellKnown]).annotate({ discriminator: "type", identifier: "Auth" })
|
||||
export const Info = Object.assign(_Info, { zod: zod(_Info) })
|
||||
export type Info = Schema.Schema.Type<typeof _Info>
|
||||
export const Info = Schema.Union([Oauth, Api, WellKnown]).annotate({ discriminator: "type", identifier: "Auth" })
|
||||
export type Info = Schema.Schema.Type<typeof Info>
|
||||
|
||||
export class AuthError extends Schema.TaggedErrorClass<AuthError>()("AuthError", {
|
||||
message: Schema.String,
|
||||
|
||||
@@ -5,6 +5,7 @@ import { createBindingLookup } from "@opentui/keymap/extras"
|
||||
import { mergeDeep, unique } from "remeda"
|
||||
import { Context, Effect, Fiber, Layer } from "effect"
|
||||
import { ConfigParse } from "@/config/parse"
|
||||
import { InvalidError } from "@/config/error"
|
||||
import * as ConfigPaths from "@/config/paths"
|
||||
import { migrateTuiConfig } from "./tui-migrate"
|
||||
import { KeymapLeaderTimeoutDefault, TuiInfo, TuiJsonSchemaInfo } from "./tui-schema"
|
||||
@@ -91,10 +92,12 @@ const loadState = Effect.fn("TuiConfig.loadState")(function* (ctx: { directory:
|
||||
if (!isRecord(data)) return {} as Info
|
||||
// Flatten a nested "tui" key so users who wrote `{ "tui": { ... } }` inside tui.json
|
||||
// (mirroring the old opencode.json shape) still get their settings applied.
|
||||
const validated = ConfigParse.schema(Info, normalize(data), configFilepath)
|
||||
const parsed = Info.safeParse(normalize(data))
|
||||
if (!parsed.success) throw new InvalidError({ path: configFilepath, issues: parsed.error.issues })
|
||||
const validated = parsed.data
|
||||
return yield* resolvePlugins(validated, configFilepath)
|
||||
}).pipe(
|
||||
// catchCause (not tapErrorCause + orElseSucceed) because ConfigParse.jsonc/.schema
|
||||
// catchCause (not tapErrorCause + orElseSucceed) because JSONC parsing and validation
|
||||
// can sync-throw — those become defects, which orElseSucceed wouldn't catch.
|
||||
Effect.catchCause((cause) =>
|
||||
Effect.sync(() => {
|
||||
|
||||
@@ -5,8 +5,7 @@ import type { InstanceContext } from "@/project/instance"
|
||||
import { SessionID, MessageID } from "@/session/schema"
|
||||
import { Effect, Layer, Context, Schema } from "effect"
|
||||
import z from "zod"
|
||||
import { zod, ZodOverride } from "@opencode-ai/core/effect-zod"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
import { ZodOverride } from "@opencode-ai/core/effect-zod"
|
||||
import { Config } from "@/config/config"
|
||||
import { MCP } from "../mcp"
|
||||
import { Skill } from "../skill"
|
||||
@@ -39,9 +38,7 @@ export const Info = Schema.Struct({
|
||||
template: Schema.Unknown.annotate({ [ZodOverride]: z.promise(z.string()).or(z.string()) }),
|
||||
subtask: Schema.optional(Schema.Boolean),
|
||||
hints: Schema.Array(Schema.String),
|
||||
})
|
||||
.annotate({ identifier: "Command" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "Command" })
|
||||
|
||||
// for some reason zod is inferring `string` for z.promise(z.string()).or(z.string()) so we have to manually override it
|
||||
export type Info = Omit<Schema.Schema.Type<typeof Info>, "template"> & { template: Promise<string> | string }
|
||||
|
||||
@@ -2,8 +2,7 @@ export * as ConfigAgent from "./agent"
|
||||
|
||||
import { Exit, Schema, SchemaGetter } from "effect"
|
||||
import { Bus } from "@/bus"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { PositiveInt, withStatics } from "@opencode-ai/core/schema"
|
||||
import { PositiveInt } from "@opencode-ai/core/schema"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { NamedError } from "@opencode-ai/core/util/error"
|
||||
import { Glob } from "@opencode-ai/core/util/glob"
|
||||
@@ -102,9 +101,7 @@ export const Info = AgentSchema.pipe(
|
||||
decode: SchemaGetter.transform(normalize),
|
||||
encode: SchemaGetter.passthrough({ strict: false }),
|
||||
}),
|
||||
)
|
||||
.annotate({ identifier: "AgentConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
).annotate({ identifier: "AgentConfig" })
|
||||
export type Info = Schema.Schema.Type<typeof Info>
|
||||
|
||||
export async function load(dir: string) {
|
||||
@@ -134,7 +131,7 @@ export async function load(dir: string) {
|
||||
...md.data,
|
||||
prompt: md.content.trim(),
|
||||
}
|
||||
result[config.name] = ConfigParse.effectSchema(Info, config, item)
|
||||
result[config.name] = ConfigParse.schema(Info, config, item)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
export * as ConfigAttachment from "./attachment"
|
||||
|
||||
import { Schema } from "effect"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { PositiveInt, withStatics } from "@opencode-ai/core/schema"
|
||||
import { PositiveInt } from "@opencode-ai/core/schema"
|
||||
|
||||
export const Image = Schema.Struct({
|
||||
auto_resize: Schema.optional(Schema.Boolean).annotate({
|
||||
@@ -17,14 +16,10 @@ export const Image = Schema.Struct({
|
||||
max_base64_bytes: Schema.optional(PositiveInt).annotate({
|
||||
description: "Maximum base64 payload bytes for an image attachment (default: 4718592)",
|
||||
}),
|
||||
})
|
||||
.annotate({ identifier: "ImageAttachmentConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ImageAttachmentConfig" })
|
||||
export type Image = Schema.Schema.Type<typeof Image>
|
||||
|
||||
export const Info = Schema.Struct({
|
||||
image: Schema.optional(Image).annotate({ description: "Image attachment configuration" }),
|
||||
})
|
||||
.annotate({ identifier: "AttachmentConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "AttachmentConfig" })
|
||||
export type Info = Schema.Schema.Type<typeof Info>
|
||||
|
||||
@@ -388,7 +388,7 @@ export const layer = Layer.effect(
|
||||
),
|
||||
)
|
||||
const parsed = ConfigParse.jsonc(expanded, source)
|
||||
const data = ConfigParse.effectSchema(Info, normalizeLoadedConfig(parsed, source), source)
|
||||
const data = ConfigParse.schema(Info, normalizeLoadedConfig(parsed, source), source)
|
||||
if (!("path" in options)) return data
|
||||
|
||||
yield* Effect.promise(() => resolveLoadedPlugins(data, options.path))
|
||||
@@ -786,7 +786,7 @@ export const layer = Layer.effect(
|
||||
let next: Info
|
||||
let changed: boolean
|
||||
if (!file.endsWith(".jsonc")) {
|
||||
const existing = ConfigParse.effectSchema(Info, ConfigParse.jsonc(before, file), file)
|
||||
const existing = ConfigParse.schema(Info, ConfigParse.jsonc(before, file), file)
|
||||
const merged = mergeDeep(writable(existing), patch)
|
||||
const serialized = JSON.stringify(merged, null, 2)
|
||||
changed = serialized !== before
|
||||
@@ -794,7 +794,7 @@ export const layer = Layer.effect(
|
||||
next = merged
|
||||
} else {
|
||||
const updated = patchJsonc(before, patch)
|
||||
next = ConfigParse.effectSchema(Info, ConfigParse.jsonc(updated, file), file)
|
||||
next = ConfigParse.schema(Info, ConfigParse.jsonc(updated, file), file)
|
||||
changed = updated !== before
|
||||
if (changed) yield* fs.writeFileString(file, updated).pipe(Effect.orDie)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import { Schema } from "effect"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { NonNegativeInt } from "@opencode-ai/core/schema"
|
||||
|
||||
export class ConsoleState extends Schema.Class<ConsoleState>("ConsoleState")({
|
||||
consoleManagedProviders: Schema.mutable(Schema.Array(Schema.String)),
|
||||
activeOrgName: Schema.optional(Schema.String),
|
||||
switchableOrgCount: NonNegativeInt,
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
}) {}
|
||||
|
||||
export const emptyConsoleState: ConsoleState = ConsoleState.make({
|
||||
consoleManagedProviders: [],
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
export * as ConfigFormatter from "./formatter"
|
||||
|
||||
import { Schema } from "effect"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
|
||||
export const Entry = Schema.Struct({
|
||||
disabled: Schema.optional(Schema.Boolean),
|
||||
command: Schema.optional(Schema.mutable(Schema.Array(Schema.String))),
|
||||
environment: Schema.optional(Schema.Record(Schema.String, Schema.String)),
|
||||
extensions: Schema.optional(Schema.mutable(Schema.Array(Schema.String))),
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
})
|
||||
|
||||
export const Info = Schema.Union([Schema.Boolean, Schema.Record(Schema.String, Entry)]).pipe(
|
||||
withStatics((s) => ({ zod: zod(s) })),
|
||||
)
|
||||
export const Info = Schema.Union([Schema.Boolean, Schema.Record(Schema.String, Entry)])
|
||||
export type Info = Schema.Schema.Type<typeof Info>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { Schema } from "effect"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
|
||||
export const Layout = Schema.Literals(["auto", "stretch"])
|
||||
.annotate({ identifier: "LayoutConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Layout = Schema.Literals(["auto", "stretch"]).annotate({ identifier: "LayoutConfig" })
|
||||
export type Layout = Schema.Schema.Type<typeof Layout>
|
||||
|
||||
export * as ConfigLayout from "./layout"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Schema } from "effect"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { PositiveInt, withStatics } from "@opencode-ai/core/schema"
|
||||
import { PositiveInt } from "@opencode-ai/core/schema"
|
||||
|
||||
export const Local = Schema.Struct({
|
||||
type: Schema.Literal("local").annotate({ description: "Type of MCP server connection" }),
|
||||
@@ -16,9 +15,7 @@ export const Local = Schema.Struct({
|
||||
timeout: Schema.optional(PositiveInt).annotate({
|
||||
description: "Timeout in ms for MCP server requests. Defaults to 5000 (5 seconds) if not specified.",
|
||||
}),
|
||||
})
|
||||
.annotate({ identifier: "McpLocalConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "McpLocalConfig" })
|
||||
export type Local = Schema.Schema.Type<typeof Local>
|
||||
|
||||
export const OAuth = Schema.Struct({
|
||||
@@ -32,9 +29,7 @@ export const OAuth = Schema.Struct({
|
||||
redirectUri: Schema.optional(Schema.String).annotate({
|
||||
description: "OAuth redirect URI (default: http://127.0.0.1:19876/mcp/oauth/callback).",
|
||||
}),
|
||||
})
|
||||
.annotate({ identifier: "McpOAuthConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "McpOAuthConfig" })
|
||||
export type OAuth = Schema.Schema.Type<typeof OAuth>
|
||||
|
||||
export const Remote = Schema.Struct({
|
||||
@@ -52,14 +47,10 @@ export const Remote = Schema.Struct({
|
||||
timeout: Schema.optional(PositiveInt).annotate({
|
||||
description: "Timeout in ms for MCP server requests. Defaults to 5000 (5 seconds) if not specified.",
|
||||
}),
|
||||
})
|
||||
.annotate({ identifier: "McpRemoteConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "McpRemoteConfig" })
|
||||
export type Remote = Schema.Schema.Type<typeof Remote>
|
||||
|
||||
export const Info = Schema.Union([Local, Remote])
|
||||
.annotate({ discriminator: "type" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Info = Schema.Union([Local, Remote]).annotate({ discriminator: "type" })
|
||||
export type Info = Schema.Schema.Type<typeof Info>
|
||||
|
||||
export * as ConfigMCP from "./mcp"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Schema } from "effect"
|
||||
import z from "zod"
|
||||
import { zod, ZodOverride } from "@opencode-ai/core/effect-zod"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
import { ZodOverride } from "@opencode-ai/core/effect-zod"
|
||||
|
||||
// The original Zod schema carried an external $ref pointing at the models.dev
|
||||
// JSON schema. That external reference is not a named SDK component — it is a
|
||||
@@ -9,6 +8,6 @@ import { withStatics } from "@opencode-ai/core/schema"
|
||||
// from AST metadata. Preserve the exact original Zod via ZodOverride.
|
||||
export const ConfigModelID = Schema.String.annotate({
|
||||
[ZodOverride]: z.string().meta({ $ref: "https://models.dev/model-schema.json#/$defs/Model" }),
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
})
|
||||
|
||||
export type ConfigModelID = Schema.Schema.Type<typeof ConfigModelID>
|
||||
|
||||
@@ -2,12 +2,10 @@ export * as ConfigParse from "./parse"
|
||||
|
||||
import { type ParseError as JsoncParseError, parse as parseJsoncImpl, printParseErrorCode } from "jsonc-parser"
|
||||
import { Cause, Exit, Schema as EffectSchema, SchemaIssue } from "effect"
|
||||
import z from "zod"
|
||||
import type z from "zod"
|
||||
import type { DeepMutable } from "@opencode-ai/core/schema"
|
||||
import { InvalidError, JsonError } from "./error"
|
||||
|
||||
type ZodSchema<T> = z.ZodType<T>
|
||||
|
||||
export function jsonc(text: string, filepath: string): unknown {
|
||||
const errors: JsoncParseError[] = []
|
||||
const data = parseJsoncImpl(text, errors, { allowTrailingComma: true })
|
||||
@@ -35,17 +33,7 @@ export function jsonc(text: string, filepath: string): unknown {
|
||||
return data
|
||||
}
|
||||
|
||||
export function schema<T>(schema: ZodSchema<T>, data: unknown, source: string): T {
|
||||
const parsed = schema.safeParse(data)
|
||||
if (parsed.success) return parsed.data
|
||||
|
||||
throw new InvalidError({
|
||||
path: source,
|
||||
issues: parsed.error.issues,
|
||||
})
|
||||
}
|
||||
|
||||
export function effectSchema<S extends EffectSchema.Decoder<unknown, never>>(
|
||||
export function schema<S extends EffectSchema.Decoder<unknown, never>>(
|
||||
schema: S,
|
||||
data: unknown,
|
||||
source: string,
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
export * as ConfigPermission from "./permission"
|
||||
import { Schema, SchemaGetter } from "effect"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
|
||||
export const Action = Schema.Literals(["ask", "allow", "deny"])
|
||||
.annotate({ identifier: "PermissionActionConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Action = Schema.Literals(["ask", "allow", "deny"]).annotate({ identifier: "PermissionActionConfig" })
|
||||
export type Action = Schema.Schema.Type<typeof Action>
|
||||
|
||||
export const Object = Schema.Record(Schema.String, Action)
|
||||
.annotate({ identifier: "PermissionObjectConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Object = Schema.Record(Schema.String, Action).annotate({ identifier: "PermissionObjectConfig" })
|
||||
export type Object = Schema.Schema.Type<typeof Object>
|
||||
|
||||
export const Rule = Schema.Union([Action, Object])
|
||||
.annotate({ identifier: "PermissionRuleConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Rule = Schema.Union([Action, Object]).annotate({ identifier: "PermissionRuleConfig" })
|
||||
export type Rule = Schema.Schema.Type<typeof Rule>
|
||||
|
||||
// Known permission keys get explicit types in the Effect schema for generated
|
||||
@@ -62,12 +54,6 @@ export const Info = InputSchema.pipe(
|
||||
// of the same rules.
|
||||
encode: SchemaGetter.passthrough({ strict: false }),
|
||||
}),
|
||||
)
|
||||
.annotate({ identifier: "PermissionConfig" })
|
||||
.pipe(
|
||||
// Walker already emits the decodeTo transform into the derived zod (see
|
||||
// `encoded()` in effect-zod.ts), so just expose that directly.
|
||||
withStatics((s) => ({ zod: zod(s) })),
|
||||
)
|
||||
).annotate({ identifier: "PermissionConfig" })
|
||||
type _Info = Schema.Schema.Type<typeof InputObject>
|
||||
export type Info = { -readonly [K in keyof _Info]: _Info[K] }
|
||||
|
||||
@@ -6,7 +6,7 @@ import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
import path from "path"
|
||||
|
||||
export const Options = Schema.Record(Schema.String, Schema.Unknown).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Options = Schema.Record(Schema.String, Schema.Unknown)
|
||||
export type Options = Schema.Schema.Type<typeof Options>
|
||||
|
||||
// Spec is the user-config value: either just a plugin identifier, or the identifier plus inline options.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Schema } from "effect"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { PositiveInt, withStatics } from "@opencode-ai/core/schema"
|
||||
import { PositiveInt } from "@opencode-ai/core/schema"
|
||||
import { ModelStatus } from "@/provider/model-status"
|
||||
|
||||
export const Model = Schema.Struct({
|
||||
@@ -67,7 +66,7 @@ export const Model = Schema.Struct({
|
||||
),
|
||||
).annotate({ description: "Variant-specific configuration" }),
|
||||
),
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
})
|
||||
|
||||
export const Info = Schema.Struct({
|
||||
api: Schema.optional(Schema.String),
|
||||
@@ -106,9 +105,7 @@ export const Info = Schema.Struct({
|
||||
),
|
||||
),
|
||||
models: Schema.optional(Schema.Record(Schema.String, Model)),
|
||||
})
|
||||
.annotate({ identifier: "ProviderConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ProviderConfig" })
|
||||
export type Info = Schema.Schema.Type<typeof Info>
|
||||
|
||||
export * as ConfigProvider from "./provider"
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
export * as ConfigReference from "./reference"
|
||||
|
||||
import { Schema } from "effect"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
|
||||
const Git = Schema.Struct({
|
||||
repository: Schema.String.annotate({
|
||||
@@ -21,7 +19,5 @@ const Local = Schema.Struct({
|
||||
|
||||
export const Entry = Schema.Union([Schema.String, Git, Local]).annotate({ identifier: "ReferenceConfigEntry" })
|
||||
|
||||
export const Info = Schema.Record(Schema.String, Entry)
|
||||
.annotate({ identifier: "ReferenceConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Info = Schema.Record(Schema.String, Entry).annotate({ identifier: "ReferenceConfig" })
|
||||
export type Info = Schema.Schema.Type<typeof Info>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Schema } from "effect"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { PositiveInt, withStatics } from "@opencode-ai/core/schema"
|
||||
import { PositiveInt } from "@opencode-ai/core/schema"
|
||||
|
||||
export const Server = Schema.Struct({
|
||||
port: Schema.optional(PositiveInt).annotate({
|
||||
@@ -14,9 +13,7 @@ export const Server = Schema.Struct({
|
||||
cors: Schema.optional(Schema.mutable(Schema.Array(Schema.String))).annotate({
|
||||
description: "Additional domains to allow for CORS",
|
||||
}),
|
||||
})
|
||||
.annotate({ identifier: "ServerConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ServerConfig" })
|
||||
export type Server = Schema.Schema.Type<typeof Server>
|
||||
|
||||
export * as ConfigServer from "./server"
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { Schema } from "effect"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
|
||||
export const Info = Schema.Struct({
|
||||
paths: Schema.optional(Schema.Array(Schema.String)).annotate({
|
||||
@@ -9,7 +7,7 @@ export const Info = Schema.Struct({
|
||||
urls: Schema.optional(Schema.Array(Schema.String)).annotate({
|
||||
description: "URLs to fetch skills from (e.g., https://example.com/.well-known/skills/)",
|
||||
}),
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
})
|
||||
|
||||
export type Info = Schema.Schema.Type<typeof Info>
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ import { spawn as lspspawn } from "./launch"
|
||||
import { Effect, Layer, Context, Schema } from "effect"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
import { containsPath } from "@/project/instance-context"
|
||||
import { NonNegativeInt, withStatics } from "@opencode-ai/core/schema"
|
||||
import { zod, ZodOverride } from "@opencode-ai/core/effect-zod"
|
||||
import { NonNegativeInt } from "@opencode-ai/core/schema"
|
||||
import { ZodOverride } from "@opencode-ai/core/effect-zod"
|
||||
|
||||
const log = Log.create({ service: "lsp" })
|
||||
|
||||
@@ -30,9 +30,7 @@ const Position = Schema.Struct({
|
||||
export const Range = Schema.Struct({
|
||||
start: Position,
|
||||
end: Position,
|
||||
})
|
||||
.annotate({ identifier: "Range" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "Range" })
|
||||
export type Range = typeof Range.Type
|
||||
|
||||
export const Symbol = Schema.Struct({
|
||||
@@ -42,9 +40,7 @@ export const Symbol = Schema.Struct({
|
||||
uri: Schema.String,
|
||||
range: Range,
|
||||
}),
|
||||
})
|
||||
.annotate({ identifier: "Symbol" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "Symbol" })
|
||||
export type Symbol = typeof Symbol.Type
|
||||
|
||||
export const DocumentSymbol = Schema.Struct({
|
||||
@@ -53,9 +49,7 @@ export const DocumentSymbol = Schema.Struct({
|
||||
kind: NonNegativeInt,
|
||||
range: Range,
|
||||
selectionRange: Range,
|
||||
})
|
||||
.annotate({ identifier: "DocumentSymbol" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "DocumentSymbol" })
|
||||
export type DocumentSymbol = typeof DocumentSymbol.Type
|
||||
|
||||
export const Status = Schema.Struct({
|
||||
@@ -65,9 +59,7 @@ export const Status = Schema.Struct({
|
||||
status: Schema.Literals(["connected", "error"]).annotate({
|
||||
[ZodOverride]: z.union([z.literal("connected"), z.literal("error")]),
|
||||
}),
|
||||
})
|
||||
.annotate({ identifier: "LSPStatus" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "LSPStatus" })
|
||||
export type Status = typeof Status.Type
|
||||
|
||||
enum SymbolKind {
|
||||
|
||||
@@ -31,8 +31,6 @@ import { EffectBridge } from "@/effect/bridge"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
|
||||
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
||||
import { zod as effectZod } from "@opencode-ai/core/effect-zod"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
|
||||
const log = Log.create({ service: "mcp" })
|
||||
const DEFAULT_TIMEOUT = 30_000
|
||||
@@ -52,9 +50,7 @@ export const Resource = Schema.Struct({
|
||||
description: Schema.optional(Schema.String),
|
||||
mimeType: Schema.optional(Schema.String),
|
||||
client: Schema.String,
|
||||
})
|
||||
.annotate({ identifier: "McpResource" })
|
||||
.pipe(withStatics((s) => ({ zod: effectZod(s) })))
|
||||
}).annotate({ identifier: "McpResource" })
|
||||
export type Resource = Schema.Schema.Type<typeof Resource>
|
||||
|
||||
export const ToolsChanged = BusEvent.define(
|
||||
@@ -104,9 +100,7 @@ export const Status = Schema.Union([
|
||||
StatusFailed,
|
||||
StatusNeedsAuth,
|
||||
StatusNeedsClientRegistration,
|
||||
])
|
||||
.annotate({ identifier: "MCPStatus", discriminator: "status" })
|
||||
.pipe(withStatics((s) => ({ zod: effectZod(s) })))
|
||||
]).annotate({ identifier: "MCPStatus", discriminator: "status" })
|
||||
export type Status = Schema.Schema.Type<typeof Status>
|
||||
|
||||
// Store transports for OAuth servers to allow finishing auth
|
||||
|
||||
@@ -7,9 +7,7 @@ import { MessageID, SessionID } from "@/session/schema"
|
||||
import { PermissionTable } from "@/session/session.sql"
|
||||
import { Database } from "@/storage/db"
|
||||
import { eq } from "drizzle-orm"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
import { Wildcard } from "@/util/wildcard"
|
||||
import { Deferred, Effect, Layer, Schema, Context } from "effect"
|
||||
import os from "os"
|
||||
@@ -18,23 +16,17 @@ import { PermissionID } from "./schema"
|
||||
|
||||
const log = Log.create({ service: "permission" })
|
||||
|
||||
export const Action = Schema.Literals(["allow", "deny", "ask"])
|
||||
.annotate({ identifier: "PermissionAction" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Action = Schema.Literals(["allow", "deny", "ask"]).annotate({ identifier: "PermissionAction" })
|
||||
export type Action = Schema.Schema.Type<typeof Action>
|
||||
|
||||
export const Rule = Schema.Struct({
|
||||
permission: Schema.String,
|
||||
pattern: Schema.String,
|
||||
action: Action,
|
||||
})
|
||||
.annotate({ identifier: "PermissionRule" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "PermissionRule" })
|
||||
export type Rule = Schema.Schema.Type<typeof Rule>
|
||||
|
||||
export const Ruleset = Schema.mutable(Schema.Array(Rule))
|
||||
.annotate({ identifier: "PermissionRuleset" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Ruleset = Schema.mutable(Schema.Array(Rule)).annotate({ identifier: "PermissionRuleset" })
|
||||
export type Ruleset = Schema.Schema.Type<typeof Ruleset>
|
||||
|
||||
export class Request extends Schema.Class<Request>("PermissionRequest")({
|
||||
@@ -50,11 +42,9 @@ export class Request extends Schema.Class<Request>("PermissionRequest")({
|
||||
callID: Schema.String,
|
||||
}),
|
||||
),
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
}) {}
|
||||
|
||||
export const Reply = Schema.Literals(["once", "always", "reject"]).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Reply = Schema.Literals(["once", "always", "reject"])
|
||||
export type Reply = Schema.Schema.Type<typeof Reply>
|
||||
|
||||
const reply = {
|
||||
@@ -62,17 +52,13 @@ const reply = {
|
||||
message: Schema.optional(Schema.String),
|
||||
}
|
||||
|
||||
export const ReplyBody = Schema.Struct(reply)
|
||||
.annotate({ identifier: "PermissionReplyBody" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const ReplyBody = Schema.Struct(reply).annotate({ identifier: "PermissionReplyBody" })
|
||||
export type ReplyBody = Schema.Schema.Type<typeof ReplyBody>
|
||||
|
||||
export class Approval extends Schema.Class<Approval>("PermissionApproval")({
|
||||
projectID: ProjectID,
|
||||
patterns: Schema.Array(Schema.String),
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
}) {}
|
||||
|
||||
export const Event = {
|
||||
Asked: BusEvent.define("permission.asked", Request),
|
||||
@@ -114,17 +100,13 @@ export const AskInput = Schema.Struct({
|
||||
...Request.fields,
|
||||
id: Schema.optional(PermissionID),
|
||||
ruleset: Ruleset,
|
||||
})
|
||||
.annotate({ identifier: "PermissionAskInput" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "PermissionAskInput" })
|
||||
export type AskInput = Schema.Schema.Type<typeof AskInput>
|
||||
|
||||
export const ReplyInput = Schema.Struct({
|
||||
requestID: PermissionID,
|
||||
...reply,
|
||||
})
|
||||
.annotate({ identifier: "PermissionReplyInput" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "PermissionReplyInput" })
|
||||
export type ReplyInput = Schema.Schema.Type<typeof ReplyInput>
|
||||
|
||||
export interface Interface {
|
||||
|
||||
@@ -17,8 +17,7 @@ import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
|
||||
import { NodePath } from "@effect/platform-node"
|
||||
import { AppFileSystem } from "@opencode-ai/core/filesystem"
|
||||
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { NonNegativeInt, optionalOmitUndefined, withStatics } from "@opencode-ai/core/schema"
|
||||
import { NonNegativeInt, optionalOmitUndefined } from "@opencode-ai/core/schema"
|
||||
import { serviceUse } from "@/effect/service-use"
|
||||
|
||||
const log = Log.create({ service: "project" })
|
||||
@@ -52,9 +51,7 @@ export const Info = Schema.Struct({
|
||||
commands: optionalOmitUndefined(ProjectCommands),
|
||||
time: ProjectTime,
|
||||
sandboxes: Schema.Array(Schema.String),
|
||||
})
|
||||
.annotate({ identifier: "Project" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "Project" })
|
||||
export type Info = Types.DeepMutable<Schema.Schema.Type<typeof Info>>
|
||||
|
||||
export const Event = {
|
||||
@@ -100,9 +97,7 @@ export const UpdatePayload = Schema.Struct({
|
||||
name: Schema.optional(Schema.String),
|
||||
icon: Schema.optional(ProjectIcon),
|
||||
commands: Schema.optional(ProjectCommands),
|
||||
})
|
||||
.annotate({ identifier: "ProjectUpdateInput" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ProjectUpdateInput" })
|
||||
export type UpdatePayload = Types.DeepMutable<Schema.Schema.Type<typeof UpdatePayload>>
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -6,8 +6,6 @@ import { InstanceState } from "@/effect/instance-state"
|
||||
import { FileWatcher } from "@/file/watcher"
|
||||
import { Git } from "@/git"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { zod, zodObject } from "@opencode-ai/core/effect-zod"
|
||||
import { NonNegativeInt, withStatics } from "@opencode-ai/core/schema"
|
||||
|
||||
const log = Log.create({ service: "vcs" })
|
||||
const PATCH_CONTEXT_LINES = 2_147_483_647
|
||||
@@ -208,7 +206,7 @@ const track = Effect.fnUntraced(function* (git: Git.Interface, cwd: string, ref:
|
||||
return yield* diffAgainstRef(git, cwd, ref)
|
||||
})
|
||||
|
||||
export const Mode = Schema.Literals(["git", "branch"]).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Mode = Schema.Literals(["git", "branch"])
|
||||
export type Mode = Schema.Schema.Type<typeof Mode>
|
||||
|
||||
export const Event = {
|
||||
@@ -223,9 +221,7 @@ export const Event = {
|
||||
export const Info = Schema.Struct({
|
||||
branch: Schema.optional(Schema.String),
|
||||
default_branch: Schema.optional(Schema.String),
|
||||
})
|
||||
.annotate({ identifier: "VcsInfo" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "VcsInfo" })
|
||||
export type Info = Schema.Schema.Type<typeof Info>
|
||||
|
||||
export const FileDiff = Schema.Struct({
|
||||
@@ -237,9 +233,7 @@ export const FileDiff = Schema.Struct({
|
||||
additions: Schema.Finite,
|
||||
deletions: Schema.Finite,
|
||||
status: Schema.optional(Schema.Literals(["added", "deleted", "modified"])),
|
||||
})
|
||||
.annotate({ identifier: "VcsFileDiff" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "VcsFileDiff" })
|
||||
export type FileDiff = Schema.Schema.Type<typeof FileDiff>
|
||||
|
||||
export const FileStatus = Schema.Struct({
|
||||
@@ -247,19 +241,17 @@ export const FileStatus = Schema.Struct({
|
||||
additions: Schema.Finite,
|
||||
deletions: Schema.Finite,
|
||||
status: Schema.Literals(["added", "deleted", "modified"]),
|
||||
})
|
||||
.annotate({ identifier: "VcsFileStatus" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "VcsFileStatus" })
|
||||
export type FileStatus = Schema.Schema.Type<typeof FileStatus>
|
||||
|
||||
export const ApplyInput = Schema.Struct({
|
||||
patch: Schema.String,
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s), zodObject: zodObject(s) })))
|
||||
})
|
||||
export type ApplyInput = Schema.Schema.Type<typeof ApplyInput>
|
||||
|
||||
export const ApplyResult = Schema.Struct({
|
||||
applied: Schema.Boolean,
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
})
|
||||
export type ApplyResult = Schema.Schema.Type<typeof ApplyResult>
|
||||
|
||||
export class PatchApplyError extends Schema.TaggedErrorClass<PatchApplyError>()("VcsPatchApplyError", {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import type { AuthOAuthResult, Hooks } from "@opencode-ai/plugin"
|
||||
import { Auth } from "@/auth"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { namedSchemaError } from "@/util/named-schema-error"
|
||||
import { optionalOmitUndefined, withStatics } from "@opencode-ai/core/schema"
|
||||
import { optionalOmitUndefined } from "@opencode-ai/core/schema"
|
||||
import { Plugin } from "../plugin"
|
||||
import { ProviderID } from "./schema"
|
||||
import { Array as Arr, Effect, Layer, Record, Result, Context, Schema } from "effect"
|
||||
@@ -42,31 +41,27 @@ export class Method extends Schema.Class<Method>("ProviderAuthMethod")({
|
||||
type: Schema.Literals(["oauth", "api"]),
|
||||
label: Schema.String,
|
||||
prompts: optionalOmitUndefined(Schema.Array(Prompt)),
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
}) {}
|
||||
|
||||
export const Methods = Schema.Record(Schema.String, Schema.Array(Method)).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Methods = Schema.Record(Schema.String, Schema.Array(Method))
|
||||
export type Methods = typeof Methods.Type
|
||||
|
||||
export class Authorization extends Schema.Class<Authorization>("ProviderAuthAuthorization")({
|
||||
url: Schema.String,
|
||||
method: Schema.Literals(["auto", "code"]),
|
||||
instructions: Schema.String,
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
}) {}
|
||||
|
||||
export const AuthorizeInput = Schema.Struct({
|
||||
method: Schema.Finite.annotate({ description: "Auth method index" }),
|
||||
inputs: Schema.optional(Schema.Record(Schema.String, Schema.String)).annotate({ description: "Prompt inputs" }),
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
})
|
||||
export type AuthorizeInput = Schema.Schema.Type<typeof AuthorizeInput>
|
||||
|
||||
export const CallbackInput = Schema.Struct({
|
||||
method: Schema.Finite.annotate({ description: "Auth method index" }),
|
||||
code: Schema.optional(Schema.String).annotate({ description: "OAuth authorization code" }),
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
})
|
||||
export type CallbackInput = Schema.Schema.Type<typeof CallbackInput>
|
||||
|
||||
export const OauthMissing = namedSchemaError("ProviderAuthOauthMissing", { providerID: ProviderID })
|
||||
|
||||
@@ -13,7 +13,6 @@ import { Auth } from "../auth"
|
||||
import { Env } from "../env"
|
||||
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { namedSchemaError } from "@/util/named-schema-error"
|
||||
import { iife } from "@/util/iife"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
@@ -24,7 +23,7 @@ import { EffectBridge } from "@/effect/bridge"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
import { AppFileSystem } from "@opencode-ai/core/filesystem"
|
||||
import { isRecord } from "@/util/record"
|
||||
import { optionalOmitUndefined, withStatics } from "@opencode-ai/core/schema"
|
||||
import { optionalOmitUndefined } from "@opencode-ai/core/schema"
|
||||
|
||||
import * as ProviderTransform from "./transform"
|
||||
import { ModelID, ProviderID } from "./schema"
|
||||
@@ -903,9 +902,7 @@ export const Model = Schema.Struct({
|
||||
headers: Schema.Record(Schema.String, Schema.String),
|
||||
release_date: Schema.String,
|
||||
variants: optionalOmitUndefined(Schema.Record(Schema.String, Schema.Record(Schema.String, Schema.Any))),
|
||||
})
|
||||
.annotate({ identifier: "Model" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "Model" })
|
||||
export type Model = Types.DeepMutable<Schema.Schema.Type<typeof Model>>
|
||||
|
||||
export const Info = Schema.Struct({
|
||||
@@ -916,9 +913,7 @@ export const Info = Schema.Struct({
|
||||
key: optionalOmitUndefined(Schema.String),
|
||||
options: Schema.Record(Schema.String, Schema.Any),
|
||||
models: Schema.Record(Schema.String, Model),
|
||||
})
|
||||
.annotate({ identifier: "Provider" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "Provider" })
|
||||
export type Info = Types.DeepMutable<Schema.Schema.Type<typeof Info>>
|
||||
|
||||
const DefaultModelIDs = Schema.Record(Schema.String, Schema.String)
|
||||
@@ -927,13 +922,13 @@ export const ListResult = Schema.Struct({
|
||||
all: Schema.Array(Info),
|
||||
default: DefaultModelIDs,
|
||||
connected: Schema.Array(Schema.String),
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
})
|
||||
export type ListResult = Types.DeepMutable<Schema.Schema.Type<typeof ListResult>>
|
||||
|
||||
export const ConfigProvidersResult = Schema.Struct({
|
||||
providers: Schema.Array(Info),
|
||||
default: DefaultModelIDs,
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
})
|
||||
export type ConfigProvidersResult = Types.DeepMutable<Schema.Schema.Type<typeof ConfigProvidersResult>>
|
||||
|
||||
export function toPublicInfo(provider: Info): Info {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Schema } from "effect"
|
||||
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
|
||||
const providerIdSchema = Schema.String.pipe(Schema.brand("ProviderID"))
|
||||
@@ -9,7 +8,6 @@ export type ProviderID = typeof providerIdSchema.Type
|
||||
|
||||
export const ProviderID = providerIdSchema.pipe(
|
||||
withStatics((schema: typeof providerIdSchema) => ({
|
||||
zod: zod(schema),
|
||||
// Well-known providers
|
||||
opencode: schema.make("opencode"),
|
||||
anthropic: schema.make("anthropic"),
|
||||
@@ -29,8 +27,4 @@ const modelIdSchema = Schema.String.pipe(Schema.brand("ModelID"))
|
||||
|
||||
export type ModelID = typeof modelIdSchema.Type
|
||||
|
||||
export const ModelID = modelIdSchema.pipe(
|
||||
withStatics((schema: typeof modelIdSchema) => ({
|
||||
zod: zod(schema),
|
||||
})),
|
||||
)
|
||||
export const ModelID = modelIdSchema
|
||||
|
||||
@@ -3,9 +3,7 @@ import { Bus } from "@/bus"
|
||||
import { BusEvent } from "@/bus/bus-event"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
import { SessionID, MessageID } from "@/session/schema"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
import { QuestionID } from "./schema"
|
||||
|
||||
const log = Log.create({ service: "question" })
|
||||
@@ -19,9 +17,7 @@ export class Option extends Schema.Class<Option>("QuestionOption")({
|
||||
description: Schema.String.annotate({
|
||||
description: "Explanation of choice",
|
||||
}),
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
}) {}
|
||||
|
||||
const base = {
|
||||
question: Schema.String.annotate({
|
||||
@@ -43,20 +39,14 @@ export class Info extends Schema.Class<Info>("QuestionInfo")({
|
||||
custom: Schema.optional(Schema.Boolean).annotate({
|
||||
description: "Allow typing a custom answer (default: true)",
|
||||
}),
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
}) {}
|
||||
|
||||
export class Prompt extends Schema.Class<Prompt>("QuestionPrompt")(base) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
export class Prompt extends Schema.Class<Prompt>("QuestionPrompt")(base) {}
|
||||
|
||||
export class Tool extends Schema.Class<Tool>("QuestionTool")({
|
||||
messageID: MessageID,
|
||||
callID: Schema.String,
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
}) {}
|
||||
|
||||
export class Request extends Schema.Class<Request>("QuestionRequest")({
|
||||
id: QuestionID,
|
||||
@@ -65,22 +55,16 @@ export class Request extends Schema.Class<Request>("QuestionRequest")({
|
||||
description: "Questions to ask",
|
||||
}),
|
||||
tool: Schema.optional(Tool),
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
}) {}
|
||||
|
||||
export const Answer = Schema.Array(Schema.String)
|
||||
.annotate({ identifier: "QuestionAnswer" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const Answer = Schema.Array(Schema.String).annotate({ identifier: "QuestionAnswer" })
|
||||
export type Answer = Schema.Schema.Type<typeof Answer>
|
||||
|
||||
export class Reply extends Schema.Class<Reply>("QuestionReply")({
|
||||
answers: Schema.Array(Answer).annotate({
|
||||
description: "User answers in order of questions (each answer is an array of selected labels)",
|
||||
}),
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
}) {}
|
||||
|
||||
class Replied extends Schema.Class<Replied>("QuestionReplied")({
|
||||
sessionID: SessionID,
|
||||
|
||||
@@ -23,8 +23,7 @@ import type { SystemError } from "bun"
|
||||
import type { Provider } from "@/provider/provider"
|
||||
import { ModelID, ProviderID } from "@/provider/schema"
|
||||
import { Effect, Schema, Types } from "effect"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { NonNegativeInt, withStatics } from "@opencode-ai/core/schema"
|
||||
import { NonNegativeInt } from "@opencode-ai/core/schema"
|
||||
import { namedSchemaError } from "@/util/named-schema-error"
|
||||
import * as EffectLogger from "@opencode-ai/core/effect/logger"
|
||||
|
||||
@@ -88,9 +87,7 @@ export const SnapshotPart = Schema.Struct({
|
||||
...partBase,
|
||||
type: Schema.Literal("snapshot"),
|
||||
snapshot: Schema.String,
|
||||
})
|
||||
.annotate({ identifier: "SnapshotPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "SnapshotPart" })
|
||||
export type SnapshotPart = Types.DeepMutable<Schema.Schema.Type<typeof SnapshotPart>>
|
||||
|
||||
export const PatchPart = Schema.Struct({
|
||||
@@ -98,9 +95,7 @@ export const PatchPart = Schema.Struct({
|
||||
type: Schema.Literal("patch"),
|
||||
hash: Schema.String,
|
||||
files: Schema.Array(Schema.String),
|
||||
})
|
||||
.annotate({ identifier: "PatchPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "PatchPart" })
|
||||
export type PatchPart = Types.DeepMutable<Schema.Schema.Type<typeof PatchPart>>
|
||||
|
||||
export const TextPart = Schema.Struct({
|
||||
@@ -116,9 +111,7 @@ export const TextPart = Schema.Struct({
|
||||
}),
|
||||
),
|
||||
metadata: Schema.optional(Schema.Record(Schema.String, Schema.Any)),
|
||||
})
|
||||
.annotate({ identifier: "TextPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "TextPart" })
|
||||
export type TextPart = Types.DeepMutable<Schema.Schema.Type<typeof TextPart>>
|
||||
|
||||
export const ReasoningPart = Schema.Struct({
|
||||
@@ -130,9 +123,7 @@ export const ReasoningPart = Schema.Struct({
|
||||
start: NonNegativeInt,
|
||||
end: Schema.optional(NonNegativeInt),
|
||||
}),
|
||||
})
|
||||
.annotate({ identifier: "ReasoningPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ReasoningPart" })
|
||||
export type ReasoningPart = Types.DeepMutable<Schema.Schema.Type<typeof ReasoningPart>>
|
||||
|
||||
const filePartSourceBase = {
|
||||
@@ -147,9 +138,7 @@ export const FileSource = Schema.Struct({
|
||||
...filePartSourceBase,
|
||||
type: Schema.Literal("file"),
|
||||
path: Schema.String,
|
||||
})
|
||||
.annotate({ identifier: "FileSource" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "FileSource" })
|
||||
|
||||
export const SymbolSource = Schema.Struct({
|
||||
...filePartSourceBase,
|
||||
@@ -158,24 +147,19 @@ export const SymbolSource = Schema.Struct({
|
||||
range: LSP.Range,
|
||||
name: Schema.String,
|
||||
kind: NonNegativeInt,
|
||||
})
|
||||
.annotate({ identifier: "SymbolSource" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "SymbolSource" })
|
||||
|
||||
export const ResourceSource = Schema.Struct({
|
||||
...filePartSourceBase,
|
||||
type: Schema.Literal("resource"),
|
||||
clientName: Schema.String,
|
||||
uri: Schema.String,
|
||||
})
|
||||
.annotate({ identifier: "ResourceSource" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ResourceSource" })
|
||||
|
||||
const _FilePartSource = Schema.Union([FileSource, SymbolSource, ResourceSource]).annotate({
|
||||
export const FilePartSource = Schema.Union([FileSource, SymbolSource, ResourceSource]).annotate({
|
||||
discriminator: "type",
|
||||
identifier: "FilePartSource",
|
||||
})
|
||||
export const FilePartSource = Object.assign(_FilePartSource, { zod: zod(_FilePartSource) })
|
||||
|
||||
export const FilePart = Schema.Struct({
|
||||
...partBase,
|
||||
@@ -183,10 +167,8 @@ export const FilePart = Schema.Struct({
|
||||
mime: Schema.String,
|
||||
filename: Schema.optional(Schema.String),
|
||||
url: Schema.String,
|
||||
source: Schema.optional(_FilePartSource),
|
||||
})
|
||||
.annotate({ identifier: "FilePart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
source: Schema.optional(FilePartSource),
|
||||
}).annotate({ identifier: "FilePart" })
|
||||
export type FilePart = Types.DeepMutable<Schema.Schema.Type<typeof FilePart>>
|
||||
|
||||
export const AgentPart = Schema.Struct({
|
||||
@@ -200,9 +182,7 @@ export const AgentPart = Schema.Struct({
|
||||
end: NonNegativeInt,
|
||||
}),
|
||||
),
|
||||
})
|
||||
.annotate({ identifier: "AgentPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "AgentPart" })
|
||||
export type AgentPart = Types.DeepMutable<Schema.Schema.Type<typeof AgentPart>>
|
||||
|
||||
export const CompactionPart = Schema.Struct({
|
||||
@@ -211,9 +191,7 @@ export const CompactionPart = Schema.Struct({
|
||||
auto: Schema.Boolean,
|
||||
overflow: Schema.optional(Schema.Boolean),
|
||||
tail_start_id: Schema.optional(MessageID),
|
||||
})
|
||||
.annotate({ identifier: "CompactionPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "CompactionPart" })
|
||||
export type CompactionPart = Types.DeepMutable<Schema.Schema.Type<typeof CompactionPart>>
|
||||
|
||||
export const SubtaskPart = Schema.Struct({
|
||||
@@ -229,9 +207,7 @@ export const SubtaskPart = Schema.Struct({
|
||||
}),
|
||||
),
|
||||
command: Schema.optional(Schema.String),
|
||||
})
|
||||
.annotate({ identifier: "SubtaskPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "SubtaskPart" })
|
||||
export type SubtaskPart = Types.DeepMutable<Schema.Schema.Type<typeof SubtaskPart>>
|
||||
|
||||
export const RetryPart = Schema.Struct({
|
||||
@@ -242,9 +218,7 @@ export const RetryPart = Schema.Struct({
|
||||
time: Schema.Struct({
|
||||
created: NonNegativeInt,
|
||||
}),
|
||||
})
|
||||
.annotate({ identifier: "RetryPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "RetryPart" })
|
||||
export type RetryPart = Omit<Types.DeepMutable<Schema.Schema.Type<typeof RetryPart>>, "error"> & {
|
||||
error: APIError
|
||||
}
|
||||
@@ -253,9 +227,7 @@ export const StepStartPart = Schema.Struct({
|
||||
...partBase,
|
||||
type: Schema.Literal("step-start"),
|
||||
snapshot: Schema.optional(Schema.String),
|
||||
})
|
||||
.annotate({ identifier: "StepStartPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "StepStartPart" })
|
||||
export type StepStartPart = Types.DeepMutable<Schema.Schema.Type<typeof StepStartPart>>
|
||||
|
||||
export const StepFinishPart = Schema.Struct({
|
||||
@@ -274,18 +246,14 @@ export const StepFinishPart = Schema.Struct({
|
||||
write: Schema.Finite,
|
||||
}),
|
||||
}),
|
||||
})
|
||||
.annotate({ identifier: "StepFinishPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "StepFinishPart" })
|
||||
export type StepFinishPart = Types.DeepMutable<Schema.Schema.Type<typeof StepFinishPart>>
|
||||
|
||||
export const ToolStatePending = Schema.Struct({
|
||||
status: Schema.Literal("pending"),
|
||||
input: Schema.Record(Schema.String, Schema.Any),
|
||||
raw: Schema.String,
|
||||
})
|
||||
.annotate({ identifier: "ToolStatePending" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ToolStatePending" })
|
||||
export type ToolStatePending = Types.DeepMutable<Schema.Schema.Type<typeof ToolStatePending>>
|
||||
|
||||
export const ToolStateRunning = Schema.Struct({
|
||||
@@ -296,9 +264,7 @@ export const ToolStateRunning = Schema.Struct({
|
||||
time: Schema.Struct({
|
||||
start: NonNegativeInt,
|
||||
}),
|
||||
})
|
||||
.annotate({ identifier: "ToolStateRunning" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ToolStateRunning" })
|
||||
export type ToolStateRunning = Types.DeepMutable<Schema.Schema.Type<typeof ToolStateRunning>>
|
||||
|
||||
export const ToolStateCompleted = Schema.Struct({
|
||||
@@ -313,9 +279,7 @@ export const ToolStateCompleted = Schema.Struct({
|
||||
compacted: Schema.optional(NonNegativeInt),
|
||||
}),
|
||||
attachments: Schema.optional(Schema.Array(FilePart)),
|
||||
})
|
||||
.annotate({ identifier: "ToolStateCompleted" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ToolStateCompleted" })
|
||||
export type ToolStateCompleted = Types.DeepMutable<Schema.Schema.Type<typeof ToolStateCompleted>>
|
||||
|
||||
function truncateToolOutput(text: string, maxChars?: number) {
|
||||
@@ -333,22 +297,18 @@ export const ToolStateError = Schema.Struct({
|
||||
start: NonNegativeInt,
|
||||
end: NonNegativeInt,
|
||||
}),
|
||||
})
|
||||
.annotate({ identifier: "ToolStateError" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ToolStateError" })
|
||||
export type ToolStateError = Types.DeepMutable<Schema.Schema.Type<typeof ToolStateError>>
|
||||
|
||||
const _ToolState = Schema.Union([ToolStatePending, ToolStateRunning, ToolStateCompleted, ToolStateError]).annotate({
|
||||
export const ToolState = Schema.Union([
|
||||
ToolStatePending,
|
||||
ToolStateRunning,
|
||||
ToolStateCompleted,
|
||||
ToolStateError,
|
||||
]).annotate({
|
||||
discriminator: "status",
|
||||
identifier: "ToolState",
|
||||
})
|
||||
// Cast the derived zod so downstream z.infer sees the same mutable shape that
|
||||
// our exported TS types expose (the pre-migration Zod inferences were mutable).
|
||||
export const ToolState = Object.assign(_ToolState, {
|
||||
zod: zod(_ToolState) as unknown as z.ZodType<
|
||||
ToolStatePending | ToolStateRunning | ToolStateCompleted | ToolStateError
|
||||
>,
|
||||
})
|
||||
export type ToolState = ToolStatePending | ToolStateRunning | ToolStateCompleted | ToolStateError
|
||||
|
||||
export const ToolPart = Schema.Struct({
|
||||
@@ -356,11 +316,9 @@ export const ToolPart = Schema.Struct({
|
||||
type: Schema.Literal("tool"),
|
||||
callID: Schema.String,
|
||||
tool: Schema.String,
|
||||
state: _ToolState,
|
||||
state: ToolState,
|
||||
metadata: Schema.optional(Schema.Record(Schema.String, Schema.Any)),
|
||||
})
|
||||
.annotate({ identifier: "ToolPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ToolPart" })
|
||||
export type ToolPart = Omit<Types.DeepMutable<Schema.Schema.Type<typeof ToolPart>>, "state"> & {
|
||||
state: ToolState
|
||||
}
|
||||
@@ -441,8 +399,7 @@ type AssistantError = Schema.Schema.Type<typeof AssistantErrorSchema>
|
||||
// Consumers of `SessionPrompt.PromptInput.parts` send part drafts without the
|
||||
// ambient IDs (`messageID`, `sessionID`) that live on stored parts, and may
|
||||
// omit `id` to let the server allocate one. These Schema-Struct variants
|
||||
// carry that shape, and `SessionPrompt.PromptInput` just references the
|
||||
// derived `.zod` (no omit/partial gymnastics needed at the call site).
|
||||
// carry that shape so prompt decoding can accept drafts without stored IDs.
|
||||
|
||||
export const TextPartInput = Schema.Struct({
|
||||
id: Schema.optional(PartID),
|
||||
@@ -457,9 +414,7 @@ export const TextPartInput = Schema.Struct({
|
||||
}),
|
||||
),
|
||||
metadata: Schema.optional(Schema.Record(Schema.String, Schema.Any)),
|
||||
})
|
||||
.annotate({ identifier: "TextPartInput" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "TextPartInput" })
|
||||
export type TextPartInput = Types.DeepMutable<Schema.Schema.Type<typeof TextPartInput>>
|
||||
|
||||
export const FilePartInput = Schema.Struct({
|
||||
@@ -468,10 +423,8 @@ export const FilePartInput = Schema.Struct({
|
||||
mime: Schema.String,
|
||||
filename: Schema.optional(Schema.String),
|
||||
url: Schema.String,
|
||||
source: Schema.optional(_FilePartSource),
|
||||
})
|
||||
.annotate({ identifier: "FilePartInput" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
source: Schema.optional(FilePartSource),
|
||||
}).annotate({ identifier: "FilePartInput" })
|
||||
export type FilePartInput = Types.DeepMutable<Schema.Schema.Type<typeof FilePartInput>>
|
||||
|
||||
export const AgentPartInput = Schema.Struct({
|
||||
@@ -485,9 +438,7 @@ export const AgentPartInput = Schema.Struct({
|
||||
end: NonNegativeInt,
|
||||
}),
|
||||
),
|
||||
})
|
||||
.annotate({ identifier: "AgentPartInput" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "AgentPartInput" })
|
||||
export type AgentPartInput = Types.DeepMutable<Schema.Schema.Type<typeof AgentPartInput>>
|
||||
|
||||
export const SubtaskPartInput = Schema.Struct({
|
||||
@@ -503,9 +454,7 @@ export const SubtaskPartInput = Schema.Struct({
|
||||
}),
|
||||
),
|
||||
command: Schema.optional(Schema.String),
|
||||
})
|
||||
.annotate({ identifier: "SubtaskPartInput" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "SubtaskPartInput" })
|
||||
export type SubtaskPartInput = Types.DeepMutable<Schema.Schema.Type<typeof SubtaskPartInput>>
|
||||
|
||||
export const Assistant = Schema.Struct({
|
||||
@@ -613,7 +562,7 @@ export const Event = {
|
||||
export const WithParts = Schema.Struct({
|
||||
info: Info,
|
||||
parts: Schema.Array(Part),
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
})
|
||||
export type WithParts = {
|
||||
info: Info
|
||||
parts: Part[]
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Schema } from "effect"
|
||||
import { SessionID } from "./schema"
|
||||
import { ModelID, ProviderID } from "../provider/schema"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { NonNegativeInt, withStatics } from "@opencode-ai/core/schema"
|
||||
import { NonNegativeInt } from "@opencode-ai/core/schema"
|
||||
import { namedSchemaError } from "@/util/named-schema-error"
|
||||
|
||||
export const OutputLengthError = namedSchemaError("MessageOutputLengthError", {})
|
||||
@@ -37,9 +36,7 @@ export const ToolCall = Schema.Struct({
|
||||
toolCallId: Schema.String,
|
||||
toolName: Schema.String,
|
||||
args: Schema.Unknown,
|
||||
})
|
||||
.annotate({ identifier: "ToolCall" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ToolCall" })
|
||||
export type ToolCall = Schema.Schema.Type<typeof ToolCall>
|
||||
|
||||
export const ToolPartialCall = Schema.Struct({
|
||||
@@ -48,9 +45,7 @@ export const ToolPartialCall = Schema.Struct({
|
||||
toolCallId: Schema.String,
|
||||
toolName: Schema.String,
|
||||
args: Schema.Unknown,
|
||||
})
|
||||
.annotate({ identifier: "ToolPartialCall" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ToolPartialCall" })
|
||||
export type ToolPartialCall = Schema.Schema.Type<typeof ToolPartialCall>
|
||||
|
||||
export const ToolResult = Schema.Struct({
|
||||
@@ -60,39 +55,32 @@ export const ToolResult = Schema.Struct({
|
||||
toolName: Schema.String,
|
||||
args: Schema.Unknown,
|
||||
result: Schema.String,
|
||||
})
|
||||
.annotate({ identifier: "ToolResult" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ToolResult" })
|
||||
export type ToolResult = Schema.Schema.Type<typeof ToolResult>
|
||||
|
||||
export const ToolInvocation = Schema.Union([ToolCall, ToolPartialCall, ToolResult])
|
||||
.annotate({ identifier: "ToolInvocation", discriminator: "state" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export const ToolInvocation = Schema.Union([ToolCall, ToolPartialCall, ToolResult]).annotate({
|
||||
identifier: "ToolInvocation",
|
||||
discriminator: "state",
|
||||
})
|
||||
export type ToolInvocation = Schema.Schema.Type<typeof ToolInvocation>
|
||||
|
||||
export const TextPart = Schema.Struct({
|
||||
type: Schema.Literal("text"),
|
||||
text: Schema.String,
|
||||
})
|
||||
.annotate({ identifier: "TextPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "TextPart" })
|
||||
export type TextPart = Schema.Schema.Type<typeof TextPart>
|
||||
|
||||
export const ReasoningPart = Schema.Struct({
|
||||
type: Schema.Literal("reasoning"),
|
||||
text: Schema.String,
|
||||
providerMetadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
|
||||
})
|
||||
.annotate({ identifier: "ReasoningPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ReasoningPart" })
|
||||
export type ReasoningPart = Schema.Schema.Type<typeof ReasoningPart>
|
||||
|
||||
export const ToolInvocationPart = Schema.Struct({
|
||||
type: Schema.Literal("tool-invocation"),
|
||||
toolInvocation: ToolInvocation,
|
||||
})
|
||||
.annotate({ identifier: "ToolInvocationPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "ToolInvocationPart" })
|
||||
export type ToolInvocationPart = Schema.Schema.Type<typeof ToolInvocationPart>
|
||||
|
||||
export const SourceUrlPart = Schema.Struct({
|
||||
@@ -101,9 +89,7 @@ export const SourceUrlPart = Schema.Struct({
|
||||
url: Schema.String,
|
||||
title: Schema.optional(Schema.String),
|
||||
providerMetadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
|
||||
})
|
||||
.annotate({ identifier: "SourceUrlPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "SourceUrlPart" })
|
||||
export type SourceUrlPart = Schema.Schema.Type<typeof SourceUrlPart>
|
||||
|
||||
export const FilePart = Schema.Struct({
|
||||
@@ -111,16 +97,12 @@ export const FilePart = Schema.Struct({
|
||||
mediaType: Schema.String,
|
||||
filename: Schema.optional(Schema.String),
|
||||
url: Schema.String,
|
||||
})
|
||||
.annotate({ identifier: "FilePart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "FilePart" })
|
||||
export type FilePart = Schema.Schema.Type<typeof FilePart>
|
||||
|
||||
export const StepStartPart = Schema.Struct({
|
||||
type: Schema.Literal("step-start"),
|
||||
})
|
||||
.annotate({ identifier: "StepStartPart" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "StepStartPart" })
|
||||
export type StepStartPart = Schema.Schema.Type<typeof StepStartPart>
|
||||
|
||||
export const MessagePart = Schema.Union([
|
||||
@@ -130,9 +112,7 @@ export const MessagePart = Schema.Union([
|
||||
SourceUrlPart,
|
||||
FilePart,
|
||||
StepStartPart,
|
||||
])
|
||||
.annotate({ identifier: "MessagePart", discriminator: "type" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
]).annotate({ identifier: "MessagePart", discriminator: "type" })
|
||||
export type MessagePart = Schema.Schema.Type<typeof MessagePart>
|
||||
|
||||
export const Info = Schema.Struct({
|
||||
@@ -184,9 +164,7 @@ export const Info = Schema.Struct({
|
||||
),
|
||||
snapshot: Schema.optional(Schema.String),
|
||||
}).annotate({ identifier: "MessageMetadata" }),
|
||||
})
|
||||
.annotate({ identifier: "Message" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
}).annotate({ identifier: "Message" })
|
||||
export type Info = Schema.Schema.Type<typeof Info>
|
||||
|
||||
export * as Message from "./message"
|
||||
|
||||
@@ -2,8 +2,6 @@ import { Effect, Layer, Context, Schema } from "effect"
|
||||
import { Bus } from "@/bus"
|
||||
import { Snapshot } from "@/snapshot"
|
||||
import { Storage } from "@/storage/storage"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
import * as Session from "./session"
|
||||
import { MessageV2 } from "./message-v2"
|
||||
import { SessionID, MessageID } from "./schema"
|
||||
@@ -160,7 +158,7 @@ export const defaultLayer = Layer.suspend(() =>
|
||||
export const DiffInput = Schema.Struct({
|
||||
sessionID: SessionID,
|
||||
messageID: Schema.optional(MessageID),
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
})
|
||||
export type DiffInput = Schema.Schema.Type<typeof DiffInput>
|
||||
|
||||
export * as SessionSummary from "./summary"
|
||||
|
||||
@@ -55,9 +55,9 @@ There are now "sync events" which are different than "bus events". Bus events ar
|
||||
```ts
|
||||
const Diff = BusEvent.define(
|
||||
"session.diff",
|
||||
z.object({
|
||||
sessionID: SessionID.zod,
|
||||
diff: Snapshot.FileDiff.array(),
|
||||
Schema.Struct({
|
||||
sessionID: SessionID,
|
||||
diff: Schema.Array(Snapshot.FileDiff),
|
||||
}),
|
||||
)
|
||||
```
|
||||
@@ -71,8 +71,8 @@ const Created = SyncEvent.define({
|
||||
type: "session.created",
|
||||
version: 1,
|
||||
aggregate: "sessionID",
|
||||
schema: z.object({
|
||||
sessionID: SessionID.zod,
|
||||
schema: Schema.Struct({
|
||||
sessionID: SessionID,
|
||||
info: Info,
|
||||
}),
|
||||
})
|
||||
@@ -114,7 +114,7 @@ This allows you to "reshape" an event from the sync system before it's published
|
||||
|
||||
The only time we use this is the `session.updated` event. Previously this event contained the entire session object. The sync event only contains the fields updated. We convert the event to contain the full object for backwards compatibility (but ideally we'd remove this).
|
||||
|
||||
It's very important that types are correct when working with events. Event definitions have a `schema` which carries the definition of the event shape (provided by a zod schema, inferred into a TypeScript type). Examples:
|
||||
It's very important that types are correct when working with events. Event definitions have a `schema` which carries the definition of the event shape. Examples:
|
||||
|
||||
```ts
|
||||
// The schema from `Updated` typechecks the object correctly
|
||||
@@ -149,12 +149,12 @@ const Update = SyncEvent.define({
|
||||
type: "session.updated",
|
||||
version: 1,
|
||||
aggregate: "sessionID",
|
||||
schema: z.object({
|
||||
sessionID: SessionID.zod,
|
||||
schema: Schema.Struct({
|
||||
sessionID: SessionID,
|
||||
info: partialSchema(Info),
|
||||
}),
|
||||
busSchema: z.object({
|
||||
sessionID: SessionID.zod,
|
||||
busSchema: Schema.Struct({
|
||||
sessionID: SessionID,
|
||||
info: Info,
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Schema } from "effect"
|
||||
|
||||
import { Identifier } from "@/id/id"
|
||||
import { zod } from "@opencode-ai/core/effect-zod"
|
||||
import { withStatics } from "@opencode-ai/core/schema"
|
||||
|
||||
const toolIdSchema = Schema.String.check(Schema.isStartsWith("tool")).pipe(Schema.brand("ToolID"))
|
||||
@@ -11,6 +10,5 @@ export type ToolID = typeof toolIdSchema.Type
|
||||
export const ToolID = toolIdSchema.pipe(
|
||||
withStatics((schema: typeof toolIdSchema) => ({
|
||||
ascending: (id?: string) => schema.make(Identifier.ascending("tool", id)),
|
||||
zod: zod(schema),
|
||||
})),
|
||||
)
|
||||
|
||||
@@ -251,7 +251,7 @@ test("updates global config and omits empty shell key in jsonc", async () => {
|
||||
|
||||
const file = path.join(tmp.path, "opencode.jsonc")
|
||||
const writtenConfig = await Filesystem.readText(file)
|
||||
const parsed = ConfigParse.effectSchema(Config.Info, ConfigParse.jsonc(writtenConfig, file), file)
|
||||
const parsed = ConfigParse.schema(Config.Info, ConfigParse.jsonc(writtenConfig, file), file)
|
||||
expect(writtenConfig).not.toContain('"shell"')
|
||||
expect(parsed.shell).toBeUndefined()
|
||||
expect(parsed.model).toBe("test/model")
|
||||
@@ -1681,8 +1681,8 @@ test("permission config preserves user key order", async () => {
|
||||
})
|
||||
})
|
||||
|
||||
test("Effect config parser preserves permission order while rejecting unknown top-level keys", () => {
|
||||
const config = ConfigParse.effectSchema(
|
||||
test("config parser preserves permission order while rejecting unknown top-level keys", () => {
|
||||
const config = ConfigParse.schema(
|
||||
Config.Info,
|
||||
{
|
||||
permission: {
|
||||
@@ -1696,7 +1696,7 @@ test("Effect config parser preserves permission order while rejecting unknown to
|
||||
|
||||
expect(Object.keys(config.permission!)).toEqual(["bash", "*", "edit"])
|
||||
try {
|
||||
ConfigParse.effectSchema(Config.Info, { invalid_field: true }, "test")
|
||||
ConfigParse.schema(Config.Info, { invalid_field: true }, "test")
|
||||
throw new Error("expected config parse to fail")
|
||||
} catch (err) {
|
||||
const error = err as { data?: { issues?: Array<{ code?: string; keys?: string[]; path?: string[] }> } }
|
||||
@@ -2463,7 +2463,7 @@ describe("OPENCODE_CONFIG_CONTENT token substitution", () => {
|
||||
// parseManagedPlist unit tests — pure function, no OS interaction
|
||||
|
||||
test("parseManagedPlist strips MDM metadata keys", async () => {
|
||||
const config = ConfigParse.effectSchema(
|
||||
const config = ConfigParse.schema(
|
||||
Config.Info,
|
||||
ConfigParse.jsonc(
|
||||
await ConfigManaged.parseManagedPlist(
|
||||
@@ -2491,7 +2491,7 @@ test("parseManagedPlist strips MDM metadata keys", async () => {
|
||||
})
|
||||
|
||||
test("parseManagedPlist parses server settings", async () => {
|
||||
const config = ConfigParse.effectSchema(
|
||||
const config = ConfigParse.schema(
|
||||
Config.Info,
|
||||
ConfigParse.jsonc(
|
||||
await ConfigManaged.parseManagedPlist(
|
||||
@@ -2511,7 +2511,7 @@ test("parseManagedPlist parses server settings", async () => {
|
||||
})
|
||||
|
||||
test("parseManagedPlist parses permission rules", async () => {
|
||||
const config = ConfigParse.effectSchema(
|
||||
const config = ConfigParse.schema(
|
||||
Config.Info,
|
||||
ConfigParse.jsonc(
|
||||
await ConfigManaged.parseManagedPlist(
|
||||
@@ -2541,7 +2541,7 @@ test("parseManagedPlist parses permission rules", async () => {
|
||||
})
|
||||
|
||||
test("parseManagedPlist parses enabled_providers", async () => {
|
||||
const config = ConfigParse.effectSchema(
|
||||
const config = ConfigParse.schema(
|
||||
Config.Info,
|
||||
ConfigParse.jsonc(
|
||||
await ConfigManaged.parseManagedPlist(
|
||||
@@ -2558,7 +2558,7 @@ test("parseManagedPlist parses enabled_providers", async () => {
|
||||
})
|
||||
|
||||
test("parseManagedPlist handles empty config", async () => {
|
||||
const config = ConfigParse.effectSchema(
|
||||
const config = ConfigParse.schema(
|
||||
Config.Info,
|
||||
ConfigParse.jsonc(
|
||||
await ConfigManaged.parseManagedPlist(JSON.stringify({ $schema: "https://opencode.ai/config.json" })),
|
||||
|
||||
@@ -14,12 +14,7 @@ import { WorkspaceID } from "../../src/control-plane/schema"
|
||||
// Covers the session-domain Effect Schema migration. For each migrated
|
||||
// schema we assert:
|
||||
// 1. The Effect decoder (`Schema.decodeUnknownSync`) accepts valid input.
|
||||
// 2. The derived Zod (`X.zod.parse`) accepts the same input and returns the
|
||||
// same shape for schemas that still expose Zod statics.
|
||||
// 3. Clearly-invalid input is rejected by both paths where both exist.
|
||||
//
|
||||
// The point is to lock down the Schema <-> Zod bridge so a future edit to
|
||||
// any input schema can't silently drop or widen a field on one side.
|
||||
// 2. Clearly-invalid input is rejected.
|
||||
|
||||
// Representative valid IDs — the branded schemas require the right prefix
|
||||
// (see src/id/id.ts).
|
||||
|
||||
Reference in New Issue
Block a user