wip: api for tui

This commit is contained in:
Dax Raad
2025-07-21 19:53:22 -04:00
parent 5611ef8b28
commit f20ef61bc7
18 changed files with 594 additions and 39 deletions

View File

@@ -1,6 +1,5 @@
import { Provider } from "../../provider/provider"
import { Server } from "../../server/server"
import { Share } from "../../share/share"
import { bootstrap } from "../bootstrap"
import { cmd } from "./cmd"
@@ -32,7 +31,6 @@ export const ServeCommand = cmd({
const hostname = args.hostname
const port = args.port
await Share.init()
const server = Server.listen({
port,
hostname,

View File

@@ -36,6 +36,17 @@ export const TuiCommand = cmd({
.option("mode", {
type: "string",
describe: "mode to use",
})
.option("port", {
type: "number",
describe: "port to listen on",
default: 0,
})
.option("hostname", {
alias: ["h"],
type: "string",
describe: "hostname to listen on",
default: "127.0.0.1",
}),
handler: async (args) => {
while (true) {
@@ -54,8 +65,8 @@ export const TuiCommand = cmd({
}
const server = Server.listen({
port: 0,
hostname: "127.0.0.1",
port: args.port,
hostname: args.hostname,
})
let cmd = ["go", "run", "./main.go"]

View File

@@ -17,6 +17,7 @@ import { File } from "../file"
import { LSP } from "../lsp"
import { MessageV2 } from "../session/message-v2"
import { Mode } from "../session/mode"
import { callTui, TuiRoute } from "./tui"
const ERRORS = {
400: {
@@ -703,6 +704,48 @@ export namespace Server {
return c.json(modes)
},
)
.post(
"/tui/prompt",
describeRoute({
description: "Send a prompt to the TUI",
responses: {
200: {
description: "Prompt processed successfully",
content: {
"application/json": {
schema: resolver(z.boolean()),
},
},
},
},
}),
zValidator(
"json",
z.object({
text: z.string(),
parts: MessageV2.Part.array(),
}),
),
async (c) => c.json(await callTui(c)),
)
.post(
"/tui/open-help",
describeRoute({
description: "Open the help dialog",
responses: {
200: {
description: "Help dialog opened successfully",
content: {
"application/json": {
schema: resolver(z.boolean()),
},
},
},
},
}),
async (c) => c.json(await callTui(c)),
)
.route("/tui/control", TuiRoute)
return result
}

View File

@@ -0,0 +1,30 @@
import { Hono, type Context } from "hono"
import { AsyncQueue } from "../util/queue"
interface Request {
path: string
body: any
}
const request = new AsyncQueue<Request>()
const response = new AsyncQueue<any>()
export async function callTui(ctx: Context) {
const body = await ctx.req.json()
request.push({
path: ctx.req.path,
body,
})
return response.next()
}
export const TuiRoute = new Hono()
.get("/next", async (c) => {
const req = await request.next()
return c.json(req)
})
.post("/response", async (c) => {
const body = await c.req.json()
response.push(body)
return c.json(true)
})

View File

@@ -0,0 +1,19 @@
export class AsyncQueue<T> implements AsyncIterable<T> {
private queue: T[] = []
private resolvers: ((value: T) => void)[] = []
push(item: T) {
const resolve = this.resolvers.shift()
if (resolve) resolve(item)
else this.queue.push(item)
}
async next(): Promise<T> {
if (this.queue.length > 0) return this.queue.shift()!
return new Promise((resolve) => this.resolvers.push(resolve))
}
async *[Symbol.asyncIterator]() {
while (true) yield await this.next()
}
}