opencontrol
Version:
82 lines (78 loc) • 2.13 kB
text/typescript
import { Hono } from "hono"
import { Tool } from "./tool.js"
import { createMcp } from "./mcp.js"
import { cors } from "hono/cors"
import HTML from "opencontrol-frontend/dist/index.html" with { type: "text" }
import { zValidator } from "@hono/zod-validator"
import {
AISDKError,
APICallError,
LanguageModelV1,
LanguageModelV1CallOptions,
} from "ai"
import { z } from "zod"
import { HTTPException } from "hono/http-exception"
import { bearerAuth } from "hono/bearer-auth"
export interface OpenControlOptions {
tools: Tool[]
password?: string
model?: LanguageModelV1
app?: Hono
}
export type App = ReturnType<typeof create>
export function create(input: OpenControlOptions) {
const mcp = createMcp({ tools: input.tools })
const token =
input.password ||
process.env.OPENCONTROL_PASSWORD ||
process.env.OPENCONTROL_KEY ||
"password"
console.log("opencontrol password:", token)
const app = input.app ?? new Hono()
return app
.use(
cors({
origin: "*",
allowHeaders: ["*"],
allowMethods: ["GET"],
credentials: false,
}),
)
.get("/", (c) => {
return c.html(HTML)
})
.use(
bearerAuth({
token,
}),
)
.get("/auth", (c) => {
return c.json({})
})
.post(
"/generate",
zValidator("json", z.custom<LanguageModelV1CallOptions>()),
async (c) => {
if (!input.model)
throw new HTTPException(400, { message: "No model configured" })
const body = c.req.valid("json")
try {
const result = await input.model.doGenerate(body)
return c.json(result)
} catch (error) {
console.error(error)
if (error instanceof APICallError) {
throw new HTTPException(error.statusCode || (500 as any), {
message: "error",
})
}
throw new HTTPException(500, { message: "error" })
}
},
)
.post("/mcp", async (c) => {
const body = await c.req.json()
const result = await mcp.process(body)
return c.json(result)
})
}