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
25 changes: 25 additions & 0 deletions cli/azd/extensions/azure.ai.agents/internal/cmd/init_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,32 @@ func (a *InitAction) ProcessModels(ctx context.Context, manifest *agent_yaml.Age
return nil, nil, fmt.Errorf("failed to inject deployment names into manifest: %w", err)
}

setEnv := func(ctx context.Context, key, value string) error {
return setEnvValue(ctx, a.azdClient, a.environment.Name, key, value)
}
if err := persistFirstDeploymentName(ctx, setEnv, deploymentDetails); err != nil {
return nil, nil, fmt.Errorf("failed to set AZURE_AI_MODEL_DEPLOYMENT_NAME: %w", err)
}

fmt.Println("Model deployment details processed and injected into agent definition. Deployment details can also be found in the JSON formatted AI_PROJECT_DEPLOYMENTS environment variable.")

return updatedManifest, deploymentDetails, nil
}

// envValueSetter writes a single key-value pair to the azd environment.
type envValueSetter func(ctx context.Context, key, value string) error

// persistFirstDeploymentName persists the first deployment's name as
// AZURE_AI_MODEL_DEPLOYMENT_NAME so templates and agent code can reference it.
// It is a no-op when the deployments slice is empty.
func persistFirstDeploymentName(
ctx context.Context,
setEnv envValueSetter,
deployments []project.Deployment,
) error {
if len(deployments) == 0 {
return nil
}

return setEnv(ctx, "AZURE_AI_MODEL_DEPLOYMENT_NAME", deployments[0].Name)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
package cmd

import (
"azureaiagent/internal/project"
"context"
"errors"
"testing"

"github.com/azure/azure-dev/cli/azd/pkg/azdext"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestResolveNoPromptCapacity(t *testing.T) {
Expand Down Expand Up @@ -172,3 +176,89 @@ func TestSkuPriority(t *testing.T) {
})
}
}

func TestPersistFirstDeploymentName(t *testing.T) {
t.Parallel()

tests := []struct {
name string
deployments []project.Deployment
setEnvErr error
wantCalled bool
wantKey string
wantValue string
wantErr bool
}{
{
name: "empty deployments does not call setter",
deployments: []project.Deployment{},
wantCalled: false,
},
{
name: "nil deployments does not call setter",
deployments: nil,
wantCalled: false,
},
{
name: "single deployment persists its name",
deployments: []project.Deployment{
{Name: "gpt-4o"},
},
wantCalled: true,
wantKey: "AZURE_AI_MODEL_DEPLOYMENT_NAME",
wantValue: "gpt-4o",
},
{
name: "multiple deployments persists first name only",
deployments: []project.Deployment{
{Name: "gpt-4o"},
{Name: "text-embedding-ada-002"},
},
wantCalled: true,
wantKey: "AZURE_AI_MODEL_DEPLOYMENT_NAME",
wantValue: "gpt-4o",
},
{
name: "setter error is propagated",
deployments: []project.Deployment{
{Name: "gpt-4o"},
},
setEnvErr: errors.New("grpc unavailable"),
wantCalled: true,
wantKey: "AZURE_AI_MODEL_DEPLOYMENT_NAME",
wantValue: "gpt-4o",
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

var called bool
var gotKey, gotValue string

setter := func(_ context.Context, key, value string) error {
called = true
gotKey = key
gotValue = value
return tt.setEnvErr
}

err := persistFirstDeploymentName(t.Context(), setter, tt.deployments)

assert.Equal(t, tt.wantCalled, called, "setter call expectation mismatch")

if tt.wantCalled {
assert.Equal(t, tt.wantKey, gotKey)
assert.Equal(t, tt.wantValue, gotValue)
}

if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
})
}
}
Loading