summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKit Langton <[email protected]>2026-04-23 13:22:48 -0400
committerGitHub <[email protected]>2026-04-23 13:22:48 -0400
commit0590452456a746457d5255e2ce3ecd9c5a4a621d (patch)
tree5f8ada459f663ba66bc3133553438ada343a008d
parent93940a1859530b8fe46df376e7d7ba74fcd3e0d1 (diff)
downloadopencode-0590452456a746457d5255e2ce3ecd9c5a4a621d.tar.gz
opencode-0590452456a746457d5255e2ce3ecd9c5a4a621d.zip
refactor(schema): use Schema.Int and consolidate PositiveInt/NonNegativeInt (#24029)
-rw-r--r--packages/opencode/src/config/agent.ts3
-rw-r--r--packages/opencode/src/config/config.ts5
-rw-r--r--packages/opencode/src/config/provider.ts4
-rw-r--r--packages/opencode/src/config/server.ts4
-rw-r--r--packages/opencode/src/session/message-v2.ts20
-rw-r--r--packages/opencode/src/util/schema.ts10
6 files changed, 24 insertions, 22 deletions
diff --git a/packages/opencode/src/config/agent.ts b/packages/opencode/src/config/agent.ts
index 85021407c..2978916b5 100644
--- a/packages/opencode/src/config/agent.ts
+++ b/packages/opencode/src/config/agent.ts
@@ -4,6 +4,7 @@ import { Schema } from "effect"
import z from "zod"
import { Bus } from "@/bus"
import { zod } from "@/util/effect-zod"
+import { PositiveInt } from "@/util/schema"
import { Log } from "../util"
import { NamedError } from "@opencode-ai/shared/util/error"
import { Glob } from "@opencode-ai/shared/util/glob"
@@ -15,8 +16,6 @@ import { ConfigPermission } from "./permission"
const log = Log.create({ service: "config" })
-const PositiveInt = Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThan(0))
-
const Color = Schema.Union([
Schema.String.check(Schema.isPattern(/^#[0-9a-fA-F]{6}$/)),
Schema.Literals(["primary", "secondary", "accent", "success", "warning", "error", "info"]),
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index 5423ba3ba..9814017d1 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -25,7 +25,7 @@ import { Context, Duration, Effect, Exit, Fiber, Layer, Option, Schema } from "e
import { EffectFlock } from "@opencode-ai/shared/util/effect-flock"
import { InstanceRef } from "@/effect/instance-ref"
import { zod, ZodOverride } from "@/util/effect-zod"
-import { withStatics } from "@/util/schema"
+import { NonNegativeInt, PositiveInt, withStatics } from "@/util/schema"
import { ConfigAgent } from "./agent"
import { ConfigCommand } from "./command"
import { ConfigFormatter } from "./formatter"
@@ -88,9 +88,6 @@ export type Layout = ConfigLayout.Layout
const AgentRef = Schema.Any.annotate({ [ZodOverride]: ConfigAgent.Info })
const LogLevelRef = Schema.Any.annotate({ [ZodOverride]: Log.Level })
-const PositiveInt = Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThan(0))
-const NonNegativeInt = Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThanOrEqualTo(0))
-
// The Effect Schema is the canonical source of truth. The `.zod` compatibility
// surface is derived so existing Hono validators keep working without a parallel
// Zod definition.
diff --git a/packages/opencode/src/config/provider.ts b/packages/opencode/src/config/provider.ts
index bd6ae3599..cd7469435 100644
--- a/packages/opencode/src/config/provider.ts
+++ b/packages/opencode/src/config/provider.ts
@@ -1,8 +1,6 @@
import { Schema } from "effect"
import { zod } from "@/util/effect-zod"
-import { withStatics } from "@/util/schema"
-
-const PositiveInt = Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThan(0))
+import { PositiveInt, withStatics } from "@/util/schema"
export const Model = Schema.Struct({
id: Schema.optional(Schema.String),
diff --git a/packages/opencode/src/config/server.ts b/packages/opencode/src/config/server.ts
index 3ce4fe626..3f1369826 100644
--- a/packages/opencode/src/config/server.ts
+++ b/packages/opencode/src/config/server.ts
@@ -1,9 +1,9 @@
import { Schema } from "effect"
import { zod } from "@/util/effect-zod"
-import { withStatics } from "@/util/schema"
+import { PositiveInt, withStatics } from "@/util/schema"
export const Server = Schema.Struct({
- port: Schema.optional(Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThan(0))).annotate({
+ port: Schema.optional(PositiveInt).annotate({
description: "Port to listen on",
}),
hostname: Schema.optional(Schema.String).annotate({ description: "Hostname to listen on" }),
diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts
index a4b25d95e..c5a35c7b4 100644
--- a/packages/opencode/src/session/message-v2.ts
+++ b/packages/opencode/src/session/message-v2.ts
@@ -17,7 +17,7 @@ import type { Provider } from "@/provider"
import { ModelID, ProviderID } from "@/provider/schema"
import { Effect, Schema, Types } from "effect"
import { zod, ZodOverride } from "@/util/effect-zod"
-import { withStatics } from "@/util/schema"
+import { NonNegativeInt, withStatics } from "@/util/schema"
import { namedSchemaError } from "@/util/named-schema-error"
import { EffectLogger } from "@/effect"
@@ -64,9 +64,7 @@ export class OutputFormatText extends Schema.Class<OutputFormatText>("OutputForm
export class OutputFormatJsonSchema extends Schema.Class<OutputFormatJsonSchema>("OutputFormatJsonSchema")({
type: Schema.Literal("json_schema"),
schema: Schema.Record(Schema.String, Schema.Any).annotate({ identifier: "JSONSchema" }),
- retryCount: Schema.Number.check(Schema.isInt())
- .check(Schema.isGreaterThanOrEqualTo(0))
- .pipe(Schema.optional, Schema.withDecodingDefault(Effect.succeed(2))),
+ retryCount: NonNegativeInt.pipe(Schema.optional, Schema.withDecodingDefault(Effect.succeed(2))),
}) {
static readonly zod = zod(this)
}
@@ -138,8 +136,8 @@ export type ReasoningPart = Types.DeepMutable<Schema.Schema.Type<typeof Reasonin
const filePartSourceBase = {
text: Schema.Struct({
value: Schema.String,
- start: Schema.Number.check(Schema.isInt()),
- end: Schema.Number.check(Schema.isInt()),
+ start: Schema.Int,
+ end: Schema.Int,
}).annotate({ identifier: "FilePartSourceText" }),
}
@@ -157,7 +155,7 @@ export const SymbolSource = Schema.Struct({
path: Schema.String,
range: LSP.Range,
name: Schema.String,
- kind: Schema.Number.check(Schema.isInt()),
+ kind: Schema.Int,
})
.annotate({ identifier: "SymbolSource" })
.pipe(withStatics((s) => ({ zod: zod(s) })))
@@ -196,8 +194,8 @@ export const AgentPart = Schema.Struct({
source: Schema.optional(
Schema.Struct({
value: Schema.String,
- start: Schema.Number.check(Schema.isInt()),
- end: Schema.Number.check(Schema.isInt()),
+ start: Schema.Int,
+ end: Schema.Int,
}),
),
})
@@ -501,8 +499,8 @@ export const AgentPartInput = Schema.Struct({
source: Schema.optional(
Schema.Struct({
value: Schema.String,
- start: Schema.Number.check(Schema.isInt()),
- end: Schema.Number.check(Schema.isInt()),
+ start: Schema.Int,
+ end: Schema.Int,
}),
),
})
diff --git a/packages/opencode/src/util/schema.ts b/packages/opencode/src/util/schema.ts
index 405f6a718..7f94ee5d1 100644
--- a/packages/opencode/src/util/schema.ts
+++ b/packages/opencode/src/util/schema.ts
@@ -1,6 +1,16 @@
import { Schema } from "effect"
/**
+ * Integer greater than zero.
+ */
+export const PositiveInt = Schema.Int.check(Schema.isGreaterThan(0))
+
+/**
+ * Integer greater than or equal to zero.
+ */
+export const NonNegativeInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))
+
+/**
* Attach static methods to a schema object. Designed to be used with `.pipe()`:
*
* @example