chore(damn): detekt, build, tests, formatting
fixed detekt issues where possible. fixed disttar failing build because tools is added twice in the server module. added workflowId where required. fixed some tests not being recognized because of runBlocking without explicit return type. formatting + imports.
This commit is contained in:
+1
-1
@@ -8,8 +8,8 @@ import com.correx.infrastructure.artifactscas.compact.CompactionReport
|
||||
import com.correx.infrastructure.artifactscas.compact.Compactor
|
||||
import com.correx.infrastructure.artifactscas.compact.LivenessScanner
|
||||
import com.correx.infrastructure.artifactscas.config.CasConfig
|
||||
import com.correx.infrastructure.artifactscas.evict.Evictor
|
||||
import com.correx.infrastructure.artifactscas.evict.EvictionReport
|
||||
import com.correx.infrastructure.artifactscas.evict.Evictor
|
||||
import com.correx.infrastructure.artifactscas.index.ArtifactIndex
|
||||
import com.correx.infrastructure.artifactscas.recovery.TailScanReport
|
||||
import com.correx.infrastructure.artifactscas.recovery.TailScanner
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ package com.correx.infrastructure.artifactscas.segment
|
||||
import org.bouncycastle.crypto.digests.Blake3Digest
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.util.zip.CRC32C
|
||||
import java.util.zip.*
|
||||
|
||||
object SegmentLayout {
|
||||
const val HASH_SIZE: Int = 32
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.io.TempDir
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.UUID
|
||||
import java.util.*
|
||||
import kotlin.io.path.listDirectoryEntries
|
||||
|
||||
class CompactorTest {
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.io.TempDir
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.UUID
|
||||
import java.util.*
|
||||
import kotlin.io.path.listDirectoryEntries
|
||||
|
||||
class EvictorTest {
|
||||
|
||||
+1
-1
@@ -77,4 +77,4 @@ class InMemoryEventStore : EventStore {
|
||||
|
||||
return stored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ import kotlinx.coroutines.withContext
|
||||
import kotlinx.datetime.Instant
|
||||
import java.sql.Connection
|
||||
import java.sql.ResultSet
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.*
|
||||
|
||||
class SqliteEventStore(
|
||||
private val connection: Connection,
|
||||
@@ -254,4 +254,4 @@ private fun ResultSet.toStoredEvent(jsonSerializer: JsonEventSerializer): Stored
|
||||
),
|
||||
sequence = getLong("sequence"),
|
||||
payload = jsonSerializer.deserialize(getString("payload"))
|
||||
)
|
||||
)
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.*
|
||||
|
||||
class LiveArtifactRepository(
|
||||
private val eventStore: EventStore,
|
||||
|
||||
+1
-1
@@ -20,4 +20,4 @@ object JDBCHelper {
|
||||
autoCommit = oldAutoCommit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,4 +5,4 @@ import com.correx.testing.contracts.fixtures.events.store.EventStoreContractTest
|
||||
|
||||
class InMemoryEventStoreTest : EventStoreContractTest() {
|
||||
override fun store(): EventStore = InMemoryEventStore()
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,4 +20,4 @@ class InMemoryReplayTest : SessionReplayContractTest() {
|
||||
SessionCounterProjection("s1")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,4 +10,4 @@ class SqliteEventStoreTest : EventStoreContractTest() {
|
||||
val conn = DriverManager.getConnection("jdbc:sqlite::memory:")
|
||||
return SqliteEventStore(conn, artifactStore = NoopArtifactStore())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,4 +26,4 @@ class SqliteReplayTest : SessionReplayContractTest() {
|
||||
SessionCounterProjection("s1")
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.correx.infrastructure
|
||||
|
||||
import com.correx.core.artifacts.DefaultArtifactReducer
|
||||
import com.correx.core.artifacts.repository.ArtifactRepository
|
||||
import com.correx.core.artifactstore.ArtifactStore
|
||||
import com.correx.core.events.EventDispatcher
|
||||
import com.correx.core.events.stores.EventStore
|
||||
@@ -8,8 +10,19 @@ import com.correx.core.inference.InferenceProvider
|
||||
import com.correx.core.inference.InferenceRouter
|
||||
import com.correx.core.inference.ProviderRegistry
|
||||
import com.correx.core.inference.RoutingStrategy
|
||||
import com.correx.core.router.DefaultRouterContextBuilder
|
||||
import com.correx.core.router.DefaultRouterFacade
|
||||
import com.correx.core.router.DefaultRouterReducer
|
||||
import com.correx.core.router.DefaultRouterRepository
|
||||
import com.correx.core.router.RouterFacade
|
||||
import com.correx.core.router.RouterProjector
|
||||
import com.correx.core.router.model.RouterConfig
|
||||
import com.correx.core.sessions.projections.replay.DefaultEventReplayer
|
||||
import com.correx.core.tools.contract.ToolExecutor
|
||||
import com.correx.core.tools.registry.ToolRegistry
|
||||
import com.correx.infrastructure.artifactscas.CasArtifactStore
|
||||
import com.correx.infrastructure.artifactscas.config.CasConfig
|
||||
import com.correx.infrastructure.artifactscas.index.SqliteArtifactIndex
|
||||
import com.correx.infrastructure.inference.DefaultProviderRegistry
|
||||
import com.correx.infrastructure.inference.FirstAvailableRoutingStrategy
|
||||
import com.correx.infrastructure.inference.commons.ModelDescriptor
|
||||
@@ -17,11 +30,8 @@ import com.correx.infrastructure.inference.commons.ModelManager
|
||||
import com.correx.infrastructure.inference.commons.ResidencyMode
|
||||
import com.correx.infrastructure.inference.llama.cpp.DefaultModelManager
|
||||
import com.correx.infrastructure.inference.llama.cpp.LlamaCppInferenceProvider
|
||||
import com.correx.infrastructure.artifactscas.CasArtifactStore
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import com.correx.infrastructure.artifactscas.config.CasConfig
|
||||
import com.correx.infrastructure.artifactscas.index.SqliteArtifactIndex
|
||||
import com.correx.infrastructure.persistence.SqliteEventStore
|
||||
import com.correx.infrastructure.persistence.artifact.LiveArtifactRepository
|
||||
import com.correx.infrastructure.tools.DefaultToolRegistry
|
||||
import com.correx.infrastructure.tools.DispatchingToolExecutor
|
||||
import com.correx.infrastructure.tools.SandboxedToolExecutor
|
||||
@@ -31,18 +41,8 @@ import com.correx.infrastructure.workflow.FileSystemPromptLoader
|
||||
import com.correx.infrastructure.workflow.PromptLoader
|
||||
import com.correx.infrastructure.workflow.TomlWorkflowLoader
|
||||
import com.correx.infrastructure.workflow.WorkflowLoader
|
||||
import com.correx.infrastructure.persistence.artifact.LiveArtifactRepository
|
||||
import com.correx.core.artifacts.repository.ArtifactRepository
|
||||
import com.correx.core.artifacts.DefaultArtifactReducer
|
||||
import com.correx.core.router.DefaultRouterContextBuilder
|
||||
import com.correx.core.router.DefaultRouterFacade
|
||||
import com.correx.core.router.DefaultRouterRepository
|
||||
import com.correx.core.router.DefaultRouterReducer
|
||||
import com.correx.core.router.RouterFacade
|
||||
import com.correx.core.router.RouterProjector
|
||||
import com.correx.core.router.model.RouterConfig
|
||||
import com.correx.core.sessions.projections.replay.DefaultEventReplayer
|
||||
import io.ktor.client.HttpClient
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ class FileReadTool(
|
||||
(request.parameters["path"] as? String)?.let { pathString ->
|
||||
runCatching {
|
||||
val path = Paths.get(pathString).normalize().toAbsolutePath()
|
||||
if (allowedPaths.isNotEmpty() && allowedPaths.none { path.startsWith(it.normalize().toAbsolutePath()) }) {
|
||||
if (allowedPaths.none { path.startsWith(it.normalize().toAbsolutePath()) }) {
|
||||
return@runCatching ValidationResult.Invalid("Path '$pathString' is not in the allowed list")
|
||||
}
|
||||
ValidationResult.Valid
|
||||
|
||||
+5
-1
@@ -65,7 +65,11 @@ class FileWriteTool(
|
||||
}
|
||||
put(
|
||||
"required",
|
||||
buildJsonArray { add(JsonPrimitive("path")); add(JsonPrimitive("content")); add(JsonPrimitive("operation")) },
|
||||
buildJsonArray {
|
||||
add(JsonPrimitive("path"))
|
||||
add(JsonPrimitive("content"))
|
||||
add(JsonPrimitive("operation"))
|
||||
},
|
||||
)
|
||||
}
|
||||
override val tier: Tier = Tier.T2
|
||||
|
||||
+9
-9
@@ -33,7 +33,7 @@ class FileEditToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute patch success`() = runBlocking {
|
||||
fun `execute patch success`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_edit_patch")
|
||||
val filePath = tempDir.resolve("test.txt")
|
||||
Files.writeString(filePath, "line1\nline2\nline3\n")
|
||||
@@ -63,7 +63,7 @@ class FileEditToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for disallowed path`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for disallowed path`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_edit_test")
|
||||
val otherDir = Files.createTempDirectory("other_dir")
|
||||
val tool = FileEditTool(allowedPaths = setOf(tempDir))
|
||||
@@ -80,7 +80,7 @@ class FileEditToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for non-existent file`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for non-existent file`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_edit_test")
|
||||
val tool = FileEditTool(allowedPaths = setOf(tempDir))
|
||||
val request = createRequest(
|
||||
@@ -96,7 +96,7 @@ class FileEditToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for missing parameters`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for missing parameters`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_edit_test")
|
||||
val filePath = tempDir.resolve("test.txt")
|
||||
Files.writeString(filePath, "content")
|
||||
@@ -120,7 +120,7 @@ class FileEditToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute append success`() = runBlocking {
|
||||
fun `execute append success`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_edit_append")
|
||||
val filePath = tempDir.resolve("test.txt")
|
||||
Files.writeString(filePath, "hello")
|
||||
@@ -139,7 +139,7 @@ class FileEditToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute replace success`() = runBlocking {
|
||||
fun `execute replace success`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_edit_replace")
|
||||
val filePath = tempDir.resolve("test.txt")
|
||||
Files.writeString(filePath, "the quick brown fox")
|
||||
@@ -159,7 +159,7 @@ class FileEditToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute replace failure zero matches`() = runBlocking {
|
||||
fun `execute replace failure zero matches`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_edit_replace_fail")
|
||||
val filePath = tempDir.resolve("test.txt")
|
||||
Files.writeString(filePath, "the quick brown fox")
|
||||
@@ -180,7 +180,7 @@ class FileEditToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute replace failure multiple matches`() = runBlocking {
|
||||
fun `execute replace failure multiple matches`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_edit_replace_fail_multi")
|
||||
val filePath = tempDir.resolve("test.txt")
|
||||
Files.writeString(filePath, "fox fox fox")
|
||||
@@ -202,7 +202,7 @@ class FileEditToolTest {
|
||||
|
||||
|
||||
@Test
|
||||
fun `execute patch failure`() = runBlocking {
|
||||
fun `execute patch failure`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_edit_patch_fail")
|
||||
val filePath = tempDir.resolve("test.txt")
|
||||
Files.writeString(filePath, "original")
|
||||
|
||||
+8
-8
@@ -31,15 +31,15 @@ class FileReadToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Valid for allowed path`() = runBlocking {
|
||||
val tool = FileReadTool(allowedPaths = emptySet())
|
||||
fun `validateRequest returns Valid for allowed path`(): Unit = runBlocking {
|
||||
val tempFile = Files.createTempFile("test_allowed", ".txt")
|
||||
val tool = FileReadTool(allowedPaths = setOf(tempFile.parent))
|
||||
val request = createRequest(tempFile.toString())
|
||||
assertEquals(ValidationResult.Valid, tool.validateRequest(request))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for disallowed path`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for disallowed path`(): Unit = runBlocking {
|
||||
val tempFile = Files.createTempFile("test_disallowed", ".txt")
|
||||
val tool = FileReadTool(allowedPaths = setOf(tempFile.parent.resolve("subdir")))
|
||||
val request = createRequest(tempFile.toString())
|
||||
@@ -49,7 +49,7 @@ class FileReadToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for missing path parameter`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for missing path parameter`(): Unit = runBlocking {
|
||||
val tool = FileReadTool()
|
||||
val request = ToolRequest(
|
||||
invocationId = invocationId,
|
||||
@@ -67,12 +67,12 @@ class FileReadToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute returns Success for valid file`() = runBlocking {
|
||||
fun `execute returns Success for valid file`(): Unit = runBlocking {
|
||||
val content = "Hello, world!"
|
||||
val tempFile = Files.createTempFile("test_content", ".txt")
|
||||
Files.writeString(tempFile, content)
|
||||
|
||||
val tool = FileReadTool(allowedPaths = emptySet())
|
||||
val tool = FileReadTool(allowedPaths = setOf(tempFile.parent))
|
||||
val request = createRequest(tempFile.toString())
|
||||
val result = tool.execute(request)
|
||||
|
||||
@@ -83,7 +83,7 @@ class FileReadToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute returns Failure for non-existent file`() = runBlocking {
|
||||
fun `execute returns Failure for non-existent file`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("test_dir")
|
||||
val nonExistentFile = tempDir.resolve("missing.txt")
|
||||
|
||||
@@ -98,7 +98,7 @@ class FileReadToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute returns Failure for disallowed path`() = runBlocking {
|
||||
fun `execute returns Failure for disallowed path`(): Unit = runBlocking {
|
||||
val tempFile = Files.createTempFile("test_disallowed_exec", ".txt")
|
||||
val tool = FileReadTool(allowedPaths = setOf(tempFile.parent.resolve("other")))
|
||||
val request = createRequest(tempFile.toString())
|
||||
|
||||
+11
-16
@@ -34,7 +34,7 @@ class FileWriteToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Valid for allowed path and valid operation`() = runBlocking {
|
||||
fun `validateRequest returns Valid for allowed path and valid operation`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_write_test")
|
||||
val tool = FileWriteTool(allowedPaths = setOf(tempDir))
|
||||
val request = createRequest(
|
||||
@@ -48,7 +48,7 @@ class FileWriteToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for disallowed path`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for disallowed path`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_write_test")
|
||||
val otherDir = Files.createTempDirectory("other_dir")
|
||||
val tool = FileWriteTool(allowedPaths = setOf(tempDir))
|
||||
@@ -65,7 +65,7 @@ class FileWriteToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for missing operation`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for missing operation`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_write_test")
|
||||
val tool = FileWriteTool(allowedPaths = setOf(tempDir))
|
||||
val request = createRequest(
|
||||
@@ -83,7 +83,7 @@ class FileWriteToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for missing path`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for missing path`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_write_test")
|
||||
val tool = FileWriteTool(allowedPaths = setOf(tempDir))
|
||||
val request = createRequest(
|
||||
@@ -98,7 +98,7 @@ class FileWriteToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for missing content on write`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for missing content on write`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_write_test")
|
||||
val tool = FileWriteTool(allowedPaths = setOf(tempDir))
|
||||
val request = createRequest(
|
||||
@@ -113,7 +113,7 @@ class FileWriteToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for unknown operation`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for unknown operation`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_write_test")
|
||||
val tool = FileWriteTool(allowedPaths = setOf(tempDir))
|
||||
val request = createRequest(
|
||||
@@ -128,7 +128,7 @@ class FileWriteToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute returns Success for write operation`() = runBlocking {
|
||||
fun `execute returns Success for write operation`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_write_test")
|
||||
val tool = FileWriteTool(allowedPaths = setOf(tempDir))
|
||||
val filePath = tempDir.resolve("test.txt")
|
||||
@@ -151,7 +151,7 @@ class FileWriteToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute returns Success for delete operation`() = runBlocking {
|
||||
fun `execute returns Success for delete operation`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_write_test")
|
||||
val tool = FileWriteTool(allowedPaths = setOf(tempDir))
|
||||
val filePath = tempDir.resolve("to_delete.txt")
|
||||
@@ -164,12 +164,7 @@ class FileWriteToolTest {
|
||||
),
|
||||
)
|
||||
|
||||
println("TempDir: $tempDir")
|
||||
println("FilePath: $filePath")
|
||||
println("PathString from request: ${request.parameters["path"]}")
|
||||
val result = tool.execute(request)
|
||||
println("Result: $result")
|
||||
println("Exists after: ${Files.exists(filePath)}")
|
||||
assertTrue(result is ToolResult.Success)
|
||||
val success = result as ToolResult.Success
|
||||
assertEquals("File deleted successfully: $filePath", success.output)
|
||||
@@ -178,7 +173,7 @@ class FileWriteToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute returns Failure for deleting non-existent file`() = runBlocking {
|
||||
fun `execute returns Failure for deleting non-existent file`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_write_test")
|
||||
val tool = FileWriteTool(allowedPaths = setOf(tempDir))
|
||||
val filePath = tempDir.resolve("non_existent.txt")
|
||||
@@ -199,7 +194,7 @@ class FileWriteToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute returns Failure for disallowed path`() = runBlocking {
|
||||
fun `execute returns Failure for disallowed path`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_write_test")
|
||||
val otherDir = Files.createTempDirectory("other_dir")
|
||||
val tool = FileWriteTool(allowedPaths = setOf(tempDir))
|
||||
@@ -221,7 +216,7 @@ class FileWriteToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Valid for existing file in allowed directory`() = runBlocking {
|
||||
fun `validateRequest returns Valid for existing file in allowed directory`(): Unit = runBlocking {
|
||||
val tempDir = Files.createTempDirectory("file_write_test_existing")
|
||||
val filePath = tempDir.resolve("existing.txt")
|
||||
Files.writeString(filePath, "content")
|
||||
|
||||
-1
@@ -21,7 +21,6 @@ import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.util.*
|
||||
|
||||
@SuppressWarnings("TooManyFunctions", "LongParameterList")
|
||||
class SandboxedToolExecutor(
|
||||
|
||||
+34
-20
@@ -1,7 +1,7 @@
|
||||
package com.correx.infrastructure.tools
|
||||
|
||||
import com.correx.core.artifactstore.ArtifactStore
|
||||
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
|
||||
@@ -25,41 +25,55 @@ data class FileWriteConfig(
|
||||
val sandboxRoot: Path? = null,
|
||||
val workingDir: Path? = null,
|
||||
)
|
||||
|
||||
data class FileEditConfig(
|
||||
val enabled: Boolean = false,
|
||||
val allowedPaths: Set<Path> = emptySet(),
|
||||
val workingDir: Path? = null,
|
||||
)
|
||||
data class ShellConfig(val enabled: Boolean = false, val allowedExecutables: Set<String> = emptySet(), val workingDir: Path? = null)
|
||||
|
||||
data class ShellConfig(
|
||||
val enabled: Boolean = false,
|
||||
val allowedExecutables: Set<String> = emptySet(),
|
||||
val workingDir: Path? = null,
|
||||
)
|
||||
|
||||
/**
|
||||
* Extension function to convert [ToolConfig] into a list of [Tool] implementations.
|
||||
*/
|
||||
fun ToolConfig.buildTools(): List<Tool> = buildList {
|
||||
if (shell.enabled) {
|
||||
add(ShellTool(
|
||||
allowedExecutables = shell.allowedExecutables,
|
||||
workingDir = shell.workingDir,
|
||||
))
|
||||
add(
|
||||
ShellTool(
|
||||
allowedExecutables = shell.allowedExecutables,
|
||||
workingDir = shell.workingDir,
|
||||
),
|
||||
)
|
||||
}
|
||||
if (fileRead.enabled) {
|
||||
add(FileReadTool(
|
||||
allowedPaths = fileRead.allowedPaths
|
||||
))
|
||||
add(
|
||||
FileReadTool(
|
||||
allowedPaths = fileRead.allowedPaths,
|
||||
),
|
||||
)
|
||||
}
|
||||
if (fileWrite.enabled) {
|
||||
add(FileWriteTool(
|
||||
allowedPaths = fileWrite.allowedPaths,
|
||||
artifactStore = fileWrite.artifactStore,
|
||||
materializingWriter = fileWrite.materializingWriter,
|
||||
sandboxRoot = fileWrite.sandboxRoot,
|
||||
workingDir = fileWrite.workingDir,
|
||||
))
|
||||
add(
|
||||
FileWriteTool(
|
||||
allowedPaths = fileWrite.allowedPaths,
|
||||
artifactStore = fileWrite.artifactStore,
|
||||
materializingWriter = fileWrite.materializingWriter,
|
||||
sandboxRoot = fileWrite.sandboxRoot,
|
||||
workingDir = fileWrite.workingDir,
|
||||
),
|
||||
)
|
||||
}
|
||||
if (fileEdit.enabled) {
|
||||
add(FileEditTool(
|
||||
allowedPaths = fileEdit.allowedPaths,
|
||||
workingDir = fileEdit.workingDir,
|
||||
))
|
||||
add(
|
||||
FileEditTool(
|
||||
allowedPaths = fileEdit.allowedPaths,
|
||||
workingDir = fileEdit.workingDir,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -30,14 +30,14 @@ class ShellToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Valid for allowed executable`() = runBlocking {
|
||||
fun `validateRequest returns Valid for allowed executable`(): Unit = runBlocking {
|
||||
val tool = ShellTool(allowedExecutables = setOf("echo"))
|
||||
val request = createRequest(listOf("echo", "hello"))
|
||||
assertEquals(ValidationResult.Valid, tool.validateRequest(request))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for disallowed executable`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for disallowed executable`(): Unit = runBlocking {
|
||||
val tool = ShellTool(allowedExecutables = setOf("echo"))
|
||||
val request = createRequest(listOf("ls"))
|
||||
val result = tool.validateRequest(request)
|
||||
@@ -46,7 +46,7 @@ class ShellToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for empty argv`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for empty argv`(): Unit = runBlocking {
|
||||
val tool = ShellTool(allowedExecutables = setOf("echo"))
|
||||
val request = createRequest(emptyList())
|
||||
val result = tool.validateRequest(request)
|
||||
@@ -58,7 +58,7 @@ class ShellToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `validateRequest returns Invalid for null argv`() = runBlocking {
|
||||
fun `validateRequest returns Invalid for null argv`(): Unit = runBlocking {
|
||||
val tool = ShellTool(allowedExecutables = setOf("echo"))
|
||||
val request = ToolRequest(
|
||||
invocationId = invocationId,
|
||||
@@ -76,7 +76,7 @@ class ShellToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute returns Success for exit code 0`() = runBlocking {
|
||||
fun `execute returns Success for exit code 0`(): Unit = runBlocking {
|
||||
val tool = ShellTool(allowedExecutables = setOf("echo"))
|
||||
val request = createRequest(listOf("echo", "hello"))
|
||||
val result = tool.execute(request)
|
||||
@@ -89,7 +89,7 @@ class ShellToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute returns Failure with non-zero exit code for failed process`() = runBlocking {
|
||||
fun `execute returns Failure with non-zero exit code for failed process`(): Unit = runBlocking {
|
||||
val tool = ShellTool(allowedExecutables = setOf("false"))
|
||||
val request = createRequest(listOf("false"))
|
||||
val result = tool.execute(request)
|
||||
@@ -101,7 +101,7 @@ class ShellToolTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `execute returns Failure on timeout`() = runBlocking {
|
||||
fun `execute returns Failure on timeout`(): Unit = runBlocking {
|
||||
// Using sleep command to simulate timeout
|
||||
val tool = ShellTool(allowedExecutables = setOf("sleep"), timeoutMs = 100L)
|
||||
val request = createRequest(listOf("sleep", "1"))
|
||||
|
||||
+8
-8
@@ -32,12 +32,12 @@ private data class ProducesEntry(
|
||||
private data class StageSection(
|
||||
val id: String = "",
|
||||
val prompt: String? = null,
|
||||
@JsonProperty("system_prompt") val systemPrompt: String? = null,
|
||||
@param:JsonProperty("system_prompt") val systemPrompt: String? = null,
|
||||
val produces: List<ProducesEntry> = emptyList(),
|
||||
val needs: List<String> = emptyList(),
|
||||
@JsonProperty("allowed_tools") val allowedTools: List<String> = emptyList(),
|
||||
@JsonProperty("token_budget") val tokenBudget: Int = 4096,
|
||||
@JsonProperty("max_retries") val maxRetries: Int = 3,
|
||||
@param:JsonProperty("allowed_tools") val allowedTools: List<String> = emptyList(),
|
||||
@param:JsonProperty("token_budget") val tokenBudget: Int = 4096,
|
||||
@param:JsonProperty("max_retries") val maxRetries: Int = 3,
|
||||
)
|
||||
|
||||
// condition fields flattened into the transition row
|
||||
@@ -45,10 +45,10 @@ private data class TransitionSection(
|
||||
val id: String = "",
|
||||
val from: String = "",
|
||||
val to: String = "",
|
||||
@JsonProperty("condition_type") val conditionType: String = "",
|
||||
@JsonProperty("condition_artifact_id") val conditionArtifactId: String? = null,
|
||||
@JsonProperty("condition_key") val conditionKey: String? = null,
|
||||
@JsonProperty("condition_value") val conditionValue: String? = null,
|
||||
@param:JsonProperty("condition_type") val conditionType: String = "",
|
||||
@param:JsonProperty("condition_artifact_id") val conditionArtifactId: String? = null,
|
||||
@param:JsonProperty("condition_key") val conditionKey: String? = null,
|
||||
@param:JsonProperty("condition_value") val conditionValue: String? = null,
|
||||
)
|
||||
|
||||
private const val TERMINAL = "done"
|
||||
|
||||
+1
-1
@@ -4,8 +4,8 @@ import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertThrows
|
||||
import java.nio.file.Files
|
||||
import kotlin.io.path.writeText
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertContains
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class FileSystemPromptLoaderTest {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user