feat(agent): harden loop recovery and permission hook lifecycle
Some checks failed
Release Gate / gate (push) Has been cancelled

This commit is contained in:
2026-04-03 19:24:08 +09:00
parent 0c3921feb5
commit 5de5c74040
8 changed files with 523 additions and 115 deletions

View File

@@ -1864,6 +1864,42 @@ public class AgentLoopCodeQualityTests
delay2.Should().BeLessThan(1850);
}
[Fact]
public void IsContextOverflowError_DetectsMaxOutputTokenPatterns()
{
var maxOutput = InvokePrivateStatic<bool>(
"IsContextOverflowError",
"Request failed: maximum output tokens exceeded");
var truncated = InvokePrivateStatic<bool>(
"IsContextOverflowError",
"response was truncated due to token limit");
var unrelated = InvokePrivateStatic<bool>(
"IsContextOverflowError",
"invalid api key");
maxOutput.Should().BeTrue();
truncated.Should().BeTrue();
unrelated.Should().BeFalse();
}
[Fact]
public void IsLikelyWithheldOrOverflowResponse_DetectsWithheldAndLimitHints()
{
var withheld = InvokePrivateStatic<bool>(
"IsLikelyWithheldOrOverflowResponse",
"output withheld because prompt too long");
var maxOutput = InvokePrivateStatic<bool>(
"IsLikelyWithheldOrOverflowResponse",
"max_output_tokens reached");
var normal = InvokePrivateStatic<bool>(
"IsLikelyWithheldOrOverflowResponse",
"completed successfully");
withheld.Should().BeTrue();
maxOutput.Should().BeTrue();
normal.Should().BeFalse();
}
[Fact]
public void GetToolExecutionTimeoutMs_UsesDefaultWhenEnvMissing()
{

View File

@@ -207,6 +207,22 @@ public class TaskRunServiceTests
service.ActiveTasks.Should().Contain(t => t.Kind == "permission" && t.Status == "waiting");
}
[Fact]
[Trait("Suite", "ReplayStability")]
public void RestoreRecentFromExecutionEvents_RebuildsSkillCallAsActiveTask()
{
var service = new TaskRunService();
var now = DateTime.Now;
service.RestoreRecentFromExecutionEvents(
[
new Models.ChatExecutionEvent { Timestamp = now.AddSeconds(-2), RunId = "run-s1", Type = "SkillCall", ToolName = "review_skill", Summary = "skill running", Iteration = 1 },
new Models.ChatExecutionEvent { Timestamp = now.AddSeconds(-1), RunId = "run-s1", Type = "Thinking", Summary = "thinking", Iteration = 2 },
]);
service.ActiveTasks.Should().Contain(t => t.Kind == "skill" && t.Title == "review_skill" && t.Status == "running");
}
[Fact]
public void RestoreRecentFromExecutionEvents_RemovesActiveTaskWhenTerminalEventAppears()
{