tool for writing files
This commit is contained in:
parent
63abe037d8
commit
816f5e526b
4 changed files with 41 additions and 1 deletions
|
|
@ -300,6 +300,14 @@ function createServer(options: Options) {
|
||||||
},
|
},
|
||||||
async (input) => toolResult(await control(options, "POST", "/experimental/simulation/filesystem/seed", input)),
|
async (input) => toolResult(await control(options, "POST", "/experimental/simulation/filesystem/seed", input)),
|
||||||
)
|
)
|
||||||
|
server.registerTool(
|
||||||
|
"simulation_control_filesystem_write",
|
||||||
|
{
|
||||||
|
description: "Write one file into the backend simulated filesystem.",
|
||||||
|
inputSchema: z.object({ path: z.string(), content: FileContentSchema }),
|
||||||
|
},
|
||||||
|
async (input) => toolResult(await control(options, "POST", "/experimental/simulation/filesystem/write", input)),
|
||||||
|
)
|
||||||
server.registerTool(
|
server.registerTool(
|
||||||
"simulation_control_network_register",
|
"simulation_control_network_register",
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,15 @@ export const simulationRoute = HttpRouter.use((router) =>
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
yield* router.add("POST", "/experimental/simulation/filesystem/write", () =>
|
||||||
|
json(
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const input = yield* HttpServerRequest.schemaBodyJson(Simulation.FilesystemWriteInput)
|
||||||
|
return yield* simulation.writeFile(input)
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
yield* router.add("POST", "/experimental/simulation/network/register", () =>
|
yield* router.add("POST", "/experimental/simulation/network/register", () =>
|
||||||
json(
|
json(
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,11 @@ export const FilesystemSeedInput = Schema.Struct({
|
||||||
files: Schema.Record(Schema.String, FileContent),
|
files: Schema.Record(Schema.String, FileContent),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const FilesystemWriteInput = Schema.Struct({
|
||||||
|
path: Schema.String,
|
||||||
|
content: FileContent,
|
||||||
|
})
|
||||||
|
|
||||||
export const NetworkRegisterInput = Schema.Union([
|
export const NetworkRegisterInput = Schema.Union([
|
||||||
Schema.Struct({
|
Schema.Struct({
|
||||||
kind: Schema.Literal("json"),
|
kind: Schema.Literal("json"),
|
||||||
|
|
@ -80,6 +85,7 @@ export class SimulationLLMError extends Schema.TaggedErrorClass<SimulationLLMErr
|
||||||
export interface Interface {
|
export interface Interface {
|
||||||
readonly reset: () => Effect.Effect<void>
|
readonly reset: () => Effect.Effect<void>
|
||||||
readonly seedFilesystem: (input: typeof FilesystemSeedInput.Type) => Effect.Effect<{ files: string[] }, unknown>
|
readonly seedFilesystem: (input: typeof FilesystemSeedInput.Type) => Effect.Effect<{ files: string[] }, unknown>
|
||||||
|
readonly writeFile: (input: typeof FilesystemWriteInput.Type) => Effect.Effect<{ file: string }, unknown>
|
||||||
readonly registerNetwork: (input: typeof NetworkRegisterInput.Type) => Effect.Effect<{ registered: string }, unknown>
|
readonly registerNetwork: (input: typeof NetworkRegisterInput.Type) => Effect.Effect<{ registered: string }, unknown>
|
||||||
readonly enqueueLLM: (input: typeof LLMEnqueueInput.Type) => Effect.Effect<{ queued: number }>
|
readonly enqueueLLM: (input: typeof LLMEnqueueInput.Type) => Effect.Effect<{ queued: number }>
|
||||||
readonly nextLLM: () => Effect.Effect<LLMScript, SimulationLLMError>
|
readonly nextLLM: () => Effect.Effect<LLMScript, SimulationLLMError>
|
||||||
|
|
@ -131,6 +137,12 @@ export const layer = Layer.effect(
|
||||||
return { files }
|
return { files }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const writeFile = Effect.fn("Simulation.writeFile")(function* (input: typeof FilesystemWriteInput.Type) {
|
||||||
|
yield* fs.writeWithDirs(path.isAbsolute(input.path) ? input.path : path.join("/opencode", input.path), fileContent(input.content))
|
||||||
|
yield* Ref.update(state, (current) => ({ ...current, files: [...current.files, input.path] }))
|
||||||
|
return { file: input.path }
|
||||||
|
})
|
||||||
|
|
||||||
const registerNetwork = Effect.fn("Simulation.registerNetwork")(function* (input: typeof NetworkRegisterInput.Type) {
|
const registerNetwork = Effect.fn("Simulation.registerNetwork")(function* (input: typeof NetworkRegisterInput.Type) {
|
||||||
switch (input.kind) {
|
switch (input.kind) {
|
||||||
case "json":
|
case "json":
|
||||||
|
|
@ -178,7 +190,7 @@ export const layer = Layer.effect(
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return Service.of({ reset, seedFilesystem, registerNetwork, enqueueLLM, nextLLM, snapshot })
|
return Service.of({ reset, seedFilesystem, writeFile, registerNetwork, enqueueLLM, nextLLM, snapshot })
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,17 @@ describe("Simulation", () => {
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
it.effect("writes one file into the simulated filesystem", () =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const simulation = yield* Simulation.Service
|
||||||
|
const fs = yield* AppFileSystem.Service
|
||||||
|
|
||||||
|
expect(yield* simulation.writeFile({ path: "src/generated.txt", content: "generated" })).toEqual({ file: "src/generated.txt" })
|
||||||
|
expect(yield* fs.readFileString("/opencode/src/generated.txt")).toBe("generated")
|
||||||
|
expect((yield* simulation.snapshot()).files).toContain("src/generated.txt")
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
it.effect("registers network responses through control state", () =>
|
it.effect("registers network responses through control state", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const simulation = yield* Simulation.Service
|
const simulation = yield* Simulation.Service
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue