feat(core): bridge GET /config through experimental HttpApi (#23712)
This commit is contained in:
@@ -101,7 +101,8 @@ const normalize = (agent: z.infer<typeof Info>) => {
|
||||
}
|
||||
globalThis.Object.assign(permission, agent.permission)
|
||||
|
||||
return { ...agent, options, permission, steps: agent.steps ?? agent.maxSteps }
|
||||
const steps = agent.steps ?? agent.maxSteps
|
||||
return { ...agent, options, permission, ...(steps !== undefined ? { steps } : {}) }
|
||||
}
|
||||
|
||||
export const Info = zod(AgentSchema).transform(normalize).meta({ ref: "AgentConfig" }) as unknown as z.ZodType<
|
||||
|
||||
@@ -91,7 +91,7 @@ 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))
|
||||
|
||||
const InfoSchema = Schema.Struct({
|
||||
export const InfoSchema = Schema.Struct({
|
||||
$schema: Schema.optional(Schema.String).annotate({
|
||||
description: "JSON schema reference for configuration validation",
|
||||
}),
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Schema } from "effect"
|
||||
import { zod } from "@/util/effect-zod"
|
||||
import { withStatics } from "@/util/schema"
|
||||
|
||||
export class Local extends Schema.Class<Local>("McpLocalConfig")({
|
||||
export const Local = Schema.Struct({
|
||||
type: Schema.Literal("local").annotate({ description: "Type of MCP server connection" }),
|
||||
command: Schema.mutable(Schema.Array(Schema.String)).annotate({
|
||||
description: "Command and arguments to run the MCP server",
|
||||
@@ -16,11 +16,12 @@ export class Local extends Schema.Class<Local>("McpLocalConfig")({
|
||||
timeout: Schema.optional(Schema.Number).annotate({
|
||||
description: "Timeout in ms for MCP server requests. Defaults to 5000 (5 seconds) if not specified.",
|
||||
}),
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
})
|
||||
.annotate({ identifier: "McpLocalConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export type Local = Schema.Schema.Type<typeof Local>
|
||||
|
||||
export class OAuth extends Schema.Class<OAuth>("McpOAuthConfig")({
|
||||
export const OAuth = Schema.Struct({
|
||||
clientId: Schema.optional(Schema.String).annotate({
|
||||
description: "OAuth client ID. If not provided, dynamic client registration (RFC 7591) will be attempted.",
|
||||
}),
|
||||
@@ -31,11 +32,12 @@ export class OAuth extends Schema.Class<OAuth>("McpOAuthConfig")({
|
||||
redirectUri: Schema.optional(Schema.String).annotate({
|
||||
description: "OAuth redirect URI (default: http://127.0.0.1:19876/mcp/oauth/callback).",
|
||||
}),
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
})
|
||||
.annotate({ identifier: "McpOAuthConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export type OAuth = Schema.Schema.Type<typeof OAuth>
|
||||
|
||||
export class Remote extends Schema.Class<Remote>("McpRemoteConfig")({
|
||||
export const Remote = Schema.Struct({
|
||||
type: Schema.Literal("remote").annotate({ description: "Type of MCP server connection" }),
|
||||
url: Schema.String.annotate({ description: "URL of the remote MCP server" }),
|
||||
enabled: Schema.optional(Schema.Boolean).annotate({
|
||||
@@ -50,9 +52,10 @@ export class Remote extends Schema.Class<Remote>("McpRemoteConfig")({
|
||||
timeout: Schema.optional(Schema.Number).annotate({
|
||||
description: "Timeout in ms for MCP server requests. Defaults to 5000 (5 seconds) if not specified.",
|
||||
}),
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
})
|
||||
.annotate({ identifier: "McpRemoteConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export type Remote = Schema.Schema.Type<typeof Remote>
|
||||
|
||||
export const Info = Schema.Union([Local, Remote])
|
||||
.annotate({ discriminator: "type" })
|
||||
|
||||
@@ -70,7 +70,7 @@ export const Model = Schema.Struct({
|
||||
),
|
||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
|
||||
export class Info extends Schema.Class<Info>("ProviderConfig")({
|
||||
export const Info = Schema.Struct({
|
||||
api: Schema.optional(Schema.String),
|
||||
name: Schema.optional(Schema.String),
|
||||
env: Schema.optional(Schema.mutable(Schema.Array(Schema.String))),
|
||||
@@ -107,8 +107,9 @@ export class Info extends Schema.Class<Info>("ProviderConfig")({
|
||||
),
|
||||
),
|
||||
models: Schema.optional(Schema.Record(Schema.String, Model)),
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
})
|
||||
.annotate({ identifier: "ProviderConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export type Info = Schema.Schema.Type<typeof Info>
|
||||
|
||||
export * as ConfigProvider from "./provider"
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Schema } from "effect"
|
||||
import { zod } from "@/util/effect-zod"
|
||||
import { withStatics } from "@/util/schema"
|
||||
|
||||
export class Server extends Schema.Class<Server>("ServerConfig")({
|
||||
export const Server = Schema.Struct({
|
||||
port: Schema.optional(Schema.Number.check(Schema.isInt()).check(Schema.isGreaterThan(0))).annotate({
|
||||
description: "Port to listen on",
|
||||
}),
|
||||
@@ -13,8 +14,9 @@ export class Server extends Schema.Class<Server>("ServerConfig")({
|
||||
cors: Schema.optional(Schema.mutable(Schema.Array(Schema.String))).annotate({
|
||||
description: "Additional domains to allow for CORS",
|
||||
}),
|
||||
}) {
|
||||
static readonly zod = zod(this)
|
||||
}
|
||||
})
|
||||
.annotate({ identifier: "ServerConfig" })
|
||||
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||
export type Server = Schema.Schema.Type<typeof Server>
|
||||
|
||||
export * as ConfigServer from "./server"
|
||||
|
||||
@@ -9,6 +9,15 @@ export const ConfigApi = HttpApi.make("config")
|
||||
.add(
|
||||
HttpApiGroup.make("config")
|
||||
.add(
|
||||
HttpApiEndpoint.get("get", root, {
|
||||
success: Config.InfoSchema,
|
||||
}).annotateMerge(
|
||||
OpenApi.annotations({
|
||||
identifier: "config.get",
|
||||
summary: "Get configuration",
|
||||
description: "Retrieve the current OpenCode configuration settings and preferences.",
|
||||
}),
|
||||
),
|
||||
HttpApiEndpoint.get("providers", `${root}/providers`, {
|
||||
success: Provider.ConfigProvidersResult,
|
||||
}).annotateMerge(
|
||||
@@ -36,16 +45,23 @@ export const ConfigApi = HttpApi.make("config")
|
||||
|
||||
export const configHandlers = Layer.unwrap(
|
||||
Effect.gen(function* () {
|
||||
const svc = yield* Provider.Service
|
||||
const providerSvc = yield* Provider.Service
|
||||
const configSvc = yield* Config.Service
|
||||
|
||||
const get = Effect.fn("ConfigHttpApi.get")(function* () {
|
||||
return yield* configSvc.get()
|
||||
})
|
||||
|
||||
const providers = Effect.fn("ConfigHttpApi.providers")(function* () {
|
||||
const providers = yield* svc.list()
|
||||
const providers = yield* providerSvc.list()
|
||||
return {
|
||||
providers: Object.values(providers),
|
||||
default: Provider.defaultModelIDs(providers),
|
||||
}
|
||||
})
|
||||
|
||||
return HttpApiBuilder.group(ConfigApi, "config", (handlers) => handlers.handle("providers", providers))
|
||||
return HttpApiBuilder.group(ConfigApi, "config", (handlers) =>
|
||||
handlers.handle("get", get).handle("providers", providers),
|
||||
)
|
||||
}),
|
||||
).pipe(Layer.provide(Provider.defaultLayer), Layer.provide(Config.defaultLayer))
|
||||
|
||||
@@ -40,6 +40,7 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
|
||||
app.post("/question/:requestID/reject", (c) => handler(c.req.raw, context))
|
||||
app.get("/permission", (c) => handler(c.req.raw, context))
|
||||
app.post("/permission/:requestID/reply", (c) => handler(c.req.raw, context))
|
||||
app.get("/config", (c) => handler(c.req.raw, context))
|
||||
app.get("/config/providers", (c) => handler(c.req.raw, context))
|
||||
app.get("/provider", (c) => handler(c.req.raw, context))
|
||||
app.get("/provider/auth", (c) => handler(c.req.raw, context))
|
||||
|
||||
Reference in New Issue
Block a user