/
Alex_Ural
/
opencode
Обзор
Документация
Войти
/
Alex_Ural
/
opencode
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
packages/core/src/tool/write.ts
101 строка
4 KB
James Long
refactor(core): remove tool layer exports (#34622)
30 июн 2026, 18:18
Не верифицирован
30 июн 2026, 18:18
5691f36
Код
Авторство
О чём код?
/** * Model-facing V2 file-write leaf. Relative paths resolve within the active * Location. Absolute paths inside that Location are accepted, while explicit * absolute external paths retain mutation capability through a separate * external_directory approval before edit approval. */ export * as WriteTool from "./write" import { ToolFailure } from "@opencode-ai/llm" import { Effect, Layer, Schema } from "effect" import { makeLocationNode } from "../effect/app-node" import { FileMutation } from "../file-mutation" import { LocationMutation } from "../location-mutation" import { PermissionV2 } from "../permission" import { ToolRegistry } from "./registry" import { Tool } from "./tool" import { Tools } from "./tools" export const name = "write" // TODO: Revisit whether model-facing mutation schemas should prefer absolute `filePath` naming for trained-in compatibility after evaluating model behavior. export const Input = Schema.Struct({ path: Schema.String.annotate({ description: "File path to write. Relative paths resolve within the active Location. Absolute paths inside that Location are accepted; external absolute paths require external_directory approval.", }), content: Schema.String.annotate({ description: "Content to write to the file" }), }) export const Output = Schema.Struct({ operation: Schema.Literal("write"), target: Schema.String, resource: Schema.String, existed: Schema.Boolean, }) export type Output = typeof Output.Type export const toModelOutput = (output: Output) => `${output.existed ? "Wrote" : "Created"} file successfully: ${output.resource}` /** Deferred V2 write UX integrations remain visible at the model-facing seam. */ // TODO: Add formatter integration after V2 formatter runtime exists. // TODO: Publish watcher/file-edit events after V2 watcher integration exists. // TODO: Add snapshots / undo after design exists. // TODO: Add LSP notification and diagnostics after V2 LSP runtime exists. const layer = Layer.effectDiscard( Effect.gen(function* () { const tools = yield* Tools.Service const mutation = yield* LocationMutation.Service const files = yield* FileMutation.Service const permission = yield* PermissionV2.Service yield* tools .register({ [name]: Tool.withPermission( Tool.make({ description: "Write content to one file. Relative paths resolve within the active Location. Absolute paths inside the Location are accepted. Explicit external absolute paths require external_directory approval before edit approval.", input: Input, output: Output, toModelOutput: ({ output }) => [{ type: "text", text: toModelOutput(output) }], execute: (input, context) => Effect.gen(function* () { const source = { type: "tool" as const, messageID: context.assistantMessageID, callID: context.toolCallID, } const target = yield* mutation.resolve({ path: input.path, kind: "file" }) const external = target.externalDirectory if (external) yield* permission.assert({ ...LocationMutation.externalDirectoryPermission(external), sessionID: context.sessionID, agent: context.agent, source, }) yield* permission.assert({ action: "edit", resources: [target.resource], save: ["*"], sessionID: context.sessionID, agent: context.agent, source, }) return yield* files.writeTextPreservingBom({ target, content: input.content }) }).pipe(Effect.mapError(() => new ToolFailure({ message: `Unable to write ${input.path}` }))), }), "edit", ), }) .pipe(Effect.orDie) }), ) export const node = makeLocationNode({ name: "tool/write", layer, deps: [ToolRegistry.node, LocationMutation.node, FileMutation.node, PermissionV2.node], })