feat: approval gates block indefinitely instead of auto-rejecting on timeout
Remove the wall-clock approval timeout that auto-rejected pending approvals. The timeout modeled machine latency, but approvals are human latency (unbounded); it also created an intent/outcome divergence where a human approving at the same instant the timeout fired was silently overridden by the auto-reject. Approvals now block until the operator decides; the resolved-request dedup still guards against double-submit. Add ServerMessage.ApprovalResolved and map ApprovalDecisionResolvedEvent to it in DomainEventMapper so clients are notified when any approval is resolved (by anyone) — letting a second connected client clear its prompt. This is the event-sourced replacement for the removed timeout notification path. Drop the now-dead ApprovalConfig (timeout_ms) and its loader/test/sample-config references. ApprovalStatus.TIMED_OUT is retained for replay of historical events.
This commit is contained in:
@@ -204,13 +204,11 @@ object ConfigLoader {
|
||||
val serverSection = sections["server"] ?: emptyMap()
|
||||
val tuiSection = sections["tui"] ?: emptyMap()
|
||||
val cliSection = sections["cli"] ?: emptyMap()
|
||||
val approvalSection = sections["approval"] ?: emptyMap()
|
||||
val toolsSection = sections["tools"] ?: emptyMap()
|
||||
val toolsShellSection = sections["tools.shell"] ?: emptyMap()
|
||||
val toolsFileReadSection = sections["tools.file_read"] ?: emptyMap()
|
||||
val toolsFileWriteSection = sections["tools.file_write"] ?: emptyMap()
|
||||
val toolsFileEditSection = sections["tools.file_edit"] ?: emptyMap()
|
||||
val routerSection = sections["router"] ?: emptyMap()
|
||||
val routerEmbedderSection = sections["router.embedder"] ?: emptyMap()
|
||||
val routerL3Section = sections["router.l3"] ?: emptyMap()
|
||||
|
||||
@@ -228,10 +226,6 @@ object ConfigLoader {
|
||||
defaultOutput = asString(cliSection["default_output"], "human"),
|
||||
)
|
||||
|
||||
val approval = ApprovalConfig(
|
||||
timeoutMs = asLong(approvalSection["timeout_ms"], 300_000L),
|
||||
)
|
||||
|
||||
// Resolve tool enable flags: prefer nested [tools.shell], [tools.file_read], etc.
|
||||
// Fall back to flat [tools] section for backward compat
|
||||
val shellEnabled = when {
|
||||
@@ -350,7 +344,6 @@ object ConfigLoader {
|
||||
server = server,
|
||||
tui = tui,
|
||||
cli = cli,
|
||||
approval = approval,
|
||||
tools = tools,
|
||||
providers = providers,
|
||||
router = router,
|
||||
@@ -392,15 +385,6 @@ object ConfigLoader {
|
||||
}
|
||||
}
|
||||
|
||||
private fun asLong(value: Any?, default: Long = 0L): Long {
|
||||
return when (value) {
|
||||
is Long -> value
|
||||
is Int -> value.toLong()
|
||||
is String -> value.toLongOrNull() ?: default
|
||||
else -> default
|
||||
}
|
||||
}
|
||||
|
||||
private fun asBoolean(value: Any?, default: Boolean = false): Boolean {
|
||||
return when (value) {
|
||||
is Boolean -> value
|
||||
|
||||
@@ -7,7 +7,6 @@ data class CorrexConfig(
|
||||
val server: ServerConfig = ServerConfig(),
|
||||
val tui: TuiConfig = TuiConfig(),
|
||||
val cli: CliConfig = CliConfig(),
|
||||
val approval: ApprovalConfig = ApprovalConfig(),
|
||||
val tools: ToolsConfig = ToolsConfig(),
|
||||
val providers: List<ProviderConfig> = emptyList(),
|
||||
val router: RouterConfig = RouterConfig(),
|
||||
@@ -30,11 +29,6 @@ data class CliConfig(
|
||||
val defaultOutput: String = "human",
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ApprovalConfig(
|
||||
val timeoutMs: Long = 300_000L,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ToolsConfig(
|
||||
val sandboxRoot: String = "",
|
||||
|
||||
@@ -12,7 +12,6 @@ class ConfigLoaderTest {
|
||||
assertEquals("dark", config.tui.theme)
|
||||
assertEquals(5, config.tui.sessionListLimit)
|
||||
assertEquals("human", config.cli.defaultOutput)
|
||||
assertEquals(300_000L, config.approval.timeoutMs)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -28,9 +27,6 @@ class ConfigLoaderTest {
|
||||
|
||||
[cli]
|
||||
default_output = "json"
|
||||
|
||||
[approval]
|
||||
timeout_ms = 600000
|
||||
""".trimIndent()
|
||||
|
||||
val loader = ConfigLoader::class.java
|
||||
@@ -43,7 +39,6 @@ class ConfigLoaderTest {
|
||||
assertEquals("light", result.tui.theme)
|
||||
assertEquals(10, result.tui.sessionListLimit)
|
||||
assertEquals("json", result.cli.defaultOutput)
|
||||
assertEquals(600_000L, result.approval.timeoutMs)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user