|
|
@@ -15,141 +15,141 @@ import { InstanceHttpApi } from "../api"
|
|
|
import { ConsoleSwitchPayload, SessionListQuery, ToolListQuery } from "../groups/experimental"
|
|
|
|
|
|
export const experimentalHandlers = HttpApiBuilder.group(InstanceHttpApi, "experimental", (handlers) =>
|
|
|
- Effect.gen(function* () {
|
|
|
- const account = yield* Account.Service
|
|
|
- const agents = yield* Agent.Service
|
|
|
- const config = yield* Config.Service
|
|
|
- const mcp = yield* MCP.Service
|
|
|
- const project = yield* Project.Service
|
|
|
- const registry = yield* ToolRegistry.Service
|
|
|
- const worktreeSvc = yield* Worktree.Service
|
|
|
+ Effect.gen(function* () {
|
|
|
+ const account = yield* Account.Service
|
|
|
+ const agents = yield* Agent.Service
|
|
|
+ const config = yield* Config.Service
|
|
|
+ const mcp = yield* MCP.Service
|
|
|
+ const project = yield* Project.Service
|
|
|
+ const registry = yield* ToolRegistry.Service
|
|
|
+ const worktreeSvc = yield* Worktree.Service
|
|
|
|
|
|
- const getConsole = Effect.fn("ExperimentalHttpApi.console")(function* () {
|
|
|
- const [state, groups] = yield* Effect.all(
|
|
|
- [config.getConsoleState(), account.orgsByAccount().pipe(Effect.orDie)],
|
|
|
- {
|
|
|
- concurrency: "unbounded",
|
|
|
- },
|
|
|
- )
|
|
|
- return {
|
|
|
- consoleManagedProviders: state.consoleManagedProviders,
|
|
|
- ...(state.activeOrgName ? { activeOrgName: state.activeOrgName } : {}),
|
|
|
- switchableOrgCount: groups.reduce((count, group) => count + group.orgs.length, 0),
|
|
|
- }
|
|
|
- })
|
|
|
+ const getConsole = Effect.fn("ExperimentalHttpApi.console")(function* () {
|
|
|
+ const [state, groups] = yield* Effect.all(
|
|
|
+ [config.getConsoleState(), account.orgsByAccount().pipe(Effect.orDie)],
|
|
|
+ {
|
|
|
+ concurrency: "unbounded",
|
|
|
+ },
|
|
|
+ )
|
|
|
+ return {
|
|
|
+ consoleManagedProviders: state.consoleManagedProviders,
|
|
|
+ ...(state.activeOrgName ? { activeOrgName: state.activeOrgName } : {}),
|
|
|
+ switchableOrgCount: groups.reduce((count, group) => count + group.orgs.length, 0),
|
|
|
+ }
|
|
|
+ })
|
|
|
|
|
|
- const listConsoleOrgs = Effect.fn("ExperimentalHttpApi.consoleOrgs")(function* () {
|
|
|
- const [groups, active] = yield* Effect.all(
|
|
|
- [account.orgsByAccount().pipe(Effect.orDie), account.active().pipe(Effect.orDie)],
|
|
|
- {
|
|
|
- concurrency: "unbounded",
|
|
|
- },
|
|
|
- )
|
|
|
- const info = Option.getOrUndefined(active)
|
|
|
- return {
|
|
|
- orgs: groups.flatMap((group) =>
|
|
|
- group.orgs.map((org) => ({
|
|
|
- accountID: group.account.id,
|
|
|
- accountEmail: group.account.email,
|
|
|
- accountUrl: group.account.url,
|
|
|
- orgID: org.id,
|
|
|
- orgName: org.name,
|
|
|
- active: !!info && info.id === group.account.id && info.active_org_id === org.id,
|
|
|
- })),
|
|
|
- ),
|
|
|
- }
|
|
|
- })
|
|
|
+ const listConsoleOrgs = Effect.fn("ExperimentalHttpApi.consoleOrgs")(function* () {
|
|
|
+ const [groups, active] = yield* Effect.all(
|
|
|
+ [account.orgsByAccount().pipe(Effect.orDie), account.active().pipe(Effect.orDie)],
|
|
|
+ {
|
|
|
+ concurrency: "unbounded",
|
|
|
+ },
|
|
|
+ )
|
|
|
+ const info = Option.getOrUndefined(active)
|
|
|
+ return {
|
|
|
+ orgs: groups.flatMap((group) =>
|
|
|
+ group.orgs.map((org) => ({
|
|
|
+ accountID: group.account.id,
|
|
|
+ accountEmail: group.account.email,
|
|
|
+ accountUrl: group.account.url,
|
|
|
+ orgID: org.id,
|
|
|
+ orgName: org.name,
|
|
|
+ active: !!info && info.id === group.account.id && info.active_org_id === org.id,
|
|
|
+ })),
|
|
|
+ ),
|
|
|
+ }
|
|
|
+ })
|
|
|
|
|
|
- const switchConsole = Effect.fn("ExperimentalHttpApi.consoleSwitch")(function* (ctx: {
|
|
|
- payload: typeof ConsoleSwitchPayload.Type
|
|
|
- }) {
|
|
|
- yield* account
|
|
|
- .use(ctx.payload.accountID, Option.some(ctx.payload.orgID))
|
|
|
- .pipe(Effect.catch(() => Effect.fail(new HttpApiError.BadRequest({}))))
|
|
|
- return true
|
|
|
- })
|
|
|
+ const switchConsole = Effect.fn("ExperimentalHttpApi.consoleSwitch")(function* (ctx: {
|
|
|
+ payload: typeof ConsoleSwitchPayload.Type
|
|
|
+ }) {
|
|
|
+ yield* account
|
|
|
+ .use(ctx.payload.accountID, Option.some(ctx.payload.orgID))
|
|
|
+ .pipe(Effect.catch(() => Effect.fail(new HttpApiError.BadRequest({}))))
|
|
|
+ return true
|
|
|
+ })
|
|
|
|
|
|
- const tool = Effect.fn("ExperimentalHttpApi.tool")(function* (ctx: { query: typeof ToolListQuery.Type }) {
|
|
|
- const list = yield* registry.tools({
|
|
|
- providerID: ctx.query.provider,
|
|
|
- modelID: ctx.query.model,
|
|
|
- agent: yield* agents.get(yield* agents.defaultAgent()),
|
|
|
- })
|
|
|
- return list.map((item) => ({
|
|
|
- id: item.id,
|
|
|
- description: item.description,
|
|
|
- parameters: EffectZod.toJsonSchema(item.parameters),
|
|
|
- }))
|
|
|
+ const tool = Effect.fn("ExperimentalHttpApi.tool")(function* (ctx: { query: typeof ToolListQuery.Type }) {
|
|
|
+ const list = yield* registry.tools({
|
|
|
+ providerID: ctx.query.provider,
|
|
|
+ modelID: ctx.query.model,
|
|
|
+ agent: yield* agents.get(yield* agents.defaultAgent()),
|
|
|
})
|
|
|
+ return list.map((item) => ({
|
|
|
+ id: item.id,
|
|
|
+ description: item.description,
|
|
|
+ parameters: EffectZod.toJsonSchema(item.parameters),
|
|
|
+ }))
|
|
|
+ })
|
|
|
|
|
|
- const toolIDs = Effect.fn("ExperimentalHttpApi.toolIDs")(function* () {
|
|
|
- return yield* registry.ids()
|
|
|
- })
|
|
|
+ const toolIDs = Effect.fn("ExperimentalHttpApi.toolIDs")(function* () {
|
|
|
+ return yield* registry.ids()
|
|
|
+ })
|
|
|
|
|
|
- const worktree = Effect.fn("ExperimentalHttpApi.worktree")(function* () {
|
|
|
- const ctx = yield* InstanceState.context
|
|
|
- return yield* project.sandboxes(ctx.project.id)
|
|
|
- })
|
|
|
+ const worktree = Effect.fn("ExperimentalHttpApi.worktree")(function* () {
|
|
|
+ const ctx = yield* InstanceState.context
|
|
|
+ return yield* project.sandboxes(ctx.project.id)
|
|
|
+ })
|
|
|
|
|
|
- const worktreeCreate = Effect.fn("ExperimentalHttpApi.worktreeCreate")(function* (ctx: {
|
|
|
- payload: Worktree.CreateInput | undefined
|
|
|
- }) {
|
|
|
- return yield* worktreeSvc.create(ctx.payload)
|
|
|
- })
|
|
|
+ const worktreeCreate = Effect.fn("ExperimentalHttpApi.worktreeCreate")(function* (ctx: {
|
|
|
+ payload: Worktree.CreateInput | undefined
|
|
|
+ }) {
|
|
|
+ return yield* worktreeSvc.create(ctx.payload)
|
|
|
+ })
|
|
|
|
|
|
- const worktreeRemove = Effect.fn("ExperimentalHttpApi.worktreeRemove")(function* (input: {
|
|
|
- payload: Worktree.RemoveInput
|
|
|
- }) {
|
|
|
- const ctx = yield* InstanceState.context
|
|
|
- yield* worktreeSvc.remove(input.payload)
|
|
|
- yield* project.removeSandbox(ctx.project.id, input.payload.directory)
|
|
|
- return true
|
|
|
- })
|
|
|
+ const worktreeRemove = Effect.fn("ExperimentalHttpApi.worktreeRemove")(function* (input: {
|
|
|
+ payload: Worktree.RemoveInput
|
|
|
+ }) {
|
|
|
+ const ctx = yield* InstanceState.context
|
|
|
+ yield* worktreeSvc.remove(input.payload)
|
|
|
+ yield* project.removeSandbox(ctx.project.id, input.payload.directory)
|
|
|
+ return true
|
|
|
+ })
|
|
|
|
|
|
- const worktreeReset = Effect.fn("ExperimentalHttpApi.worktreeReset")(function* (ctx: {
|
|
|
- payload: Worktree.ResetInput
|
|
|
- }) {
|
|
|
- yield* worktreeSvc.reset(ctx.payload)
|
|
|
- return true
|
|
|
- })
|
|
|
+ const worktreeReset = Effect.fn("ExperimentalHttpApi.worktreeReset")(function* (ctx: {
|
|
|
+ payload: Worktree.ResetInput
|
|
|
+ }) {
|
|
|
+ yield* worktreeSvc.reset(ctx.payload)
|
|
|
+ return true
|
|
|
+ })
|
|
|
|
|
|
- const session = Effect.fn("ExperimentalHttpApi.session")(function* (ctx: { query: typeof SessionListQuery.Type }) {
|
|
|
- const limit = ctx.query.limit ?? 100
|
|
|
- const sessions = Array.from(
|
|
|
- Session.listGlobal({
|
|
|
- directory: ctx.query.directory,
|
|
|
- roots: ctx.query.roots,
|
|
|
- start: ctx.query.start,
|
|
|
- cursor: ctx.query.cursor,
|
|
|
- search: ctx.query.search,
|
|
|
- limit: limit + 1,
|
|
|
- archived: ctx.query.archived,
|
|
|
- }),
|
|
|
- )
|
|
|
- const list = sessions.length > limit ? sessions.slice(0, limit) : sessions
|
|
|
- return HttpServerResponse.jsonUnsafe(list, {
|
|
|
- headers:
|
|
|
- sessions.length > limit && list.length > 0
|
|
|
- ? { "x-next-cursor": String(list[list.length - 1].time.updated) }
|
|
|
- : undefined,
|
|
|
- })
|
|
|
+ const session = Effect.fn("ExperimentalHttpApi.session")(function* (ctx: { query: typeof SessionListQuery.Type }) {
|
|
|
+ const limit = ctx.query.limit ?? 100
|
|
|
+ const sessions = Array.from(
|
|
|
+ Session.listGlobal({
|
|
|
+ directory: ctx.query.directory,
|
|
|
+ roots: ctx.query.roots,
|
|
|
+ start: ctx.query.start,
|
|
|
+ cursor: ctx.query.cursor,
|
|
|
+ search: ctx.query.search,
|
|
|
+ limit: limit + 1,
|
|
|
+ archived: ctx.query.archived,
|
|
|
+ }),
|
|
|
+ )
|
|
|
+ const list = sessions.length > limit ? sessions.slice(0, limit) : sessions
|
|
|
+ return HttpServerResponse.jsonUnsafe(list, {
|
|
|
+ headers:
|
|
|
+ sessions.length > limit && list.length > 0
|
|
|
+ ? { "x-next-cursor": String(list[list.length - 1].time.updated) }
|
|
|
+ : undefined,
|
|
|
})
|
|
|
+ })
|
|
|
|
|
|
- const resource = Effect.fn("ExperimentalHttpApi.resource")(function* () {
|
|
|
- return yield* mcp.resources()
|
|
|
- })
|
|
|
+ const resource = Effect.fn("ExperimentalHttpApi.resource")(function* () {
|
|
|
+ return yield* mcp.resources()
|
|
|
+ })
|
|
|
|
|
|
- return handlers
|
|
|
- .handle("console", getConsole)
|
|
|
- .handle("consoleOrgs", listConsoleOrgs)
|
|
|
- .handle("consoleSwitch", switchConsole)
|
|
|
- .handle("tool", tool)
|
|
|
- .handle("toolIDs", toolIDs)
|
|
|
- .handle("worktree", worktree)
|
|
|
- .handle("worktreeCreate", worktreeCreate)
|
|
|
- .handle("worktreeRemove", worktreeRemove)
|
|
|
- .handle("worktreeReset", worktreeReset)
|
|
|
- .handle("session", session)
|
|
|
- .handle("resource", resource)
|
|
|
- }),
|
|
|
+ return handlers
|
|
|
+ .handle("console", getConsole)
|
|
|
+ .handle("consoleOrgs", listConsoleOrgs)
|
|
|
+ .handle("consoleSwitch", switchConsole)
|
|
|
+ .handle("tool", tool)
|
|
|
+ .handle("toolIDs", toolIDs)
|
|
|
+ .handle("worktree", worktree)
|
|
|
+ .handle("worktreeCreate", worktreeCreate)
|
|
|
+ .handle("worktreeRemove", worktreeRemove)
|
|
|
+ .handle("worktreeReset", worktreeReset)
|
|
|
+ .handle("session", session)
|
|
|
+ .handle("resource", resource)
|
|
|
+ }),
|
|
|
)
|