feat(httpapi): bridge catalog read endpoints (#24353)

This commit is contained in:
Kit Langton
2026-04-25 14:00:30 -04:00
committed by GitHub
parent 705f792e87
commit eb0219988b
9 changed files with 208 additions and 81 deletions

View File

@@ -1,5 +1,10 @@
import { Agent } from "@/agent/agent"
import { Command } from "@/command"
import { Format } from "@/format"
import { Global } from "@opencode-ai/core/global"
import { LSP } from "@/lsp"
import { Vcs } from "@/project"
import { Skill } from "@/skill"
import * as InstanceState from "@/effect/instance-state"
import { Effect, Layer, Schema } from "effect"
import { HttpApi, HttpApiBuilder, HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
@@ -21,6 +26,11 @@ export const InstancePaths = {
path: "/path",
vcs: "/vcs",
vcsDiff: "/vcs/diff",
command: "/command",
agent: "/agent",
skill: "/skill",
lsp: "/lsp",
formatter: "/formatter",
} as const
export const InstanceApi = HttpApi.make("instance")
@@ -57,6 +67,51 @@ export const InstanceApi = HttpApi.make("instance")
description: "Retrieve the current git diff for the working tree or against the default branch.",
}),
),
HttpApiEndpoint.get("command", InstancePaths.command, {
success: Schema.Array(Command.Info),
}).annotateMerge(
OpenApi.annotations({
identifier: "command.list",
summary: "List commands",
description: "Get a list of all available commands in the OpenCode system.",
}),
),
HttpApiEndpoint.get("agent", InstancePaths.agent, {
success: Schema.Array(Agent.Info),
}).annotateMerge(
OpenApi.annotations({
identifier: "app.agents",
summary: "List agents",
description: "Get a list of all available AI agents in the OpenCode system.",
}),
),
HttpApiEndpoint.get("skill", InstancePaths.skill, {
success: Schema.Array(Skill.Info),
}).annotateMerge(
OpenApi.annotations({
identifier: "app.skills",
summary: "List skills",
description: "Get a list of all available skills in the OpenCode system.",
}),
),
HttpApiEndpoint.get("lsp", InstancePaths.lsp, {
success: Schema.Array(LSP.Status),
}).annotateMerge(
OpenApi.annotations({
identifier: "lsp.status",
summary: "Get LSP status",
description: "Get LSP server status",
}),
),
HttpApiEndpoint.get("formatter", InstancePaths.formatter, {
success: Schema.Array(Format.Status),
}).annotateMerge(
OpenApi.annotations({
identifier: "formatter.status",
summary: "Get formatter status",
description: "Get formatter status",
}),
),
)
.annotateMerge(
OpenApi.annotations({
@@ -76,6 +131,11 @@ export const InstanceApi = HttpApi.make("instance")
export const instanceHandlers = Layer.unwrap(
Effect.gen(function* () {
const agent = yield* Agent.Service
const command = yield* Command.Service
const format = yield* Format.Service
const lsp = yield* LSP.Service
const skill = yield* Skill.Service
const vcs = yield* Vcs.Service
const getPath = Effect.fn("InstanceHttpApi.path")(function* () {
@@ -98,8 +158,43 @@ export const instanceHandlers = Layer.unwrap(
return yield* vcs.diff(ctx.query.mode)
})
const getCommand = Effect.fn("InstanceHttpApi.command")(function* () {
return yield* command.list()
})
const getAgent = Effect.fn("InstanceHttpApi.agent")(function* () {
return yield* agent.list()
})
const getSkill = Effect.fn("InstanceHttpApi.skill")(function* () {
return yield* skill.all()
})
const getLsp = Effect.fn("InstanceHttpApi.lsp")(function* () {
return yield* lsp.status()
})
const getFormatter = Effect.fn("InstanceHttpApi.formatter")(function* () {
return yield* format.status()
})
return HttpApiBuilder.group(InstanceApi, "instance", (handlers) =>
handlers.handle("path", getPath).handle("vcs", getVcs).handle("vcsDiff", getVcsDiff),
handlers
.handle("path", getPath)
.handle("vcs", getVcs)
.handle("vcsDiff", getVcsDiff)
.handle("command", getCommand)
.handle("agent", getAgent)
.handle("skill", getSkill)
.handle("lsp", getLsp)
.handle("formatter", getFormatter),
)
}),
).pipe(Layer.provide(Vcs.defaultLayer))
).pipe(
Layer.provide(Agent.defaultLayer),
Layer.provide(Command.defaultLayer),
Layer.provide(Format.defaultLayer),
Layer.provide(LSP.defaultLayer),
Layer.provide(Skill.defaultLayer),
Layer.provide(Vcs.defaultLayer),
)

View File

@@ -57,6 +57,11 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
app.get(InstancePaths.path, (c) => handler(c.req.raw, context))
app.get(InstancePaths.vcs, (c) => handler(c.req.raw, context))
app.get(InstancePaths.vcsDiff, (c) => handler(c.req.raw, context))
app.get(InstancePaths.command, (c) => handler(c.req.raw, context))
app.get(InstancePaths.agent, (c) => handler(c.req.raw, context))
app.get(InstancePaths.skill, (c) => handler(c.req.raw, context))
app.get(InstancePaths.lsp, (c) => handler(c.req.raw, context))
app.get(InstancePaths.formatter, (c) => handler(c.req.raw, context))
app.get(McpPaths.status, (c) => handler(c.req.raw, context))
}
@@ -201,7 +206,7 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
description: "List of commands",
content: {
"application/json": {
schema: resolver(Command.Info.array()),
schema: resolver(Command.Info.zod.array()),
},
},
},
@@ -224,7 +229,7 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
description: "List of agents",
content: {
"application/json": {
schema: resolver(Agent.Info.array()),
schema: resolver(Agent.Info.zod.array()),
},
},
},
@@ -247,7 +252,7 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
description: "List of skills",
content: {
"application/json": {
schema: resolver(Skill.Info.array()),
schema: resolver(Skill.Info.zod.array()),
},
},
},
@@ -293,7 +298,7 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
description: "Formatter status",
content: {
"application/json": {
schema: resolver(Format.Status.array()),
schema: resolver(Format.Status.zod.array()),
},
},
},