fix: implement stage_complete tool for LLM-driven stage completion
- Add STAGE_COMPLETE_TOOL constant and meta-tool handler in executeStage loop: when LLM calls stage_complete, break out of tool dispatch loop and proceed to normal validation/transition - Inject stage_complete tool definition in every inference request so the LLM always has the option to signal stage completion - Replace expand-all diff with scrollable diff window in approval surface (ctrl+x toggles, up/down scrolls, shows line range)
This commit is contained in:
+16
-1
@@ -92,6 +92,7 @@ import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.util.*
|
||||
import java.util.concurrent.*
|
||||
@@ -99,6 +100,7 @@ import java.util.concurrent.atomic.*
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
private const val MAX_TOOL_ROUNDS = 10
|
||||
private const val STAGE_COMPLETE_TOOL = "stage_complete"
|
||||
|
||||
@SuppressWarnings(
|
||||
"ForbiddenComment",
|
||||
@@ -258,6 +260,12 @@ abstract class SessionOrchestrator(
|
||||
inferenceResult.response.finishReason is FinishReason.ToolCall &&
|
||||
toolRounds < MAX_TOOL_ROUNDS
|
||||
) {
|
||||
// stage_complete is a meta-tool: the LLM calls it to signal the stage's goal is met.
|
||||
// Skip tool dispatch — the loop exits and normal validation/transition follows
|
||||
// (emitToolArtifacts + verifyProduces run on the success path after the loop).
|
||||
if (inferenceResult.response.toolCalls.any { it.function.name == STAGE_COMPLETE_TOOL }) {
|
||||
break
|
||||
}
|
||||
val toolEntries = dispatchToolCalls(sessionId, stageId,
|
||||
inferenceResult.response.toolCalls, stageConfig)
|
||||
val fatalEntry = toolEntries.firstOrNull { it.content.startsWith("FATAL:") }
|
||||
@@ -670,7 +678,14 @@ abstract class SessionOrchestrator(
|
||||
parameters = tool.parametersSchema,
|
||||
),
|
||||
)
|
||||
},
|
||||
} + ToolDefinition(
|
||||
function = ToolFunction(
|
||||
name = STAGE_COMPLETE_TOOL,
|
||||
description = "Call this tool when the stage's goal is fully met and no further tool calls are needed. " +
|
||||
"The orchestrator will proceed to the next stage.",
|
||||
parameters = JsonObject(emptyMap()),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// TODO: capture rendered prompt; currently contextpack.toString()
|
||||
|
||||
Reference in New Issue
Block a user