refactor(core): replace bash tool with shell tool

This commit is contained in:
Dax Raad 2026-06-29 00:43:04 -04:00
commit 5ae93092aa
37 changed files with 2260 additions and 901 deletions

View file

@ -12,6 +12,7 @@ import { EventHandler } from "./handlers/event"
import { AgentHandler } from "./handlers/agent"
import { HealthHandler } from "./handlers/health"
import { PtyHandler } from "./handlers/pty"
import { ShellHandler } from "./handlers/shell"
import { QuestionHandler } from "./handlers/question"
import { ReferenceHandler } from "./handlers/reference"
import { LocationHandler } from "./handlers/location"
@ -36,6 +37,7 @@ export const handlers = Layer.mergeAll(
SkillHandler,
EventHandler,
PtyHandler,
ShellHandler,
QuestionHandler,
ReferenceHandler,
ProjectCopyHandler,

View file

@ -0,0 +1,69 @@
import { Shell } from "@opencode-ai/core/shell"
import { Location } from "@opencode-ai/core/location"
import { Effect } from "effect"
import { HttpApiBuilder, HttpApiSchema } from "effect/unstable/httpapi"
import { ShellNotFoundError } from "@opencode-ai/protocol/errors"
import { Api } from "../api"
import { response } from "../location"
export const ShellHandler = HttpApiBuilder.group(Api, "server.shell", (handlers) =>
Effect.gen(function* () {
return handlers
.handle(
"shell.list",
Effect.fn(function* () {
const shell = yield* Shell.Service
return yield* response(shell.list())
}),
)
.handle(
"shell.create",
Effect.fn(function* (ctx) {
const shell = yield* Shell.Service
const location = yield* Location.Service
return yield* response(shell.create({ ...ctx.payload, cwd: ctx.payload.cwd || location.directory }))
}),
)
.handle(
"shell.get",
Effect.fn(function* (ctx) {
const shell = yield* Shell.Service
return yield* response(
shell.get(ctx.params.id).pipe(
Effect.catchTag(
"Shell.NotFoundError",
() => new ShellNotFoundError({ id: ctx.params.id, message: `Shell command not found: ${ctx.params.id}` }),
),
),
)
}),
)
.handle(
"shell.output",
Effect.fn(function* (ctx) {
const shell = yield* Shell.Service
return yield* response(
shell.output(ctx.params.id, { cursor: ctx.query.cursor, limit: ctx.query.limit }).pipe(
Effect.catchTag(
"Shell.NotFoundError",
() => new ShellNotFoundError({ id: ctx.params.id, message: `Shell command not found: ${ctx.params.id}` }),
),
),
)
}),
)
.handle(
"shell.remove",
Effect.fn(function* (ctx) {
const shell = yield* Shell.Service
yield* shell.remove(ctx.params.id).pipe(
Effect.catchTag(
"Shell.NotFoundError",
() => new ShellNotFoundError({ id: ctx.params.id, message: `Shell command not found: ${ctx.params.id}` }),
),
)
return HttpApiSchema.NoContent.make()
}),
)
}),
)