Skip to content
Draft
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
dc4d59e
feat: Add roots support
jeromelaban Dec 2, 2025
76616eb
test: Enhance devserver MCP testing
jeromelaban Dec 2, 2025
57fa37e
chore: Adjust variable names
jeromelaban Dec 2, 2025
61a3dda
chore: Adjust openapi token
jeromelaban Dec 2, 2025
0cf2f56
chore: Adjust token
jeromelaban Dec 2, 2025
204ef05
chore: Adjust codex install
jeromelaban Dec 3, 2025
46e8ad9
chore: Adjust codex invocation
jeromelaban Dec 3, 2025
276d96e
chore: Adjust launch args
jeromelaban Dec 3, 2025
f2640a2
chore: Adjust escaping
jeromelaban Dec 3, 2025
bd6f7ab
chore: Adjust codex startup, devserver command
jeromelaban Dec 3, 2025
d981ee1
chore: Use stdin for codex
jeromelaban Dec 3, 2025
14e92ec
chore: Adjust logging for codex
jeromelaban Dec 3, 2025
bcc34a2
chore: Add more tracing
jeromelaban Dec 3, 2025
e1b4096
chore: Adjust for unix paths support from Uri
jeromelaban Dec 3, 2025
3674afb
chore: Synchronous list reporting
jeromelaban Dec 3, 2025
aa833d3
chore: Adjust devserver dotnet
jeromelaban Dec 3, 2025
fee5125
chore: Adjust mcp tools list
jeromelaban Dec 4, 2025
978fbcd
chore: Adjust license vars
jeromelaban Dec 4, 2025
8d82b14
chore: Adjust model
jeromelaban Dec 4, 2025
dc2dbb4
chore: Adjust token key
jeromelaban Dec 4, 2025
6b93777
chore: Adjust logging
jeromelaban Dec 4, 2025
73101a3
chore: launch RC priming
jeromelaban Dec 4, 2025
2f2be2b
chore: adjust test ordering
jeromelaban Dec 4, 2025
f72bceb
chore: Upstream logging
jeromelaban Dec 4, 2025
7d9e37f
chore: Adjust dotnet root, adjust prompt for listing tools
jeromelaban Dec 4, 2025
2b6056f
chore: Adjust for possible race condition in client init
jeromelaban Dec 5, 2025
24dce25
chore: Fail devserver test on missing tools
jeromelaban Dec 5, 2025
4b4d93f
chore: Adjust global net10 install
jeromelaban Dec 5, 2025
8e61601
chore: Delayed tool update, more trace
jeromelaban Dec 5, 2025
75a4390
ci: Fail devserver script on npm install failure
jeromelaban Dec 5, 2025
f0e7b38
chore: Propagate DOTNET_ROOT
jeromelaban Dec 7, 2025
b91a71d
chore: Propagate XDG
jeromelaban Dec 7, 2025
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
12 changes: 2 additions & 10 deletions build/ci/templates/dotnet-install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,16 @@ steps:

- pwsh: |
echo "##vso[task.setvariable variable=DOTNET_INSTALL_DIR;]$(Build.SourcesDirectory)/.dotnet"
echo "##vso[task.setvariable variable=DOTNET_ROOT;]$(Build.SourcesDirectory)/.dotnet"
displayName: "Set DOTNET_INSTALL_DIR for macOS/Linux"
condition: or(eq(variables['Agent.OS'], 'Linux'), eq(variables['Agent.OS'], 'Darwin'))

- pwsh: |
echo "##vso[task.setvariable variable=DOTNET_INSTALL_DIR;]$(Build.SourcesDirectory)\.dotnet"
echo "##vso[task.setvariable variable=DOTNET_ROOT;]$(Build.SourcesDirectory)\.dotnet"
displayName: "Set DOTNET_INSTALL_DIR for Windows"
condition: eq(variables['Agent.OS'], 'Windows_NT')

- task: UseDotNet@2
displayName: 'Install .NET 9 Runtime'
retryCountOnTaskFailure: 3
inputs:
packageType: sdk
useGlobalJson: false
includePreviewVersions: false
version: 9.0.300
installationPath: $(DOTNET_INSTALL_DIR)

- task: UseDotNet@2
displayName: 'Use .NET SDK from global.json'
retryCountOnTaskFailure: 3
Expand Down
13 changes: 12 additions & 1 deletion build/ci/tests/.azure-devops-tests-templates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,16 @@ jobs:
inputs:
artifactName: 'Nuget_Packages'

# Install the .NET 10 SDK in the default system location so
# the devserver tests can find them.
- task: UseDotNet@2
displayName: Install .NET 10 SDK
inputs:
packageType: 'sdk'
version: '10.0.100'

- template: ../templates/gitversion.yml
- template: ../templates/dotnet-mobile-install-windows.yml
- template: ../templates/dotnet-install.yml
- template: ../templates/uno-dev-feed.yml

- task: CopyFiles@2
Expand Down Expand Up @@ -289,3 +297,6 @@ jobs:
BUILD_SOURCESDIRECTORY: $(BUILD.SOURCESDIRECTORY)
NBGV_SemVer2: $(NBGV_SemVer2)
WasmCachePath: $(WasmCachePath)
CODEX_API_KEY: $(OPENAPI_TOKEN)
UNO_STUDIO_LICENSES_BIN: $(UNO_STUDIO_LICENSES_BIN)
UNO_STUDIO_USER_JSON: $(UNO_STUDIO_USER_JSON)
251 changes: 250 additions & 1 deletion build/test-scripts/run-devserver-cli-tests.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Set-PSDebug -Trace 1
# Set-PSDebug -Trace 1
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out debug code should be removed rather than left in the codebase. Either remove this line entirely or add a comment explaining why it's being kept for future debugging needs.

Suggested change
# Set-PSDebug -Trace 1

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug trace commented out. While this is appropriate for production, consider removing the commented line entirely rather than leaving it commented, as it adds no value and creates maintenance clutter. If debug tracing is needed in the future, it can be easily re-added.

Suggested change
# Set-PSDebug -Trace 1

Copilot uses AI. Check for mistakes.

$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
Expand Down Expand Up @@ -91,6 +91,237 @@ function Get-PortFromCsprojUser([string]$UserFilePath) {
return $null
}

function Ensure-CodexCli {
$codexCommand = Get-Command codex -ErrorAction SilentlyContinue
if ($codexCommand) {
Write-Log "Codex CLI already available at $($codexCommand.Source)"
return $true
}

Write-Log "Codex CLI not detected. Attempting installation via npm."

$npmCommand = Get-Command npm -ErrorAction SilentlyContinue
if (-not $npmCommand) {
Write-Log "npm command not found. Cannot install Codex CLI automatically."
return $false
}

$packageName = '@openai/codex'
$npmArgs = @('install', '-g', $packageName)

& npm @npmArgs
if ($LASTEXITCODE -ne 0) {
Write-Log "npm could not install Codex CLI package $packageName (exit code $LASTEXITCODE)."
return $false
}

$codexCommand = Get-Command codex -ErrorAction SilentlyContinue
if (-not $codexCommand) {
Write-Log "Codex CLI still unavailable after npm install attempt."
return $false
}

Write-Log "Codex CLI installed via npm at $($codexCommand.Source)"
return $true
}

function Invoke-CodexMcpAdd {
param(
[string]$Name,
[string[]]$Arguments
)

Write-Log "Registering Codex MCP '$Name'"
& codex mcp add $Name @Arguments
if ($LASTEXITCODE -ne 0) {
Write-Log "codex mcp add '$Name' exited with code $LASTEXITCODE. Continuing."
}
}

function Register-UnoCodexMcps {
param([string]$WorkingDirectory)

Push-Location $WorkingDirectory
try {
Invoke-CodexMcpAdd -Name "uno" -Arguments @("--url", "https://mcp.platform.uno/v1")
Invoke-CodexMcpAdd -Name "uno-app" -Arguments @("--", "dotnet", "uno-devserver", "--mcp-app", "-l", "trace")
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command argument for the MCP registration uses --mcp-app, but this should match the actual flag name in the application. Verify this matches line 26-28 in Program.cs where the flag is documented. Also note there's a trace log level specified (-l trace) which may produce excessive output in CI logs.

Suggested change
Invoke-CodexMcpAdd -Name "uno-app" -Arguments @("--", "dotnet", "uno-devserver", "--mcp-app", "-l", "trace")
Invoke-CodexMcpAdd -Name "uno-app" -Arguments @("--", "dotnet", "uno-devserver", "--app", "-l", "info")

Copilot uses AI. Check for mistakes.
}
finally {
Pop-Location
}
}

function Invoke-CodexToolEnumerationTest {
param([string]$WorkingDirectory)

$toolsFile = Join-Path $WorkingDirectory "codex-tools.json"
if (Test-Path $toolsFile) {
Remove-Item $toolsFile -Force
}

$toolsFileName = Split-Path $toolsFile -Leaf
$instructions = @"
You are running inside an automated CI validation for the Uno Platform devserver CLI.

Tasks:
1. Create a list of all MCP tools available to you
2. Create or overwrite a JSON file named '$toolsFileName' in the current working directory.
The JSON must be an object that contains a property ``"tools"`` whose value is an alphabetically sorted array listing every tool identifier you discovered.
3. Confirm completion and exit when finished.

Begin now.
"@

$stdOutFile = [System.IO.Path]::GetTempFileName()
$stdErrFile = [System.IO.Path]::GetTempFileName()
$instructionsFile = [System.IO.Path]::GetTempFileName()

Set-Content -Path $instructionsFile -Value $instructions -Encoding utf8

$model = if (-not [string]::IsNullOrWhiteSpace($env:CODEX_MODEL)) { $env:CODEX_MODEL } else { "gpt-5-mini" }
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Model name appears incorrect: gpt-5-mini should likely be gpt-4o-mini (the actual OpenAI model name). GPT-5 has not been released as of the current date.

Suggested change
$model = if (-not [string]::IsNullOrWhiteSpace($env:CODEX_MODEL)) { $env:CODEX_MODEL } else { "gpt-5-mini" }
$model = if (-not [string]::IsNullOrWhiteSpace($env:CODEX_MODEL)) { $env:CODEX_MODEL } else { "gpt-4o-mini" }

Copilot uses AI. Check for mistakes.

Write-Log "Invoking Codex CLI to enumerate MCP tools."
$codexArgs = @(
'--ask-for-approval','never',
'exec',
'-m',$model,
'--sandbox','workspace-write',
'-c','mcp_servers."uno-app".startup_timeout_sec=120',
'-c','features.web_search_request=true',
'-c','features.rmcp_client=true',
'-c','sandbox_workspace_write.network_access=true'
)

$codexExecutable = "codex"
$codexArguments = $codexArgs
if ($IsWindows) {
# npm exposes Codex CLI through a .cmd shim on Windows, so run it via cmd.exe
$codexExecutable = "cmd.exe"
$codexArguments = @("/c", "codex") + $codexArgs
}
Comment on lines +197 to +201
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block builds a Codex CLI command using the CODEX_MODEL environment variable and, on Windows, executes it via cmd.exe /c codex ..., which allows shell metacharacters in CODEX_MODEL to be interpreted by cmd.exe. An attacker who can influence CODEX_MODEL (for example through CI variables or the process environment) can inject additional commands using characters like & or | and execute arbitrary code in the build agent context. To remediate this, avoid invoking codex via cmd.exe (execute the codex binary directly) or strictly whitelist/validate CODEX_MODEL and ensure it is passed as a single, safely quoted argument that cannot break out into the surrounding shell command.

Suggested change
if ($IsWindows) {
# npm exposes Codex CLI through a .cmd shim on Windows, so run it via cmd.exe
$codexExecutable = "cmd.exe"
$codexArguments = @("/c", "codex") + $codexArgs
}
# On Windows, PowerShell Start-Process can invoke .cmd shims directly, so we do not need to use cmd.exe /c.

Copilot uses AI. Check for mistakes.

$previousRustLog = $env:RUST_LOG
$env:RUST_LOG = 'debug'
try {
$process = Start-Process -FilePath $codexExecutable -ArgumentList $codexArguments -WorkingDirectory $WorkingDirectory -RedirectStandardOutput $stdOutFile -RedirectStandardError $stdErrFile -RedirectStandardInput $instructionsFile -PassThru

Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timeout is set to 300000ms (5 minutes), which is quite long for a CI test. Consider if this timeout is appropriate or if it could be reduced to fail faster when there are genuine issues. Document why such a long timeout is needed if it's intentional (e.g., for cold-start scenarios, model inference time, etc.).

Suggested change
# Codex CLI may require up to 5 minutes for cold start/model inference in CI environments.
# Do not reduce this timeout unless you are certain all scenarios complete faster.

Copilot uses AI. Check for mistakes.
$timeoutMs = 300000
if (-not $process.WaitForExit($timeoutMs)) {
try { $process.Kill() } catch {}
$stdErrContent = Get-Content $stdErrFile -ErrorAction SilentlyContinue -Raw
throw "Codex CLI timed out after $($timeoutMs / 1000) seconds. STDERR:`n$stdErrContent"
}

$stdout = Get-Content $stdOutFile -ErrorAction SilentlyContinue -Raw
$stderr = Get-Content $stdErrFile -ErrorAction SilentlyContinue -Raw

Remove-Item $stdOutFile -ErrorAction SilentlyContinue
Remove-Item $stdErrFile -ErrorAction SilentlyContinue
Remove-Item $instructionsFile -ErrorAction SilentlyContinue
Comment on lines +175 to +220
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The temporary files created with [System.IO.Path]::GetTempFileName() are cleaned up in lines 218-220, but this cleanup only happens if the process exits normally. If an exception occurs before reaching the cleanup code (e.g., at line 206 during process start), these temp files will leak. Consider moving the cleanup into a finally block or using a try-finally pattern to ensure cleanup always occurs.

Copilot uses AI. Check for mistakes.

if ($process.ExitCode -ne 0) {
throw "Codex CLI exited with code $($process.ExitCode).`nSTDOUT:`n$stdout`nSTDERR:`n$stderr"
}
else{
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after else. Should be else { instead of else{ for consistency with PowerShell formatting conventions.

Suggested change
else{
else {

Copilot uses AI. Check for mistakes.
Write-Log "Codex CLI completed successfully."
Write-Log "STDOUT:`n$stdout`nSTDERR:`n$stderr"
}
}
finally {
if ($null -ne $previousRustLog) {
$env:RUST_LOG = $previousRustLog
}
else {
Remove-Item Env:RUST_LOG -ErrorAction SilentlyContinue
}
}

if (-not (Test-Path $toolsFile)) {
throw "Codex CLI did not create $toolsFile.`nSTDOUT:`n$stdout`nSTDERR:`n$stderr"
}

$jsonText = Get-Content $toolsFile -Raw -ErrorAction Stop
try {
$json = $jsonText | ConvertFrom-Json -ErrorAction Stop
}
catch {
throw "codex-tools.json is not valid JSON: $($_.Exception.Message)"
}

if (-not $json.tools -or $json.tools.Count -eq 0) {
throw "codex-tools.json does not contain a non-empty 'tools' array."
}

Write-Log "Codex CLI reported $($json.tools.Count) tools via codex-tools.json:"
foreach ($tool in $json.tools) {
Write-Log " - $tool"
}

$screenshotTool = $json.tools | Where-Object { $_ -like '*uno_app_get_screenshot*' } | Select-Object -First 1
if (-not $screenshotTool) {
throw "Codex CLI did not report the required 'uno_app_get_screenshot' tool."
}
}

function Setup-UnoStudioLicenses {
param([string]$WorkDirectory)

if ($IsWindows) {
$dataRoot = if (-not [string]::IsNullOrWhiteSpace($env:LOCALAPPDATA)) { $env:LOCALAPPDATA } else { Join-Path $WorkDirectory '.local' }
}
elseif ($IsMacOS) {
$homePath = if (-not [string]::IsNullOrWhiteSpace($env:HOME)) { $env:HOME } else { $WorkDirectory }
$dataRoot = Join-Path $homePath 'Library/Application Support'
}
else {
$dataRoot = Join-Path $WorkDirectory '.local'
$env:XDG_DATA_HOME = $dataRoot
Write-Log "Set XDG_DATA_HOME to $dataRoot"
}

if (-not (Test-Path $dataRoot)) {
try { New-Item -ItemType Directory -Path $dataRoot -Force | Out-Null; Write-Log "Ensured application data folder: $dataRoot" }
catch { Write-Warning "Failed to create application data folder '$dataRoot': $_" }
}

$unoDir = Join-Path $dataRoot 'Uno Platform'
if (-not (Test-Path $unoDir)) {
try { New-Item -ItemType Directory -Path $unoDir -Force | Out-Null; Write-Log "Created Uno data folder: $unoDir" }
catch { Write-Warning "Failed to create Uno data folder '$unoDir': $_" }
}

# Setting up license files this way is temporary until we get API keys.
if ($env:UNO_STUDIO_LICENSES_BIN) {
$licensesPath = Join-Path $unoDir 'licenses.bin'
try {
$env:UNO_STUDIO_LICENSES_BIN | Out-File -FilePath $licensesPath -Encoding utf8 -Force
Write-Log "Wrote UNO_STUDIO_LICENSES_BIN to: $licensesPath"
}
catch {
Write-Warning "Failed to write UNO_STUDIO_LICENSES_BIN to $licensesPath : $_"
}
}
else {
Write-Log "UNO_STUDIO_LICENSES_BIN environment variable not set. Skipping license setup."
}

Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same environment variable naming issue: The variable name OPENAPI_TOKEN in the Azure DevOps configuration should match the corrected name (e.g., OPENAI_API_KEY or OPENAI_TOKEN) to maintain consistency and clarity.

Copilot uses AI. Check for mistakes.
if ($env:UNO_STUDIO_USER_JSON) {
$userJsonPath = Join-Path $unoDir 'user.json'
try {
$env:UNO_STUDIO_USER_JSON | Out-File -FilePath $userJsonPath -Encoding utf8 -Force
Write-Log "Wrote UNO_STUDIO_USER_JSON to: $userJsonPath"
}
catch {
Write-Warning "Failed to write UNO_STUDIO_USER_JSON to $userJsonPath : $_"
}
}
else {
Write-Log "UNO_STUDIO_USER_JSON environment variable not set. Skipping user.json setup."
}

return $unoDir
}

try {
cd $env:BUILD_SOURCESDIRECTORY/src/SolutionTemplate
& $env:BUILD_SOURCESDIRECTORY/build/test-scripts/update-uno-sdk-globaljson.ps1
Expand All @@ -104,11 +335,14 @@ try {
$csprojPath = "$env:BUILD_SOURCESDIRECTORY/src/SolutionTemplate/5.6/uno56netcurrent/uno56netcurrent/uno56netcurrent.csproj"
$csprojDir = Split-Path $csprojPath -Parent
$slnDir = Split-Path $csprojDir -Parent
$workDir = $slnDir

if (-not (Test-Path $csprojDir)) {
throw "Project directory not found: $csprojDir"
}

Setup-UnoStudioLicenses -WorkDirectory $workDir

Set-Location $slnDir

# Default port
Expand Down Expand Up @@ -153,6 +387,21 @@ try {

& dotnet uno-devserver stop

$openApiToken = $env:CODEX_API_KEY
if ([string]::IsNullOrWhiteSpace($openApiToken)) {
Comment on lines +390 to +391
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent naming: variable is named $openApiToken but the environment variable is CODEX_API_KEY. The variable should be named $codexApiKey to match the environment variable it reads from.

Suggested change
$openApiToken = $env:CODEX_API_KEY
if ([string]::IsNullOrWhiteSpace($openApiToken)) {
$codexApiKey = $env:CODEX_API_KEY
if ([string]::IsNullOrWhiteSpace($codexApiKey)) {

Copilot uses AI. Check for mistakes.
Comment on lines +390 to +391
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable name typo: $openApiToken should likely be $openAiToken (AI, not API) since it refers to OpenAI's Codex API. The environment variable is correctly named CODEX_API_KEY.

Suggested change
$openApiToken = $env:CODEX_API_KEY
if ([string]::IsNullOrWhiteSpace($openApiToken)) {
$openAiToken = $env:CODEX_API_KEY
if ([string]::IsNullOrWhiteSpace($openAiToken)) {

Copilot uses AI. Check for mistakes.
Comment on lines +390 to +391
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable naming inconsistency: the variable is named $openApiToken but it stores the value from $env:CODEX_API_KEY, and it's used to access the Codex API. The variable should be named $codexApiKey to match its purpose and source. Also note that the CI configuration uses OPENAPI_TOKEN (line 300 in .azure-devops-tests-templates.yml) which should be CODEX_API_KEY for consistency.

Suggested change
$openApiToken = $env:CODEX_API_KEY
if ([string]::IsNullOrWhiteSpace($openApiToken)) {
$codexApiKey = $env:CODEX_API_KEY
if ([string]::IsNullOrWhiteSpace($codexApiKey)) {

Copilot uses AI. Check for mistakes.
Write-Log "CODEX_API_KEY not provided. Skipping Codex MCP integration test."
}
else {
Write-Log "CODEX_API_KEY detected. Starting Codex MCP integration test."
if (Ensure-CodexCli) {
Register-UnoCodexMcps -WorkingDirectory $slnDir
Invoke-CodexToolEnumerationTest -WorkingDirectory $slnDir
}
else {
Write-Log "Codex CLI unavailable after installation attempt. Skipping Codex MCP integration test."
}
}

exit 0
}
catch {
Expand Down
2 changes: 1 addition & 1 deletion doc/articles/dev-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ You can manage the Dev Server from the command line using the dotnet tool `Uno.D
- `uno-devserver list`: List running Dev Server instances
- `uno-devserver cleanup`: Terminate stale Dev Server processes
- `uno-devserver login`: Open the Uno Platform settings application
- `--mcp`: Run an MCP proxy mode for integration with MCP-based tooling
- `--mcp-app`: Run an MCP proxy mode for integration with MCP-based tooling
- `--port | -p <int>`: Optional port value for MCP proxy mode

## Hot Reload
Expand Down
9 changes: 8 additions & 1 deletion doc/articles/get-started-ai-codex.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@ This guide will walk you through the setup process for getting started with Code

Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is missing a required GitHub issue reference. According to the coding guidelines, every PR MUST reference a proper GitHub issue using one of these formats:

  • Fixes https://github.com/unoplatform/uno/issues/#<ISSUE_NUMBER>
  • Closes https://github.com/unoplatform/uno/issues/#<ISSUE_NUMBER>
  • Related to https://github.com/unoplatform/uno/issues/#<ISSUE_NUMBER>

Please add the issue reference to the PR description, or if there is no issue, add a note explaining why (e.g., "Note: No related issue (Internal maintenance / Approved by Team member: @username)").

Copilot generated this review using guidance from organization custom instructions.
## Setting up Uno Platform MCPs

1. Install [Codex CLI](https://developers.openai.com/codex/cli)
1. Install [Codex CLI](https://developers.openai.com/codex/cli) using the official commands, for example:

```bash
npm i -g @openai/codex
# or on macOS
brew install --cask codex
```

Comment on lines +15 to +22
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation refers to "official commands" but the provided examples show different installation methods (npm vs brew). Consider clarifying which method is recommended or under what circumstances each should be used. Additionally, the URL "https://developers.openai.com/codex/cli" should be verified as it may not be the correct documentation link for the Codex CLI installation instructions.

Suggested change
1. Install [Codex CLI](https://developers.openai.com/codex/cli) using the official commands, for example:
```bash
npm i -g @openai/codex
# or on macOS
brew install --cask codex
```
1. Install Codex CLI. The recommended installation method depends on your platform:
- **All platforms (recommended):**
Use [npm](https://www.npmjs.com/package/@openai/codex) (requires [Node.js](https://nodejs.org/)):
```bash
npm i -g @openai/codex
```
- **macOS only (alternative):**
You can also use [Homebrew](https://formulae.brew.sh/cask/codex):
```bash
brew install --cask codex
```
For the latest installation instructions, see the [official Codex CLI documentation](https://platform.openai.com/docs/assistants/tools/codex-cli).

Copilot uses AI. Check for mistakes.
1. Register the Uno Platform MCPs:

```bash
Expand Down
1 change: 1 addition & 0 deletions doc/articles/studio/Hot Design
Submodule Hot Design added at 4c090b
3 changes: 1 addition & 2 deletions src/SamplesApp/UITests.Shared/UITests.Shared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -4346,7 +4346,6 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>

<Page Include="$(MSBuildThisFileDirectory)Microsoft_UI_Xaml_Controls\WebView2Tests\WebView2_TargetBlank.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down Expand Up @@ -10227,4 +10226,4 @@
</Compile>
</ItemGroup>
<Import Project="ItemExclusions.props" />
</Project>
</Project>
Loading
Loading