refactor: retire sandbox dual-write; file tools write in-place into workspace

This commit is contained in:
2026-05-31 10:39:58 +04:00
parent 3c90ac4aef
commit 95e79bffb8
3 changed files with 34 additions and 77 deletions
@@ -1,11 +1,6 @@
package com.correx.infrastructure.tools.filesystem
import com.correx.core.approvals.Tier
import com.correx.core.artifacts.MaterializationResult
import com.correx.core.artifacts.MaterializingArtifactWriter
import com.correx.core.artifacts.kind.FileWrittenArtifact
import com.correx.core.artifacts.kind.FileWrittenPayload
import com.correx.core.artifactstore.ArtifactStore
import com.correx.core.events.events.ToolRequest
import com.correx.core.events.types.ToolInvocationId
import com.correx.core.tools.contract.FileAffectingTool
@@ -17,15 +12,12 @@ import com.correx.core.tools.contract.ValidationResult
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonArray
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonObject
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.IOException
import java.nio.file.Files
import java.nio.file.InvalidPathException
@@ -34,16 +26,9 @@ import java.nio.file.Paths
class FileWriteTool(
allowedPaths: Set<Path> = emptySet(),
private val artifactStore: ArtifactStore? = null,
private val materializingWriter: MaterializingArtifactWriter? = null,
private val sandboxRoot: Path? = null,
private val workingDir: Path? = null,
) : Tool, FileAffectingTool, ToolExecutor {
private companion object {
val log: Logger = LoggerFactory.getLogger(FileWriteTool::class.java)
}
private val normalizedAllowedPaths: Set<Path> = allowedPaths.map { it.normalize().toAbsolutePath() }.toSet()
override val name: String = "file_write"
@@ -174,7 +159,6 @@ class FileWriteTool(
withContext(Dispatchers.IO) {
AtomicFileWriter.write(path, content.toByteArray(Charsets.UTF_8))
}
storeArtifact(pathString, content, request.parameters["mode"] as? String ?: "0644")
ToolResult.Success(
invocationId = request.invocationId,
output = "File written successfully to $pathString",
@@ -206,26 +190,6 @@ class FileWriteTool(
)
}
@Suppress("ReturnCount")
private suspend fun storeArtifact(pathString: String, content: String, mode: String) {
val writer = materializingWriter ?: return
val store = artifactStore ?: return
val root = sandboxRoot ?: return
val payload = FileWrittenPayload(path = pathString, content = content, mode = mode)
when (val result = writer.materialize(payload, root)) {
is MaterializationResult.Success -> {
val canonicalBytes = Json.encodeToString(
FileWrittenArtifact.serializer(),
result.artifact,
).toByteArray(Charsets.UTF_8)
store.put(canonicalBytes)
}
is MaterializationResult.Failure ->
log.warn("[FileWriteTool] artifact materialization failed for {}: {}", pathString, result.reason)
}
}
private fun handleExecutionException(
e: Throwable,
invocationId: ToolInvocationId,
@@ -1,7 +1,5 @@
package com.correx.infrastructure.tools
import com.correx.core.artifacts.MaterializingArtifactWriter
import com.correx.core.artifactstore.ArtifactStore
import com.correx.core.tools.contract.Tool
import com.correx.infrastructure.tools.filesystem.FileEditTool
import com.correx.infrastructure.tools.filesystem.FileReadTool
@@ -20,9 +18,6 @@ data class FileReadConfig(val enabled: Boolean = false, val allowedPaths: Set<Pa
data class FileWriteConfig(
val enabled: Boolean = false,
val allowedPaths: Set<Path> = emptySet(),
val artifactStore: ArtifactStore? = null,
val materializingWriter: MaterializingArtifactWriter? = null,
val sandboxRoot: Path? = null,
val workingDir: Path? = null,
)
@@ -61,9 +56,6 @@ fun ToolConfig.buildTools(): List<Tool> = buildList {
add(
FileWriteTool(
allowedPaths = fileWrite.allowedPaths,
artifactStore = fileWrite.artifactStore,
materializingWriter = fileWrite.materializingWriter,
sandboxRoot = fileWrite.sandboxRoot,
workingDir = fileWrite.workingDir,
),
)