feat(agent): /interrupt slash command for in-flight agent turn #39

Merged
jasoncouture merged 2 commits from feat/agent-interrupt-slash into main 2026-05-07 16:11:14 -04:00
jasoncouture commented 2026-05-07 11:46:53 -04:00 (Migrated from github.com)

Summary

/interrupt cancels the agent's in-flight turn (model inference, eager tool dispatch) without affecting the agent's lifetime. Persisted context up to the interrupt is preserved; partial assistant text or thought fragments emitted by the canceled turn are dropped. The agent stays live and resumes on the next inbound message.

Closes the Interrupt in-flight agent item under TASKS.md → "Web UI" (per the no-UI-buttons-for-control policy, surfaced as a slash command instead of a button).

What's in here

IAgent.InterruptAsync (Abstractions.Agent)

New method on the public IAgent contract: Task InterruptAsync(CancellationToken). Idempotent.

Agent impl (Core)

  • Per-turn CancellationTokenSource _activeTurnCts, installed at the top of each batch in RunLoopAsync (linked to the run-loop's outer shutdown CT) and cleared on completion.
  • A small _interruptLock guards the field assignment against the InterruptAsync caller.
  • InterruptAsync cancels the per-turn CTS without affecting _shutdown. With no turn in flight, _activeTurnCts is null and the call is a no-op.
  • Cancellation propagates through ProcessBatchAsync. The run-loop's catch (OperationCanceledException) when (turnCts.IsCancellationRequested && !cancellationToken.IsCancellationRequested) path logs the interrupt and continues to the next batch.

Plumbing

  • IAgentDirectory.InterruptAsync(string agentId, CancellationToken) — UI-side façade.
  • AgentDirectory.InterruptAsync — looks up the agent on the manager and forwards.
  • InterruptCommand : ISlashCommand/interrupt, no parameters, calls into the directory. Registered in AddSlashCommands.

Behavior at the interrupt point

  • User turn: already persisted before the model is invoked, so context isn't rolled back.
  • Partial assistant text / thought fragments: dropped. InferenceRunner stops publishing the moment it observes the cancellation, and PublishToolTurnsAsync isn't reached, so no partial ModelTurn is emitted on the bus → nothing lands in the persisted history.
  • Tool turns: with the current pipeline, tool turns are persisted only at end-of-RunAsync (via PublishToolTurnsAsync). Cancelling before that point leaves no orphan tool_call in history. See "Out of scope" below.

Tests

2 new TUnit cases (AgentInterruptTests):

  • InterruptOnIdleAgentIsNoOp — repeated calls without a turn in flight don't throw.
  • InterruptCancelsInFlightTurnAndAgentRemainsLive — a HangingLanguageModel blocks forever on the cancellation token; after InterruptAsync, the agent's processing gate releases and is reacquirable, proving the run-loop returned to idle.

HangingLanguageModel is a small new fixture for tests that need to drive interrupt scenarios.

Out of scope (deferred)

Persisting synthetic "The user interrupted execution" tool-result entries for tool calls that were dispatched but didn't complete at interrupt time. The current pipeline persists tool turns in a single batch at end-of-RunAsync, so cancelling before that point leaves nothing on the bus to write. A follow-up can either (a) track in-flight tool dispatches at the agent level and synthesise paired ModelTurns on cancel, or (b) move tool-turn publishing into the per-call dispatch site.

Test plan

  • dotnet test --solution LlamaShears.slnx — 391 passing (was 389).
  • Husky dotnet-test-on-source-change pre-commit check passed.
  • Husky docs-api-up-to-date pre-push check passed.

Stacking note

Targets feat/slash-command-registry (PR #38). Will retarget main automatically as the chain merges. This is the last PR in the 9-branch chain.

🤖 Generated with Claude Code

## Summary `/interrupt` cancels the agent's in-flight turn (model inference, eager tool dispatch) without affecting the agent's lifetime. Persisted context up to the interrupt is preserved; partial assistant text or thought fragments emitted by the canceled turn are dropped. The agent stays live and resumes on the next inbound message. Closes the *Interrupt in-flight agent* item under TASKS.md → "Web UI" (per the no-UI-buttons-for-control policy, surfaced as a slash command instead of a button). ## What's in here ### `IAgent.InterruptAsync` (Abstractions.Agent) New method on the public `IAgent` contract: `Task InterruptAsync(CancellationToken)`. Idempotent. ### `Agent` impl (Core) - Per-turn `CancellationTokenSource _activeTurnCts`, installed at the top of each batch in `RunLoopAsync` (linked to the run-loop's outer shutdown CT) and cleared on completion. - A small `_interruptLock` guards the field assignment against the `InterruptAsync` caller. - `InterruptAsync` cancels the per-turn CTS without affecting `_shutdown`. With no turn in flight, `_activeTurnCts` is null and the call is a no-op. - Cancellation propagates through `ProcessBatchAsync`. The run-loop's `catch (OperationCanceledException) when (turnCts.IsCancellationRequested && !cancellationToken.IsCancellationRequested)` path logs the interrupt and continues to the next batch. ### Plumbing - `IAgentDirectory.InterruptAsync(string agentId, CancellationToken)` — UI-side façade. - `AgentDirectory.InterruptAsync` — looks up the agent on the manager and forwards. - `InterruptCommand : ISlashCommand` — `/interrupt`, no parameters, calls into the directory. Registered in `AddSlashCommands`. ## Behavior at the interrupt point - **User turn**: already persisted before the model is invoked, so context isn't rolled back. - **Partial assistant text / thought fragments**: dropped. `InferenceRunner` stops publishing the moment it observes the cancellation, and `PublishToolTurnsAsync` isn't reached, so no partial `ModelTurn` is emitted on the bus → nothing lands in the persisted history. - **Tool turns**: with the current pipeline, tool turns are persisted only at end-of-`RunAsync` (via `PublishToolTurnsAsync`). Cancelling before that point leaves no orphan `tool_call` in history. See "Out of scope" below. ## Tests 2 new TUnit cases (`AgentInterruptTests`): - `InterruptOnIdleAgentIsNoOp` — repeated calls without a turn in flight don't throw. - `InterruptCancelsInFlightTurnAndAgentRemainsLive` — a `HangingLanguageModel` blocks forever on the cancellation token; after `InterruptAsync`, the agent's processing gate releases and is reacquirable, proving the run-loop returned to idle. `HangingLanguageModel` is a small new fixture for tests that need to drive interrupt scenarios. ## Out of scope (deferred) Persisting synthetic `"The user interrupted execution"` tool-result entries for tool calls that were dispatched but didn't complete at interrupt time. The current pipeline persists tool turns in a single batch at end-of-`RunAsync`, so cancelling before that point leaves nothing on the bus to write. A follow-up can either (a) track in-flight tool dispatches at the agent level and synthesise paired `ModelTurn`s on cancel, or (b) move tool-turn publishing into the per-call dispatch site. ## Test plan - [x] `dotnet test --solution LlamaShears.slnx` — 391 passing (was 389). - [x] Husky `dotnet-test-on-source-change` pre-commit check passed. - [x] Husky `docs-api-up-to-date` pre-push check passed. ## Stacking note Targets `feat/slash-command-registry` (PR #38). Will retarget `main` automatically as the chain merges. This is the last PR in the 9-branch chain. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2026-05-07 11:52:45 -04:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull request overview

Adds an /interrupt slash command and corresponding agent API to cancel an in-flight agent turn (model inference / eager tool dispatch) while keeping the agent process alive for subsequent messages.

Changes:

  • Extends the public IAgent contract with InterruptAsync and implements per-turn cancellation in Agent’s run loop.
  • Adds UI-side plumbing (IAgentDirectory + AgentDirectory) and a new /interrupt ISlashCommand.
  • Adds unit test coverage for interrupting both idle and in-flight turns (with a new hanging model fixture).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/LlamaShears.UnitTests/Agent/Core/HangingLanguageModel.cs Adds a test fixture model that blocks until cancellation, enabling interrupt scenarios.
tests/LlamaShears.UnitTests/Agent/Core/AgentInterruptTests.cs Adds unit tests verifying interrupt idempotence and that the agent remains live after canceling an in-flight turn.
src/public/LlamaShears.Core.Abstractions.Agent/IAgent.cs Introduces the new public InterruptAsync API contract with documentation.
src/LlamaShears.Core/Agent.cs Implements per-turn CTS wiring, InterruptAsync, and an “interrupted turn” log path in the run loop.
src/LlamaShears.Api/Web/AgentDirectory.cs Forwards interrupt requests to the loaded agent instance.
src/LlamaShears.Api.Web/Services/IAgentDirectory.cs Exposes InterruptAsync on the UI-side agent directory abstraction.
src/LlamaShears.Api.Web/Services/SlashCommands/SlashCommandsServiceCollectionExtensions.cs Registers the new /interrupt slash command in DI.
src/LlamaShears.Api.Web/Services/SlashCommands/InterruptCommand.cs Implements the /interrupt command that invokes the directory interrupt endpoint.
docs/api/LlamaShears.Core.Abstractions.Agent/LlamaShears/Core/Abstractions/Agent/IAgent.md Updates generated API docs to include InterruptAsync.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

## Pull request overview Adds an `/interrupt` slash command and corresponding agent API to cancel an in-flight agent turn (model inference / eager tool dispatch) while keeping the agent process alive for subsequent messages. **Changes:** - Extends the public `IAgent` contract with `InterruptAsync` and implements per-turn cancellation in `Agent`’s run loop. - Adds UI-side plumbing (`IAgentDirectory` + `AgentDirectory`) and a new `/interrupt` `ISlashCommand`. - Adds unit test coverage for interrupting both idle and in-flight turns (with a new hanging model fixture). ### Reviewed changes Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | tests/LlamaShears.UnitTests/Agent/Core/HangingLanguageModel.cs | Adds a test fixture model that blocks until cancellation, enabling interrupt scenarios. | | tests/LlamaShears.UnitTests/Agent/Core/AgentInterruptTests.cs | Adds unit tests verifying interrupt idempotence and that the agent remains live after canceling an in-flight turn. | | src/public/LlamaShears.Core.Abstractions.Agent/IAgent.cs | Introduces the new public `InterruptAsync` API contract with documentation. | | src/LlamaShears.Core/Agent.cs | Implements per-turn CTS wiring, `InterruptAsync`, and an “interrupted turn” log path in the run loop. | | src/LlamaShears.Api/Web/AgentDirectory.cs | Forwards interrupt requests to the loaded agent instance. | | src/LlamaShears.Api.Web/Services/IAgentDirectory.cs | Exposes `InterruptAsync` on the UI-side agent directory abstraction. | | src/LlamaShears.Api.Web/Services/SlashCommands/SlashCommandsServiceCollectionExtensions.cs | Registers the new `/interrupt` slash command in DI. | | src/LlamaShears.Api.Web/Services/SlashCommands/InterruptCommand.cs | Implements the `/interrupt` command that invokes the directory interrupt endpoint. | | docs/api/LlamaShears.Core.Abstractions.Agent/LlamaShears/Core/Abstractions/Agent/IAgent.md | Updates generated API docs to include `InterruptAsync`. | </details> --- 💡 <a href="/jasoncouture/llama-shears/new/feat/slash-command-registry?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.
@ -0,0 +1,26 @@
using System.Collections.Immutable;
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-05-07 11:52:45 -04:00

/interrupt returns SlashCommandResult.Default, which means the dispatcher won’t perform any UI-side cleanup. If the agent is interrupted mid-stream, the UI can be left with a “streaming” bubble that never receives a Final=true fragment (since inference stops abruptly). Consider adding a post-execute hint (e.g. “StopStreaming/RefreshView”) or otherwise clearing streaming state on interrupt so the chat view doesn’t get stuck.

`/interrupt` returns `SlashCommandResult.Default`, which means the dispatcher won’t perform any UI-side cleanup. If the agent is interrupted mid-stream, the UI can be left with a “streaming” bubble that never receives a `Final=true` fragment (since inference stops abruptly). Consider adding a post-execute hint (e.g. “StopStreaming/RefreshView”) or otherwise clearing streaming state on interrupt so the chat view doesn’t get stuck.
@ -125,6 +127,24 @@ public sealed partial class Agent : IAgent, IEventHandler<ChannelMessage>, IAsyn
return ValueTask.CompletedTask;
}
public Task InterruptAsync(CancellationToken cancellationToken)
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-05-07 11:52:44 -04:00

InterruptAsync accepts a CancellationToken but currently ignores it and always returns a completed task. If callers pass request-abort tokens (e.g. from the web UI), this method won’t respect cancellation semantics; either remove the parameter (if possible) or explicitly observe it (e.g., throw if already canceled) to match the rest of the API surface.

`InterruptAsync` accepts a `CancellationToken` but currently ignores it and always returns a completed task. If callers pass request-abort tokens (e.g. from the web UI), this method won’t respect cancellation semantics; either remove the parameter (if possible) or explicitly observe it (e.g., throw if already canceled) to match the rest of the API surface.
@ -128,0 +139,4 @@
CancellationTokenSource? cancellationTokenSource;
lock (_interruptLock)
{
cancellationTokenSource = _activeTurnCts;
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-05-07 11:52:45 -04:00

Calling CancellationTokenSource.Cancel() while holding _interruptLock risks running cancellation callbacks under the lock (callbacks can run synchronously), which can lead to lock inversion/deadlocks if any callback ever touches agent state that also uses _interruptLock. Safer pattern is to copy _activeTurnCts to a local under the lock, release the lock, then call Cancel() on the local reference.

Calling `CancellationTokenSource.Cancel()` while holding `_interruptLock` risks running cancellation callbacks under the lock (callbacks can run synchronously), which can lead to lock inversion/deadlocks if any callback ever touches agent state that also uses `_interruptLock`. Safer pattern is to copy `_activeTurnCts` to a local under the lock, release the lock, then call `Cancel()` on the local reference.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-05-07 11:52:44 -04:00

turnCts.Token is passed through to ProcessBatchAsync, which means /interrupt can cancel before the user turn is published/persisted (the first await in ProcessBatchAsync uses this token). If an interrupt happens early in the turn, the inbound ChannelMessage has already been dequeued and the user message can be lost entirely. Consider using the per-turn CTS only for inference/tool dispatch, while publishing/persisting the user turn (and any other must-not-drop bookkeeping) under the outer run-loop/shutdown token instead.

`turnCts.Token` is passed through to `ProcessBatchAsync`, which means `/interrupt` can cancel *before* the user turn is published/persisted (the first await in `ProcessBatchAsync` uses this token). If an interrupt happens early in the turn, the inbound `ChannelMessage` has already been dequeued and the user message can be lost entirely. Consider using the per-turn CTS only for inference/tool dispatch, while publishing/persisting the user turn (and any other must-not-drop bookkeeping) under the outer run-loop/shutdown token instead.
@ -42,4 +42,18 @@ public interface IAgent : IDisposable
/// or unconfigured context is left alone.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-05-07 11:52:45 -04:00

The XML docs say “partial assistant text or thought fragments … are dropped”, but fragment events (AgentMessageFragment/AgentThoughtFragment) can already have been published before cancellation is observed, and there’s no corresponding “retract/clear” event. Consider clarifying that partial fragments are dropped from persisted history (ModelTurns), while live subscribers may have seen partial fragments.

The XML docs say “partial assistant text or thought fragments … are dropped”, but fragment events (`AgentMessageFragment`/`AgentThoughtFragment`) can already have been published before cancellation is observed, and there’s no corresponding “retract/clear” event. Consider clarifying that partial fragments are dropped from *persisted history* (ModelTurns), while live subscribers may have seen partial fragments.
github-actions[bot] commented 2026-05-07 15:52:40 -04:00 (Migrated from github.com)
Package Line Rate Branch Rate Complexity Health
LlamaShears.Core.Abstractions.Context 100% 100% 4
LlamaShears.Provider.Ollama 3% 1% 166
LlamaShears.IntegrationTests 87% 73% 71
LlamaShears.Core 46% 31% 879
LlamaShears.Core.Abstractions.Content 0% 100% 1
LlamaShears.Core.Abstractions.Caching 100% 100% 1
LlamaShears.Core.Eventing 96% 76% 51
StrangeSoft.Plugins.Host 20% 21% 87
LlamaShears.Core.Abstractions.Commands 64% 100% 3
LlamaShears.Core.Abstractions.Provider 32% 20% 66
LlamaShears.Core.Abstractions.Memory 0% 100% 3
LlamaShears.Api.Web 37% 20% 348
LlamaShears.Hosting 26% 8% 27
LlamaShears.Core.Abstractions.Events 21% 6% 79
LlamaShears.Core.Abstractions.SystemPrompt 100% 100% 2
LlamaShears 65% 25% 11
LlamaShears.Core.Abstractions.PromptContext 89% 100% 2
LlamaShears.Provider.Onnx.Embeddings 4% 0% 68
LlamaShears.Plugins.Host 34% 24% 36
LlamaShears.Core.Abstractions.Agent 73% 100% 11
LlamaShears.Api 10% 3% 344
LlamaShears.Plugins 0% 100% 1
LlamaShears.Core.Eventing.Extensions 100% 100% 1
LlamaShears.Core.Abstractions.Context 100% 100% 4
LlamaShears.Provider.Ollama 3% 1% 166
LlamaShears.Core 45% 31% 879
LlamaShears.Core.Abstractions.Content 0% 100% 1
LlamaShears.Core.Abstractions.Caching 100% 100% 1
LlamaShears.Core.Eventing 96% 76% 51
StrangeSoft.Plugins.Host 20% 21% 87
LlamaShears.Core.Abstractions.Commands 64% 100% 3
LlamaShears.Core.Abstractions.Provider 32% 20% 66
LlamaShears.Core.Abstractions.Memory 0% 100% 3
LlamaShears.Api.Web 25% 12% 348
LlamaShears.Hosting 26% 8% 27
LlamaShears.Core.Abstractions.Events 21% 6% 79
LlamaShears.Core.Abstractions.SystemPrompt 100% 100% 2
LlamaShears 65% 25% 11
LlamaShears.Core.Abstractions.PromptContext 89% 100% 2
LlamaShears.Provider.Onnx.Embeddings 4% 0% 68
LlamaShears.Plugins.Host 34% 24% 36
LlamaShears.Core.Abstractions.Agent 73% 100% 11
LlamaShears.Api 9% 1% 344
LlamaShears.Plugins 0% 100% 1
LlamaShears.Core.Eventing.Extensions 100% 100% 1
LlamaShears.Core.Abstractions.Context 100% 100% 4
LlamaShears.Provider.Ollama 44% 24% 166
LlamaShears.Core 47% 44% 879
LlamaShears.Core.Abstractions.Content 0% 100% 1
LlamaShears.Core.Abstractions.Caching 100% 100% 1
LlamaShears.Core.Eventing 93% 86% 51
LlamaShears.Core.Abstractions.Commands 0% 100% 3
LlamaShears.Core.Abstractions.Provider 78% 64% 66
LlamaShears.Core.Abstractions.Memory 100% 100% 3
LlamaShears.Api.Web 1% 1% 348
LlamaShears.Hosting 33% 21% 27
LlamaShears.Core.Abstractions.Events 15% 3% 79
LlamaShears.Core.Abstractions.SystemPrompt 100% 100% 2
LlamaShears.Core.Abstractions.PromptContext 89% 100% 2
LlamaShears.Provider.Onnx.Embeddings 33% 36% 68
LlamaShears.Core.Abstractions.Agent 86% 100% 11
LlamaShears.Api 27% 29% 344
LlamaShears.Core.Eventing.Extensions 100% 100% 1
LlamaShears.Analyzers 89% 76% 199
LlamaShears.Analyzers.CodeFixes 85% 69% 60
Summary 48% (8393 / 22579) 37% (1612 / 6181) 6768
Package | Line Rate | Branch Rate | Complexity | Health -------- | --------- | ----------- | ---------- | ------ LlamaShears.Core.Abstractions.Context | 100% | 100% | 4 | ✔ LlamaShears.Provider.Ollama | 3% | 1% | 166 | ❌ LlamaShears.IntegrationTests | 87% | 73% | 71 | ✔ LlamaShears.Core | 46% | 31% | 879 | ❌ LlamaShears.Core.Abstractions.Content | 0% | 100% | 1 | ❌ LlamaShears.Core.Abstractions.Caching | 100% | 100% | 1 | ✔ LlamaShears.Core.Eventing | 96% | 76% | 51 | ✔ StrangeSoft.Plugins.Host | 20% | 21% | 87 | ❌ LlamaShears.Core.Abstractions.Commands | 64% | 100% | 3 | ➖ LlamaShears.Core.Abstractions.Provider | 32% | 20% | 66 | ❌ LlamaShears.Core.Abstractions.Memory | 0% | 100% | 3 | ❌ LlamaShears.Api.Web | 37% | 20% | 348 | ❌ LlamaShears.Hosting | 26% | 8% | 27 | ❌ LlamaShears.Core.Abstractions.Events | 21% | 6% | 79 | ❌ LlamaShears.Core.Abstractions.SystemPrompt | 100% | 100% | 2 | ✔ LlamaShears | 65% | 25% | 11 | ➖ LlamaShears.Core.Abstractions.PromptContext | 89% | 100% | 2 | ✔ LlamaShears.Provider.Onnx.Embeddings | 4% | 0% | 68 | ❌ LlamaShears.Plugins.Host | 34% | 24% | 36 | ❌ LlamaShears.Core.Abstractions.Agent | 73% | 100% | 11 | ➖ LlamaShears.Api | 10% | 3% | 344 | ❌ LlamaShears.Plugins | 0% | 100% | 1 | ❌ LlamaShears.Core.Eventing.Extensions | 100% | 100% | 1 | ✔ LlamaShears.Core.Abstractions.Context | 100% | 100% | 4 | ✔ LlamaShears.Provider.Ollama | 3% | 1% | 166 | ❌ LlamaShears.Core | 45% | 31% | 879 | ❌ LlamaShears.Core.Abstractions.Content | 0% | 100% | 1 | ❌ LlamaShears.Core.Abstractions.Caching | 100% | 100% | 1 | ✔ LlamaShears.Core.Eventing | 96% | 76% | 51 | ✔ StrangeSoft.Plugins.Host | 20% | 21% | 87 | ❌ LlamaShears.Core.Abstractions.Commands | 64% | 100% | 3 | ➖ LlamaShears.Core.Abstractions.Provider | 32% | 20% | 66 | ❌ LlamaShears.Core.Abstractions.Memory | 0% | 100% | 3 | ❌ LlamaShears.Api.Web | 25% | 12% | 348 | ❌ LlamaShears.Hosting | 26% | 8% | 27 | ❌ LlamaShears.Core.Abstractions.Events | 21% | 6% | 79 | ❌ LlamaShears.Core.Abstractions.SystemPrompt | 100% | 100% | 2 | ✔ LlamaShears | 65% | 25% | 11 | ➖ LlamaShears.Core.Abstractions.PromptContext | 89% | 100% | 2 | ✔ LlamaShears.Provider.Onnx.Embeddings | 4% | 0% | 68 | ❌ LlamaShears.Plugins.Host | 34% | 24% | 36 | ❌ LlamaShears.Core.Abstractions.Agent | 73% | 100% | 11 | ➖ LlamaShears.Api | 9% | 1% | 344 | ❌ LlamaShears.Plugins | 0% | 100% | 1 | ❌ LlamaShears.Core.Eventing.Extensions | 100% | 100% | 1 | ✔ LlamaShears.Core.Abstractions.Context | 100% | 100% | 4 | ✔ LlamaShears.Provider.Ollama | 44% | 24% | 166 | ❌ LlamaShears.Core | 47% | 44% | 879 | ❌ LlamaShears.Core.Abstractions.Content | 0% | 100% | 1 | ❌ LlamaShears.Core.Abstractions.Caching | 100% | 100% | 1 | ✔ LlamaShears.Core.Eventing | 93% | 86% | 51 | ✔ LlamaShears.Core.Abstractions.Commands | 0% | 100% | 3 | ❌ LlamaShears.Core.Abstractions.Provider | 78% | 64% | 66 | ✔ LlamaShears.Core.Abstractions.Memory | 100% | 100% | 3 | ✔ LlamaShears.Api.Web | 1% | 1% | 348 | ❌ LlamaShears.Hosting | 33% | 21% | 27 | ❌ LlamaShears.Core.Abstractions.Events | 15% | 3% | 79 | ❌ LlamaShears.Core.Abstractions.SystemPrompt | 100% | 100% | 2 | ✔ LlamaShears.Core.Abstractions.PromptContext | 89% | 100% | 2 | ✔ LlamaShears.Provider.Onnx.Embeddings | 33% | 36% | 68 | ❌ LlamaShears.Core.Abstractions.Agent | 86% | 100% | 11 | ✔ LlamaShears.Api | 27% | 29% | 344 | ❌ LlamaShears.Core.Eventing.Extensions | 100% | 100% | 1 | ✔ LlamaShears.Analyzers | 89% | 76% | 199 | ✔ LlamaShears.Analyzers.CodeFixes | 85% | 69% | 60 | ✔ **Summary** | **48%** (8393 / 22579) | **37%** (1612 / 6181) | **6768** | ❌ <!-- Sticky Pull Request Commentcoverage -->
Sign in to join this conversation.
No description provided.