Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ tmp
dist
ts-dist
.turbo
packages/*/generated
**/.serena
.serena/
/result
Expand Down
19 changes: 17 additions & 2 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"scripts": {
"dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts",
"typecheck": "bun turbo typecheck",
"generate": "bun ./script/generate.ts",
"generate:schemas": "bun ./script/generate-from-schemas.ts",
"prepare": "husky",
"random": "echo 'Random script'",
"hello": "echo 'Hello World!'",
Expand Down Expand Up @@ -62,7 +64,10 @@
"devDependencies": {
"@actions/artifact": "5.0.1",
"@tsconfig/bun": "catalog:",
"ajv": "8.17.1",
"ajv-formats": "3.0.1",
"husky": "9.1.7",
"json-schema-to-zod": "2.7.0",
"prettier": "3.6.2",
"sst": "3.17.23",
"turbo": "2.5.6"
Expand Down
31 changes: 6 additions & 25 deletions packages/opencode/src/agent/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,13 @@ import PROMPT_TITLE from "./prompt/title.txt"
import { PermissionNext } from "@/permission/next"
import { mergeDeep, pipe, sortBy, values } from "remeda"

// Generated from JSON Schema - see schema/agentInfo.schema.json
import { agentInfoSchema, type AgentInfo } from "@generated/validators/agentInfo"

export namespace Agent {
export const Info = z
.object({
name: z.string(),
description: z.string().optional(),
mode: z.enum(["subagent", "primary", "all"]),
native: z.boolean().optional(),
hidden: z.boolean().optional(),
topP: z.number().optional(),
temperature: z.number().optional(),
color: z.string().optional(),
permission: PermissionNext.Ruleset,
model: z
.object({
modelID: z.string(),
providerID: z.string(),
})
.optional(),
prompt: z.string().optional(),
options: z.record(z.string(), z.any()),
steps: z.number().int().positive().optional(),
})
.meta({
ref: "Agent",
})
export type Info = z.infer<typeof Info>
// Generated from JSON Schema - see schema/agentInfo.schema.json
export const Info = agentInfoSchema
export type Info = AgentInfo

const state = Instance.state(async () => {
const cfg = await Config.get()
Expand Down
41 changes: 16 additions & 25 deletions packages/opencode/src/auth/index.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,27 @@
import path from "path"
import { Global } from "../global"
import fs from "fs/promises"
import z from "zod"
import { authSchema, type Auth as AuthType } from "@generated/validators/auth"
import { oauthSchema, type Oauth as OauthType } from "@generated/validators/oauth"
import { apiAuthSchema, type ApiAuth as ApiAuthType } from "@generated/validators/apiAuth"
import { wellKnownAuthSchema, type WellKnownAuth as WellKnownAuthType } from "@generated/validators/wellKnownAuth"

export namespace Auth {
export const Oauth = z
.object({
type: z.literal("oauth"),
refresh: z.string(),
access: z.string(),
expires: z.number(),
enterpriseUrl: z.string().optional(),
})
.meta({ ref: "OAuth" })
// Generated from JSON Schema - see schema/oauth.schema.json
export const Oauth = oauthSchema
export type Oauth = OauthType

export const Api = z
.object({
type: z.literal("api"),
key: z.string(),
})
.meta({ ref: "ApiAuth" })
// Generated from JSON Schema - see schema/apiAuth.schema.json
export const Api = apiAuthSchema
export type Api = ApiAuthType

export const WellKnown = z
.object({
type: z.literal("wellknown"),
key: z.string(),
token: z.string(),
})
.meta({ ref: "WellKnownAuth" })
// Generated from JSON Schema - see schema/wellKnownAuth.schema.json
export const WellKnown = wellKnownAuthSchema
export type WellKnown = WellKnownAuthType

export const Info = z.discriminatedUnion("type", [Oauth, Api, WellKnown]).meta({ ref: "Auth" })
export type Info = z.infer<typeof Info>
// Generated from JSON Schema - see schema/auth.schema.json
export const Info = authSchema
export type Info = AuthType

const filepath = path.join(Global.Path.data, "auth.json")

Expand Down
62 changes: 22 additions & 40 deletions packages/opencode/src/permission/next.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,27 @@ import { Log } from "@/util/log"
import { Wildcard } from "@/util/wildcard"
import z from "zod"

// Generated from JSON Schema - see schema/*.schema.json
import { permissionActionSchema, type PermissionAction } from "@generated/validators/permissionAction"
import { permissionReplySchema, type PermissionReply } from "@generated/validators/permissionReply"
import { permissionRequestSchema, type PermissionRequest } from "@generated/validators/permissionRequest"
import { permissionRuleSchema, type PermissionRule } from "@generated/validators/permissionRule"
import { permissionRulesetSchema, type PermissionRuleset } from "@generated/validators/permissionRuleset"

export namespace PermissionNext {
const log = Log.create({ service: "permission" })

export const Action = z.enum(["allow", "deny", "ask"]).meta({
ref: "PermissionAction",
})
export type Action = z.infer<typeof Action>
// Generated from JSON Schema - see schema/permissionAction.schema.json
export const Action = permissionActionSchema
export type Action = PermissionAction

export const Rule = z
.object({
permission: z.string(),
pattern: z.string(),
action: Action,
})
.meta({
ref: "PermissionRule",
})
export type Rule = z.infer<typeof Rule>
// Generated from JSON Schema - see schema/permissionRule.schema.json
export const Rule = permissionRuleSchema
export type Rule = PermissionRule

export const Ruleset = Rule.array().meta({
ref: "PermissionRuleset",
})
export type Ruleset = z.infer<typeof Ruleset>
// Generated from JSON Schema - see schema/permissionRuleset.schema.json
export const Ruleset = permissionRulesetSchema
export type Ruleset = PermissionRuleset

export function fromConfig(permission: Config.Permission) {
const ruleset: Ruleset = []
Expand All @@ -53,29 +51,13 @@ export namespace PermissionNext {
return rulesets.flat()
}

export const Request = z
.object({
id: Identifier.schema("permission"),
sessionID: Identifier.schema("session"),
permission: z.string(),
patterns: z.string().array(),
metadata: z.record(z.string(), z.any()),
always: z.string().array(),
tool: z
.object({
messageID: z.string(),
callID: z.string(),
})
.optional(),
})
.meta({
ref: "PermissionRequest",
})

export type Request = z.infer<typeof Request>
// Generated from JSON Schema - see schema/permissionRequest.schema.json
export const Request = permissionRequestSchema
export type Request = PermissionRequest

export const Reply = z.enum(["once", "always", "reject"])
export type Reply = z.infer<typeof Reply>
// Generated from JSON Schema - see schema/permissionReply.schema.json
export const Reply = permissionReplySchema
export type Reply = PermissionReply

export const Approval = z.object({
projectID: z.string(),
Expand Down
93 changes: 9 additions & 84 deletions packages/opencode/src/provider/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { Env } from "../env"
import { Instance } from "../project/instance"
import { Flag } from "../flag/flag"
import { iife } from "@/util/iife"
import { modelInfoSchema, type ModelInfo } from "@generated/validators/modelInfo"
import { providerInfoSchema, type ProviderInfo } from "@generated/validators/providerInfo"

// Direct imports for bundled providers
import { createAmazonBedrock, type AmazonBedrockProviderSettings } from "@ai-sdk/amazon-bedrock"
Expand Down Expand Up @@ -429,90 +431,13 @@ export namespace Provider {
},
}

export const Model = z
.object({
id: z.string(),
providerID: z.string(),
api: z.object({
id: z.string(),
url: z.string(),
npm: z.string(),
}),
name: z.string(),
family: z.string().optional(),
capabilities: z.object({
temperature: z.boolean(),
reasoning: z.boolean(),
attachment: z.boolean(),
toolcall: z.boolean(),
input: z.object({
text: z.boolean(),
audio: z.boolean(),
image: z.boolean(),
video: z.boolean(),
pdf: z.boolean(),
}),
output: z.object({
text: z.boolean(),
audio: z.boolean(),
image: z.boolean(),
video: z.boolean(),
pdf: z.boolean(),
}),
interleaved: z.union([
z.boolean(),
z.object({
field: z.enum(["reasoning_content", "reasoning_details"]),
}),
]),
}),
cost: z.object({
input: z.number(),
output: z.number(),
cache: z.object({
read: z.number(),
write: z.number(),
}),
experimentalOver200K: z
.object({
input: z.number(),
output: z.number(),
cache: z.object({
read: z.number(),
write: z.number(),
}),
})
.optional(),
}),
limit: z.object({
context: z.number(),
output: z.number(),
}),
status: z.enum(["alpha", "beta", "deprecated", "active"]),
options: z.record(z.string(), z.any()),
headers: z.record(z.string(), z.string()),
release_date: z.string(),
variants: z.record(z.string(), z.record(z.string(), z.any())).optional(),
})
.meta({
ref: "Model",
})
export type Model = z.infer<typeof Model>

export const Info = z
.object({
id: z.string(),
name: z.string(),
source: z.enum(["env", "config", "custom", "api"]),
env: z.string().array(),
key: z.string().optional(),
options: z.record(z.string(), z.any()),
models: z.record(z.string(), Model),
})
.meta({
ref: "Provider",
})
export type Info = z.infer<typeof Info>
// Generated from JSON Schema - see schema/modelInfo.schema.json
export const Model = modelInfoSchema
export type Model = ModelInfo

// Generated from JSON Schema - see schema/providerInfo.schema.json
export const Info = providerInfoSchema
export type Info = ProviderInfo

function fromModelsDevModel(provider: ModelsDev.Provider, model: ModelsDev.Model): Model {
const m: Model = {
Expand Down
Loading