feat(server): wrap remaining route handlers in request spans (#23169)
This commit is contained in:
@@ -5,7 +5,6 @@ import { Config } from "@/config"
|
|||||||
import { Provider } from "@/provider"
|
import { Provider } from "@/provider"
|
||||||
import { errors } from "../../error"
|
import { errors } from "../../error"
|
||||||
import { lazy } from "@/util/lazy"
|
import { lazy } from "@/util/lazy"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
|
||||||
import { jsonRequest } from "./trace"
|
import { jsonRequest } from "./trace"
|
||||||
|
|
||||||
export const ConfigRoutes = lazy(() =>
|
export const ConfigRoutes = lazy(() =>
|
||||||
@@ -52,11 +51,13 @@ export const ConfigRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
validator("json", Config.Info),
|
validator("json", Config.Info),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const config = c.req.valid("json")
|
jsonRequest("ConfigRoutes.update", c, function* () {
|
||||||
await AppRuntime.runPromise(Config.Service.use((cfg) => cfg.update(config)))
|
const config = c.req.valid("json")
|
||||||
return c.json(config)
|
const cfg = yield* Config.Service
|
||||||
},
|
yield* cfg.update(config)
|
||||||
|
return config
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/providers",
|
"/providers",
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ import { Config } from "@/config"
|
|||||||
import { ConsoleState } from "@/config/console-state"
|
import { ConsoleState } from "@/config/console-state"
|
||||||
import { Account } from "@/account/account"
|
import { Account } from "@/account/account"
|
||||||
import { AccountID, OrgID } from "@/account/schema"
|
import { AccountID, OrgID } from "@/account/schema"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
|
||||||
import { errors } from "../../error"
|
import { errors } from "../../error"
|
||||||
import { lazy } from "@/util/lazy"
|
import { lazy } from "@/util/lazy"
|
||||||
import { Effect, Option } from "effect"
|
import { Effect, Option } from "effect"
|
||||||
import { Agent } from "@/agent/agent"
|
import { Agent } from "@/agent/agent"
|
||||||
|
import { jsonRequest, runRequest } from "./trace"
|
||||||
|
|
||||||
const ConsoleOrgOption = z.object({
|
const ConsoleOrgOption = z.object({
|
||||||
accountID: z.string(),
|
accountID: z.string(),
|
||||||
@@ -55,22 +55,18 @@ export const ExperimentalRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const result = await AppRuntime.runPromise(
|
jsonRequest("ExperimentalRoutes.console.get", c, function* () {
|
||||||
Effect.gen(function* () {
|
const config = yield* Config.Service
|
||||||
const config = yield* Config.Service
|
const account = yield* Account.Service
|
||||||
const account = yield* Account.Service
|
const [state, groups] = yield* Effect.all([config.getConsoleState(), account.orgsByAccount()], {
|
||||||
const [state, groups] = yield* Effect.all([config.getConsoleState(), account.orgsByAccount()], {
|
concurrency: "unbounded",
|
||||||
concurrency: "unbounded",
|
})
|
||||||
})
|
return {
|
||||||
return {
|
...state,
|
||||||
...state,
|
switchableOrgCount: groups.reduce((count, group) => count + group.orgs.length, 0),
|
||||||
switchableOrgCount: groups.reduce((count, group) => count + group.orgs.length, 0),
|
}
|
||||||
}
|
}),
|
||||||
}),
|
|
||||||
)
|
|
||||||
return c.json(result)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/console/orgs",
|
"/console/orgs",
|
||||||
@@ -89,28 +85,25 @@ export const ExperimentalRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const orgs = await AppRuntime.runPromise(
|
jsonRequest("ExperimentalRoutes.console.listOrgs", c, function* () {
|
||||||
Effect.gen(function* () {
|
const account = yield* Account.Service
|
||||||
const account = yield* Account.Service
|
const [groups, active] = yield* Effect.all([account.orgsByAccount(), account.active()], {
|
||||||
const [groups, active] = yield* Effect.all([account.orgsByAccount(), account.active()], {
|
concurrency: "unbounded",
|
||||||
concurrency: "unbounded",
|
})
|
||||||
})
|
const info = Option.getOrUndefined(active)
|
||||||
const info = Option.getOrUndefined(active)
|
const orgs = groups.flatMap((group) =>
|
||||||
return groups.flatMap((group) =>
|
group.orgs.map((org) => ({
|
||||||
group.orgs.map((org) => ({
|
accountID: group.account.id,
|
||||||
accountID: group.account.id,
|
accountEmail: group.account.email,
|
||||||
accountEmail: group.account.email,
|
accountUrl: group.account.url,
|
||||||
accountUrl: group.account.url,
|
orgID: org.id,
|
||||||
orgID: org.id,
|
orgName: org.name,
|
||||||
orgName: org.name,
|
active: !!info && info.id === group.account.id && info.active_org_id === org.id,
|
||||||
active: !!info && info.id === group.account.id && info.active_org_id === org.id,
|
})),
|
||||||
})),
|
)
|
||||||
)
|
return { orgs }
|
||||||
}),
|
}),
|
||||||
)
|
|
||||||
return c.json({ orgs })
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/console/switch",
|
"/console/switch",
|
||||||
@@ -130,16 +123,13 @@ export const ExperimentalRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
validator("json", ConsoleSwitchBody),
|
validator("json", ConsoleSwitchBody),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const body = c.req.valid("json")
|
jsonRequest("ExperimentalRoutes.console.switchOrg", c, function* () {
|
||||||
await AppRuntime.runPromise(
|
const body = c.req.valid("json")
|
||||||
Effect.gen(function* () {
|
const account = yield* Account.Service
|
||||||
const account = yield* Account.Service
|
yield* account.use(AccountID.make(body.accountID), Option.some(OrgID.make(body.orgID)))
|
||||||
yield* account.use(AccountID.make(body.accountID), Option.some(OrgID.make(body.orgID)))
|
return true
|
||||||
}),
|
}),
|
||||||
)
|
|
||||||
return c.json(true)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/tool/ids",
|
"/tool/ids",
|
||||||
@@ -160,15 +150,11 @@ export const ExperimentalRoutes = lazy(() =>
|
|||||||
...errors(400),
|
...errors(400),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const ids = await AppRuntime.runPromise(
|
jsonRequest("ExperimentalRoutes.tool.ids", c, function* () {
|
||||||
Effect.gen(function* () {
|
const registry = yield* ToolRegistry.Service
|
||||||
const registry = yield* ToolRegistry.Service
|
return yield* registry.ids()
|
||||||
return yield* registry.ids()
|
}),
|
||||||
}),
|
|
||||||
)
|
|
||||||
return c.json(ids)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/tool",
|
"/tool",
|
||||||
@@ -210,7 +196,9 @@ export const ExperimentalRoutes = lazy(() =>
|
|||||||
),
|
),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const { provider, model } = c.req.valid("query")
|
const { provider, model } = c.req.valid("query")
|
||||||
const tools = await AppRuntime.runPromise(
|
const tools = await runRequest(
|
||||||
|
"ExperimentalRoutes.tool.list",
|
||||||
|
c,
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const agents = yield* Agent.Service
|
const agents = yield* Agent.Service
|
||||||
const registry = yield* ToolRegistry.Service
|
const registry = yield* ToolRegistry.Service
|
||||||
@@ -249,11 +237,12 @@ export const ExperimentalRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
validator("json", Worktree.CreateInput.optional()),
|
validator("json", Worktree.CreateInput.optional()),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const body = c.req.valid("json")
|
jsonRequest("ExperimentalRoutes.worktree.create", c, function* () {
|
||||||
const worktree = await AppRuntime.runPromise(Worktree.Service.use((svc) => svc.create(body)))
|
const body = c.req.valid("json")
|
||||||
return c.json(worktree)
|
const svc = yield* Worktree.Service
|
||||||
},
|
return yield* svc.create(body)
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/worktree",
|
"/worktree",
|
||||||
@@ -272,10 +261,11 @@ export const ExperimentalRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const sandboxes = await AppRuntime.runPromise(Project.Service.use((svc) => svc.sandboxes(Instance.project.id)))
|
jsonRequest("ExperimentalRoutes.worktree.list", c, function* () {
|
||||||
return c.json(sandboxes)
|
const svc = yield* Project.Service
|
||||||
},
|
return yield* svc.sandboxes(Instance.project.id)
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.delete(
|
.delete(
|
||||||
"/worktree",
|
"/worktree",
|
||||||
@@ -296,14 +286,15 @@ export const ExperimentalRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
validator("json", Worktree.RemoveInput),
|
validator("json", Worktree.RemoveInput),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const body = c.req.valid("json")
|
jsonRequest("ExperimentalRoutes.worktree.remove", c, function* () {
|
||||||
await AppRuntime.runPromise(Worktree.Service.use((svc) => svc.remove(body)))
|
const body = c.req.valid("json")
|
||||||
await AppRuntime.runPromise(
|
const worktree = yield* Worktree.Service
|
||||||
Project.Service.use((svc) => svc.removeSandbox(Instance.project.id, body.directory)),
|
const project = yield* Project.Service
|
||||||
)
|
yield* worktree.remove(body)
|
||||||
return c.json(true)
|
yield* project.removeSandbox(Instance.project.id, body.directory)
|
||||||
},
|
return true
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/worktree/reset",
|
"/worktree/reset",
|
||||||
@@ -324,11 +315,13 @@ export const ExperimentalRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
validator("json", Worktree.ResetInput),
|
validator("json", Worktree.ResetInput),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const body = c.req.valid("json")
|
jsonRequest("ExperimentalRoutes.worktree.reset", c, function* () {
|
||||||
await AppRuntime.runPromise(Worktree.Service.use((svc) => svc.reset(body)))
|
const body = c.req.valid("json")
|
||||||
return c.json(true)
|
const svc = yield* Worktree.Service
|
||||||
},
|
yield* svc.reset(body)
|
||||||
|
return true
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/session",
|
"/session",
|
||||||
@@ -406,15 +399,10 @@ export const ExperimentalRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
return c.json(
|
jsonRequest("ExperimentalRoutes.resource.list", c, function* () {
|
||||||
await AppRuntime.runPromise(
|
const mcp = yield* MCP.Service
|
||||||
Effect.gen(function* () {
|
return yield* mcp.resources()
|
||||||
const mcp = yield* MCP.Service
|
}),
|
||||||
return yield* mcp.resources()
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import { Hono } from "hono"
|
import { Hono } from "hono"
|
||||||
import { describeRoute, validator, resolver } from "hono-openapi"
|
import { describeRoute, validator, resolver } from "hono-openapi"
|
||||||
import { Effect } from "effect"
|
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
|
||||||
import { File } from "@/file"
|
import { File } from "@/file"
|
||||||
import { Ripgrep } from "@/file/ripgrep"
|
import { Ripgrep } from "@/file/ripgrep"
|
||||||
import { LSP } from "@/lsp"
|
import { LSP } from "@/lsp"
|
||||||
import { Instance } from "@/project/instance"
|
import { Instance } from "@/project/instance"
|
||||||
import { lazy } from "@/util/lazy"
|
import { lazy } from "@/util/lazy"
|
||||||
|
import { jsonRequest } from "./trace"
|
||||||
|
|
||||||
export const FileRoutes = lazy(() =>
|
export const FileRoutes = lazy(() =>
|
||||||
new Hono()
|
new Hono()
|
||||||
@@ -34,13 +33,13 @@ export const FileRoutes = lazy(() =>
|
|||||||
pattern: z.string(),
|
pattern: z.string(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const pattern = c.req.valid("query").pattern
|
jsonRequest("FileRoutes.findText", c, function* () {
|
||||||
const result = await AppRuntime.runPromise(
|
const pattern = c.req.valid("query").pattern
|
||||||
Ripgrep.Service.use((svc) => svc.search({ cwd: Instance.directory, pattern, limit: 10 })),
|
const svc = yield* Ripgrep.Service
|
||||||
)
|
const result = yield* svc.search({ cwd: Instance.directory, pattern, limit: 10 })
|
||||||
return c.json(result.items)
|
return result.items
|
||||||
},
|
}),
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/find/file",
|
"/find/file",
|
||||||
@@ -68,25 +67,17 @@ export const FileRoutes = lazy(() =>
|
|||||||
limit: z.coerce.number().int().min(1).max(200).optional(),
|
limit: z.coerce.number().int().min(1).max(200).optional(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const query = c.req.valid("query").query
|
jsonRequest("FileRoutes.findFile", c, function* () {
|
||||||
const dirs = c.req.valid("query").dirs
|
const query = c.req.valid("query")
|
||||||
const type = c.req.valid("query").type
|
const svc = yield* File.Service
|
||||||
const limit = c.req.valid("query").limit
|
return yield* svc.search({
|
||||||
const results = await AppRuntime.runPromise(
|
query: query.query,
|
||||||
Effect.gen(function* () {
|
limit: query.limit ?? 10,
|
||||||
return yield* File.Service.use((svc) =>
|
dirs: query.dirs !== "false",
|
||||||
svc.search({
|
type: query.type,
|
||||||
query,
|
})
|
||||||
limit: limit ?? 10,
|
}),
|
||||||
dirs: dirs !== "false",
|
|
||||||
type,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
return c.json(results)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/find/symbol",
|
"/find/symbol",
|
||||||
@@ -138,15 +129,11 @@ export const FileRoutes = lazy(() =>
|
|||||||
path: z.string(),
|
path: z.string(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const path = c.req.valid("query").path
|
jsonRequest("FileRoutes.list", c, function* () {
|
||||||
const content = await AppRuntime.runPromise(
|
const svc = yield* File.Service
|
||||||
Effect.gen(function* () {
|
return yield* svc.list(c.req.valid("query").path)
|
||||||
return yield* File.Service.use((svc) => svc.list(path))
|
}),
|
||||||
}),
|
|
||||||
)
|
|
||||||
return c.json(content)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/file/content",
|
"/file/content",
|
||||||
@@ -171,15 +158,11 @@ export const FileRoutes = lazy(() =>
|
|||||||
path: z.string(),
|
path: z.string(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const path = c.req.valid("query").path
|
jsonRequest("FileRoutes.read", c, function* () {
|
||||||
const content = await AppRuntime.runPromise(
|
const svc = yield* File.Service
|
||||||
Effect.gen(function* () {
|
return yield* svc.read(c.req.valid("query").path)
|
||||||
return yield* File.Service.use((svc) => svc.read(path))
|
}),
|
||||||
}),
|
|
||||||
)
|
|
||||||
return c.json(content)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/file/status",
|
"/file/status",
|
||||||
@@ -198,13 +181,10 @@ export const FileRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const content = await AppRuntime.runPromise(
|
jsonRequest("FileRoutes.status", c, function* () {
|
||||||
Effect.gen(function* () {
|
const svc = yield* File.Service
|
||||||
return yield* File.Service.use((svc) => svc.status())
|
return yield* svc.status()
|
||||||
}),
|
}),
|
||||||
)
|
|
||||||
return c.json(content)
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ import { ExperimentalRoutes } from "./experimental"
|
|||||||
import { ProviderRoutes } from "./provider"
|
import { ProviderRoutes } from "./provider"
|
||||||
import { EventRoutes } from "./event"
|
import { EventRoutes } from "./event"
|
||||||
import { SyncRoutes } from "./sync"
|
import { SyncRoutes } from "./sync"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
|
||||||
import { InstanceMiddleware } from "./middleware"
|
import { InstanceMiddleware } from "./middleware"
|
||||||
|
import { jsonRequest } from "./trace"
|
||||||
|
|
||||||
export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
|
export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
|
||||||
const app = new Hono()
|
const app = new Hono()
|
||||||
@@ -141,19 +141,14 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
return c.json(
|
jsonRequest("InstanceRoutes.vcs.get", c, function* () {
|
||||||
await AppRuntime.runPromise(
|
const vcs = yield* Vcs.Service
|
||||||
Effect.gen(function* () {
|
const [branch, default_branch] = yield* Effect.all([vcs.branch(), vcs.defaultBranch()], {
|
||||||
const vcs = yield* Vcs.Service
|
concurrency: 2,
|
||||||
const [branch, default_branch] = yield* Effect.all([vcs.branch(), vcs.defaultBranch()], {
|
})
|
||||||
concurrency: 2,
|
return { branch, default_branch }
|
||||||
})
|
}),
|
||||||
return { branch, default_branch }
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/vcs/diff",
|
"/vcs/diff",
|
||||||
@@ -178,16 +173,11 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
|
|||||||
mode: Vcs.Mode,
|
mode: Vcs.Mode,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
return c.json(
|
jsonRequest("InstanceRoutes.vcs.diff", c, function* () {
|
||||||
await AppRuntime.runPromise(
|
const vcs = yield* Vcs.Service
|
||||||
Effect.gen(function* () {
|
return yield* vcs.diff(c.req.valid("query").mode)
|
||||||
const vcs = yield* Vcs.Service
|
}),
|
||||||
return yield* vcs.diff(c.req.valid("query").mode)
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/command",
|
"/command",
|
||||||
@@ -206,10 +196,11 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const commands = await AppRuntime.runPromise(Command.Service.use((svc) => svc.list()))
|
jsonRequest("InstanceRoutes.command.list", c, function* () {
|
||||||
return c.json(commands)
|
const svc = yield* Command.Service
|
||||||
},
|
return yield* svc.list()
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/agent",
|
"/agent",
|
||||||
@@ -228,10 +219,11 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const modes = await AppRuntime.runPromise(Agent.Service.use((svc) => svc.list()))
|
jsonRequest("InstanceRoutes.agent.list", c, function* () {
|
||||||
return c.json(modes)
|
const svc = yield* Agent.Service
|
||||||
},
|
return yield* svc.list()
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/skill",
|
"/skill",
|
||||||
@@ -250,15 +242,11 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const skills = await AppRuntime.runPromise(
|
jsonRequest("InstanceRoutes.skill.list", c, function* () {
|
||||||
Effect.gen(function* () {
|
const skill = yield* Skill.Service
|
||||||
const skill = yield* Skill.Service
|
return yield* skill.all()
|
||||||
return yield* skill.all()
|
}),
|
||||||
}),
|
|
||||||
)
|
|
||||||
return c.json(skills)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/lsp",
|
"/lsp",
|
||||||
@@ -277,10 +265,11 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const items = await AppRuntime.runPromise(LSP.Service.use((lsp) => lsp.status()))
|
jsonRequest("InstanceRoutes.lsp.status", c, function* () {
|
||||||
return c.json(items)
|
const lsp = yield* LSP.Service
|
||||||
},
|
return yield* lsp.status()
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/formatter",
|
"/formatter",
|
||||||
@@ -299,8 +288,10 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
return c.json(await AppRuntime.runPromise(Format.Service.use((svc) => svc.status())))
|
jsonRequest("InstanceRoutes.formatter.status", c, function* () {
|
||||||
},
|
const svc = yield* Format.Service
|
||||||
|
return yield* svc.status()
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,11 @@ import { Hono } from "hono"
|
|||||||
import { describeRoute, validator, resolver } from "hono-openapi"
|
import { describeRoute, validator, resolver } from "hono-openapi"
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { MCP } from "@/mcp"
|
import { MCP } from "@/mcp"
|
||||||
import { Config } from "@/config"
|
|
||||||
import { ConfigMCP } from "@/config/mcp"
|
import { ConfigMCP } from "@/config/mcp"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
|
||||||
import { errors } from "../../error"
|
import { errors } from "../../error"
|
||||||
import { lazy } from "@/util/lazy"
|
import { lazy } from "@/util/lazy"
|
||||||
import { Effect } from "effect"
|
import { Effect } from "effect"
|
||||||
|
import { jsonRequest, runRequest } from "./trace"
|
||||||
|
|
||||||
export const McpRoutes = lazy(() =>
|
export const McpRoutes = lazy(() =>
|
||||||
new Hono()
|
new Hono()
|
||||||
@@ -28,9 +27,11 @@ export const McpRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
return c.json(await AppRuntime.runPromise(MCP.Service.use((mcp) => mcp.status())))
|
jsonRequest("McpRoutes.status", c, function* () {
|
||||||
},
|
const mcp = yield* MCP.Service
|
||||||
|
return yield* mcp.status()
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/",
|
"/",
|
||||||
@@ -57,11 +58,13 @@ export const McpRoutes = lazy(() =>
|
|||||||
config: ConfigMCP.Info.zod,
|
config: ConfigMCP.Info.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const { name, config } = c.req.valid("json")
|
jsonRequest("McpRoutes.add", c, function* () {
|
||||||
const result = await AppRuntime.runPromise(MCP.Service.use((mcp) => mcp.add(name, config)))
|
const { name, config } = c.req.valid("json")
|
||||||
return c.json(result.status)
|
const mcp = yield* MCP.Service
|
||||||
},
|
const result = yield* mcp.add(name, config)
|
||||||
|
return result.status
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:name/auth",
|
"/:name/auth",
|
||||||
@@ -87,7 +90,9 @@ export const McpRoutes = lazy(() =>
|
|||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const name = c.req.param("name")
|
const name = c.req.param("name")
|
||||||
const result = await AppRuntime.runPromise(
|
const result = await runRequest(
|
||||||
|
"McpRoutes.auth.start",
|
||||||
|
c,
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const mcp = yield* MCP.Service
|
const mcp = yield* MCP.Service
|
||||||
const supports = yield* mcp.supportsOAuth(name)
|
const supports = yield* mcp.supportsOAuth(name)
|
||||||
@@ -129,12 +134,13 @@ export const McpRoutes = lazy(() =>
|
|||||||
code: z.string().describe("Authorization code from OAuth callback"),
|
code: z.string().describe("Authorization code from OAuth callback"),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const name = c.req.param("name")
|
jsonRequest("McpRoutes.auth.callback", c, function* () {
|
||||||
const { code } = c.req.valid("json")
|
const name = c.req.param("name")
|
||||||
const status = await AppRuntime.runPromise(MCP.Service.use((mcp) => mcp.finishAuth(name, code)))
|
const { code } = c.req.valid("json")
|
||||||
return c.json(status)
|
const mcp = yield* MCP.Service
|
||||||
},
|
return yield* mcp.finishAuth(name, code)
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:name/auth/authenticate",
|
"/:name/auth/authenticate",
|
||||||
@@ -156,7 +162,9 @@ export const McpRoutes = lazy(() =>
|
|||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const name = c.req.param("name")
|
const name = c.req.param("name")
|
||||||
const result = await AppRuntime.runPromise(
|
const result = await runRequest(
|
||||||
|
"McpRoutes.auth.authenticate",
|
||||||
|
c,
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const mcp = yield* MCP.Service
|
const mcp = yield* MCP.Service
|
||||||
const supports = yield* mcp.supportsOAuth(name)
|
const supports = yield* mcp.supportsOAuth(name)
|
||||||
@@ -191,11 +199,13 @@ export const McpRoutes = lazy(() =>
|
|||||||
...errors(404),
|
...errors(404),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const name = c.req.param("name")
|
jsonRequest("McpRoutes.auth.remove", c, function* () {
|
||||||
await AppRuntime.runPromise(MCP.Service.use((mcp) => mcp.removeAuth(name)))
|
const name = c.req.param("name")
|
||||||
return c.json({ success: true as const })
|
const mcp = yield* MCP.Service
|
||||||
},
|
yield* mcp.removeAuth(name)
|
||||||
|
return { success: true as const }
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:name/connect",
|
"/:name/connect",
|
||||||
@@ -214,11 +224,13 @@ export const McpRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
validator("param", z.object({ name: z.string() })),
|
validator("param", z.object({ name: z.string() })),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const { name } = c.req.valid("param")
|
jsonRequest("McpRoutes.connect", c, function* () {
|
||||||
await AppRuntime.runPromise(MCP.Service.use((mcp) => mcp.connect(name)))
|
const { name } = c.req.valid("param")
|
||||||
return c.json(true)
|
const mcp = yield* MCP.Service
|
||||||
},
|
yield* mcp.connect(name)
|
||||||
|
return true
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:name/disconnect",
|
"/:name/disconnect",
|
||||||
@@ -237,10 +249,12 @@ export const McpRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
validator("param", z.object({ name: z.string() })),
|
validator("param", z.object({ name: z.string() })),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const { name } = c.req.valid("param")
|
jsonRequest("McpRoutes.disconnect", c, function* () {
|
||||||
await AppRuntime.runPromise(MCP.Service.use((mcp) => mcp.disconnect(name)))
|
const { name } = c.req.valid("param")
|
||||||
return c.json(true)
|
const mcp = yield* MCP.Service
|
||||||
},
|
yield* mcp.disconnect(name)
|
||||||
|
return true
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Hono } from "hono"
|
import { Hono } from "hono"
|
||||||
import { describeRoute, validator, resolver } from "hono-openapi"
|
import { describeRoute, validator, resolver } from "hono-openapi"
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
|
||||||
import { Permission } from "@/permission"
|
import { Permission } from "@/permission"
|
||||||
import { PermissionID } from "@/permission/schema"
|
import { PermissionID } from "@/permission/schema"
|
||||||
import { errors } from "../../error"
|
import { errors } from "../../error"
|
||||||
import { lazy } from "@/util/lazy"
|
import { lazy } from "@/util/lazy"
|
||||||
|
import { jsonRequest } from "./trace"
|
||||||
|
|
||||||
export const PermissionRoutes = lazy(() =>
|
export const PermissionRoutes = lazy(() =>
|
||||||
new Hono()
|
new Hono()
|
||||||
@@ -34,20 +34,18 @@ export const PermissionRoutes = lazy(() =>
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
validator("json", z.object({ reply: Permission.Reply.zod, message: z.string().optional() })),
|
validator("json", z.object({ reply: Permission.Reply.zod, message: z.string().optional() })),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const params = c.req.valid("param")
|
jsonRequest("PermissionRoutes.reply", c, function* () {
|
||||||
const json = c.req.valid("json")
|
const params = c.req.valid("param")
|
||||||
await AppRuntime.runPromise(
|
const json = c.req.valid("json")
|
||||||
Permission.Service.use((svc) =>
|
const svc = yield* Permission.Service
|
||||||
svc.reply({
|
yield* svc.reply({
|
||||||
requestID: params.requestID,
|
requestID: params.requestID,
|
||||||
reply: json.reply,
|
reply: json.reply,
|
||||||
message: json.message,
|
message: json.message,
|
||||||
}),
|
})
|
||||||
),
|
return true
|
||||||
)
|
}),
|
||||||
return c.json(true)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/",
|
"/",
|
||||||
@@ -66,9 +64,10 @@ export const PermissionRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const permissions = await AppRuntime.runPromise(Permission.Service.use((svc) => svc.list()))
|
jsonRequest("PermissionRoutes.list", c, function* () {
|
||||||
return c.json(permissions)
|
const svc = yield* Permission.Service
|
||||||
},
|
return yield* svc.list()
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { errors } from "../../error"
|
|||||||
import { lazy } from "@/util/lazy"
|
import { lazy } from "@/util/lazy"
|
||||||
import { InstanceBootstrap } from "@/project/bootstrap"
|
import { InstanceBootstrap } from "@/project/bootstrap"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
import { AppRuntime } from "@/effect/app-runtime"
|
||||||
|
import { jsonRequest, runRequest } from "./trace"
|
||||||
|
|
||||||
export const ProjectRoutes = lazy(() =>
|
export const ProjectRoutes = lazy(() =>
|
||||||
new Hono()
|
new Hono()
|
||||||
@@ -75,7 +76,9 @@ export const ProjectRoutes = lazy(() =>
|
|||||||
async (c) => {
|
async (c) => {
|
||||||
const dir = Instance.directory
|
const dir = Instance.directory
|
||||||
const prev = Instance.project
|
const prev = Instance.project
|
||||||
const next = await AppRuntime.runPromise(
|
const next = await runRequest(
|
||||||
|
"ProjectRoutes.initGit",
|
||||||
|
c,
|
||||||
Project.Service.use((svc) => svc.initGit({ directory: dir, project: prev })),
|
Project.Service.use((svc) => svc.initGit({ directory: dir, project: prev })),
|
||||||
)
|
)
|
||||||
if (next.id === prev.id && next.vcs === prev.vcs && next.worktree === prev.worktree) return c.json(next)
|
if (next.id === prev.id && next.vcs === prev.vcs && next.worktree === prev.worktree) return c.json(next)
|
||||||
@@ -108,11 +111,12 @@ export const ProjectRoutes = lazy(() =>
|
|||||||
}),
|
}),
|
||||||
validator("param", z.object({ projectID: ProjectID.zod })),
|
validator("param", z.object({ projectID: ProjectID.zod })),
|
||||||
validator("json", Project.UpdateInput.omit({ projectID: true })),
|
validator("json", Project.UpdateInput.omit({ projectID: true })),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const projectID = c.req.valid("param").projectID
|
jsonRequest("ProjectRoutes.update", c, function* () {
|
||||||
const body = c.req.valid("json")
|
const projectID = c.req.valid("param").projectID
|
||||||
const project = await AppRuntime.runPromise(Project.Service.use((svc) => svc.update({ ...body, projectID })))
|
const body = c.req.valid("json")
|
||||||
return c.json(project)
|
const svc = yield* Project.Service
|
||||||
},
|
return yield* svc.update({ ...body, projectID })
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import { Provider } from "@/provider"
|
|||||||
import { ModelsDev } from "@/provider"
|
import { ModelsDev } from "@/provider"
|
||||||
import { ProviderAuth } from "@/provider"
|
import { ProviderAuth } from "@/provider"
|
||||||
import { ProviderID } from "@/provider/schema"
|
import { ProviderID } from "@/provider/schema"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
|
||||||
import { mapValues } from "remeda"
|
import { mapValues } from "remeda"
|
||||||
import { errors } from "../../error"
|
import { errors } from "../../error"
|
||||||
import { lazy } from "@/util/lazy"
|
import { lazy } from "@/util/lazy"
|
||||||
import { Effect } from "effect"
|
import { Effect } from "effect"
|
||||||
|
import { jsonRequest } from "./trace"
|
||||||
|
|
||||||
export const ProviderRoutes = lazy(() =>
|
export const ProviderRoutes = lazy(() =>
|
||||||
new Hono()
|
new Hono()
|
||||||
@@ -31,39 +31,31 @@ export const ProviderRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const result = await AppRuntime.runPromise(
|
jsonRequest("ProviderRoutes.list", c, function* () {
|
||||||
Effect.gen(function* () {
|
const svc = yield* Provider.Service
|
||||||
const svc = yield* Provider.Service
|
const cfg = yield* Config.Service
|
||||||
const cfg = yield* Config.Service
|
const config = yield* cfg.get()
|
||||||
const config = yield* cfg.get()
|
const all = yield* Effect.promise(() => ModelsDev.get())
|
||||||
const all = yield* Effect.promise(() => ModelsDev.get())
|
const disabled = new Set(config.disabled_providers ?? [])
|
||||||
const disabled = new Set(config.disabled_providers ?? [])
|
const enabled = config.enabled_providers ? new Set(config.enabled_providers) : undefined
|
||||||
const enabled = config.enabled_providers ? new Set(config.enabled_providers) : undefined
|
const filtered: Record<string, (typeof all)[string]> = {}
|
||||||
const filtered: Record<string, (typeof all)[string]> = {}
|
for (const [key, value] of Object.entries(all)) {
|
||||||
for (const [key, value] of Object.entries(all)) {
|
if ((enabled ? enabled.has(key) : true) && !disabled.has(key)) {
|
||||||
if ((enabled ? enabled.has(key) : true) && !disabled.has(key)) {
|
filtered[key] = value
|
||||||
filtered[key] = value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const connected = yield* svc.list()
|
}
|
||||||
const providers = Object.assign(
|
const connected = yield* svc.list()
|
||||||
mapValues(filtered, (x) => Provider.fromModelsDevProvider(x)),
|
const providers = Object.assign(
|
||||||
connected,
|
mapValues(filtered, (x) => Provider.fromModelsDevProvider(x)),
|
||||||
)
|
connected,
|
||||||
return {
|
)
|
||||||
all: Object.values(providers),
|
return {
|
||||||
default: Provider.defaultModelIDs(providers),
|
all: Object.values(providers),
|
||||||
connected: Object.keys(connected),
|
default: Provider.defaultModelIDs(providers),
|
||||||
}
|
connected: Object.keys(connected),
|
||||||
}),
|
}
|
||||||
)
|
}),
|
||||||
return c.json({
|
|
||||||
all: result.all,
|
|
||||||
default: result.default,
|
|
||||||
connected: result.connected,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/auth",
|
"/auth",
|
||||||
@@ -82,9 +74,11 @@ export const ProviderRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
return c.json(await AppRuntime.runPromise(ProviderAuth.Service.use((svc) => svc.methods())))
|
jsonRequest("ProviderRoutes.auth", c, function* () {
|
||||||
},
|
const svc = yield* ProviderAuth.Service
|
||||||
|
return yield* svc.methods()
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:providerID/oauth/authorize",
|
"/:providerID/oauth/authorize",
|
||||||
@@ -111,20 +105,17 @@ export const ProviderRoutes = lazy(() =>
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
validator("json", ProviderAuth.AuthorizeInput.zod),
|
validator("json", ProviderAuth.AuthorizeInput.zod),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const providerID = c.req.valid("param").providerID
|
jsonRequest("ProviderRoutes.oauth.authorize", c, function* () {
|
||||||
const { method, inputs } = c.req.valid("json")
|
const providerID = c.req.valid("param").providerID
|
||||||
const result = await AppRuntime.runPromise(
|
const { method, inputs } = c.req.valid("json")
|
||||||
ProviderAuth.Service.use((svc) =>
|
const svc = yield* ProviderAuth.Service
|
||||||
svc.authorize({
|
return yield* svc.authorize({
|
||||||
providerID,
|
providerID,
|
||||||
method,
|
method,
|
||||||
inputs,
|
inputs,
|
||||||
}),
|
})
|
||||||
),
|
}),
|
||||||
)
|
|
||||||
return c.json(result)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:providerID/oauth/callback",
|
"/:providerID/oauth/callback",
|
||||||
@@ -151,19 +142,17 @@ export const ProviderRoutes = lazy(() =>
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
validator("json", ProviderAuth.CallbackInput.zod),
|
validator("json", ProviderAuth.CallbackInput.zod),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const providerID = c.req.valid("param").providerID
|
jsonRequest("ProviderRoutes.oauth.callback", c, function* () {
|
||||||
const { method, code } = c.req.valid("json")
|
const providerID = c.req.valid("param").providerID
|
||||||
await AppRuntime.runPromise(
|
const { method, code } = c.req.valid("json")
|
||||||
ProviderAuth.Service.use((svc) =>
|
const svc = yield* ProviderAuth.Service
|
||||||
svc.callback({
|
yield* svc.callback({
|
||||||
providerID,
|
providerID,
|
||||||
method,
|
method,
|
||||||
code,
|
code,
|
||||||
}),
|
})
|
||||||
),
|
return true
|
||||||
)
|
}),
|
||||||
return c.json(true)
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { Pty } from "@/pty"
|
|||||||
import { PtyID } from "@/pty/schema"
|
import { PtyID } from "@/pty/schema"
|
||||||
import { NotFoundError } from "@/storage"
|
import { NotFoundError } from "@/storage"
|
||||||
import { errors } from "../../error"
|
import { errors } from "../../error"
|
||||||
|
import { jsonRequest, runRequest } from "./trace"
|
||||||
|
|
||||||
export function PtyRoutes(upgradeWebSocket: UpgradeWebSocket) {
|
export function PtyRoutes(upgradeWebSocket: UpgradeWebSocket) {
|
||||||
return new Hono()
|
return new Hono()
|
||||||
@@ -28,16 +29,11 @@ export function PtyRoutes(upgradeWebSocket: UpgradeWebSocket) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
return c.json(
|
jsonRequest("PtyRoutes.list", c, function* () {
|
||||||
await AppRuntime.runPromise(
|
const pty = yield* Pty.Service
|
||||||
Effect.gen(function* () {
|
return yield* pty.list()
|
||||||
const pty = yield* Pty.Service
|
}),
|
||||||
return yield* pty.list()
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/",
|
"/",
|
||||||
@@ -58,15 +54,11 @@ export function PtyRoutes(upgradeWebSocket: UpgradeWebSocket) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
validator("json", Pty.CreateInput),
|
validator("json", Pty.CreateInput),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const info = await AppRuntime.runPromise(
|
jsonRequest("PtyRoutes.create", c, function* () {
|
||||||
Effect.gen(function* () {
|
const pty = yield* Pty.Service
|
||||||
const pty = yield* Pty.Service
|
return yield* pty.create(c.req.valid("json"))
|
||||||
return yield* pty.create(c.req.valid("json"))
|
}),
|
||||||
}),
|
|
||||||
)
|
|
||||||
return c.json(info)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/:ptyID",
|
"/:ptyID",
|
||||||
@@ -88,7 +80,9 @@ export function PtyRoutes(upgradeWebSocket: UpgradeWebSocket) {
|
|||||||
}),
|
}),
|
||||||
validator("param", z.object({ ptyID: PtyID.zod })),
|
validator("param", z.object({ ptyID: PtyID.zod })),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const info = await AppRuntime.runPromise(
|
const info = await runRequest(
|
||||||
|
"PtyRoutes.get",
|
||||||
|
c,
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const pty = yield* Pty.Service
|
const pty = yield* Pty.Service
|
||||||
return yield* pty.get(c.req.valid("param").ptyID)
|
return yield* pty.get(c.req.valid("param").ptyID)
|
||||||
@@ -120,15 +114,11 @@ export function PtyRoutes(upgradeWebSocket: UpgradeWebSocket) {
|
|||||||
}),
|
}),
|
||||||
validator("param", z.object({ ptyID: PtyID.zod })),
|
validator("param", z.object({ ptyID: PtyID.zod })),
|
||||||
validator("json", Pty.UpdateInput),
|
validator("json", Pty.UpdateInput),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const info = await AppRuntime.runPromise(
|
jsonRequest("PtyRoutes.update", c, function* () {
|
||||||
Effect.gen(function* () {
|
const pty = yield* Pty.Service
|
||||||
const pty = yield* Pty.Service
|
return yield* pty.update(c.req.valid("param").ptyID, c.req.valid("json"))
|
||||||
return yield* pty.update(c.req.valid("param").ptyID, c.req.valid("json"))
|
}),
|
||||||
}),
|
|
||||||
)
|
|
||||||
return c.json(info)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.delete(
|
.delete(
|
||||||
"/:ptyID",
|
"/:ptyID",
|
||||||
@@ -149,15 +139,12 @@ export function PtyRoutes(upgradeWebSocket: UpgradeWebSocket) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
validator("param", z.object({ ptyID: PtyID.zod })),
|
validator("param", z.object({ ptyID: PtyID.zod })),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
await AppRuntime.runPromise(
|
jsonRequest("PtyRoutes.remove", c, function* () {
|
||||||
Effect.gen(function* () {
|
const pty = yield* Pty.Service
|
||||||
const pty = yield* Pty.Service
|
yield* pty.remove(c.req.valid("param").ptyID)
|
||||||
yield* pty.remove(c.req.valid("param").ptyID)
|
return true
|
||||||
}),
|
}),
|
||||||
)
|
|
||||||
return c.json(true)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/:ptyID/connect",
|
"/:ptyID/connect",
|
||||||
@@ -194,7 +181,9 @@ export function PtyRoutes(upgradeWebSocket: UpgradeWebSocket) {
|
|||||||
})()
|
})()
|
||||||
let handler: Handler | undefined
|
let handler: Handler | undefined
|
||||||
if (
|
if (
|
||||||
!(await AppRuntime.runPromise(
|
!(await runRequest(
|
||||||
|
"PtyRoutes.connect",
|
||||||
|
c,
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const pty = yield* Pty.Service
|
const pty = yield* Pty.Service
|
||||||
return yield* pty.get(id)
|
return yield* pty.get(id)
|
||||||
@@ -232,7 +221,7 @@ export function PtyRoutes(upgradeWebSocket: UpgradeWebSocket) {
|
|||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const pty = yield* Pty.Service
|
const pty = yield* Pty.Service
|
||||||
return yield* pty.connect(id, socket, cursor)
|
return yield* pty.connect(id, socket, cursor)
|
||||||
}),
|
}).pipe(Effect.withSpan("PtyRoutes.connect.open")),
|
||||||
)
|
)
|
||||||
ready = true
|
ready = true
|
||||||
for (const msg of pending) handler?.onMessage(msg)
|
for (const msg of pending) handler?.onMessage(msg)
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import { describeRoute, validator } from "hono-openapi"
|
|||||||
import { resolver } from "hono-openapi"
|
import { resolver } from "hono-openapi"
|
||||||
import { QuestionID } from "@/question/schema"
|
import { QuestionID } from "@/question/schema"
|
||||||
import { Question } from "@/question"
|
import { Question } from "@/question"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
|
||||||
import z from "zod"
|
import z from "zod"
|
||||||
import { errors } from "../../error"
|
import { errors } from "../../error"
|
||||||
import { lazy } from "@/util/lazy"
|
import { lazy } from "@/util/lazy"
|
||||||
|
import { jsonRequest } from "./trace"
|
||||||
|
|
||||||
const Reply = z.object({
|
const Reply = z.object({
|
||||||
answers: Question.Answer.zod
|
answers: Question.Answer.zod
|
||||||
@@ -33,10 +33,11 @@ export const QuestionRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const questions = await AppRuntime.runPromise(Question.Service.use((svc) => svc.list()))
|
jsonRequest("QuestionRoutes.list", c, function* () {
|
||||||
return c.json(questions)
|
const svc = yield* Question.Service
|
||||||
},
|
return yield* svc.list()
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:requestID/reply",
|
"/:requestID/reply",
|
||||||
@@ -63,19 +64,17 @@ export const QuestionRoutes = lazy(() =>
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
validator("json", Reply),
|
validator("json", Reply),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const params = c.req.valid("param")
|
jsonRequest("QuestionRoutes.reply", c, function* () {
|
||||||
const json = c.req.valid("json")
|
const params = c.req.valid("param")
|
||||||
await AppRuntime.runPromise(
|
const json = c.req.valid("json")
|
||||||
Question.Service.use((svc) =>
|
const svc = yield* Question.Service
|
||||||
svc.reply({
|
yield* svc.reply({
|
||||||
requestID: params.requestID,
|
requestID: params.requestID,
|
||||||
answers: json.answers,
|
answers: json.answers,
|
||||||
}),
|
})
|
||||||
),
|
return true
|
||||||
)
|
}),
|
||||||
return c.json(true)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:requestID/reject",
|
"/:requestID/reject",
|
||||||
@@ -101,10 +100,12 @@ export const QuestionRoutes = lazy(() =>
|
|||||||
requestID: QuestionID.zod,
|
requestID: QuestionID.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const params = c.req.valid("param")
|
jsonRequest("QuestionRoutes.reject", c, function* () {
|
||||||
await AppRuntime.runPromise(Question.Service.use((svc) => svc.reject(params.requestID)))
|
const params = c.req.valid("param")
|
||||||
return c.json(true)
|
const svc = yield* Question.Service
|
||||||
},
|
yield* svc.reject(params.requestID)
|
||||||
|
return true
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import { SessionStatus } from "@/session/status"
|
|||||||
import { SessionSummary } from "@/session/summary"
|
import { SessionSummary } from "@/session/summary"
|
||||||
import { Todo } from "@/session/todo"
|
import { Todo } from "@/session/todo"
|
||||||
import { Effect } from "effect"
|
import { Effect } from "effect"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
|
||||||
import { Agent } from "@/agent/agent"
|
import { Agent } from "@/agent/agent"
|
||||||
import { Snapshot } from "@/snapshot"
|
import { Snapshot } from "@/snapshot"
|
||||||
import { Command } from "@/command"
|
import { Command } from "@/command"
|
||||||
@@ -26,7 +25,7 @@ import { errors } from "../../error"
|
|||||||
import { lazy } from "@/util/lazy"
|
import { lazy } from "@/util/lazy"
|
||||||
import { Bus } from "@/bus"
|
import { Bus } from "@/bus"
|
||||||
import { NamedError } from "@opencode-ai/shared/util/error"
|
import { NamedError } from "@opencode-ai/shared/util/error"
|
||||||
import { jsonRequest } from "./trace"
|
import { jsonRequest, runRequest } from "./trace"
|
||||||
|
|
||||||
const log = Log.create({ service: "server" })
|
const log = Log.create({ service: "server" })
|
||||||
|
|
||||||
@@ -218,11 +217,12 @@ export const SessionRoutes = lazy(() =>
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
validator("json", Session.CreateInput),
|
validator("json", Session.CreateInput),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const body = c.req.valid("json") ?? {}
|
jsonRequest("SessionRoutes.create", c, function* () {
|
||||||
const session = await AppRuntime.runPromise(SessionShare.Service.use((svc) => svc.create(body)))
|
const body = c.req.valid("json") ?? {}
|
||||||
return c.json(session)
|
const svc = yield* SessionShare.Service
|
||||||
},
|
return yield* svc.create(body)
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.delete(
|
.delete(
|
||||||
"/:sessionID",
|
"/:sessionID",
|
||||||
@@ -248,11 +248,13 @@ export const SessionRoutes = lazy(() =>
|
|||||||
sessionID: Session.RemoveInput,
|
sessionID: Session.RemoveInput,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const sessionID = c.req.valid("param").sessionID
|
jsonRequest("SessionRoutes.delete", c, function* () {
|
||||||
await AppRuntime.runPromise(Session.Service.use((svc) => svc.remove(sessionID)))
|
const sessionID = c.req.valid("param").sessionID
|
||||||
return c.json(true)
|
const svc = yield* Session.Service
|
||||||
},
|
yield* svc.remove(sessionID)
|
||||||
|
return true
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.patch(
|
.patch(
|
||||||
"/:sessionID",
|
"/:sessionID",
|
||||||
@@ -290,32 +292,28 @@ export const SessionRoutes = lazy(() =>
|
|||||||
.optional(),
|
.optional(),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const sessionID = c.req.valid("param").sessionID
|
jsonRequest("SessionRoutes.update", c, function* () {
|
||||||
const updates = c.req.valid("json")
|
const sessionID = c.req.valid("param").sessionID
|
||||||
const session = await AppRuntime.runPromise(
|
const updates = c.req.valid("json")
|
||||||
Effect.gen(function* () {
|
const session = yield* Session.Service
|
||||||
const session = yield* Session.Service
|
const current = yield* session.get(sessionID)
|
||||||
const current = yield* session.get(sessionID)
|
|
||||||
|
|
||||||
if (updates.title !== undefined) {
|
if (updates.title !== undefined) {
|
||||||
yield* session.setTitle({ sessionID, title: updates.title })
|
yield* session.setTitle({ sessionID, title: updates.title })
|
||||||
}
|
}
|
||||||
if (updates.permission !== undefined) {
|
if (updates.permission !== undefined) {
|
||||||
yield* session.setPermission({
|
yield* session.setPermission({
|
||||||
sessionID,
|
sessionID,
|
||||||
permission: Permission.merge(current.permission ?? [], updates.permission),
|
permission: Permission.merge(current.permission ?? [], updates.permission),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (updates.time?.archived !== undefined) {
|
if (updates.time?.archived !== undefined) {
|
||||||
yield* session.setArchived({ sessionID, time: updates.time.archived })
|
yield* session.setArchived({ sessionID, time: updates.time.archived })
|
||||||
}
|
}
|
||||||
|
|
||||||
return yield* session.get(sessionID)
|
return yield* session.get(sessionID)
|
||||||
}),
|
}),
|
||||||
)
|
|
||||||
return c.json(session)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
// TODO(v2): remove this dedicated route and rely on the normal `/init` command flow.
|
// TODO(v2): remove this dedicated route and rely on the normal `/init` command flow.
|
||||||
.post(
|
.post(
|
||||||
@@ -351,22 +349,20 @@ export const SessionRoutes = lazy(() =>
|
|||||||
messageID: MessageID.zod,
|
messageID: MessageID.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const sessionID = c.req.valid("param").sessionID
|
jsonRequest("SessionRoutes.init", c, function* () {
|
||||||
const body = c.req.valid("json")
|
const sessionID = c.req.valid("param").sessionID
|
||||||
await AppRuntime.runPromise(
|
const body = c.req.valid("json")
|
||||||
SessionPrompt.Service.use((svc) =>
|
const svc = yield* SessionPrompt.Service
|
||||||
svc.command({
|
yield* svc.command({
|
||||||
sessionID,
|
sessionID,
|
||||||
messageID: body.messageID,
|
messageID: body.messageID,
|
||||||
model: body.providerID + "/" + body.modelID,
|
model: body.providerID + "/" + body.modelID,
|
||||||
command: Command.Default.INIT,
|
command: Command.Default.INIT,
|
||||||
arguments: "",
|
arguments: "",
|
||||||
}),
|
})
|
||||||
),
|
return true
|
||||||
)
|
}),
|
||||||
return c.json(true)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:sessionID/fork",
|
"/:sessionID/fork",
|
||||||
@@ -392,12 +388,13 @@ export const SessionRoutes = lazy(() =>
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
validator("json", Session.ForkInput.omit({ sessionID: true })),
|
validator("json", Session.ForkInput.omit({ sessionID: true })),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const sessionID = c.req.valid("param").sessionID
|
jsonRequest("SessionRoutes.fork", c, function* () {
|
||||||
const body = c.req.valid("json")
|
const sessionID = c.req.valid("param").sessionID
|
||||||
const result = await AppRuntime.runPromise(Session.Service.use((svc) => svc.fork({ ...body, sessionID })))
|
const body = c.req.valid("json")
|
||||||
return c.json(result)
|
const svc = yield* Session.Service
|
||||||
},
|
return yield* svc.fork({ ...body, sessionID })
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:sessionID/abort",
|
"/:sessionID/abort",
|
||||||
@@ -423,10 +420,12 @@ export const SessionRoutes = lazy(() =>
|
|||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
await AppRuntime.runPromise(SessionPrompt.Service.use((svc) => svc.cancel(c.req.valid("param").sessionID)))
|
jsonRequest("SessionRoutes.abort", c, function* () {
|
||||||
return c.json(true)
|
const svc = yield* SessionPrompt.Service
|
||||||
},
|
yield* svc.cancel(c.req.valid("param").sessionID)
|
||||||
|
return true
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:sessionID/share",
|
"/:sessionID/share",
|
||||||
@@ -452,18 +451,14 @@ export const SessionRoutes = lazy(() =>
|
|||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const sessionID = c.req.valid("param").sessionID
|
jsonRequest("SessionRoutes.share", c, function* () {
|
||||||
const session = await AppRuntime.runPromise(
|
const sessionID = c.req.valid("param").sessionID
|
||||||
Effect.gen(function* () {
|
const share = yield* SessionShare.Service
|
||||||
const share = yield* SessionShare.Service
|
const session = yield* Session.Service
|
||||||
const session = yield* Session.Service
|
yield* share.share(sessionID)
|
||||||
yield* share.share(sessionID)
|
return yield* session.get(sessionID)
|
||||||
return yield* session.get(sessionID)
|
}),
|
||||||
}),
|
|
||||||
)
|
|
||||||
return c.json(session)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/:sessionID/diff",
|
"/:sessionID/diff",
|
||||||
@@ -494,19 +489,16 @@ export const SessionRoutes = lazy(() =>
|
|||||||
messageID: SessionSummary.DiffInput.shape.messageID,
|
messageID: SessionSummary.DiffInput.shape.messageID,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const query = c.req.valid("query")
|
jsonRequest("SessionRoutes.diff", c, function* () {
|
||||||
const params = c.req.valid("param")
|
const query = c.req.valid("query")
|
||||||
const result = await AppRuntime.runPromise(
|
const params = c.req.valid("param")
|
||||||
SessionSummary.Service.use((summary) =>
|
const summary = yield* SessionSummary.Service
|
||||||
summary.diff({
|
return yield* summary.diff({
|
||||||
sessionID: params.sessionID,
|
sessionID: params.sessionID,
|
||||||
messageID: query.messageID,
|
messageID: query.messageID,
|
||||||
}),
|
})
|
||||||
),
|
}),
|
||||||
)
|
|
||||||
return c.json(result)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.delete(
|
.delete(
|
||||||
"/:sessionID/share",
|
"/:sessionID/share",
|
||||||
@@ -532,18 +524,14 @@ export const SessionRoutes = lazy(() =>
|
|||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const sessionID = c.req.valid("param").sessionID
|
jsonRequest("SessionRoutes.unshare", c, function* () {
|
||||||
const session = await AppRuntime.runPromise(
|
const sessionID = c.req.valid("param").sessionID
|
||||||
Effect.gen(function* () {
|
const share = yield* SessionShare.Service
|
||||||
const share = yield* SessionShare.Service
|
const session = yield* Session.Service
|
||||||
const session = yield* Session.Service
|
yield* share.unshare(sessionID)
|
||||||
yield* share.unshare(sessionID)
|
return yield* session.get(sessionID)
|
||||||
return yield* session.get(sessionID)
|
}),
|
||||||
}),
|
|
||||||
)
|
|
||||||
return c.json(session)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:sessionID/summarize",
|
"/:sessionID/summarize",
|
||||||
@@ -577,43 +565,40 @@ export const SessionRoutes = lazy(() =>
|
|||||||
auto: z.boolean().optional().default(false),
|
auto: z.boolean().optional().default(false),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const sessionID = c.req.valid("param").sessionID
|
jsonRequest("SessionRoutes.summarize", c, function* () {
|
||||||
const body = c.req.valid("json")
|
const sessionID = c.req.valid("param").sessionID
|
||||||
await AppRuntime.runPromise(
|
const body = c.req.valid("json")
|
||||||
Effect.gen(function* () {
|
const session = yield* Session.Service
|
||||||
const session = yield* Session.Service
|
const revert = yield* SessionRevert.Service
|
||||||
const revert = yield* SessionRevert.Service
|
const compact = yield* SessionCompaction.Service
|
||||||
const compact = yield* SessionCompaction.Service
|
const prompt = yield* SessionPrompt.Service
|
||||||
const prompt = yield* SessionPrompt.Service
|
const agent = yield* Agent.Service
|
||||||
const agent = yield* Agent.Service
|
|
||||||
|
|
||||||
yield* revert.cleanup(yield* session.get(sessionID))
|
yield* revert.cleanup(yield* session.get(sessionID))
|
||||||
const msgs = yield* session.messages({ sessionID })
|
const msgs = yield* session.messages({ sessionID })
|
||||||
const defaultAgent = yield* agent.defaultAgent()
|
const defaultAgent = yield* agent.defaultAgent()
|
||||||
let currentAgent = defaultAgent
|
let currentAgent = defaultAgent
|
||||||
for (let i = msgs.length - 1; i >= 0; i--) {
|
for (let i = msgs.length - 1; i >= 0; i--) {
|
||||||
const info = msgs[i].info
|
const info = msgs[i].info
|
||||||
if (info.role === "user") {
|
if (info.role === "user") {
|
||||||
currentAgent = info.agent || defaultAgent
|
currentAgent = info.agent || defaultAgent
|
||||||
break
|
break
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
yield* compact.create({
|
yield* compact.create({
|
||||||
sessionID,
|
sessionID,
|
||||||
agent: currentAgent,
|
agent: currentAgent,
|
||||||
model: {
|
model: {
|
||||||
providerID: body.providerID,
|
providerID: body.providerID,
|
||||||
modelID: body.modelID,
|
modelID: body.modelID,
|
||||||
},
|
},
|
||||||
auto: body.auto,
|
auto: body.auto,
|
||||||
})
|
})
|
||||||
yield* prompt.loop({ sessionID })
|
yield* prompt.loop({ sessionID })
|
||||||
}),
|
return true
|
||||||
)
|
}),
|
||||||
return c.json(true)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/:sessionID/message",
|
"/:sessionID/message",
|
||||||
@@ -675,7 +660,9 @@ export const SessionRoutes = lazy(() =>
|
|||||||
const query = c.req.valid("query")
|
const query = c.req.valid("query")
|
||||||
const sessionID = c.req.valid("param").sessionID
|
const sessionID = c.req.valid("param").sessionID
|
||||||
if (query.limit === undefined || query.limit === 0) {
|
if (query.limit === undefined || query.limit === 0) {
|
||||||
const messages = await AppRuntime.runPromise(
|
const messages = await runRequest(
|
||||||
|
"SessionRoutes.messages",
|
||||||
|
c,
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const session = yield* Session.Service
|
const session = yield* Session.Service
|
||||||
yield* session.get(sessionID)
|
yield* session.get(sessionID)
|
||||||
@@ -766,21 +753,18 @@ export const SessionRoutes = lazy(() =>
|
|||||||
messageID: MessageID.zod,
|
messageID: MessageID.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const params = c.req.valid("param")
|
jsonRequest("SessionRoutes.deleteMessage", c, function* () {
|
||||||
await AppRuntime.runPromise(
|
const params = c.req.valid("param")
|
||||||
Effect.gen(function* () {
|
const state = yield* SessionRunState.Service
|
||||||
const state = yield* SessionRunState.Service
|
const session = yield* Session.Service
|
||||||
const session = yield* Session.Service
|
yield* state.assertNotBusy(params.sessionID)
|
||||||
yield* state.assertNotBusy(params.sessionID)
|
yield* session.removeMessage({
|
||||||
yield* session.removeMessage({
|
sessionID: params.sessionID,
|
||||||
sessionID: params.sessionID,
|
messageID: params.messageID,
|
||||||
messageID: params.messageID,
|
})
|
||||||
})
|
return true
|
||||||
}),
|
}),
|
||||||
)
|
|
||||||
return c.json(true)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.delete(
|
.delete(
|
||||||
"/:sessionID/message/:messageID/part/:partID",
|
"/:sessionID/message/:messageID/part/:partID",
|
||||||
@@ -807,19 +791,17 @@ export const SessionRoutes = lazy(() =>
|
|||||||
partID: PartID.zod,
|
partID: PartID.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const params = c.req.valid("param")
|
jsonRequest("SessionRoutes.deletePart", c, function* () {
|
||||||
await AppRuntime.runPromise(
|
const params = c.req.valid("param")
|
||||||
Session.Service.use((svc) =>
|
const svc = yield* Session.Service
|
||||||
svc.removePart({
|
yield* svc.removePart({
|
||||||
sessionID: params.sessionID,
|
sessionID: params.sessionID,
|
||||||
messageID: params.messageID,
|
messageID: params.messageID,
|
||||||
partID: params.partID,
|
partID: params.partID,
|
||||||
}),
|
})
|
||||||
),
|
return true
|
||||||
)
|
}),
|
||||||
return c.json(true)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.patch(
|
.patch(
|
||||||
"/:sessionID/message/:messageID/part/:partID",
|
"/:sessionID/message/:messageID/part/:partID",
|
||||||
@@ -855,8 +837,10 @@ export const SessionRoutes = lazy(() =>
|
|||||||
`Part mismatch: body.id='${body.id}' vs partID='${params.partID}', body.messageID='${body.messageID}' vs messageID='${params.messageID}', body.sessionID='${body.sessionID}' vs sessionID='${params.sessionID}'`,
|
`Part mismatch: body.id='${body.id}' vs partID='${params.partID}', body.messageID='${body.messageID}' vs messageID='${params.messageID}', body.sessionID='${body.sessionID}' vs sessionID='${params.sessionID}'`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const part = await AppRuntime.runPromise(Session.Service.use((svc) => svc.updatePart(body)))
|
return jsonRequest("SessionRoutes.updatePart", c, function* () {
|
||||||
return c.json(part)
|
const svc = yield* Session.Service
|
||||||
|
return yield* svc.updatePart(body)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
@@ -895,7 +879,9 @@ export const SessionRoutes = lazy(() =>
|
|||||||
return stream(c, async (stream) => {
|
return stream(c, async (stream) => {
|
||||||
const sessionID = c.req.valid("param").sessionID
|
const sessionID = c.req.valid("param").sessionID
|
||||||
const body = c.req.valid("json")
|
const body = c.req.valid("json")
|
||||||
const msg = await AppRuntime.runPromise(
|
const msg = await runRequest(
|
||||||
|
"SessionRoutes.prompt",
|
||||||
|
c,
|
||||||
SessionPrompt.Service.use((svc) => svc.prompt({ ...body, sessionID })),
|
SessionPrompt.Service.use((svc) => svc.prompt({ ...body, sessionID })),
|
||||||
)
|
)
|
||||||
void stream.write(JSON.stringify(msg))
|
void stream.write(JSON.stringify(msg))
|
||||||
@@ -926,15 +912,17 @@ export const SessionRoutes = lazy(() =>
|
|||||||
async (c) => {
|
async (c) => {
|
||||||
const sessionID = c.req.valid("param").sessionID
|
const sessionID = c.req.valid("param").sessionID
|
||||||
const body = c.req.valid("json")
|
const body = c.req.valid("json")
|
||||||
void AppRuntime.runPromise(SessionPrompt.Service.use((svc) => svc.prompt({ ...body, sessionID }))).catch(
|
void runRequest(
|
||||||
(err) => {
|
"SessionRoutes.prompt_async",
|
||||||
log.error("prompt_async failed", { sessionID, error: err })
|
c,
|
||||||
void Bus.publish(Session.Event.Error, {
|
SessionPrompt.Service.use((svc) => svc.prompt({ ...body, sessionID })),
|
||||||
sessionID,
|
).catch((err) => {
|
||||||
error: new NamedError.Unknown({ message: err instanceof Error ? err.message : String(err) }).toObject(),
|
log.error("prompt_async failed", { sessionID, error: err })
|
||||||
})
|
void Bus.publish(Session.Event.Error, {
|
||||||
},
|
sessionID,
|
||||||
)
|
error: new NamedError.Unknown({ message: err instanceof Error ? err.message : String(err) }).toObject(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
return c.body(null, 204)
|
return c.body(null, 204)
|
||||||
},
|
},
|
||||||
@@ -969,12 +957,13 @@ export const SessionRoutes = lazy(() =>
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
validator("json", SessionPrompt.CommandInput.omit({ sessionID: true })),
|
validator("json", SessionPrompt.CommandInput.omit({ sessionID: true })),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const sessionID = c.req.valid("param").sessionID
|
jsonRequest("SessionRoutes.command", c, function* () {
|
||||||
const body = c.req.valid("json")
|
const sessionID = c.req.valid("param").sessionID
|
||||||
const msg = await AppRuntime.runPromise(SessionPrompt.Service.use((svc) => svc.command({ ...body, sessionID })))
|
const body = c.req.valid("json")
|
||||||
return c.json(msg)
|
const svc = yield* SessionPrompt.Service
|
||||||
},
|
return yield* svc.command({ ...body, sessionID })
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:sessionID/shell",
|
"/:sessionID/shell",
|
||||||
@@ -1001,12 +990,13 @@ export const SessionRoutes = lazy(() =>
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
validator("json", SessionPrompt.ShellInput.omit({ sessionID: true })),
|
validator("json", SessionPrompt.ShellInput.omit({ sessionID: true })),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const sessionID = c.req.valid("param").sessionID
|
jsonRequest("SessionRoutes.shell", c, function* () {
|
||||||
const body = c.req.valid("json")
|
const sessionID = c.req.valid("param").sessionID
|
||||||
const msg = await AppRuntime.runPromise(SessionPrompt.Service.use((svc) => svc.shell({ ...body, sessionID })))
|
const body = c.req.valid("json")
|
||||||
return c.json(msg)
|
const svc = yield* SessionPrompt.Service
|
||||||
},
|
return yield* svc.shell({ ...body, sessionID })
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:sessionID/revert",
|
"/:sessionID/revert",
|
||||||
@@ -1036,15 +1026,13 @@ export const SessionRoutes = lazy(() =>
|
|||||||
async (c) => {
|
async (c) => {
|
||||||
const sessionID = c.req.valid("param").sessionID
|
const sessionID = c.req.valid("param").sessionID
|
||||||
log.info("revert", c.req.valid("json"))
|
log.info("revert", c.req.valid("json"))
|
||||||
const session = await AppRuntime.runPromise(
|
return jsonRequest("SessionRoutes.revert", c, function* () {
|
||||||
SessionRevert.Service.use((svc) =>
|
const svc = yield* SessionRevert.Service
|
||||||
svc.revert({
|
return yield* svc.revert({
|
||||||
sessionID,
|
sessionID,
|
||||||
...c.req.valid("json"),
|
...c.req.valid("json"),
|
||||||
}),
|
})
|
||||||
),
|
})
|
||||||
)
|
|
||||||
return c.json(session)
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
@@ -1071,11 +1059,12 @@ export const SessionRoutes = lazy(() =>
|
|||||||
sessionID: SessionID.zod,
|
sessionID: SessionID.zod,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const sessionID = c.req.valid("param").sessionID
|
jsonRequest("SessionRoutes.unrevert", c, function* () {
|
||||||
const session = await AppRuntime.runPromise(SessionRevert.Service.use((svc) => svc.unrevert({ sessionID })))
|
const sessionID = c.req.valid("param").sessionID
|
||||||
return c.json(session)
|
const svc = yield* SessionRevert.Service
|
||||||
},
|
return yield* svc.unrevert({ sessionID })
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
"/:sessionID/permissions/:permissionID",
|
"/:sessionID/permissions/:permissionID",
|
||||||
@@ -1104,17 +1093,15 @@ export const SessionRoutes = lazy(() =>
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
validator("json", z.object({ response: Permission.Reply.zod })),
|
validator("json", z.object({ response: Permission.Reply.zod })),
|
||||||
async (c) => {
|
async (c) =>
|
||||||
const params = c.req.valid("param")
|
jsonRequest("SessionRoutes.permissionRespond", c, function* () {
|
||||||
await AppRuntime.runPromise(
|
const params = c.req.valid("param")
|
||||||
Permission.Service.use((svc) =>
|
const svc = yield* Permission.Service
|
||||||
svc.reply({
|
yield* svc.reply({
|
||||||
requestID: params.permissionID,
|
requestID: params.permissionID,
|
||||||
reply: c.req.valid("json").response,
|
reply: c.req.valid("json").response,
|
||||||
}),
|
})
|
||||||
),
|
return true
|
||||||
)
|
}),
|
||||||
return c.json(true)
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import z from "zod"
|
|||||||
import { Bus } from "@/bus"
|
import { Bus } from "@/bus"
|
||||||
import { Session } from "@/session"
|
import { Session } from "@/session"
|
||||||
import { TuiEvent } from "@/cli/cmd/tui/event"
|
import { TuiEvent } from "@/cli/cmd/tui/event"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
|
||||||
import { AsyncQueue } from "@/util/queue"
|
import { AsyncQueue } from "@/util/queue"
|
||||||
import { errors } from "../../error"
|
import { errors } from "../../error"
|
||||||
import { lazy } from "@/util/lazy"
|
import { lazy } from "@/util/lazy"
|
||||||
|
import { runRequest } from "./trace"
|
||||||
|
|
||||||
const TuiRequest = z.object({
|
const TuiRequest = z.object({
|
||||||
path: z.string(),
|
path: z.string(),
|
||||||
@@ -371,7 +371,11 @@ export const TuiRoutes = lazy(() =>
|
|||||||
validator("json", TuiEvent.SessionSelect.properties),
|
validator("json", TuiEvent.SessionSelect.properties),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const { sessionID } = c.req.valid("json")
|
const { sessionID } = c.req.valid("json")
|
||||||
await AppRuntime.runPromise(Session.Service.use((svc) => svc.get(sessionID)))
|
await runRequest(
|
||||||
|
"TuiRoutes.sessionSelect",
|
||||||
|
c,
|
||||||
|
Session.Service.use((svc) => svc.get(sessionID)),
|
||||||
|
)
|
||||||
await Bus.publish(TuiEvent.SessionSelect, { sessionID })
|
await Bus.publish(TuiEvent.SessionSelect, { sessionID })
|
||||||
return c.json(true)
|
return c.json(true)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { Instance } from "@/project/instance"
|
|||||||
import { Session } from "@/session"
|
import { Session } from "@/session"
|
||||||
import { SessionID } from "@/session/schema"
|
import { SessionID } from "@/session/schema"
|
||||||
import { AppRuntime } from "@/effect/app-runtime"
|
import { AppRuntime } from "@/effect/app-runtime"
|
||||||
|
import { Effect } from "effect"
|
||||||
import { Log } from "@/util"
|
import { Log } from "@/util"
|
||||||
import { ServerProxy } from "./proxy"
|
import { ServerProxy } from "./proxy"
|
||||||
|
|
||||||
@@ -42,7 +43,9 @@ async function getSessionWorkspace(url: URL) {
|
|||||||
const id = getSessionID(url)
|
const id = getSessionID(url)
|
||||||
if (!id) return null
|
if (!id) return null
|
||||||
|
|
||||||
const session = await AppRuntime.runPromise(Session.Service.use((svc) => svc.get(id))).catch(() => undefined)
|
const session = await AppRuntime.runPromise(
|
||||||
|
Session.Service.use((svc) => svc.get(id)).pipe(Effect.withSpan("WorkspaceRouter.lookup")),
|
||||||
|
).catch(() => undefined)
|
||||||
return session?.workspaceID
|
return session?.workspaceID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user