-
Notifications
You must be signed in to change notification settings - Fork 270
Fix panic in agent.yaml parsing and enable CI tests for azure.ai.agents #6683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
rajeshkamal5050
merged 12 commits into
main
from
copilot/fix-agent-yaml-parsing-error-again
Feb 5, 2026
+273
−8
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
eeaa981
Initial plan
Copilot af2a583
Fix agent.yaml parsing panic when template field is missing
Copilot 428cbaf
Support 'agent' field as alias for 'template' in agent.yaml
Copilot 3a34c6a
Address code review feedback
Copilot 73d2ef2
Fix protobuf security vulnerability CVE (JSON recursion depth bypass)
Copilot 859d1e8
Remove standalone format support per review feedback
Copilot 748fbe7
Revert protobuf version change in microsoft.azd.extensions
Copilot 7073705
Standardize error messages to use AgentManifest format
Copilot bdb2c84
Remove agent field support - only template field is valid
Copilot dc2875d
Update error messages with better documentation links
Copilot 885e09f
Enable unit tests for azure.ai.agents extension in CI
Copilot 7aea223
Remove repetition in error messages
JeffreyCA File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| $gopath = go env GOPATH | ||
| $gotestsumBinary = "gotestsum" | ||
| if ($IsWindows) { | ||
| $gotestsumBinary += ".exe" | ||
| } | ||
| $gotestsum = Join-Path $gopath "bin" $gotestsumBinary | ||
|
|
||
| Write-Host "Running unit tests..." | ||
|
|
||
| if (Test-Path $gotestsum) { | ||
| # Use gotestsum for better output formatting and summary | ||
| & $gotestsum --format testname -- ./... -count=1 | ||
| } else { | ||
| # Fallback to go test if gotestsum is not installed | ||
| Write-Host "gotestsum not found, using go test..." -ForegroundColor Yellow | ||
| go test ./... -v -count=1 | ||
| } | ||
|
|
||
| if ($LASTEXITCODE -ne 0) { | ||
| Write-Host "" | ||
| Write-Host "Tests failed with exit code: $LASTEXITCODE" -ForegroundColor Red | ||
| exit $LASTEXITCODE | ||
| } | ||
|
|
||
| Write-Host "" | ||
| Write-Host "All tests passed!" -ForegroundColor Green | ||
| exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
220 changes: 220 additions & 0 deletions
220
cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_yaml/parse_test.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,220 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| package agent_yaml | ||
|
|
||
| import ( | ||
| "strings" | ||
| "testing" | ||
rajeshkamal5050 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ) | ||
|
|
||
| // TestExtractAgentDefinition_WithTemplateField tests parsing YAML with a template field (manifest format) | ||
| func TestExtractAgentDefinition_WithTemplateField(t *testing.T) { | ||
| yamlContent := []byte(` | ||
| name: test-manifest | ||
| template: | ||
| kind: hosted | ||
| name: test-agent | ||
| description: Test agent with template field | ||
| protocols: | ||
| - protocol: responses | ||
| version: v1 | ||
| `) | ||
|
|
||
| agent, err := ExtractAgentDefinition(yamlContent) | ||
| if err != nil { | ||
| t.Fatalf("ExtractAgentDefinition failed: %v", err) | ||
| } | ||
|
|
||
| containerAgent, ok := agent.(ContainerAgent) | ||
| if !ok { | ||
| t.Fatalf("Expected ContainerAgent, got %T", agent) | ||
| } | ||
|
|
||
| if containerAgent.Name != "test-agent" { | ||
| t.Errorf("Expected name 'test-agent', got '%s'", containerAgent.Name) | ||
| } | ||
|
|
||
| if containerAgent.Kind != AgentKindHosted { | ||
| t.Errorf("Expected kind 'hosted', got '%s'", containerAgent.Kind) | ||
| } | ||
| } | ||
|
|
||
| // TestExtractAgentDefinition_EmptyTemplateField tests that an empty or null template field returns an error | ||
| func TestExtractAgentDefinition_EmptyTemplateField(t *testing.T) { | ||
| testCases := []struct { | ||
| name string | ||
| yaml string | ||
| }{ | ||
| { | ||
| name: "null template field", | ||
| yaml: ` | ||
| name: test-manifest | ||
| template: null | ||
| `, | ||
| }, | ||
| { | ||
| name: "empty template field", | ||
| yaml: ` | ||
| name: test-manifest | ||
| template: {} | ||
| `, | ||
| }, | ||
| } | ||
|
|
||
| for _, tc := range testCases { | ||
| t.Run(tc.name, func(t *testing.T) { | ||
| _, err := ExtractAgentDefinition([]byte(tc.yaml)) | ||
| if err == nil { | ||
| t.Fatal("Expected error for empty/null template field, got nil") | ||
| } | ||
|
|
||
| // The error should indicate the template field issue | ||
| expectedMsg := "YAML content does not conform to AgentManifest format" | ||
| if !strings.Contains(err.Error(), expectedMsg) { | ||
| t.Errorf("Expected error message to contain '%s', got '%s'", expectedMsg, err.Error()) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| // TestExtractAgentDefinition_WithoutTemplateField tests that YAML without template field returns an error | ||
| func TestExtractAgentDefinition_WithoutTemplateField(t *testing.T) { | ||
| yamlContent := []byte(` | ||
| kind: hosted | ||
| name: lego-social-media-agent | ||
| description: An AI-powered social media content generator for LEGO products. | ||
| metadata: | ||
| authors: | ||
| - LEGO Social Media Team | ||
| tags: | ||
| - Social Media | ||
| - Content Generation | ||
| protocols: | ||
| - protocol: responses | ||
| version: v1 | ||
| environment_variables: | ||
| - name: POSTGRES_SERVER | ||
| value: ${POSTGRES_SERVER} | ||
| - name: POSTGRES_DATABASE | ||
| value: ${POSTGRES_DATABASE} | ||
| `) | ||
|
|
||
| _, err := ExtractAgentDefinition(yamlContent) | ||
| if err == nil { | ||
| t.Fatal("Expected error for YAML without template field, got nil") | ||
| } | ||
|
|
||
| expectedMsg := "must contain 'template' field" | ||
| if !strings.Contains(err.Error(), expectedMsg) { | ||
| t.Errorf("Expected error message to contain '%s', got '%s'", expectedMsg, err.Error()) | ||
| } | ||
| } | ||
|
|
||
| // TestExtractAgentDefinition_InvalidTemplate tests that an invalid template field returns an error | ||
| func TestExtractAgentDefinition_InvalidTemplate(t *testing.T) { | ||
| yamlContent := []byte(` | ||
| name: test-manifest | ||
| template: "this is not a map" | ||
| `) | ||
|
|
||
| _, err := ExtractAgentDefinition(yamlContent) | ||
| if err == nil { | ||
| t.Fatal("Expected error for invalid template field, got nil") | ||
| } | ||
|
|
||
| expectedMsg := "template field must be a map" | ||
| if !strings.Contains(err.Error(), expectedMsg) { | ||
| t.Errorf("Expected error message to contain '%s', got '%s'", expectedMsg, err.Error()) | ||
| } | ||
rajeshkamal5050 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| // TestExtractAgentDefinition_MissingTemplateField tests that YAML without template field returns an error | ||
| func TestExtractAgentDefinition_MissingTemplateField(t *testing.T) { | ||
| yamlContent := []byte(` | ||
| name: test-agent | ||
| description: Test agent without template field | ||
| `) | ||
|
|
||
| _, err := ExtractAgentDefinition(yamlContent) | ||
| if err == nil { | ||
| t.Fatal("Expected error for YAML without template field, got nil") | ||
| } | ||
|
|
||
| expectedMsg := "must contain 'template' field" | ||
| if !strings.Contains(err.Error(), expectedMsg) { | ||
| t.Errorf("Expected error message to contain '%s', got '%s'", expectedMsg, err.Error()) | ||
| } | ||
| } | ||
|
|
||
| // TestLoadAndValidateAgentManifest_WithoutTemplateField tests that YAML without template field returns an error | ||
| func TestLoadAndValidateAgentManifest_WithoutTemplateField(t *testing.T) { | ||
| yamlContent := []byte(` | ||
| kind: hosted | ||
| name: test-standalone-agent | ||
| description: A standalone agent definition | ||
| protocols: | ||
| - protocol: responses | ||
| version: v1 | ||
| `) | ||
|
|
||
| _, err := LoadAndValidateAgentManifest(yamlContent) | ||
| if err == nil { | ||
| t.Fatal("Expected error for YAML without template field, got nil") | ||
| } | ||
|
|
||
| expectedMsg := "must contain 'template' field" | ||
| if !strings.Contains(err.Error(), expectedMsg) { | ||
| t.Errorf("Expected error message to contain '%s', got '%s'", expectedMsg, err.Error()) | ||
| } | ||
| } | ||
|
|
||
| // TestExtractAgentDefinition_IssueExample tests the exact YAML from the GitHub issue | ||
| func TestExtractAgentDefinition_IssueExample(t *testing.T) { | ||
| // This is the exact YAML from the GitHub issue that was causing the panic | ||
| // It should now return a proper error message instead of panicking | ||
| yamlContent := []byte(`# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml | ||
|
|
||
| kind: hosted | ||
| name: lego-social-media-agent | ||
| description: | | ||
| An AI-powered social media content generator for LEGO products. | ||
| metadata: | ||
| authors: | ||
| - LEGO Social Media Team | ||
| example: | ||
| - content: Generate a Twitter post about Star Wars LEGO sets | ||
| role: user | ||
| tags: | ||
| - Social Media | ||
| - Content Generation | ||
| protocols: | ||
| - protocol: responses | ||
| version: v1 | ||
| environment_variables: | ||
| - name: POSTGRES_SERVER | ||
| value: ${POSTGRES_SERVER} | ||
| - name: POSTGRES_DATABASE | ||
| value: ${POSTGRES_DATABASE} | ||
| `) | ||
|
|
||
| _, err := ExtractAgentDefinition(yamlContent) | ||
| if err == nil { | ||
| t.Fatal("Expected error for YAML without template field, got nil") | ||
| } | ||
|
|
||
| expectedMsg := "must contain 'template' field" | ||
| if !strings.Contains(err.Error(), expectedMsg) { | ||
| t.Errorf("Expected error message to contain '%s', got '%s'", expectedMsg, err.Error()) | ||
| } | ||
|
|
||
| // Test full validation flow - should also return error | ||
| _, err = LoadAndValidateAgentManifest(yamlContent) | ||
| if err == nil { | ||
| t.Fatal("Expected error from LoadAndValidateAgentManifest for YAML without template field, got nil") | ||
| } | ||
|
|
||
| if !strings.Contains(err.Error(), expectedMsg) { | ||
| t.Errorf("Expected error message to contain '%s', got '%s'", expectedMsg, err.Error()) | ||
| } | ||
| } | ||
2 changes: 1 addition & 1 deletion
2
cli/azd/extensions/azure.ai.agents/tests/samples/declarativeNoTools/agent.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| agent: | ||
| template: | ||
| kind: prompt | ||
| name: Learn French Agent | ||
| description: |- | ||
|
|
||
2 changes: 1 addition & 1 deletion
2
cli/azd/extensions/azure.ai.agents/tests/samples/githubMcpAgent/agent.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.