Created
November 6, 2025 17:45
-
-
Save JeffreyCA/55654dd6cdacbfeccd080bd476545b2e to your computer and use it in GitHub Desktop.
azure.ai.agents - patched operation.go that dumps HTTP logs to disk
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
| // Copyright (c) Microsoft Corporation. All rights reserved. | |
| // Licensed under the MIT License. | |
| package agent_api | |
| import ( | |
| "bytes" | |
| "context" | |
| "encoding/json" | |
| "fmt" | |
| "io" | |
| "net/http" | |
| "net/url" | |
| "os" | |
| "strconv" | |
| "time" | |
| "github.com/Azure/azure-sdk-for-go/sdk/azcore" | |
| "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" | |
| ) | |
| // AgentClient provides methods for interacting with the Azure AI Agents API | |
| type AgentClient struct { | |
| endpoint string | |
| cred azcore.TokenCredential | |
| client *http.Client | |
| logFile *os.File | |
| } | |
| // NewAgentClient creates a new AgentClient | |
| func NewAgentClient(endpoint string, cred azcore.TokenCredential) *AgentClient { | |
| logFile, err := os.OpenFile("stderr.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) | |
| if err != nil { | |
| // Fallback to stderr if file creation fails | |
| logFile = os.Stderr | |
| } | |
| return &AgentClient{ | |
| endpoint: endpoint, | |
| cred: cred, | |
| client: &http.Client{}, | |
| logFile: logFile, | |
| } | |
| } | |
| // GetAgent retrieves a specific agent by name | |
| func (c *AgentClient) GetAgent(ctx context.Context, agentName, apiVersion string) (*AgentObject, error) { | |
| url := fmt.Sprintf("%s/agents/%s?api-version=%s", c.endpoint, agentName, apiVersion) | |
| req, err := http.NewRequestWithContext(ctx, "GET", url, nil) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| c.logRequest("GET", url, nil) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 { | |
| return nil, fmt.Errorf("failed to get agent. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var agent AgentObject | |
| if err := json.Unmarshal(body, &agent); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &agent, nil | |
| } | |
| // CreateAgent creates a new agent | |
| func (c *AgentClient) CreateAgent(ctx context.Context, request *CreateAgentRequest, apiVersion string) (*AgentObject, error) { | |
| url := fmt.Sprintf("%s/agents?api-version=%s", c.endpoint, apiVersion) | |
| payload, err := json.Marshal(request) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to marshal request: %w", err) | |
| } | |
| req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(payload)) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| req.Header.Set("Content-Type", "application/json") | |
| c.logRequest("POST", url, payload) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 && resp.StatusCode != 201 { | |
| return nil, fmt.Errorf("failed to create agent. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var agent AgentObject | |
| if err := json.Unmarshal(body, &agent); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &agent, nil | |
| } | |
| // UpdateAgent updates an existing agent | |
| func (c *AgentClient) UpdateAgent(ctx context.Context, agentName string, request *UpdateAgentRequest, apiVersion string) (*AgentObject, error) { | |
| url := fmt.Sprintf("%s/agents/%s?api-version=%s", c.endpoint, agentName, apiVersion) | |
| payload, err := json.Marshal(request) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to marshal request: %w", err) | |
| } | |
| req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(payload)) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| req.Header.Set("Content-Type", "application/json") | |
| c.logRequest("POST", url, payload) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 { | |
| return nil, fmt.Errorf("failed to update agent. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var agent AgentObject | |
| if err := json.Unmarshal(body, &agent); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &agent, nil | |
| } | |
| // DeleteAgent deletes an agent | |
| func (c *AgentClient) DeleteAgent(ctx context.Context, agentName, apiVersion string) (*DeleteAgentResponse, error) { | |
| url := fmt.Sprintf("%s/agents/%s?api-version=%s", c.endpoint, agentName, apiVersion) | |
| req, err := http.NewRequestWithContext(ctx, "DELETE", url, nil) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| c.logRequest("DELETE", url, nil) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 { | |
| return nil, fmt.Errorf("failed to delete agent. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var deleteResponse DeleteAgentResponse | |
| if err := json.Unmarshal(body, &deleteResponse); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &deleteResponse, nil | |
| } | |
| // ListAgents returns a list of all agents | |
| func (c *AgentClient) ListAgents(ctx context.Context, params *ListAgentQueryParameters, apiVersion string) (*AgentList, error) { | |
| baseURL := fmt.Sprintf("%s/agents", c.endpoint) | |
| u, err := url.Parse(baseURL) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to parse base URL: %w", err) | |
| } | |
| query := u.Query() | |
| query.Set("api-version", apiVersion) | |
| if params != nil { | |
| if params.Kind != nil { | |
| query.Set("kind", string(*params.Kind)) | |
| } | |
| if params.Limit != nil { | |
| query.Set("limit", strconv.Itoa(int(*params.Limit))) | |
| } | |
| if params.After != nil { | |
| query.Set("after", *params.After) | |
| } | |
| if params.Before != nil { | |
| query.Set("before", *params.Before) | |
| } | |
| if params.Order != nil { | |
| query.Set("order", *params.Order) | |
| } | |
| } | |
| u.RawQuery = query.Encode() | |
| req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| c.logRequest("GET", u.String(), nil) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 { | |
| return nil, fmt.Errorf("failed to list agents. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var agentList AgentList | |
| if err := json.Unmarshal(body, &agentList); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &agentList, nil | |
| } | |
| // CreateAgentVersion creates a new version of an agent | |
| func (c *AgentClient) CreateAgentVersion(ctx context.Context, agentName string, request *CreateAgentVersionRequest, apiVersion string) (*AgentVersionObject, error) { | |
| url := fmt.Sprintf("%s/agents/%s/versions?api-version=%s", c.endpoint, agentName, apiVersion) | |
| payload, err := json.Marshal(request) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to marshal request: %w", err) | |
| } | |
| req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(payload)) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| req.Header.Set("Content-Type", "application/json") | |
| c.logRequest("POST", url, payload) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 && resp.StatusCode != 201 { | |
| return nil, fmt.Errorf("failed to create agent version. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var agentVersion AgentVersionObject | |
| if err := json.Unmarshal(body, &agentVersion); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &agentVersion, nil | |
| } | |
| // GetAgentVersion retrieves a specific version of an agent | |
| func (c *AgentClient) GetAgentVersion(ctx context.Context, agentName, agentVersion, apiVersion string) (*AgentVersionObject, error) { | |
| url := fmt.Sprintf("%s/agents/%s/versions/%s?api-version=%s", c.endpoint, agentName, agentVersion, apiVersion) | |
| req, err := http.NewRequestWithContext(ctx, "GET", url, nil) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| c.logRequest("GET", url, nil) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 { | |
| return nil, fmt.Errorf("failed to get agent version. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var version AgentVersionObject | |
| if err := json.Unmarshal(body, &version); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &version, nil | |
| } | |
| // DeleteAgentVersion deletes a specific version of an agent | |
| func (c *AgentClient) DeleteAgentVersion(ctx context.Context, agentName, agentVersion, apiVersion string) (*DeleteAgentVersionResponse, error) { | |
| url := fmt.Sprintf("%s/agents/%s/versions/%s?api-version=%s", c.endpoint, agentName, agentVersion, apiVersion) | |
| req, err := http.NewRequestWithContext(ctx, "DELETE", url, nil) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| c.logRequest("DELETE", url, nil) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 { | |
| return nil, fmt.Errorf("failed to delete agent version. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var deleteResponse DeleteAgentVersionResponse | |
| if err := json.Unmarshal(body, &deleteResponse); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &deleteResponse, nil | |
| } | |
| // Common query parameters for pagination | |
| type CommonPageQueryParameters struct { | |
| Limit *int32 `json:"limit,omitempty"` | |
| After *string `json:"after,omitempty"` | |
| Before *string `json:"before,omitempty"` | |
| Order *string `json:"order,omitempty"` | |
| } | |
| // ListAgentVersions returns a list of versions for a specific agent | |
| func (c *AgentClient) ListAgentVersions(ctx context.Context, agentName string, params *CommonPageQueryParameters, apiVersion string) (*AgentVersionList, error) { | |
| baseURL := fmt.Sprintf("%s/agents/%s/versions", c.endpoint, agentName) | |
| u, err := url.Parse(baseURL) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to parse base URL: %w", err) | |
| } | |
| query := u.Query() | |
| query.Set("api-version", apiVersion) | |
| if params != nil { | |
| if params.Limit != nil { | |
| query.Set("limit", strconv.Itoa(int(*params.Limit))) | |
| } | |
| if params.After != nil { | |
| query.Set("after", *params.After) | |
| } | |
| if params.Before != nil { | |
| query.Set("before", *params.Before) | |
| } | |
| if params.Order != nil { | |
| query.Set("order", *params.Order) | |
| } | |
| } | |
| u.RawQuery = query.Encode() | |
| req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| c.logRequest("GET", u.String(), nil) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 { | |
| return nil, fmt.Errorf("failed to list agent versions. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var versionList AgentVersionList | |
| if err := json.Unmarshal(body, &versionList); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &versionList, nil | |
| } | |
| // Event Handler Operations | |
| // CreateOrUpdateAgentEventHandler creates or updates an event handler for an agent | |
| func (c *AgentClient) CreateOrUpdateAgentEventHandler(ctx context.Context, agentName, eventHandlerName string, request *AgentEventHandlerRequest, apiVersion string) (*AgentEventHandlerObject, error) { | |
| url := fmt.Sprintf("%s/agents/%s/event_handlers/%s?api-version=%s", c.endpoint, agentName, eventHandlerName, apiVersion) | |
| payload, err := json.Marshal(request) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to marshal request: %w", err) | |
| } | |
| req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(payload)) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| req.Header.Set("Content-Type", "application/json") | |
| c.logRequest("POST", url, payload) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 && resp.StatusCode != 201 { | |
| return nil, fmt.Errorf("failed to create/update event handler. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var eventHandler AgentEventHandlerObject | |
| if err := json.Unmarshal(body, &eventHandler); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &eventHandler, nil | |
| } | |
| // GetAgentEventHandler retrieves a specific event handler | |
| func (c *AgentClient) GetAgentEventHandler(ctx context.Context, agentName, eventHandlerName, apiVersion string) (*AgentEventHandlerObject, error) { | |
| url := fmt.Sprintf("%s/agents/%s/event_handlers/%s?api-version=%s", c.endpoint, agentName, eventHandlerName, apiVersion) | |
| req, err := http.NewRequestWithContext(ctx, "GET", url, nil) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| c.logRequest("GET", url, nil) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 { | |
| return nil, fmt.Errorf("failed to get event handler. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var eventHandler AgentEventHandlerObject | |
| if err := json.Unmarshal(body, &eventHandler); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &eventHandler, nil | |
| } | |
| // DeleteAgentEventHandler deletes an event handler | |
| func (c *AgentClient) DeleteAgentEventHandler(ctx context.Context, agentName, eventHandlerName, apiVersion string) (*DeleteAgentEventHandlerResponse, error) { | |
| url := fmt.Sprintf("%s/agents/%s/event_handlers/%s?api-version=%s", c.endpoint, agentName, eventHandlerName, apiVersion) | |
| req, err := http.NewRequestWithContext(ctx, "DELETE", url, nil) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| c.logRequest("DELETE", url, nil) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 { | |
| return nil, fmt.Errorf("failed to delete event handler. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var deleteResponse DeleteAgentEventHandlerResponse | |
| if err := json.Unmarshal(body, &deleteResponse); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &deleteResponse, nil | |
| } | |
| // Container Operations | |
| // StartAgentContainer starts a container for a specific version of an agent | |
| func (c *AgentClient) StartAgentContainer(ctx context.Context, agentName, agentVersion string, apiVersion string) (*AcceptedAgentContainerOperation, error) { | |
| url := fmt.Sprintf("%s/agents/%s/versions/%s/containers/default:start?api-version=%s", c.endpoint, agentName, agentVersion, apiVersion) | |
| requestBody := map[string]interface{}{} | |
| payload, err := json.Marshal(requestBody) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to marshal request: %w", err) | |
| } | |
| req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(payload)) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| req.Header.Set("Content-Type", "application/json") | |
| c.logRequest("POST", url, payload) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 202 { | |
| return nil, fmt.Errorf("failed to start agent container. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var operation AgentContainerOperationObject | |
| if err := json.Unmarshal(body, &operation); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| result := &AcceptedAgentContainerOperation{ | |
| Location: resp.Header.Get("Operation-Location"), | |
| Body: operation, | |
| } | |
| return result, nil | |
| } | |
| // UpdateAgentContainer updates a container for a specific version of an agent | |
| func (c *AgentClient) UpdateAgentContainer(ctx context.Context, agentName, agentVersion string, minReplicas, maxReplicas *int32, apiVersion string) (*AcceptedAgentContainerOperation, error) { | |
| url := fmt.Sprintf("%s/agents/%s/versions/%s/containers/default:update?api-version=%s", c.endpoint, agentName, agentVersion, apiVersion) | |
| requestBody := map[string]interface{}{} | |
| if minReplicas != nil { | |
| requestBody["min_replicas"] = *minReplicas | |
| } | |
| if maxReplicas != nil { | |
| requestBody["max_replicas"] = *maxReplicas | |
| } | |
| payload, err := json.Marshal(requestBody) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to marshal request: %w", err) | |
| } | |
| req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(payload)) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| req.Header.Set("Content-Type", "application/json") | |
| c.logRequest("POST", url, payload) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 202 { | |
| return nil, fmt.Errorf("failed to update agent container. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var operation AgentContainerOperationObject | |
| if err := json.Unmarshal(body, &operation); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| result := &AcceptedAgentContainerOperation{ | |
| Location: resp.Header.Get("Operation-Location"), | |
| Body: operation, | |
| } | |
| return result, nil | |
| } | |
| // StopAgentContainer stops a container for a specific version of an agent | |
| func (c *AgentClient) StopAgentContainer(ctx context.Context, agentName, agentVersion, apiVersion string) (*AcceptedAgentContainerOperation, error) { | |
| url := fmt.Sprintf("%s/agents/%s/versions/%s/containers/default:stop?api-version=%s", c.endpoint, agentName, agentVersion, apiVersion) | |
| req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer([]byte("{}"))) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| req.Header.Set("Content-Type", "application/json") | |
| c.logRequest("POST", url, []byte("{}")) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 202 { | |
| return nil, fmt.Errorf("failed to stop agent container. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var operation AgentContainerOperationObject | |
| if err := json.Unmarshal(body, &operation); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| result := &AcceptedAgentContainerOperation{ | |
| Location: resp.Header.Get("Operation-Location"), | |
| Body: operation, | |
| } | |
| return result, nil | |
| } | |
| // DeleteAgentContainer deletes a container for a specific version of an agent | |
| func (c *AgentClient) DeleteAgentContainer(ctx context.Context, agentName, agentVersion, apiVersion string) (*AcceptedAgentContainerOperation, error) { | |
| url := fmt.Sprintf("%s/agents/%s/versions/%s/containers/default:delete?api-version=%s", c.endpoint, agentName, agentVersion, apiVersion) | |
| req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer([]byte("{}"))) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| req.Header.Set("Content-Type", "application/json") | |
| c.logRequest("POST", url, []byte("{}")) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 202 { | |
| return nil, fmt.Errorf("failed to delete agent container. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var operation AgentContainerOperationObject | |
| if err := json.Unmarshal(body, &operation); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| result := &AcceptedAgentContainerOperation{ | |
| Location: resp.Header.Get("Operation-Location"), | |
| Body: operation, | |
| } | |
| return result, nil | |
| } | |
| // GetAgentContainer retrieves container information for a specific agent version | |
| func (c *AgentClient) GetAgentContainer(ctx context.Context, agentName, agentVersion, apiVersion string) (*AgentContainerObject, error) { | |
| url := fmt.Sprintf("%s/agents/%s/versions/%s/containers/default?api-version=%s", c.endpoint, agentName, agentVersion, apiVersion) | |
| req, err := http.NewRequestWithContext(ctx, "GET", url, nil) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| c.logRequest("GET", url, nil) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 { | |
| return nil, fmt.Errorf("failed to get agent container. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var container AgentContainerObject | |
| if err := json.Unmarshal(body, &container); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &container, nil | |
| } | |
| // GetAgentContainerOperation retrieves the status of a container operation | |
| func (c *AgentClient) GetAgentContainerOperation(ctx context.Context, agentName, operationID, apiVersion string) (*AgentContainerOperationObject, error) { | |
| url := fmt.Sprintf("%s/agents/%s/operations/%s?api-version=%s", c.endpoint, agentName, operationID, apiVersion) | |
| req, err := http.NewRequestWithContext(ctx, "GET", url, nil) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| if err := c.setAuthHeader(ctx, req); err != nil { | |
| return nil, err | |
| } | |
| c.logRequest("GET", url, nil) | |
| resp, err := c.client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("HTTP request failed: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response body: %w", err) | |
| } | |
| c.logResponse(resp.StatusCode, resp.Header, body) | |
| if resp.StatusCode != 200 { | |
| return nil, fmt.Errorf("failed to get container operation. Status code: %d, Response: %s", resp.StatusCode, string(body)) | |
| } | |
| var operation AgentContainerOperationObject | |
| if err := json.Unmarshal(body, &operation); err != nil { | |
| return nil, fmt.Errorf("failed to parse response: %w", err) | |
| } | |
| return &operation, nil | |
| } | |
| // Helper methods | |
| // setAuthHeader sets the authorization header using the credential | |
| func (c *AgentClient) setAuthHeader(ctx context.Context, req *http.Request) error { | |
| token, err := c.getAiFoundryAzureToken(ctx, c.cred) | |
| if err != nil { | |
| return fmt.Errorf("failed to get Azure token: %w", err) | |
| } | |
| req.Header.Set("Authorization", "Bearer "+token) | |
| return nil | |
| } | |
| // getAiFoundryAzureToken gets an Azure access token using the provided credential | |
| func (c *AgentClient) getAiFoundryAzureToken(ctx context.Context, cred azcore.TokenCredential) (string, error) { | |
| tokenRequestOptions := policy.TokenRequestOptions{ | |
| Scopes: []string{"https://ai.azure.com/.default"}, | |
| } | |
| token, err := cred.GetToken(ctx, tokenRequestOptions) | |
| if err != nil { | |
| return "", err | |
| } | |
| return token.Token, nil | |
| } | |
| // logRequest logs the request details to stderr.txt for debugging | |
| func (c *AgentClient) logRequest(method, url string, payload []byte) { | |
| fmt.Fprintf(c.logFile, "\n=== REQUEST [%s] ===\n", time.Now().Format(time.RFC3339)) | |
| fmt.Fprintf(c.logFile, "%s %s\n", method, url) | |
| if len(payload) > 0 { | |
| fmt.Fprintf(c.logFile, "Body:\n") | |
| var prettyPayload interface{} | |
| if err := json.Unmarshal(payload, &prettyPayload); err == nil { | |
| prettyJSON, _ := json.MarshalIndent(prettyPayload, "", " ") | |
| fmt.Fprintf(c.logFile, "%s\n", string(prettyJSON)) | |
| } else { | |
| fmt.Fprintf(c.logFile, "%s\n", string(payload)) | |
| } | |
| } else { | |
| fmt.Fprintf(c.logFile, "Body: (empty)\n") | |
| } | |
| } | |
| // logResponse logs the response details to stderr.txt for debugging | |
| func (c *AgentClient) logResponse(statusCode int, headers http.Header, body []byte) { | |
| fmt.Fprintf(c.logFile, "\n=== RESPONSE [%s] ===\n", time.Now().Format(time.RFC3339)) | |
| fmt.Fprintf(c.logFile, "Status Code: %d\n", statusCode) | |
| fmt.Fprintf(c.logFile, "Headers:\n") | |
| for key, values := range headers { | |
| for _, value := range values { | |
| fmt.Fprintf(c.logFile, " %s: %s\n", key, value) | |
| } | |
| } | |
| fmt.Fprintf(c.logFile, "Body:\n") | |
| if len(body) > 0 { | |
| var jsonResponse interface{} | |
| if err := json.Unmarshal(body, &jsonResponse); err == nil { | |
| prettyJSON, _ := json.MarshalIndent(jsonResponse, "", " ") | |
| fmt.Fprintf(c.logFile, "%s\n", string(prettyJSON)) | |
| } else { | |
| fmt.Fprintf(c.logFile, "%s\n", string(body)) | |
| } | |
| } else { | |
| fmt.Fprintf(c.logFile, "(empty)\n") | |
| } | |
| fmt.Fprintf(c.logFile, "\n") | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment