refactor(format): make formatting explicit instead of bus-driven
Replace the implicit Bus.subscribe(File.Event.Edited) formatter with an explicit Format.run(filepath) call in write/edit/apply_patch tools. This ensures formatting completes before FileTime stamps and LSP diagnostics run, rather than relying on the bus to block on subscribers. - Add Format.run() to the Effect service interface and legacy adapter - Call Format.run() in write, edit, and apply_patch tools after writes - Remove Bus subscription from Format layerkit/effect-bus
parent
f3cf519d98
commit
009d77c9d8
|
|
@ -4,9 +4,7 @@ import { InstanceContext } from "@/effect/instance-context"
|
|||
import path from "path"
|
||||
import { mergeDeep } from "remeda"
|
||||
import z from "zod"
|
||||
import { Bus } from "../bus"
|
||||
import { Config } from "../config/config"
|
||||
import { File } from "../file"
|
||||
import { Instance } from "../project/instance"
|
||||
import { Process } from "../util/process"
|
||||
import { Log } from "../util/log"
|
||||
|
|
@ -27,6 +25,7 @@ export namespace Format {
|
|||
export type Status = z.infer<typeof Status>
|
||||
|
||||
export interface Interface {
|
||||
readonly run: (filepath: string) => Effect.Effect<void>
|
||||
readonly status: () => Effect.Effect<Status[]>
|
||||
}
|
||||
|
||||
|
|
@ -90,48 +89,44 @@ export namespace Format {
|
|||
return result
|
||||
}
|
||||
|
||||
yield* Effect.acquireRelease(
|
||||
Effect.sync(() =>
|
||||
Bus.subscribe(
|
||||
File.Event.Edited,
|
||||
Instance.bind(async (payload) => {
|
||||
const file = payload.properties.file
|
||||
log.info("formatting", { file })
|
||||
const ext = path.extname(file)
|
||||
const run = Effect.fn("Format.run")(function* (filepath: string) {
|
||||
log.info("formatting", { file: filepath })
|
||||
const ext = path.extname(filepath)
|
||||
|
||||
for (const item of await getFormatter(ext)) {
|
||||
log.info("running", { command: item.command })
|
||||
try {
|
||||
const proc = Process.spawn(
|
||||
item.command.map((x) => x.replace("$FILE", file)),
|
||||
{
|
||||
cwd: instance.directory,
|
||||
env: { ...process.env, ...item.environment },
|
||||
stdout: "ignore",
|
||||
stderr: "ignore",
|
||||
},
|
||||
)
|
||||
const exit = await proc.exited
|
||||
if (exit !== 0) {
|
||||
log.error("failed", {
|
||||
command: item.command,
|
||||
...item.environment,
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
log.error("failed to format file", {
|
||||
error,
|
||||
command: item.command,
|
||||
...item.environment,
|
||||
file,
|
||||
})
|
||||
}
|
||||
for (const item of yield* Effect.promise(() => getFormatter(ext))) {
|
||||
log.info("running", { command: item.command })
|
||||
yield* Effect.tryPromise({
|
||||
try: async () => {
|
||||
const proc = Process.spawn(
|
||||
item.command.map((x) => x.replace("$FILE", filepath)),
|
||||
{
|
||||
cwd: instance.directory,
|
||||
env: { ...process.env, ...item.environment },
|
||||
stdout: "ignore",
|
||||
stderr: "ignore",
|
||||
},
|
||||
)
|
||||
const exit = await proc.exited
|
||||
if (exit !== 0) {
|
||||
log.error("failed", {
|
||||
command: item.command,
|
||||
...item.environment,
|
||||
})
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
(unsubscribe) => Effect.sync(unsubscribe),
|
||||
)
|
||||
},
|
||||
catch: (error) => {
|
||||
log.error("failed to format file", {
|
||||
error,
|
||||
command: item.command,
|
||||
...item.environment,
|
||||
file: filepath,
|
||||
})
|
||||
return error
|
||||
},
|
||||
}).pipe(Effect.ignore)
|
||||
}
|
||||
})
|
||||
|
||||
log.info("init")
|
||||
|
||||
const status = Effect.fn("Format.status")(function* () {
|
||||
|
|
@ -147,10 +142,14 @@ export namespace Format {
|
|||
return result
|
||||
})
|
||||
|
||||
return Service.of({ status })
|
||||
return Service.of({ run, status })
|
||||
}),
|
||||
)
|
||||
|
||||
export async function run(filepath: string) {
|
||||
return runPromiseInstance(Service.use((s) => s.run(filepath)))
|
||||
}
|
||||
|
||||
export async function status() {
|
||||
return runPromiseInstance(Service.use((s) => s.status()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { createTwoFilesPatch, diffLines } from "diff"
|
|||
import { assertExternalDirectory } from "./external-directory"
|
||||
import { trimDiff } from "./edit"
|
||||
import { LSP } from "../lsp"
|
||||
import { Format } from "../format"
|
||||
import { Filesystem } from "../util/filesystem"
|
||||
import DESCRIPTION from "./apply_patch.txt"
|
||||
import { File } from "../file"
|
||||
|
|
@ -220,6 +221,7 @@ export const ApplyPatchTool = Tool.define("apply_patch", {
|
|||
}
|
||||
|
||||
if (edited) {
|
||||
await Format.run(edited)
|
||||
await Bus.publish(File.Event.Edited, {
|
||||
file: edited,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { File } from "../file"
|
|||
import { FileWatcher } from "../file/watcher"
|
||||
import { Bus } from "../bus"
|
||||
import { FileTime } from "../file/time"
|
||||
import { Format } from "../format"
|
||||
import { Filesystem } from "../util/filesystem"
|
||||
import { Instance } from "../project/instance"
|
||||
import { Snapshot } from "@/snapshot"
|
||||
|
|
@ -71,6 +72,7 @@ export const EditTool = Tool.define("edit", {
|
|||
},
|
||||
})
|
||||
await Filesystem.write(filePath, params.newString)
|
||||
await Format.run(filePath)
|
||||
await Bus.publish(File.Event.Edited, {
|
||||
file: filePath,
|
||||
})
|
||||
|
|
@ -108,6 +110,7 @@ export const EditTool = Tool.define("edit", {
|
|||
})
|
||||
|
||||
await Filesystem.write(filePath, contentNew)
|
||||
await Format.run(filePath)
|
||||
await Bus.publish(File.Event.Edited, {
|
||||
file: filePath,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { Bus } from "../bus"
|
|||
import { File } from "../file"
|
||||
import { FileWatcher } from "../file/watcher"
|
||||
import { FileTime } from "../file/time"
|
||||
import { Format } from "../format"
|
||||
import { Filesystem } from "../util/filesystem"
|
||||
import { Instance } from "../project/instance"
|
||||
import { trimDiff } from "./edit"
|
||||
|
|
@ -42,6 +43,7 @@ export const WriteTool = Tool.define("write", {
|
|||
})
|
||||
|
||||
await Filesystem.write(filepath, params.content)
|
||||
await Format.run(filepath)
|
||||
await Bus.publish(File.Event.Edited, {
|
||||
file: filepath,
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue