mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-06 19:58:43 +02:00
fix: suppress noisy hook lifecycle events
Stop forwarding hook lifecycle events when a project has no configured .github/hooks/*.json commands so the UI only receives meaningful hook activity. Also expose the configured-hook state on the bundle, cover the suppression wiring with tests, and document the updated event semantics. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -53,6 +53,15 @@ public sealed class CopilotAgentBundleTests
|
||||
Assert.Equal(["glob", "view"], sessionConfig.AvailableTools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_StoresWhetherHooksAreConfigured()
|
||||
{
|
||||
CopilotAgentBundle bundle = new([], hasConfiguredHooks: true);
|
||||
|
||||
Assert.True(bundle.HasConfiguredHooks);
|
||||
Assert.Empty(bundle.Agents);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateConfiguredSessionConfig_MergesInstructionsAndConvertsHandoffDeclarations()
|
||||
{
|
||||
|
||||
@@ -212,23 +212,7 @@ public sealed class CopilotTurnExecutionStateTests
|
||||
RunTurnCommandDto command = CreateCommand();
|
||||
CopilotTurnExecutionState state = new(command);
|
||||
|
||||
state.ObserveSessionEvent(
|
||||
command.Pattern.Agents[0],
|
||||
SessionEvent.FromJson(
|
||||
"""
|
||||
{
|
||||
"type": "hook.start",
|
||||
"data": {
|
||||
"hookInvocationId": "hook-1",
|
||||
"hookType": "postToolUse",
|
||||
"input": {
|
||||
"toolName": "view"
|
||||
}
|
||||
},
|
||||
"id": "66666666-6666-6666-6666-666666666666",
|
||||
"timestamp": "2026-03-27T00:00:00Z"
|
||||
}
|
||||
"""));
|
||||
state.ObserveSessionEvent(command.Pattern.Agents[0], CreateHookStartEvent());
|
||||
|
||||
HookLifecycleEventDto evt = Assert.Single(state.DrainPendingEvents().OfType<HookLifecycleEventDto>());
|
||||
Assert.Equal("start", evt.Phase);
|
||||
@@ -237,6 +221,36 @@ public sealed class CopilotTurnExecutionStateTests
|
||||
Assert.NotNull(evt.Input);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ObserveSessionEvent_HookEnd_QueuesHookLifecycleEvent()
|
||||
{
|
||||
RunTurnCommandDto command = CreateCommand();
|
||||
CopilotTurnExecutionState state = new(command);
|
||||
|
||||
state.ObserveSessionEvent(command.Pattern.Agents[0], CreateHookEndEvent());
|
||||
|
||||
HookLifecycleEventDto evt = Assert.Single(state.DrainPendingEvents().OfType<HookLifecycleEventDto>());
|
||||
Assert.Equal("end", evt.Phase);
|
||||
Assert.Equal("postToolUse", evt.HookType);
|
||||
Assert.Equal("hook-1", evt.HookInvocationId);
|
||||
Assert.True(evt.Success);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ObserveSessionEvent_HookLifecycleEvents_AreSuppressedWhenConfigured()
|
||||
{
|
||||
RunTurnCommandDto command = CreateCommand();
|
||||
CopilotTurnExecutionState state = new(command)
|
||||
{
|
||||
SuppressHookLifecycleEvents = true,
|
||||
};
|
||||
|
||||
state.ObserveSessionEvent(command.Pattern.Agents[0], CreateHookStartEvent());
|
||||
state.ObserveSessionEvent(command.Pattern.Agents[0], CreateHookEndEvent());
|
||||
|
||||
Assert.Empty(state.DrainPendingEvents());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ObserveSessionEvent_SessionCompactionComplete_QueuesCompactionEvent()
|
||||
{
|
||||
@@ -295,6 +309,45 @@ public sealed class CopilotTurnExecutionStateTests
|
||||
Assert.Equal("agent-1", evt.AgentId);
|
||||
}
|
||||
|
||||
private static SessionEvent CreateHookStartEvent()
|
||||
{
|
||||
return SessionEvent.FromJson(
|
||||
"""
|
||||
{
|
||||
"type": "hook.start",
|
||||
"data": {
|
||||
"hookInvocationId": "hook-1",
|
||||
"hookType": "postToolUse",
|
||||
"input": {
|
||||
"toolName": "view"
|
||||
}
|
||||
},
|
||||
"id": "66666666-6666-6666-6666-666666666666",
|
||||
"timestamp": "2026-03-27T00:00:00Z"
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
private static SessionEvent CreateHookEndEvent()
|
||||
{
|
||||
return SessionEvent.FromJson(
|
||||
"""
|
||||
{
|
||||
"type": "hook.end",
|
||||
"data": {
|
||||
"hookInvocationId": "hook-1",
|
||||
"hookType": "postToolUse",
|
||||
"success": true,
|
||||
"output": {
|
||||
"status": "ok"
|
||||
}
|
||||
},
|
||||
"id": "99999999-9999-9999-9999-999999999999",
|
||||
"timestamp": "2026-03-27T00:00:00Z"
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
private static RunTurnCommandDto CreateCommand()
|
||||
{
|
||||
return new RunTurnCommandDto
|
||||
|
||||
@@ -11,6 +11,18 @@ namespace Aryx.AgentHost.Tests;
|
||||
|
||||
public sealed class CopilotWorkflowRunnerTests
|
||||
{
|
||||
[Fact]
|
||||
public void ConfigureHookLifecycleEventSuppression_SetsStateFromBundle()
|
||||
{
|
||||
RunTurnCommandDto command = CreateApprovalCommand();
|
||||
CopilotTurnExecutionState state = new(command);
|
||||
CopilotAgentBundle bundle = new(Array.Empty<AIAgent>(), hasConfiguredHooks: false);
|
||||
|
||||
CopilotWorkflowRunner.ConfigureHookLifecycleEventSuppression(state, bundle);
|
||||
|
||||
Assert.True(state.SuppressHookLifecycleEvents);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SelectNewOutputMessages_SkipsFullTranscriptPrefix()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user