Repository navigation
Commit d8c5674
feat: add CommunityToolkit.Aspire.Hosting.Squad - first-class Aspire resource for Squad AI-agent teams (#1394)
* feat: add CommunityToolkit.Aspire.Hosting.Squad
Introduces a new hosting integration that lets a .NET Aspire AppHost
model a Squad (https://github.com/bradygaster/squad) AI-agent team
as a first-class Aspire resource.
Closes #1393
What's included
---------------
- `src/CommunityToolkit.Aspire.Hosting.Squad/` — the package
- `SquadResource : Resource, IResourceWithConnectionString`
Auto-discovers the agent roster from `.squad/team.md` (table and
bullet-list formats), only keeping names that map to an existing
`.squad/agents/{name}/charter.md` to filter typos. Exposes
`squad://resource/{name}?teamRoot={...}&agents={csv}&protocol=maf-1.0`
so downstream services can consume the team via `.WithReference`.
- `SquadBuilderExtensions.AddSquad(name, teamRoot)` decorated with
`[AspireExport]` (ATS-compatible).
- `SquadLifecycleHook` publishes Spawning -> Active transitions
on the dashboard and seeds `SquadDashboardProperties` so the
roster, protocol version, and team root show on the resource row.
- Dashboard commands wired via `WithCommand` (open Copilot CLI on
the team root, etc.).
- Public API surface file at
`src/CommunityToolkit.Aspire.Hosting.Squad/api/CommunityToolkit.Aspire.Hosting.Squad.cs`
per repo convention.
- `tests/CommunityToolkit.Aspire.Hosting.Squad.Tests/` — 7 xUnit unit
tests covering: resource registration, default roster fallback,
guard clauses, table-format roster parsing, bullet-format roster
parsing, and connection-string shape. All pass locally on net10.0.
- `examples/squad/CommunityToolkit.Aspire.Hosting.Squad.AppHost/` —
minimal AppHost example with a self-contained `sample-squad/.squad/`
fixture so the example builds and runs without external state.
- Solution + root README updates (table row, link refs).
Out of scope (planned follow-ups, kept separate for reviewability)
------------------------------------------------------------------
- OpenTelemetry signals (agent spawns, token usage, session metrics).
Depends on the Squad telemetry contract still being designed at
https://github.com/bradygaster/squad/issues/1144.
- Direct `Squad.Agents.AI` consumer-side extension that constructs an
MAF `AIAgent` from a referenced squad. The connection-string shape
here is the integration point; consumer-side wiring is a separate
package design.
Local verification
------------------
- `dotnet build` on all three new projects (Release) — 0 warnings, 0 errors
- 7/7 tests pass via Microsoft Testing Platform on net10.0
- Example AppHost builds cleanly
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat(examples): wire WithReference + Squad.Agents.AI into the example
The original example AppHost only registered a SquadResource. Per the PR
review request from #1394, the example now also demonstrates end-to-end
consumption: a downstream ApiApp project receives the squad://...
connection string via .WithReference(squad), parses the team root, and
uses Squad.Agents.AI to drive a real 3-turn conversation against the
referenced team.
What's added
------------
- examples/squad/CommunityToolkit.Aspire.Hosting.Squad.ApiApp/
- ASP.NET minimal API; Program.cs reads ConnectionStrings:research-squad
(squad://... format), extracts teamRoot, registers SquadAgent via
AddSquadAgent, exposes POST /ask that runs a 3-turn conversation
through AgentSession (demonstrates session memory across turns).
- examples/squad/CommunityToolkit.Aspire.Hosting.Squad.ServiceDefaults/
- Standard Aspire ServiceDefaults shape (OTel + service discovery +
health checks), mirroring the Java example layout.
- examples/squad/CommunityToolkit.Aspire.Hosting.Squad.AppHost/
- Updated to AddProject<...>("squad-api").WithReference(researchSquad)
- Directory.Packages.props
- Added Squad.Agents.AI 0.1.0-preview.3 (centralized version), the
preview that ships the SessionConfig/OnPermissionRequest fix needed
to drive a real conversation. See bradygaster/squad#1252.
- CommunityToolkit.Aspire.slnx
- 2 new projects added (ApiApp, ServiceDefaults).
- src/CommunityToolkit.Aspire.Hosting.Squad/README.md
- New "Consume the team from a service project" section pointing
callers at the new examples/squad/ runnable.
Local verification
------------------
- dotnet build (Release) of all 5 squad-related projects: 0 warn, 0 err
- All 7 unit tests still pass on net10.0 (MTP)
- Squad.Agents.AI 0.1.0-preview.3 restores from nuget.org cleanly
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Bump Squad.Agents.AI to 0.2.0-preview.4 + workaround GitHub.Copilot.SDK direct ref
Squad.Agents.AI 0.2.0-preview.4 (released earlier today from bradygaster/squad#1259)
brings the package onto Microsoft.Agents.AI.GitHub.Copilot 1.10.0-rc1, which
transitively pulls GitHub.Copilot.SDK 1.0.0 GA. The earlier 0.1.0-preview.3 was
wedged on SDK 1.0.0-beta.2 + a CLI protocol the current copilot CLI no longer
speaks — verified by running the example ApiApp in this branch against a real
.squad-initialised team root and seeing the agent successfully read .squad/team.md
and dispatch work to multiple specialists.
Also add a direct PackageReference to GitHub.Copilot.SDK 1.0.0. This is a
temporary workaround: the SDK ships its CLI-binary-download MSBuild targets
under build/ (only auto-imported for projects with a *direct* PackageReference),
not buildTransitive/. microsoft/agent-framework#6457 (merged 2026-06-10) fixes
this at the MAF adapter level — once a MAF preview ships with that change, the
direct GitHub.Copilot.SDK ref can be dropped from Directory.Packages.props and
the ApiApp csproj. Both edit sites carry an inline comment explaining the lifecycle.
Verified: the hosting library, the ApiApp, and the AppHost all build clean, and
copilot.exe lands at the expected 'bin/{cfg}/{tfm}/runtimes/{rid}/native/' path
in the ApiApp output.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Bump to Squad.Agents.AI 0.3.0-preview.5 + wire subagent observability into ApiApp
Squad.Agents.AI 0.3.0-preview.5 (released today from bradygaster/squad#1265) adds
a first-class subagent observability surface: a typed OnSubagentTrace callback +
an OpenTelemetry ActivitySource named 'Microsoft.Agents.AI.Squad' that emits one
span per task-tool dispatch with squad.subagent.name / squad.subagent.display_name /
squad.subagent.sdk_agent_id / squad.subagent.reply_preview tags.
This commit:
* Bumps Squad.Agents.AI from 0.2.0-preview.4 to 0.3.0-preview.5 in
Directory.Packages.props.
* Wires the new ActivitySource into the ApiApp's OpenTelemetry tracer (one line
on top of the AddServiceDefaults() configuration) so every subagent dispatch
shows up as its own span in the Aspire dashboard's Traces view, with the
subagent name + a preview of its reply attached as span tags.
* Adds OnSubagentTrace logging in the ApiApp so subagent lifecycle (spawn, reply,
complete) also surfaces in the dashboard's Structured Logs view — both signals
are correlated by Activity.Current so the OTel span and the structured log
share the same trace id.
* Adds a new POST /dispatch endpoint that issues an explicit task-tool dispatch
prompt ('use the task tool to dispatch two parallel subagents...'). Hitting
this endpoint from the dashboard produces a multi-span trace showing the
coordinator + each subagent as separate spans — the headline visibility demo.
* Existing POST /ask 3-turn endpoint kept for the session-memory demo.
Verified locally: AppHost boots clean, the 'research-squad' resource registers
2 agents (ralph, picard from the sample-squad team), and the ApiApp builds + runs
with the new observability wiring against Squad.Agents.AI 0.3.0-preview.5
restored from nuget.org.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* examples/squad: replace stub sample-squad with two real squads (research + dev)
The previous bundled sample-squad/ had stub one-line charters with nothing to
dispatch to, so /ask returned coordinator role-play and /dispatch produced no
subagent spans in the Aspire dashboard.
Replace it with two real Squad teams created via 'squad init --no-workflows'
and autonomously cast by the Squad coordinator running under 'copilot --yolo':
research-squad/ Matrix-cast AI/ML research team
Morpheus (Lead) - Trinity (ML/Data) - Oracle (Eval) - Tank (Tester)
Stack: Python, PyTorch/TensorFlow, Jupyter, MLflow
dev-squad/ Simpsons-cast full-stack development team
Lisa (Lead) - Marge (Frontend) - Frink (Backend) - Comic Book Guy (Tester)
Both squads have full .squad/ scaffolding: team.md, per-agent charter.md and
history.md, casting registry, decisions ledger, ceremonies, routing, and the
.copilot/ skills the agents read. Runtime state (orchestration-log/, log/,
sessions/, decisions/inbox/) is excluded via the per-squad .gitignore that
'squad init' generates.
AppHost wires both as Aspire resources via .AddSquad('research-squad', ...) and
.AddSquad('dev-squad', ...), and references both from the ApiApp via
.WithReference(researchSquad).WithReference(devSquad). Aspire injects two
connection strings under ConnectionStrings:research-squad and
ConnectionStrings:dev-squad.
ApiApp rewritten to:
- Register one SquadAgent per squad via AddKeyedSquadAgent(serviceKey, ...)
using the keyed-DI overload shipped in Squad.Agents.AI 0.1.0-preview.2
- Resolve the right agent per request via [FromKeyedServices] / ?squad= query
- /ask?squad=research|dev runs a 3-turn conversation against the picked team
- /dispatch?squad=research|dev sends an explicit 'use the task tool to dispatch
two parallel subagents' prompt so we reliably see real subagent spawns (not
inline role-play) and one squad.subagent {Name} OTel span per spawn in the
Aspire dashboard Traces view
- OnSubagentTrace forwards subagent start/done/message to console so the
structured logs line up with the OTel trace timeline
AppHost launchSettings.json also gains DCP_IDE_REQUEST_TIMEOUT_SECONDS=300 to
prevent the 120s DCP/VS run-session race that falls back to bare dotnet.exe
and produces 'Usage: dotnet [path-to-application]' in the ApiApp logs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* examples/squad: fix ?squad=research|dev keyed-DI lookup + clean AppHost comments
The ApiApp registered SquadAgent under keys 'research-squad' and 'dev-squad'
(the Aspire resource names) but the /ask and /dispatch endpoints take
?squad=research|dev (short form). The dictionary lookup mismatched and both
endpoints returned {"error":"Unknown squad 'research'..."}.
Fix:
- Register each keyed SquadAgent under the short name ('research', 'dev')
- Resolve the longer 'research-squad' / 'dev-squad' name only when reading
the connection string (which IS keyed by the Aspire resource name)
- Drop the unused ResearchSquad/DevSquad const
Also clean up the duplicate using + stale comment block in AppHost/Program.cs
left over from the previous edit.
Verified end-to-end with a live run:
- Both squads come up Active in the dashboard (research: 7 agents discovered;
dev: 6 agents discovered)
- POST /dispatch?squad=research returns the Morpheus + Trinity answers verbatim
- POST /dispatch?squad=dev returns the Lisa + Frink answers verbatim
- ApiApp spawns one copilot.exe child per request (real subagent dispatch, not
inline role-play)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* examples/squad: ship .github/agents/squad.agent.md inside each squad folder
When 'squad init' is run from a folder that has a parent git repo (i.e. our
case — the Squad CLI's monorepo detection kicked in because Aspire-1 is a git
repo), the CLI places .github/agents/squad.agent.md at the GIT ROOT instead of
inside the squad folder. That made the example squads non-self-contained:
anyone cloning this repo and pointing SquadFolderPath at research-squad/ or
dev-squad/ would have no coordinator agent file (Copilot resolves
.github/agents/ relative to the consumer's git root, not ours).
For an in-repo example that ships as a finished artifact, the squads need to
own their own coordinator. Copy the same squad.agent.md (v0.9.6-insider.3,
71594 bytes) into each squad's own .github/agents/ directory.
Also expand each .gitignore to cover Copilot CLI SDK runtime files that get
created when a SquadAgent serves a request:
.squad/session-state/
.squad/session-store.db
.squad/session-store.db-shm
.squad/session-store.db-wal
The bundled .gitignore from 'squad init' already covered .squad/sessions/ but
those SDK-side files use slightly different paths.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* examples/squad: switch ApiApp to ILogger + emit subagent activity events
Two problems with the previous Console.WriteLine approach:
1. Console.WriteLine output did not consistently surface in the Aspire dashboard
when the SDK fired OnSubagentTrace from its background event pump (different
thread, no captured stdout context). The user reported empty Console Logs
even though the callback was firing.
2. The SDK's per-subagent OTel spans (Microsoft.Agents.AI.Squad activity source)
may end up as orphan traces — the SDK's Channel-based event pump can fire
on a thread where Activity.Current has been cleared by the AsyncLocal flow,
so StartActivity has no parent and the span becomes a new root trace
detached from the HTTP request's trace.
Fixes:
- Use ILogger<>'s structured logging via Microsoft.Extensions.Options'
Configure<ILoggerFactory> overload, which injects the fully-built
ILoggerFactory into the SquadAgentOptions post-configure step (runs after
the host is built, before any RunAsync call). Each subagent
start / message / completed lands in the Aspire dashboard's Structured Logs
view with the squad name, subagent name, and message preview as queryable
fields.
- Add an app-owned ActivitySource ("Squad.Hosting.ApiApp") and wrap each
/ask and /dispatch handler in a "squad.dispatch {endpoint} {squad}" span.
This guarantees a single, named root span per request that the user's
trace search can land on, even when the SDK's per-subagent spans become
orphans.
- Inside OnSubagentTrace, also call Activity.Current?.AddEvent(...) so each
subagent lifecycle event (start / message / completed) is attached as an
OpenTelemetry ActivityEvent to whatever span is current at callback time
(the SDK's subagent span when open, the dispatch wrapper otherwise).
Events show up as labelled annotations on the span timeline in the Aspire
dashboard trace detail view.
- Wire the new app source into AddOpenTelemetry().WithTracing(...) alongside
the existing Microsoft.Agents.AI.Squad source.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* examples/squad: upgrade to Squad.Agents.AI 0.4.0-preview.6 + simplify ApiApp wiring
0.4.0 (bradygaster/squad#1271, merged today) ships two changes that remove
the boilerplate this example needed in 0.3.0:
1. AddKeyedSquadAgent("research-squad") now resolves
ConnectionStrings:research-squad (Aspire-injected) directly, with a
fallback to the legacy ConnectionStrings:squad-research-squad form.
No more manual builder.Configuration.GetConnectionString() + URI parse +
feeding SquadFolderPath through a configure callback.
2. EmitSubagentActivities defaults to true. Just call
.AddSource(SquadAgentDiagnostics.ActivitySourceName) on the tracer and
"squad.subagent {Name}" spans appear in the Aspire dashboard's Traces view
with lifecycle ActivityEvents (start / message / completed / failed)
annotated on the timeline — without setting OnSubagentTrace at all.
OnSubagentTrace becomes a pure customisation hook now, kept here only to
surface per-subagent ILogger lines in the Structured Logs view.
ApiApp Program.cs:
- Drop the foreach that called GetConnectionString + ParseSquadTeamRoot
(16 lines) — replaced by a single AddKeyedSquadAgent("{resource}") call
per squad, with a separate AddOptions<>().Configure<ILoggerFactory>(...)
hop for the OnSubagentTrace ILogger callback.
- Drop the local ParseSquadTeamRoot helper — the SDK does the parsing.
- Drop the squadTeamRoots dictionary — was a leaky abstraction of the
SDK's connection-string handling. Replaced with squadKeysByShortName
that just maps the query-param short name ("research") to the keyed-DI
key ("research-squad").
Bumped Squad.Agents.AI 0.3.0-preview.5 → 0.4.0-preview.6 in
Directory.Packages.props.
End-to-end verified live against the published 0.4.0-preview.6 package:
- Both squads register cleanly with no manual connection-string handling
- POST /dispatch?squad=research returned the Morpheus + Trinity replies
verbatim (real task-tool subagent dispatch)
- Smaller, cleaner Program.cs that closely mirrors the README
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* examples/squad: pass --agent squad to CLI + drop terse Instructions override
When running 'copilot --agent squad' interactively in a terminal, the
coordinator loads .github/agents/squad.agent.md (1023 lines: eager
execution, parallel fan-out, dispatch via task tool) as its system prompt
and follows that contract. When the same Squad team is invoked through
Squad.Agents.AI's SquadAgent, the underlying copilot.exe child process
was using its default agent — so the coordinator had no instructions to
fan out or dispatch, and the terse 'Be concise' Instructions override we
were passing actively encouraged it to role-play the team in a single
reply instead of spawning real subagents.
Fix:
- Pass --agent squad in CliArgs so the CLI selects squad.agent.md as the
agent definition for the spawned session
- Drop the per-squad Instructions override (was overriding the full
squad.agent.md system prompt with one terse line)
Verified live against Squad.Agents.AI 0.4.0-preview.6:
- POST /ask?squad=dev with a Full Mode prompt ('Use the task tool to
dispatch each of Lisa, Marge, Frink and Comic Book Guy in parallel ...')
produced the eager-execution narration ('Waiting for all four agents
to return. Still waiting for Marge.') that only squad.agent.md emits,
AND returned four distinct subagent replies — proof that --agent squad
is active and the task tool is dispatching.
Note: 'team, i want every member to say its name' still gets a single
coordinator reply because squad.agent.md classifies that as Direct Mode
('Who's on the team?' → answer from team.md, no spawn). For the
observability demo, use either POST /dispatch?squad=X or send a Full Mode
prompt to /ask.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* examples/squad: bump Squad.Agents.AI 0.5.0-preview.7 -> 0.5.1-preview.8
0.5.0-preview.7 introduced a regression: setting sessionConfig.Agent ='squad'
caused a runtime failure ('Custom agent ''squad'' not found') because the SDK
property looks up the SDK's CustomAgents registry, NOT the on-disk
.github/agents/*.agent.md files.
0.5.1-preview.8 (bradygaster/squad#1277) reverts to the original --agent CLI
flag approach which actually reads the on-disk agent definition the same
way 'copilot --agent squad' does interactively.
Verified live: POST /dispatch?squad=dev now returns distinct subagent voices
(Lisa: 'A good software architecture makes change boring ...';
Frink: 'A well-designed API's most important property is a clear, stable
contract that makes correct usage obvious and reliable—glavin!'),
which confirms (a) --agent squad is now being passed through, (b)
squad.agent.md is loaded as the coordinator's system prompt, and (c) real
subagent dispatch via the task tool is happening (not coordinator role-play).
The ApiApp's Program.cs already drops the manual --agent CLI workaround from
the previous 0.5.0 upgrade commit, so this is a version-only bump.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* examples/squad: collapse /dispatch into /ask + fix nested-project build break
ApiApp:
- Drop /dispatch. The endpoint was just /ask with a hardcoded "Use the task
tool to dispatch ..." prompt; same SquadAgent.RunAsync path, same coordinator,
same span/log surface — the only difference was the prompt. Removing it
makes the API surface honest: there's one endpoint, the caller owns the
prompt, the coordinator picks the mode (Direct / Lightweight / Full).
- GET / now returns a copy-paste "sample_prompts" menu (roster_recall_direct_mode,
multi_turn_memory, dispatch_full_mode_research, dispatch_full_mode_dev),
each shaped like the /ask body so the user can paste straight through to
reproduce every mode and see what the corresponding spans look like.
- Drop the unused AskRequest.Default sample (the / index now owns sample prompts).
- Rename the wrapper span "squad.dispatch ask {squad}" -> "squad.ask {squad}".
AppHost build break:
Earlier interactive sessions created scratch C# projects inside the squads
(e.g. research-squad/UserNameApp/, dev-squad/UserNameApp/) when the user
asked the team to "write a program in C3 / C#". The Aspire AppHost SDK's
default <Compile>, <Content>, <None>, and <EmbeddedResource> globs sweep
any .cs / .csproj at any depth under the AppHost project folder, which
caused two cascading build errors on the next F5:
CS8802: Only one compilation unit can have top-level statements.
CS0579: Duplicate AssemblyInfo attributes.
Fix in two layers:
1. AppHost.csproj: explicit <Compile|Content|None|EmbeddedResource Remove>
on research-squad\** and dev-squad\**. The squads are scaffolding-only
(.squad/, .github/, .copilot/, .mcp.json) and should never participate
in the AppHost compile graph.
2. Each squad's .gitignore: append *.csproj / *.fsproj / *.vbproj / bin/
/ obj/ guards so future scratch projects don't get committed either.
Also delete the existing UserNameApp/ scratch dirs from both squads.
Squad.slnx:
New focused solution file — just src/CommunityToolkit.Aspire.Hosting.Squad,
the AppHost, the ApiApp, the ServiceDefaults, and the tests. Trims the
noise out of F5 / VS solution explorer for anyone who clones the example
and only wants to run the Squad bits without loading the rest of the
Aspire repo's projects.
Verified live against Squad.Agents.AI 0.5.1-preview.8:
- GET / lists 4 sample_prompts including the full-mode dispatch prompts
- POST /ask?squad=dev with the dispatch_full_mode_dev sample produced Lisa
+ Frink replies with their distinct specialist voices, confirming real
subagent dispatch through the task tool.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* review: address Copilot PR review comments on PR #1394
Five inline review comments from the Copilot reviewer, all addressed:
1. SquadResource.cs: Cast MatchCollection to IEnumerable<Match>
Explicit .Cast<Match>() on both Regex.Matches results so the LINQ
Concat/Select binding is unambiguous across TFMs (older targets expose
MatchCollection only as non-generic IEnumerable). No behavior change on
net10.0 where it already implements IList<Match>; defensive clarity only.
2. SquadBuilderExtensions.StartConsoleWindow: drop fragile cmd /c start invocation
The previous approach used 'cmd /c start <windowTitle> powershell.exe ...',
which fails or misbehaves when the title contains spaces (e.g.,
'Copilot - research-squad'): cmd's quote-stripping causes 'start' to parse
the title fragment as part of the command. Now launches powershell.exe
directly with UseShellExecute=true and sets the title from inside the new
shell via \System.Management.Automation.Internal.Host.InternalHost.UI.RawUI.WindowTitle, removing all cmd/start parsing
fragility while preserving the friendly window title.
3. api/*.cs: regenerated to match the real public signature
The hand-typed surface declared 'string teamRoot' (required) but the
implementation exposes 'string? teamRoot = null'. Re-ran
GenAPIGenerateReferenceAssemblySource; the file now correctly shows
the nullable optional parameter and also picks up SquadTeamAnnotation,
which the previous version had missed.
4. tests/AssemblyInfo.cs: removed
InternalsVisibleTo on the test assembly grants visibility to itself
(no-op). The production csproj already wires InternalsVisibleTo to the
test assembly correctly; the test-side file was duplicate dead config.
5. tests/SquadResourceCreationTests.cs: deterministic temp cleanup
Class now implements IDisposable and tracks every temp dir created by
the helpers (instance-scoped _tempRoots). Dispose() best-effort deletes
them recursively so test residue no longer accumulates in %TEMP%
across runs.
Tests: 7/7 pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* review: address Aaron's PR feedback on #1394
- Bump AppHost SDK reference from Aspire.AppHost.Sdk/13.4.0 to 13.4.3
(matches the post-13.4.3 upgrade Aaron sync'ed into main via #1397)
- Add hard PackageReference Include="MessagePack" to the hosting integration,
AppHost, and Tests projects to pull the patched 2.5.301 pinned centrally
in Directory.Packages.props instead of the vulnerable transitive version
flowing through Aspire.Hosting (CVE-2026-48109 / GHSA-hv8m-jj95-wg3x)
- Remove root-level Squad.slnx (per request — the unified Aspire.slnx covers it)
Build clean (0 warnings, 0 errors) on all three Squad projects.
MessagePack 2.5.301 verified as the resolved version via dotnet list package
--include-transitive in AppHost, hosting, and tests projects.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test(squad): raise line coverage 43% -> 79% (above the 60% gate)
Adds three test files covering the previously-untested classes:
- SquadLifecycleHookTests (12 tests, ~78% line / 100% branch)
- Tests the hook in isolation with a CapturingEventing test double,
a real ResourceNotificationService, and synthesised BeforeStart /
AfterResourcesCreated / ResourceStopped events. No DCP / Dashboard
runtime required.
- Asserts state transitions Spawning -> Active -> Finished, no-ops for
non-Squad ResourceStopped and zero-squad BeforeStart, ArgumentNullException
on null eventing, and graceful degradation when SquadDashboardProperties
raises an IOException.
- SquadDashboardPropertiesTests (7 tests, 100% line / 100% branch)
- CreateStatic shape + null guard.
- CreateWithLiveStats covers: no inbox dir, multiple .md files in inbox,
decisions.md first-non-blank line, long-line truncation at 80 chars,
whitespace-only decisions.md keeping the default 'none'.
- SquadBuilderCommandsTests (7 tests)
- Exercises each dashboard command (refresh-agents, open-team-root,
open-copilot-cli, check-inbox) by invoking the ExecuteCommand delegate
on the resource's ResourceCommandAnnotation.
- Covers the non-Windows branch of LaunchCopilotCli (the OS-bound
spawn paths themselves are marked [ExcludeFromCodeCoverage]).
Also:
- Marks StartWindowsTerminal / StartConsoleWindow with
[ExcludeFromCodeCoverage] - they hand off to wt.exe / powershell.exe
and can only be exercised by a real desktop session. Argument-list
building is simple and visible; the launch itself is OS-bound.
- Adds ProjectReference to CommunityToolkit.Aspire.Testing so we have
the shared test infra available (matches every other integration test
project in this repo).
Local verification:
- 28/28 tests pass (3-of-3 runs, no flake)
- dotnet build clean (0 warnings, 0 errors) on hosting, AppHost, tests
- Coverage measured via Microsoft.Testing.Extensions.CodeCoverage:
Total lines 353, covered 279, line rate 79.0% (was 43%).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore: update Squad.Agents.AI to stable 0.5.1
Now that bradygaster/squad PR #1313 merged and NuGet 0.5.1 (stable)
is published, switch from preview to the stable release.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review feedback: cross-platform CLI, primary ctors, remove api file
- Remove Windows-only guard from LaunchCopilotCli; add Linux/macOS support
- Convert SquadLifecycleHook to primary constructor
- Convert SquadTeamAnnotation to primary constructor
- Delete auto-generated api/CommunityToolkit.Aspire.Hosting.Squad.cs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix test: non-Windows now attempts CLI launch (cross-platform)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chore(deps): bump Squad.Agents.AI to 0.5.1-preview.16 (delegation fix)
Bumps the centrally-managed Squad.Agents.AI version from 0.5.1 to 0.5.1-preview.16
so the squad ApiApp example actually delegates work to its sub-agents via the
`task` tool. With 0.5.1, the dispatcher squads always reply directly to the
user instead of invoking sub-agents — the SDK was suppressing the dispatch
event. This was fixed upstream in microsoft/agents-ai-squad PR #1378.
Verified end-to-end on bradygaster/squad-with-aspire PR #46 (same one-line bump
on a sibling consumer of Squad.Agents.AI) — sub-agent traces and child spans now
appear correctly in the Aspire dashboard.
Side effect: 0.5.1-preview.16 requires GitHub.Copilot.SDK >= 1.0.3, so the
direct-pin workaround for GitHub.Copilot.SDK is bumped from 1.0.0 to 1.0.3 as
well (also brings the Copilot CLI runtime to 1.0.64-1, which is what the SDK
expects).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Tamir Dresher <tamirdresher@users.noreply.github.com>
Co-authored-by: Aaron Powell <me@aaron-powell.com>1 parent 7e021cf commit d8c5674
319 files changed
Lines changed: 34526 additions & 0 deletions
File tree
- examples/squad
- CommunityToolkit.Aspire.Hosting.Squad.ApiApp
- Properties
- CommunityToolkit.Aspire.Hosting.Squad.AppHost
- Properties
- dev-squad
- .copilot
- skills
- agent-collaboration
- error-recovery
- git-workflow
- reviewer-protocol
- secret-handling
- session-recovery
- squad-conventions
- test-discipline
- .github/agents
- .squad
- agents
- Rai
- comicbookguy
- frink
- lisa
- marge
- ralph
- scribe
- casting
- identity
- memory
- rai
- templates
- casting
- identity
- scripts/notes
- skills
- agent-collaboration
- agent-conduct
- architectural-proposals
- ci-validation-gates
- cli-wiring
- client-compatibility
- cross-machine-coordination
- cross-squad
- distributed-mesh
- docs-standards
- e2e-template-testing
- economy-mode
- error-recovery
- external-comms
- fact-checking
- gh-auth-isolation
- git-workflow
- github-multi-account
- history-hygiene
- humanizer
- init-mode
- iterative-retrieval
- model-selection
- nap
- notification-routing
- personal-squad
- pr-review-response
- pr-screenshots
- project-conventions
- ralph-two-pass-scan
- reflect
- release-process
- reskill
- retro-enforcement
- reviewer-protocol
- secret-handling
- session-recovery
- squad-conventions
- test-discipline
- tiered-memory
- versioning-policy
- windows-compatibility
- workflows
- research-squad
- .copilot
- skills
- agent-collaboration
- error-recovery
- git-workflow
- reviewer-protocol
- secret-handling
- session-recovery
- squad-conventions
- test-discipline
- .github/agents
- .squad
- agents
- Rai
- morpheus
- oracle
- ralph
- scribe
- tank
- trinity
- casting
- identity
- memory
- rai
- templates
- casting
- identity
- scripts/notes
- skills
- agent-collaboration
- agent-conduct
- architectural-proposals
- ci-validation-gates
- cli-wiring
- client-compatibility
- cross-machine-coordination
- cross-squad
- distributed-mesh
- docs-standards
- e2e-template-testing
- economy-mode
- error-recovery
- external-comms
- fact-checking
- gh-auth-isolation
- git-workflow
- github-multi-account
- history-hygiene
- humanizer
- init-mode
- iterative-retrieval
- model-selection
- nap
- notification-routing
- personal-squad
- pr-review-response
- pr-screenshots
- project-conventions
- ralph-two-pass-scan
- reflect
- release-process
- reskill
- retro-enforcement
- reviewer-protocol
- secret-handling
- session-recovery
- squad-conventions
- test-discipline
- tiered-memory
- versioning-policy
- windows-compatibility
- workflows
- CommunityToolkit.Aspire.Hosting.Squad.ServiceDefaults
- src/CommunityToolkit.Aspire.Hosting.Squad
- tests/CommunityToolkit.Aspire.Hosting.Squad.Tests
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
199 | 199 | | |
200 | 200 | | |
201 | 201 | | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
202 | 207 | | |
203 | 208 | | |
204 | 209 | | |
| |||
269 | 274 | | |
270 | 275 | | |
271 | 276 | | |
| 277 | + | |
272 | 278 | | |
273 | 279 | | |
274 | 280 | | |
| |||
340 | 346 | | |
341 | 347 | | |
342 | 348 | | |
| 349 | + | |
343 | 350 | | |
344 | 351 | | |
345 | 352 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
76 | 76 | | |
77 | 77 | | |
78 | 78 | | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
79 | 86 | | |
80 | 87 | | |
81 | 88 | | |
| |||
97 | 104 | | |
98 | 105 | | |
99 | 106 | | |
| 107 | + | |
100 | 108 | | |
101 | 109 | | |
102 | 110 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
| 62 | + | |
62 | 63 | | |
63 | 64 | | |
64 | 65 | | |
| |||
315 | 316 | | |
316 | 317 | | |
317 | 318 | | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
0 commit comments