Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,19 @@ permissions:
jobs:
verify:
uses: ./.github/workflows/verify.yml

# The branch ruleset requires one status check by name, and job names travel
# with the matrix and the workflow they live in — the rename in I13 left main
# waiting for a "Build & Test" that no longer existed, so no pull request
# could satisfy it. This job carries that name and nothing else: it passes
# only when every verify job passed, so the requirement stays real.
build-test:
name: Build & Test
needs: verify
if: always()
runs-on: ubuntu-latest
steps:
- name: Report the verify result
run: |
echo "verify: ${{ needs.verify.result }}"
[ "${{ needs.verify.result }}" = "success" ]
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Version bump guide:

## [Unreleased]

## [3.0.1] — 2026-09-17
## [3.0.1] — 2026-09-18

Core 3.0.1 and Agents 0.18.0 collect the unpublished I13 hardening work and
the additive I14 voice feature. The new public Live API raises the Agents
Expand All @@ -24,6 +24,9 @@ package's unpublished version from 0.17.7 to 0.18.0; Core remains a patch releas
- `DrylVoiceOptions.Live` (Agents 0.18.0) — Opt into `gpt-live-1` with an independent Responses backend, function tools and optional hosted web search. A server-owned SDP exchange keeps credentials private; the browser handles nested backend events and submits each function result once before continuing.
- `DrylVoiceRun` (Agents 0.18.0) — Preserve overlapping transcript fragments and expose completed backend responses for cited research, cumulative voice usage and the final close reason. Live close drains final events with a bounded wait while stopping microphone capture immediately. Existing Realtime consumers retain their protocol and defaults.

### Changed
- `DRYL.Components.Agents` (Agents 0.18.0) — Minimum `Microsoft.Agents.AI` raised from 1.18.0 to 1.21.0. No API of this package changes; consumers pinned to 1.18.x need to move up with it.

### Fixed
- `DrylInputText`, `DrylTextarea`, `DrylSelect`, `DrylStepper`, `DrylDialog` — Keyboard focus retains a browser outline under forced colors when glow shadows disappear, using existing tokens and preserving ordinary focus styling.
- `DrylBadge` — Success, warning and danger labels use `--fg` for readable small text while their dots, borders and tints retain semantic colors. CSS-derived and rendered checks enforce 4.5:1 on the tested light/dark surfaces.
Expand Down
2 changes: 1 addition & 1 deletion code/DRYL.Components.Agents/DRYL.Components.Agents.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Agents.AI" Version="1.18.0" />
<PackageReference Include="Microsoft.Agents.AI" Version="1.21.0" />
</ItemGroup>

<!-- The Components.Web metapackage version must track the target framework. -->
Expand Down
23 changes: 19 additions & 4 deletions tests/DRYL.BrowserHost/wwwroot/voice-fixture.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,25 @@
return result;
}

if (!navigator.mediaDevices) Object.defineProperty(navigator, "mediaDevices", { value: {} });
Object.defineProperty(navigator.mediaDevices, "getUserMedia", {
configurable: true, value: () => boundary("media", stream)
});
// Replace the accessor, not a property on the object it returns: where a browser hands
// out a real MediaDevices (Linux WebKit does, Windows WebKit has none at all), a property
// defined on that object did not survive to the next `navigator.mediaDevices` read, so the
// microphone call reached the browser — which denies it headlessly, and every startup
// stage the tests wait for was never entered. The fixture only ever needs getUserMedia.
const getUserMedia = () => boundary("media", stream);
const devices = { getUserMedia };
try {
Object.defineProperty(navigator, "mediaDevices", { configurable: true, get: () => devices });
} catch {
// A navigator that refuses the accessor still allows the object to be patched.
}
if (navigator.mediaDevices?.getUserMedia !== getUserMedia) {
if (!navigator.mediaDevices) Object.defineProperty(navigator, "mediaDevices", { configurable: true, value: devices });
else Object.defineProperty(navigator.mediaDevices, "getUserMedia", { configurable: true, value: getUserMedia });
}
// Fail loudly here rather than as a ten-second timeout inside every voice test.
if (navigator.mediaDevices.getUserMedia !== getUserMedia)
throw new Error("Voice fixture could not take over navigator.mediaDevices.getUserMedia.");

class FixtureChannel extends EventTarget {
constructor(peer) {
Expand Down
4 changes: 2 additions & 2 deletions tests/DRYL.Components.Tests/DRYL.Components.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="bunit" Version="2.9.0" />
<PackageReference Include="bunit" Version="2.11.3" />
<PackageReference Include="coverlet.collector" Version="6.0.4" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.9.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.10.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.0" />
</ItemGroup>
Expand Down
Loading