package agentidp import ( "context" "net/http" "strings" "time" ) // AgentIdPClientConfig holds all configuration for AgentIdPClient. type AgentIdPClientConfig struct { // BaseURL is the root URL of the AgentIdP server (e.g. "https://idp.example.com"). BaseURL string // ClientID is the agent's OAuth 2.0 client ID. ClientID string // ClientSecret is the agent's OAuth 2.0 client secret. ClientSecret string // Scope is the space-separated list of OAuth 2.0 scopes to request. // Defaults to all four scopes when empty. Scope string // HTTPClient allows injecting a custom *http.Client (e.g. for testing). // When nil, a default client with a 30-second timeout is used. HTTPClient *http.Client } // AgentIdPClient is the top-level client for the SentryAgent.ai AgentIdP API. // It composes all four service clients and manages token acquisition automatically. // // Usage: // // client := agentidp.NewAgentIdPClient(agentidp.AgentIdPClientConfig{ // BaseURL: "https://idp.example.com", // ClientID: "my-agent-id", // ClientSecret: "sk_live_...", // }) // agent, err := client.Agents.GetAgent(ctx, "uuid-1") type AgentIdPClient struct { // Agents provides access to the Agent Registry endpoints. Agents *AgentRegistryClient // Credentials provides access to the Credential Management endpoints. Credentials *CredentialClient // Tokens provides access to the Token introspection and revocation endpoints. Tokens *TokenServiceClient // Audit provides access to the Audit Log endpoints. Audit *AuditClient tokenManager *TokenManager } // NewAgentIdPClient creates a new AgentIdPClient with the given configuration. func NewAgentIdPClient(cfg AgentIdPClientConfig) *AgentIdPClient { baseURL := strings.TrimRight(cfg.BaseURL, "/") scope := cfg.Scope if scope == "" { scope = "agents:read agents:write tokens:read audit:read" } httpClient := cfg.HTTPClient if httpClient == nil { httpClient = &http.Client{Timeout: 30 * time.Second} } tm := NewTokenManager(baseURL, cfg.ClientID, cfg.ClientSecret, scope) getToken := func(ctx context.Context) (string, error) { return tm.GetToken(ctx) } return &AgentIdPClient{ Agents: newAgentRegistryClient(baseURL, getToken, httpClient), Credentials: newCredentialClient(baseURL, getToken, httpClient), Tokens: newTokenServiceClient(baseURL, getToken, httpClient), Audit: newAuditClient(baseURL, getToken, httpClient), tokenManager: tm, } } // ClearTokenCache invalidates the cached access token. // The next API call will fetch a fresh token from the server. func (c *AgentIdPClient) ClearTokenCache() { c.tokenManager.ClearCache() }