From 7473d1fd89473128d67fec28ec3b78322247a4fc Mon Sep 17 00:00:00 2001 From: Ambient Code Bot Date: Thu, 9 Apr 2026 21:50:11 -0400 Subject: [PATCH 1/9] feat(mcp-sidecar): implement RSA-OAEP token exchange for dynamic token refresh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the static AMBIENT_TOKEN injection with the same RSA-OAEP token exchange protocol the runner uses, so the MCP sidecar can fetch and periodically refresh its own API token from the CP token server. - Add tokenexchange package: RSA-OAEP encrypt session ID, fetch token from CP /token endpoint with retry/backoff, background refresh every 5 minutes - Make client.Client thread-safe (sync.RWMutex) with SetToken() for hot-swapping tokens on refresh - Refactor mention.Resolver to use TokenFunc instead of static string so it always reads the current token - Inject SESSION_ID into MCP sidecar env in buildMCPSidecar() - Default MCP_API_SERVER_URL to AMBIENT_API_SERVER_URL so the sidecar inherits the correct API endpoint automatically - Remove hardcoded MCP_API_SERVER_URL from mpp-openshift overlay - Add unit tests for tokenexchange, client, and mention packages 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../ambient-cli/cmd/acpctl/session/send.go | 23 +- .../internal/config/config.go | 6 +- .../internal/reconciler/kube_reconciler.go | 13 +- components/ambient-mcp/client/client.go | 17 +- components/ambient-mcp/client/client_test.go | 133 ++++++ components/ambient-mcp/main.go | 45 +- components/ambient-mcp/mention/resolve.go | 12 +- .../ambient-mcp/mention/resolve_test.go | 167 ++++++++ .../tokenexchange/tokenexchange.go | 210 ++++++++++ .../tokenexchange/tokenexchange_test.go | 396 ++++++++++++++++++ components/ambient-mcp/tools/sessions.go | 2 +- .../mpp-openshift/ambient-control-plane.yaml | 2 - 12 files changed, 990 insertions(+), 36 deletions(-) create mode 100644 components/ambient-mcp/client/client_test.go create mode 100644 components/ambient-mcp/mention/resolve_test.go create mode 100644 components/ambient-mcp/tokenexchange/tokenexchange.go create mode 100644 components/ambient-mcp/tokenexchange/tokenexchange_test.go diff --git a/components/ambient-cli/cmd/acpctl/session/send.go b/components/ambient-cli/cmd/acpctl/session/send.go index 6f05bf43b..857c49009 100644 --- a/components/ambient-cli/cmd/acpctl/session/send.go +++ b/components/ambient-cli/cmd/acpctl/session/send.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "fmt" + "io" "os" "os/signal" "strings" @@ -56,6 +57,19 @@ func runSend(cmd *cobra.Command, args []string) error { ctx, cancel := context.WithTimeout(cmd.Context(), cfg.GetRequestTimeout()) defer cancel() + streamCtx, streamCancel := signal.NotifyContext(cmd.Context(), os.Interrupt) + defer streamCancel() + + var stream io.ReadCloser + if sendFollow { + s, err := client.Sessions().StreamEvents(streamCtx, sessionID) + if err != nil { + return fmt.Errorf("stream events: %w", err) + } + stream = s + defer stream.Close() + } + msg, err := client.Sessions().PushMessage(ctx, sessionID, payload) if err != nil { return fmt.Errorf("send message: %w", err) @@ -67,15 +81,6 @@ func runSend(cmd *cobra.Command, args []string) error { return nil } - streamCtx, streamCancel := signal.NotifyContext(cmd.Context(), os.Interrupt) - defer streamCancel() - - stream, err := client.Sessions().StreamEvents(streamCtx, sessionID) - if err != nil { - return fmt.Errorf("stream events: %w", err) - } - defer stream.Close() - out := cmd.OutOrStdout() scanner := bufio.NewScanner(stream) var reasoningBuf strings.Builder diff --git a/components/ambient-control-plane/internal/config/config.go b/components/ambient-control-plane/internal/config/config.go index 08997d882..9d5fe4d28 100644 --- a/components/ambient-control-plane/internal/config/config.go +++ b/components/ambient-control-plane/internal/config/config.go @@ -70,13 +70,17 @@ func Load() (*ControlPlaneConfig, error) { VertexSecretNamespace: envOrDefault("VERTEX_SECRET_NAMESPACE", "ambient-code"), RunnerImageNamespace: os.Getenv("RUNNER_IMAGE_NAMESPACE"), MCPImage: os.Getenv("MCP_IMAGE"), - MCPAPIServerURL: envOrDefault("MCP_API_SERVER_URL", "http://ambient-api-server.ambient-code.svc:8000"), + MCPAPIServerURL: envOrDefault("MCP_API_SERVER_URL", ""), RunnerLogLevel: envOrDefault("RUNNER_LOG_LEVEL", "info"), ProjectKubeTokenFile: os.Getenv("PROJECT_KUBE_TOKEN_FILE"), CPTokenListenAddr: envOrDefault("CP_TOKEN_LISTEN_ADDR", ":8080"), CPTokenURL: os.Getenv("CP_TOKEN_URL"), } + if cfg.MCPAPIServerURL == "" { + cfg.MCPAPIServerURL = cfg.APIServerURL + } + if cfg.APIToken == "" && (cfg.OIDCClientID == "" || cfg.OIDCClientSecret == "") { return nil, fmt.Errorf("either AMBIENT_API_TOKEN or both OIDC_CLIENT_ID and OIDC_CLIENT_SECRET must be set; set AMBIENT_API_TOKEN for k8s SA token auth or OIDC_CLIENT_ID+OIDC_CLIENT_SECRET for OIDC") } diff --git a/components/ambient-control-plane/internal/reconciler/kube_reconciler.go b/components/ambient-control-plane/internal/reconciler/kube_reconciler.go index 567c63ed9..6b9ac9070 100644 --- a/components/ambient-control-plane/internal/reconciler/kube_reconciler.go +++ b/components/ambient-control-plane/internal/reconciler/kube_reconciler.go @@ -441,12 +441,7 @@ func (r *SimpleKubeReconciler) ensurePod(ctx context.Context, namespace string, } if useMCPSidecar { - ambientToken, err := r.factory.Token(ctx) - if err != nil { - r.logger.Warn().Err(err).Str("session_id", session.ID).Msg("failed to fetch token for MCP sidecar; sidecar will start without AMBIENT_TOKEN") - ambientToken = "" - } - containers = append(containers, r.buildMCPSidecar(ambientToken)) + containers = append(containers, r.buildMCPSidecar(session.ID)) r.logger.Info().Str("session_id", session.ID).Msg("MCP sidecar enabled for session") } @@ -816,7 +811,7 @@ func boolToStr(b bool) string { return "false" } -func (r *SimpleKubeReconciler) buildMCPSidecar(ambientToken string) interface{} { +func (r *SimpleKubeReconciler) buildMCPSidecar(sessionID string) interface{} { mcpImage := r.cfg.MCPImage imagePullPolicy := "Always" if strings.HasPrefix(mcpImage, "localhost/") { @@ -828,9 +823,7 @@ func (r *SimpleKubeReconciler) buildMCPSidecar(ambientToken string) interface{} envVar("AMBIENT_API_URL", r.cfg.MCPAPIServerURL), envVar("AMBIENT_CP_TOKEN_URL", r.cfg.CPTokenURL), envVar("AMBIENT_CP_TOKEN_PUBLIC_KEY", r.cfg.CPTokenPublicKey), - } - if ambientToken != "" { - env = append(env, envVar("AMBIENT_TOKEN", ambientToken)) + envVar("SESSION_ID", sessionID), } return map[string]interface{}{ "name": "ambient-mcp", diff --git a/components/ambient-mcp/client/client.go b/components/ambient-mcp/client/client.go index ec167e4fe..336a6c1da 100644 --- a/components/ambient-mcp/client/client.go +++ b/components/ambient-mcp/client/client.go @@ -9,12 +9,14 @@ import ( "net/http" "net/url" "strings" + "sync" "time" ) type Client struct { httpClient *http.Client baseURL string + mu sync.RWMutex token string } @@ -27,7 +29,18 @@ func New(baseURL, token string) *Client { } func (c *Client) BaseURL() string { return c.baseURL } -func (c *Client) Token() string { return c.token } + +func (c *Client) Token() string { + c.mu.RLock() + defer c.mu.RUnlock() + return c.token +} + +func (c *Client) SetToken(token string) { + c.mu.Lock() + defer c.mu.Unlock() + c.token = token +} func (c *Client) do(ctx context.Context, method, path string, body []byte, result interface{}, expectedStatuses ...int) error { reqURL := c.baseURL + "/api/ambient/v1" + path @@ -42,7 +55,7 @@ func (c *Client) do(ctx context.Context, method, path string, body []byte, resul if body != nil { req.Header.Set("Content-Type", "application/json") } - req.Header.Set("Authorization", "Bearer "+c.token) + req.Header.Set("Authorization", "Bearer "+c.Token()) req.Header.Set("Accept", "application/json") resp, err := c.httpClient.Do(req) diff --git a/components/ambient-mcp/client/client_test.go b/components/ambient-mcp/client/client_test.go new file mode 100644 index 000000000..daaffbedb --- /dev/null +++ b/components/ambient-mcp/client/client_test.go @@ -0,0 +1,133 @@ +package client + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "sync" + "testing" +) + +func TestNew(t *testing.T) { + c := New("http://localhost:8080/", "my-token") + if c.BaseURL() != "http://localhost:8080" { + t.Errorf("BaseURL() = %q, want trailing slash stripped", c.BaseURL()) + } + if c.Token() != "my-token" { + t.Errorf("Token() = %q, want %q", c.Token(), "my-token") + } +} + +func TestSetToken(t *testing.T) { + c := New("http://localhost:8080", "initial") + c.SetToken("refreshed") + if c.Token() != "refreshed" { + t.Errorf("Token() after SetToken = %q, want %q", c.Token(), "refreshed") + } +} + +func TestSetToken_ConcurrentAccess(t *testing.T) { + c := New("http://localhost:8080", "initial") + var wg sync.WaitGroup + + for i := range 100 { + wg.Add(2) + go func(n int) { + defer wg.Done() + c.SetToken("token-" + string(rune('A'+n%26))) + }(i) + go func() { + defer wg.Done() + _ = c.Token() + }() + } + wg.Wait() + + got := c.Token() + if got == "" { + t.Error("Token() is empty after concurrent access") + } +} + +func TestGet_SendsBearerToken(t *testing.T) { + var receivedAuth string + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + receivedAuth = r.Header.Get("Authorization") + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]string{"status": "ok"}) + })) + defer srv.Close() + + c := New(srv.URL, "test-bearer") + var result map[string]string + err := c.Get(context.Background(), "/healthz", &result) + if err != nil { + t.Fatalf("Get: %v", err) + } + if receivedAuth != "Bearer test-bearer" { + t.Errorf("Authorization = %q, want %q", receivedAuth, "Bearer test-bearer") + } +} + +func TestGet_UsesRefreshedToken(t *testing.T) { + var receivedAuth string + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + receivedAuth = r.Header.Get("Authorization") + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]string{"status": "ok"}) + })) + defer srv.Close() + + c := New(srv.URL, "old-token") + c.SetToken("new-token") + + var result map[string]string + err := c.Get(context.Background(), "/healthz", &result) + if err != nil { + t.Fatalf("Get: %v", err) + } + if receivedAuth != "Bearer new-token" { + t.Errorf("Authorization = %q, want %q", receivedAuth, "Bearer new-token") + } +} + +func TestGet_UnexpectedStatus(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.Error(w, "not found", http.StatusNotFound) + })) + defer srv.Close() + + c := New(srv.URL, "token") + err := c.Get(context.Background(), "/missing", nil) + if err == nil { + t.Fatal("expected error for 404 response") + } +} + +func TestPost_SendsBody(t *testing.T) { + var receivedBody map[string]string + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + json.NewDecoder(r.Body).Decode(&receivedBody) + if r.Header.Get("Content-Type") != "application/json" { + t.Errorf("Content-Type = %q, want application/json", r.Header.Get("Content-Type")) + } + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(map[string]string{"id": "123"}) + })) + defer srv.Close() + + c := New(srv.URL, "token") + body := map[string]string{"name": "test"} + var result map[string]string + err := c.Post(context.Background(), "/items", body, &result, http.StatusCreated) + if err != nil { + t.Fatalf("Post: %v", err) + } + if receivedBody["name"] != "test" { + t.Errorf("received body name = %q, want %q", receivedBody["name"], "test") + } + if result["id"] != "123" { + t.Errorf("result id = %q, want %q", result["id"], "123") + } +} diff --git a/components/ambient-mcp/main.go b/components/ambient-mcp/main.go index c1d577288..07ddd1394 100644 --- a/components/ambient-mcp/main.go +++ b/components/ambient-mcp/main.go @@ -8,6 +8,7 @@ import ( "github.com/mark3labs/mcp-go/server" "github.com/ambient-code/platform/components/ambient-mcp/client" + "github.com/ambient-code/platform/components/ambient-mcp/tokenexchange" ) func main() { @@ -16,18 +17,50 @@ func main() { apiURL = "http://localhost:8080" } - token := os.Getenv("AMBIENT_TOKEN") - if token == "" { - fmt.Fprintln(os.Stderr, "AMBIENT_TOKEN is required") - os.Exit(1) - } - transport := os.Getenv("MCP_TRANSPORT") if transport == "" { transport = "stdio" } + cpTokenURL := os.Getenv("AMBIENT_CP_TOKEN_URL") + cpPublicKey := os.Getenv("AMBIENT_CP_TOKEN_PUBLIC_KEY") + sessionID := os.Getenv("SESSION_ID") + + var token string + var exchanger *tokenexchange.Exchanger + + if cpTokenURL != "" && cpPublicKey != "" && sessionID != "" { + var err error + exchanger, err = tokenexchange.New(cpTokenURL, cpPublicKey, sessionID) + if err != nil { + fmt.Fprintf(os.Stderr, "token exchange init failed: %v\n", err) + os.Exit(1) + } + token, err = exchanger.FetchToken() + if err != nil { + fmt.Fprintf(os.Stderr, "initial token fetch failed: %v\n", err) + os.Exit(1) + } + fmt.Fprintln(os.Stderr, "bootstrapped token via CP token exchange") + } else { + token = os.Getenv("AMBIENT_TOKEN") + if token == "" { + fmt.Fprintln(os.Stderr, "AMBIENT_TOKEN is required when CP token exchange env vars are not set") + os.Exit(1) + } + fmt.Fprintln(os.Stderr, "using static AMBIENT_TOKEN (no CP token exchange)") + } + c := client.New(apiURL, token) + + if exchanger != nil { + exchanger.OnRefresh(func(freshToken string) { + c.SetToken(freshToken) + }) + exchanger.StartBackgroundRefresh() + defer exchanger.Stop() + } + s := newServer(c, transport) switch transport { diff --git a/components/ambient-mcp/mention/resolve.go b/components/ambient-mcp/mention/resolve.go index 7b9cf5b51..e7306b441 100644 --- a/components/ambient-mcp/mention/resolve.go +++ b/components/ambient-mcp/mention/resolve.go @@ -18,16 +18,18 @@ type Doer interface { Do(req *http.Request) (*http.Response, error) } +type TokenFunc func() string + type Resolver struct { baseURL string - token string + tokenFn TokenFunc http *http.Client } -func NewResolver(baseURL, token string) *Resolver { +func NewResolver(baseURL string, tokenFn TokenFunc) *Resolver { return &Resolver{ baseURL: strings.TrimSuffix(baseURL, "/"), - token: token, + tokenFn: tokenFn, http: &http.Client{}, } } @@ -43,7 +45,7 @@ func (r *Resolver) Resolve(ctx context.Context, projectID, identifier string) (s if uuidPattern.MatchString(strings.ToLower(identifier)) { path := r.baseURL + "/api/ambient/v1/projects/" + url.PathEscape(projectID) + "/agents/" + url.PathEscape(identifier) req, _ := http.NewRequestWithContext(ctx, http.MethodGet, path, nil) - req.Header.Set("Authorization", "Bearer "+r.token) + req.Header.Set("Authorization", "Bearer "+r.tokenFn()) resp, err := r.http.Do(req) if err != nil { return "", fmt.Errorf("lookup agent by ID: %w", err) @@ -66,7 +68,7 @@ func (r *Resolver) Resolve(ctx context.Context, projectID, identifier string) (s path := r.baseURL + "/api/ambient/v1/projects/" + url.PathEscape(projectID) + "/agents?search=name='" + url.QueryEscape(identifier) + "'" req, _ := http.NewRequestWithContext(ctx, http.MethodGet, path, nil) - req.Header.Set("Authorization", "Bearer "+r.token) + req.Header.Set("Authorization", "Bearer "+r.tokenFn()) resp, err := r.http.Do(req) if err != nil { return "", fmt.Errorf("search agent by name: %w", err) diff --git a/components/ambient-mcp/mention/resolve_test.go b/components/ambient-mcp/mention/resolve_test.go new file mode 100644 index 000000000..f47709e39 --- /dev/null +++ b/components/ambient-mcp/mention/resolve_test.go @@ -0,0 +1,167 @@ +package mention + +import ( + "context" + "encoding/json" + "net/http" + "net/http/httptest" + "sync/atomic" + "testing" +) + +func TestNewResolver_TokenFunc(t *testing.T) { + callCount := 0 + tokenFn := func() string { + callCount++ + return "dynamic-token" + } + r := NewResolver("http://localhost:8080", tokenFn) + if r == nil { + t.Fatal("NewResolver returned nil") + } + if callCount != 0 { + t.Errorf("tokenFn called %d times at construction, want 0", callCount) + } +} + +func TestResolve_ByUUID_SendsCurrentToken(t *testing.T) { + var tokenSeq atomic.Int32 + tokens := []string{"token-v1", "token-v2"} + + var receivedAuths []string + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + receivedAuths = append(receivedAuths, r.Header.Get("Authorization")) + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]string{"id": "550e8400-e29b-41d4-a716-446655440000"}) + })) + defer srv.Close() + + r := NewResolver(srv.URL, func() string { + idx := tokenSeq.Load() + if int(idx) < len(tokens) { + return tokens[idx] + } + return tokens[len(tokens)-1] + }) + + ctx := context.Background() + agentID, err := r.Resolve(ctx, "proj1", "550e8400-e29b-41d4-a716-446655440000") + if err != nil { + t.Fatalf("Resolve: %v", err) + } + if agentID != "550e8400-e29b-41d4-a716-446655440000" { + t.Errorf("agentID = %q, want UUID", agentID) + } + if receivedAuths[0] != "Bearer token-v1" { + t.Errorf("first auth = %q, want %q", receivedAuths[0], "Bearer token-v1") + } + + tokenSeq.Store(1) + _, err = r.Resolve(ctx, "proj1", "550e8400-e29b-41d4-a716-446655440000") + if err != nil { + t.Fatalf("Resolve (2nd): %v", err) + } + if receivedAuths[1] != "Bearer token-v2" { + t.Errorf("second auth = %q, want %q", receivedAuths[1], "Bearer token-v2") + } +} + +func TestResolve_ByName_SendsCurrentToken(t *testing.T) { + var receivedAuth string + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + receivedAuth = r.Header.Get("Authorization") + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(agentSearchResult{ + Items: []struct { + ID string `json:"id"` + }{{ID: "resolved-agent-id"}}, + Total: 1, + }) + })) + defer srv.Close() + + r := NewResolver(srv.URL, func() string { return "name-lookup-token" }) + agentID, err := r.Resolve(context.Background(), "proj1", "my-agent") + if err != nil { + t.Fatalf("Resolve: %v", err) + } + if agentID != "resolved-agent-id" { + t.Errorf("agentID = %q, want %q", agentID, "resolved-agent-id") + } + if receivedAuth != "Bearer name-lookup-token" { + t.Errorf("auth = %q, want %q", receivedAuth, "Bearer name-lookup-token") + } +} + +func TestResolve_ByUUID_NotFound(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.Error(w, "not found", http.StatusNotFound) + })) + defer srv.Close() + + r := NewResolver(srv.URL, func() string { return "t" }) + _, err := r.Resolve(context.Background(), "proj1", "550e8400-e29b-41d4-a716-446655440000") + if err == nil { + t.Fatal("expected error for 404") + } +} + +func TestResolve_ByName_NoMatch(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(agentSearchResult{Total: 0}) + })) + defer srv.Close() + + r := NewResolver(srv.URL, func() string { return "t" }) + _, err := r.Resolve(context.Background(), "proj1", "nonexistent") + if err == nil { + t.Fatal("expected error for no match") + } +} + +func TestResolve_ByName_Ambiguous(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(agentSearchResult{ + Items: []struct { + ID string `json:"id"` + }{{ID: "a"}, {ID: "b"}}, + Total: 2, + }) + })) + defer srv.Close() + + r := NewResolver(srv.URL, func() string { return "t" }) + _, err := r.Resolve(context.Background(), "proj1", "ambiguous") + if err == nil { + t.Fatal("expected error for ambiguous match") + } +} + +func TestExtract(t *testing.T) { + matches := Extract("Hello @alice and @bob, also @alice again") + if len(matches) != 2 { + t.Fatalf("len(matches) = %d, want 2", len(matches)) + } + if matches[0].Identifier != "alice" { + t.Errorf("matches[0].Identifier = %q, want %q", matches[0].Identifier, "alice") + } + if matches[1].Identifier != "bob" { + t.Errorf("matches[1].Identifier = %q, want %q", matches[1].Identifier, "bob") + } +} + +func TestExtract_NoMentions(t *testing.T) { + matches := Extract("no mentions here") + if len(matches) != 0 { + t.Errorf("len(matches) = %d, want 0", len(matches)) + } +} + +func TestStripToken_RemovesMention(t *testing.T) { + result := StripToken("hello @alice do this", "@alice") + if result != "hello do this" { + t.Errorf("StripToken = %q, want %q", result, "hello do this") + } +} diff --git a/components/ambient-mcp/tokenexchange/tokenexchange.go b/components/ambient-mcp/tokenexchange/tokenexchange.go new file mode 100644 index 000000000..18ce9db90 --- /dev/null +++ b/components/ambient-mcp/tokenexchange/tokenexchange.go @@ -0,0 +1,210 @@ +package tokenexchange + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "crypto/x509" + "encoding/base64" + "encoding/json" + "encoding/pem" + "fmt" + "io" + "net/http" + "net/url" + "os" + "strings" + "sync" + "time" +) + +const ( + fetchAttempts = 3 + fetchTimeout = 10 * time.Second + refreshPeriod = 5 * time.Minute + initialBackoff = 1 * time.Second +) + +type Exchanger struct { + tokenURL string + publicKey *rsa.PublicKey + sessionID string + httpClient *http.Client + mu sync.RWMutex + currentToken string + onRefresh func(string) + stopCh chan struct{} + startOnce sync.Once + stopOnce sync.Once +} + +type tokenResponse struct { + Token string `json:"token"` +} + +func New(tokenURL, publicKeyPEM, sessionID string) (*Exchanger, error) { + if err := validateTokenURL(tokenURL); err != nil { + return nil, err + } + + pubKey, err := parsePublicKey(publicKeyPEM) + if err != nil { + return nil, fmt.Errorf("parse public key: %w", err) + } + + return &Exchanger{ + tokenURL: tokenURL, + publicKey: pubKey, + sessionID: sessionID, + httpClient: &http.Client{Timeout: fetchTimeout}, + stopCh: make(chan struct{}), + }, nil +} + +func (e *Exchanger) OnRefresh(fn func(string)) { + e.mu.Lock() + defer e.mu.Unlock() + e.onRefresh = fn +} + +func (e *Exchanger) FetchToken() (string, error) { + bearer, err := encryptSessionID(e.publicKey, e.sessionID) + if err != nil { + return "", fmt.Errorf("encrypt session ID: %w", err) + } + + var lastErr error + for attempt := range fetchAttempts { + if attempt > 0 { + time.Sleep(initialBackoff * time.Duration(1<<(attempt-1))) + } + + token, err := e.doFetch(bearer) + if err != nil { + lastErr = err + continue + } + + e.mu.Lock() + e.currentToken = token + callback := e.onRefresh + e.mu.Unlock() + + if callback != nil { + callback(token) + } + + return token, nil + } + + return "", fmt.Errorf("token endpoint unreachable after %d attempts: %w", fetchAttempts, lastErr) +} + +func (e *Exchanger) Token() string { + e.mu.RLock() + defer e.mu.RUnlock() + return e.currentToken +} + +func (e *Exchanger) StartBackgroundRefresh() { + e.startOnce.Do(func() { + go func() { + ticker := time.NewTicker(refreshPeriod) + defer ticker.Stop() + for { + select { + case <-ticker.C: + if _, err := e.FetchToken(); err != nil { + fmt.Fprintf(os.Stderr, "background token refresh failed: %v\n", err) + } + case <-e.stopCh: + return + } + } + }() + }) +} + +func (e *Exchanger) Stop() { + e.stopOnce.Do(func() { + close(e.stopCh) + }) +} + +func (e *Exchanger) doFetch(bearer string) (string, error) { + req, err := http.NewRequest(http.MethodGet, e.tokenURL, nil) + if err != nil { + return "", fmt.Errorf("create request: %w", err) + } + req.Header.Set("Authorization", "Bearer "+bearer) + + resp, err := e.httpClient.Do(req) + if err != nil { + return "", fmt.Errorf("request failed: %w", err) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", fmt.Errorf("read response: %w", err) + } + + if resp.StatusCode != http.StatusOK { + return "", fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body)) + } + + var tokenResp tokenResponse + if err := json.Unmarshal(body, &tokenResp); err != nil { + return "", fmt.Errorf("unmarshal response: %w", err) + } + if tokenResp.Token == "" { + return "", fmt.Errorf("token response missing 'token' field") + } + + return tokenResp.Token, nil +} + +func encryptSessionID(pubKey *rsa.PublicKey, sessionID string) (string, error) { + ciphertext, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, pubKey, []byte(sessionID), nil) + if err != nil { + return "", fmt.Errorf("RSA-OAEP encrypt: %w", err) + } + return base64.StdEncoding.EncodeToString(ciphertext), nil +} + +func parsePublicKey(pemStr string) (*rsa.PublicKey, error) { + block, _ := pem.Decode([]byte(pemStr)) + if block == nil { + return nil, fmt.Errorf("no PEM block found in public key") + } + + pub, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + return nil, fmt.Errorf("parse PKIX public key: %w", err) + } + + rsaPub, ok := pub.(*rsa.PublicKey) + if !ok { + return nil, fmt.Errorf("public key is not RSA (got %T)", pub) + } + + return rsaPub, nil +} + +func validateTokenURL(rawURL string) error { + parsed, err := url.Parse(rawURL) + if err != nil { + return fmt.Errorf("parse token URL: %w", err) + } + scheme := strings.ToLower(parsed.Scheme) + if scheme != "http" && scheme != "https" { + return fmt.Errorf("invalid token URL scheme %q (must be http or https)", scheme) + } + if parsed.Host == "" { + return fmt.Errorf("token URL has no host") + } + if parsed.User != nil { + return fmt.Errorf("token URL must not contain credentials") + } + return nil +} diff --git a/components/ambient-mcp/tokenexchange/tokenexchange_test.go b/components/ambient-mcp/tokenexchange/tokenexchange_test.go new file mode 100644 index 000000000..9cc3f5664 --- /dev/null +++ b/components/ambient-mcp/tokenexchange/tokenexchange_test.go @@ -0,0 +1,396 @@ +package tokenexchange + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "crypto/x509" + "encoding/base64" + "encoding/json" + "encoding/pem" + "fmt" + "net/http" + "net/http/httptest" + "sync/atomic" + "testing" + "time" +) + +func generateTestKeyPair(t *testing.T) (*rsa.PrivateKey, string) { + t.Helper() + privKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatalf("generating RSA key: %v", err) + } + pubDER, err := x509.MarshalPKIXPublicKey(&privKey.PublicKey) + if err != nil { + t.Fatalf("marshaling public key: %v", err) + } + pubPEM := pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: pubDER}) + return privKey, string(pubPEM) +} + +func decryptBearer(t *testing.T, privKey *rsa.PrivateKey, bearer string) string { + t.Helper() + ciphertext, err := base64.StdEncoding.DecodeString(bearer) + if err != nil { + t.Fatalf("decoding bearer base64: %v", err) + } + plaintext, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privKey, ciphertext, nil) + if err != nil { + t.Fatalf("decrypting bearer: %v", err) + } + return string(plaintext) +} + +func newTokenServer(t *testing.T, privKey *rsa.PrivateKey, apiToken string) *httptest.Server { + t.Helper() + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + auth := r.Header.Get("Authorization") + if len(auth) < 8 || auth[:7] != "Bearer " { + http.Error(w, "missing bearer", http.StatusUnauthorized) + return + } + bearer := auth[7:] + sessionID := decryptBearer(t, privKey, bearer) + if len(sessionID) < 8 { + http.Error(w, "invalid session ID", http.StatusUnauthorized) + return + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(tokenResponse{Token: apiToken}) + })) +} + +func TestEncryptSessionID_Roundtrip(t *testing.T) { + privKey, pubPEM := generateTestKeyPair(t) + pubKey, err := parsePublicKey(pubPEM) + if err != nil { + t.Fatalf("parsePublicKey: %v", err) + } + + sessionID := "test-session-abc123" + encrypted, err := encryptSessionID(pubKey, sessionID) + if err != nil { + t.Fatalf("encryptSessionID: %v", err) + } + + ciphertext, err := base64.StdEncoding.DecodeString(encrypted) + if err != nil { + t.Fatalf("base64 decode: %v", err) + } + plaintext, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, privKey, ciphertext, nil) + if err != nil { + t.Fatalf("RSA decrypt: %v", err) + } + if string(plaintext) != sessionID { + t.Errorf("roundtrip got %q, want %q", string(plaintext), sessionID) + } +} + +func TestParsePublicKey_Valid(t *testing.T) { + _, pubPEM := generateTestKeyPair(t) + key, err := parsePublicKey(pubPEM) + if err != nil { + t.Fatalf("parsePublicKey: %v", err) + } + if key == nil { + t.Fatal("parsePublicKey returned nil key") + } +} + +func TestParsePublicKey_InvalidPEM(t *testing.T) { + _, err := parsePublicKey("not-a-pem-block") + if err == nil { + t.Fatal("expected error for invalid PEM") + } +} + +func TestParsePublicKey_NotRSA(t *testing.T) { + _, err := parsePublicKey("-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\n-----END PUBLIC KEY-----\n") + if err == nil { + t.Fatal("expected error for non-RSA key") + } +} + +func TestValidateTokenURL(t *testing.T) { + cases := []struct { + url string + valid bool + }{ + {"https://cp.example.com/token", true}, + {"http://localhost:8080/token", true}, + {"ftp://example.com/token", false}, + {"://missing-scheme", false}, + {"http://user:pass@example.com/token", false}, + {"", false}, + } + for _, tc := range cases { + err := validateTokenURL(tc.url) + if (err == nil) != tc.valid { + t.Errorf("validateTokenURL(%q): err=%v, wantValid=%v", tc.url, err, tc.valid) + } + } +} + +func TestNew_ValidConfig(t *testing.T) { + _, pubPEM := generateTestKeyPair(t) + ex, err := New("https://cp.example.com/token", pubPEM, "test-session-12345678") + if err != nil { + t.Fatalf("New: %v", err) + } + if ex == nil { + t.Fatal("New returned nil") + } +} + +func TestNew_InvalidURL(t *testing.T) { + _, pubPEM := generateTestKeyPair(t) + _, err := New("ftp://bad.example.com", pubPEM, "test-session-12345678") + if err == nil { + t.Fatal("expected error for invalid URL") + } +} + +func TestNew_InvalidPublicKey(t *testing.T) { + _, err := New("https://cp.example.com/token", "garbage", "test-session-12345678") + if err == nil { + t.Fatal("expected error for invalid public key") + } +} + +func TestFetchToken_Success(t *testing.T) { + privKey, pubPEM := generateTestKeyPair(t) + srv := newTokenServer(t, privKey, "fresh-api-token-xyz") + defer srv.Close() + + ex, err := New(srv.URL+"/token", pubPEM, "session-abcdef12") + if err != nil { + t.Fatalf("New: %v", err) + } + + token, err := ex.FetchToken() + if err != nil { + t.Fatalf("FetchToken: %v", err) + } + if token != "fresh-api-token-xyz" { + t.Errorf("token = %q, want %q", token, "fresh-api-token-xyz") + } + if ex.Token() != "fresh-api-token-xyz" { + t.Errorf("Token() = %q, want %q", ex.Token(), "fresh-api-token-xyz") + } +} + +func TestFetchToken_ServerError_Retries(t *testing.T) { + privKey, pubPEM := generateTestKeyPair(t) + var callCount atomic.Int32 + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + n := callCount.Add(1) + if n < 3 { + http.Error(w, "temporary failure", http.StatusServiceUnavailable) + return + } + bearer := r.Header.Get("Authorization")[7:] + decryptBearer(t, privKey, bearer) + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(tokenResponse{Token: "recovered-token"}) + })) + defer srv.Close() + + ex, err := New(srv.URL+"/token", pubPEM, "session-retry-test1") + if err != nil { + t.Fatalf("New: %v", err) + } + + token, err := ex.FetchToken() + if err != nil { + t.Fatalf("FetchToken: %v", err) + } + if token != "recovered-token" { + t.Errorf("token = %q, want %q", token, "recovered-token") + } + if callCount.Load() != 3 { + t.Errorf("server called %d times, want 3", callCount.Load()) + } +} + +func TestFetchToken_AllRetriesFail(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.Error(w, "permanent failure", http.StatusInternalServerError) + })) + defer srv.Close() + + _, pubPEM := generateTestKeyPair(t) + ex, err := New(srv.URL+"/token", pubPEM, "session-fail-test1") + if err != nil { + t.Fatalf("New: %v", err) + } + + _, err = ex.FetchToken() + if err == nil { + t.Fatal("expected error after all retries fail") + } +} + +func TestFetchToken_EmptyTokenResponse(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(tokenResponse{Token: ""}) + })) + defer srv.Close() + + _, pubPEM := generateTestKeyPair(t) + ex, err := New(srv.URL+"/token", pubPEM, "session-empty-test") + if err != nil { + t.Fatalf("New: %v", err) + } + + _, err = ex.FetchToken() + if err == nil { + t.Fatal("expected error for empty token response") + } +} + +func TestFetchToken_InvalidJSON(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + fmt.Fprint(w, "not-json") + })) + defer srv.Close() + + _, pubPEM := generateTestKeyPair(t) + ex, err := New(srv.URL+"/token", pubPEM, "session-badjson-x") + if err != nil { + t.Fatalf("New: %v", err) + } + + _, err = ex.FetchToken() + if err == nil { + t.Fatal("expected error for invalid JSON") + } +} + +func TestFetchToken_OnRefreshCallback(t *testing.T) { + privKey, pubPEM := generateTestKeyPair(t) + srv := newTokenServer(t, privKey, "callback-token") + defer srv.Close() + + ex, err := New(srv.URL+"/token", pubPEM, "session-callback1") + if err != nil { + t.Fatalf("New: %v", err) + } + + var received string + ex.OnRefresh(func(token string) { + received = token + }) + + token, err := ex.FetchToken() + if err != nil { + t.Fatalf("FetchToken: %v", err) + } + if received != token { + t.Errorf("OnRefresh received %q, want %q", received, token) + } +} + +func TestFetchToken_SendsCorrectBearer(t *testing.T) { + privKey, pubPEM := generateTestKeyPair(t) + sessionID := "session-bearer-check" + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + auth := r.Header.Get("Authorization") + if len(auth) < 8 || auth[:7] != "Bearer " { + t.Errorf("missing Bearer prefix in Authorization header") + http.Error(w, "bad auth", http.StatusUnauthorized) + return + } + bearer := auth[7:] + decrypted := decryptBearer(t, privKey, bearer) + if decrypted != sessionID { + t.Errorf("decrypted session ID = %q, want %q", decrypted, sessionID) + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(tokenResponse{Token: "verified-token"}) + })) + defer srv.Close() + + ex, err := New(srv.URL+"/token", pubPEM, sessionID) + if err != nil { + t.Fatalf("New: %v", err) + } + + _, err = ex.FetchToken() + if err != nil { + t.Fatalf("FetchToken: %v", err) + } +} + +func TestToken_ReturnsEmptyBeforeFetch(t *testing.T) { + _, pubPEM := generateTestKeyPair(t) + ex, err := New("https://example.com/token", pubPEM, "session-nofetch1") + if err != nil { + t.Fatalf("New: %v", err) + } + if got := ex.Token(); got != "" { + t.Errorf("Token() before fetch = %q, want empty", got) + } +} + +func TestStopBackgroundRefresh(t *testing.T) { + privKey, pubPEM := generateTestKeyPair(t) + srv := newTokenServer(t, privKey, "bg-token") + defer srv.Close() + + ex, err := New(srv.URL+"/token", pubPEM, "session-stop-test") + if err != nil { + t.Fatalf("New: %v", err) + } + ex.StartBackgroundRefresh() + ex.Stop() + time.Sleep(50 * time.Millisecond) +} + +func TestFetchToken_WrongKey_ServerRejects(t *testing.T) { + wrongKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatalf("generating wrong key: %v", err) + } + wrongPubDER, _ := x509.MarshalPKIXPublicKey(&wrongKey.PublicKey) + wrongPubPEM := string(pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: wrongPubDER})) + + realKey, _ := generateTestKeyPair(t) + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + auth := r.Header.Get("Authorization") + if len(auth) < 8 || auth[:7] != "Bearer " { + http.Error(w, "missing bearer", http.StatusUnauthorized) + return + } + bearer := auth[7:] + ciphertext, err := base64.StdEncoding.DecodeString(bearer) + if err != nil { + http.Error(w, "bad base64", http.StatusUnauthorized) + return + } + _, err = rsa.DecryptOAEP(sha256.New(), rand.Reader, realKey, ciphertext, nil) + if err != nil { + http.Error(w, "decryption failed", http.StatusUnauthorized) + return + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(tokenResponse{Token: "should-not-get-this"}) + })) + defer srv.Close() + + ex, err := New(srv.URL+"/token", wrongPubPEM, "session-wrongkey1") + if err != nil { + t.Fatalf("New: %v", err) + } + + _, err = ex.FetchToken() + if err == nil { + t.Fatal("expected error when encrypted with wrong key") + } +} diff --git a/components/ambient-mcp/tools/sessions.go b/components/ambient-mcp/tools/sessions.go index 025ab6397..485788cd1 100644 --- a/components/ambient-mcp/tools/sessions.go +++ b/components/ambient-mcp/tools/sessions.go @@ -132,7 +132,7 @@ func CreateSession(c *client.Client) func(ctx context.Context, req mcp.CallToolR } func PushMessage(c *client.Client) func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { - resolver := mention.NewResolver(c.BaseURL(), c.Token()) + resolver := mention.NewResolver(c.BaseURL(), c.Token) return func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { sessionID := mcp.ParseString(req, "session_id", "") diff --git a/components/manifests/overlays/mpp-openshift/ambient-control-plane.yaml b/components/manifests/overlays/mpp-openshift/ambient-control-plane.yaml index 8c4515998..17ebaada4 100644 --- a/components/manifests/overlays/mpp-openshift/ambient-control-plane.yaml +++ b/components/manifests/overlays/mpp-openshift/ambient-control-plane.yaml @@ -84,8 +84,6 @@ spec: value: "http://ambient-control-plane.ambient-code--ambient-s0.svc:8080/token" - name: MCP_IMAGE value: "quay.io/ambient_code/vteam_mcp:latest" - - name: MCP_API_SERVER_URL - value: "http://ambient-api-server.ambient-code--runtime-int.svc:8000" volumeMounts: - name: project-kube-token mountPath: /var/run/secrets/project-kube From 11806224a809782c51220469da265d22be0b2d98 Mon Sep 17 00:00:00 2001 From: Ambient Code Bot Date: Fri, 10 Apr 2026 20:02:48 -0400 Subject: [PATCH 2/9] chore(skills): add self-improving devflow skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Establishes the end-to-end development workflow as a Claude skill: ticket → branch → spec → PR → review → code → deploy → verify. Seeded Known Pitfalls from existing context files and guide lessons. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .claude/skills/devflow/SKILL.md | 374 ++++++++++++++++++++++++++++++++ 1 file changed, 374 insertions(+) create mode 100644 .claude/skills/devflow/SKILL.md diff --git a/.claude/skills/devflow/SKILL.md b/.claude/skills/devflow/SKILL.md new file mode 100644 index 000000000..dd8a6af1a --- /dev/null +++ b/.claude/skills/devflow/SKILL.md @@ -0,0 +1,374 @@ +--- +name: devflow +description: >- + End-to-end development workflow for the Ambient Code Platform. + Covers ticket → branch → spec → code → commit → PR → review → deploy → verify. + Self-improving: update this skill whenever a failure path is discovered or a + shortcut is validated. Git history is the audit trail. +--- + +# Devflow Skill + +You are executing the Ambient Code Platform development workflow. This skill is the literal sequence of steps performed every time code is changed — from filing a ticket to verifying a deployment. + +> **Self-improving skill.** Whenever you discover something that doesn't work, or discover something that does, **update this file immediately** before moving on. The next invocation of this skill benefits from every correction. Examples of self-improvement triggers: +> - A build command fails and you find the right flags → add them here +> - A test requires an env var you didn't know about → add it here +> - A path you tried is a dead end → document the dead end and the correct path +> - A review comment reveals a missing step → add the step here + +--- + +## Turn Counter + +**Remind the human every 10 turns to re-read this skill.** Context compaction can lose workflow state. At turns 10, 20, 30, etc., say: + +> "Reminder: we are on turn N. Re-reading `.claude/skills/devflow/SKILL.md` to refresh workflow state." + +Then re-read this file before continuing. + +--- + +## Workflow Overview + +``` +1. Ticket (optional) +2. Branch (from ticket name if available) +3. Spec change (load + modify the component's .spec.md) +4. Commit spec → push → PR against `alpha` +5. Review (agentic: thorough PR review; human: desired but optional) +6. On spec acceptance → load the component's .guide.md (the implementation workflow) +7. Branch (from ticket name if available) +8. Commit order: + a. Guide/skill/workflow self-improvement changes (1 commit) + b. Code changes grouped by component +9. Push → PR against `alpha` +10. Review (human + bot comments; local review too) +11. On merge → await quay.io image +12. Update gitops repository with new image SHA (Skill TBD) +13. After deployment → run tests / e2e suite (TBD) +``` + +--- + +## Phase 1: Ticket & Branch + +### 1a. File a Ticket (optional) + +If there is a Jira or GitHub issue, note the ticket ID. If not, proceed without one. + +### 1b. Create a Branch + +```bash +# With ticket +git checkout -b / + +# Without ticket +git checkout -b / +# type: feat, fix, refactor, docs, chore +``` + +--- + +## Phase 2: Spec Change + +### 2a. Load the Spec + +Every component has a spec file. Load the spec for the component being changed: + +| Component | Spec | Guide | +|-----------|------|-------| +| Data Model / API / CLI / RBAC | `docs/internal/design/ambient-model.spec.md` | `docs/internal/design/ambient-model.guide.md` | + +### 2b. Modify the Spec + +Edit the spec to reflect the desired change. The spec is the source of truth — code is reconciled against it. + +### 2c. Commit Spec Change + +```bash +git add docs/internal/design/ +git commit -m "spec(): " +``` + +### 2d. Push and Create PR + +```bash +git push origin -u +gh pr create --base alpha --title "spec(): " --body "Spec change for review." +``` + +- **Agentic workflow:** thorough review occurs in the PR. Feedback is incorporated. On approval/merge, the spec change becomes requirements. +- **Human workflow:** review is desired but spec commit doesn't need to be merged before code work begins. + +--- + +## Phase 3: Implementation + +### 3a. Load the Guide + +After spec acceptance (or in parallel for human workflow), load the implementation guide for the component: + +| Component | Guide | Context | +|-----------|-------|---------| +| Data Model / API | `docs/internal/design/ambient-model.guide.md` | `.claude/context/api-server-development.md` | +| SDK | (guide section in ambient-model.guide.md Wave 3) | `.claude/context/sdk-development.md` | +| CLI | (guide section Wave 5) | `.claude/context/cli-development.md` | +| Control Plane | (guide section Wave 4) | `.claude/context/control-plane-development.md` | +| Operator | (guide section Wave 5) | `.claude/context/operator-development.md` | +| Frontend | (guide section Wave 6) | `.claude/context/frontend-development.md` | +| Backend (V1) | — | `.claude/context/backend-development.md` | + +### 3b. Create Implementation Branch + +```bash +# If separate from spec branch +git checkout -b /-impl + +# Or continue on the same branch (human workflow, spec not yet merged) +``` + +### 3c. Commit Order + +Commits are ordered deliberately: + +1. **Self-improvement commit (first).** Any changes to guides, skills, workflows, or this devflow skill. Group all such changes into one commit: + ```bash + git add .claude/skills/ .claude/context/ docs/internal/design/*.guide.md + git commit -m "chore(skills): self-improvement updates from " + ``` + - Agentic workflow: this is the first commit on the branch. + - Human workflow: this is the second commit (behind the spec change), or first if spec is on a separate branch. + +2. **Code changes, grouped by component:** + ```bash + git add components/ambient-api-server/ + git commit -m "feat(api-server): " + + git add components/ambient-cli/ + git commit -m "feat(cli): " + + git add components/ambient-sdk/ + git commit -m "feat(sdk): " + ``` + +### 3d. Push and Create PR + +```bash +git push origin -u + +# Agentic: new PR against alpha +gh pr create --base alpha --title "feat(): " --body "Implementation of ." + +# Human: push adds to existing PR, or create new PR +``` + +--- + +## Phase 4: Review + +- Human and bot comments on the PR. +- Conduct local reviews as well. +- Incorporate feedback → push additional commits. + +--- + +## Phase 5: Post-Merge Deployment + +### 5a. Await Image Build + +After merge to `alpha`, images are built and pushed to `quay.io/ambient_code/`. Watch for the image: + +```bash +# Check if image exists for a given SHA +skopeo inspect docker://quay.io/ambient_code/vteam_api_server: +``` + +### 5b. Update GitOps Repository + +> **Skill TBD.** This step will be formalized as experience accumulates. + +Get the image SHA from quay.io and update the gitops repository's image references. Due to lack of autodeploy, this is a manual step. + +### 5c. Verify Deployment + +After deployment, run all available tests. E2E test suite TBD. + +--- + +## Component Build & Test Quick Reference + +### API Server (`components/ambient-api-server/`) + +```bash +cd components/ambient-api-server + +# CRITICAL: podman, not docker. And RYUK must be disabled. +systemctl --user start podman.socket +export DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock +export TESTCONTAINERS_RYUK_DISABLED=true + +make generate # after openapi changes +make proto # after .proto changes +make binary # compile +make test # integration tests (testcontainer Postgres) +go fmt ./... +go vet ./... +golangci-lint run +``` + +### CLI (`components/ambient-cli/`) + +```bash +cd components/ambient-cli +go build ./... +go fmt ./... +go vet ./... +golangci-lint run +``` + +### SDK (`components/ambient-sdk/`) + +```bash +cd components/ambient-sdk +make generate # regenerate from openapi +cd go-sdk && go build ./... +``` + +### Frontend (`components/frontend/`) + +```bash +cd components/frontend +npm run build # must pass with 0 errors, 0 warnings +npx vitest run --coverage +``` + +### Runner (`components/runners/ambient-runner/`) + +```bash +cd components/runners/ambient-runner +uv venv && uv pip install -e . +python -m pytest tests/ +``` + +### Control Plane (`components/ambient-control-plane/`) + +```bash +cd components/ambient-control-plane +go build ./... +go fmt ./... +go vet ./... +golangci-lint run +``` + +--- + +## Known Pitfalls (Self-Improving Section) + +This section is the most important part of the skill. Every dead end, every wasted cycle, every "oh, you need to do X first" gets recorded here. + +### API Server Tests Require Podman + RYUK Disabled + +**Dead end:** Running `make test` with Docker or without `TESTCONTAINERS_RYUK_DISABLED=true`. +**What happens:** Ryuk container tries to connect to `/var/run/docker.sock`, which doesn't exist on this system. Tests abort before running. +**Correct path:** +```bash +systemctl --user start podman.socket +export DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock +export TESTCONTAINERS_RYUK_DISABLED=true +make test +``` + +### Kind Image Loading with Podman + +**Dead end:** `kind load docker-image` fails with podman `localhost/` prefix images. +**Correct path:** Use `podman save | ctr import`: +```bash +CLUSTER=$(podman ps --format '{{.Names}}' | grep 'kind' | grep 'control-plane' | sed 's/-control-plane//') +podman build --no-cache -t localhost/vteam_api_server:latest components/ambient-api-server +podman save localhost/vteam_api_server:latest | \ + podman exec -i ${CLUSTER}-control-plane ctr --namespace=k8s.io images import - +kubectl rollout restart deployment/ambient-api-server -n ambient-code +``` + +### `--no-cache` Required for Podman Builds + +**Dead end:** Building without `--no-cache` when only Go source changed (go.mod/go.sum unchanged). +**What happens:** The `go build` layer hits cache and emits the old binary. +**Correct path:** Always `podman build --no-cache` for Go components. + +### Generated Code Middleware Import + +**Dead end:** Using generated plugin code as-is. +**What happens:** Generated `RegisterRoutes` uses `auth.JWTMiddleware` — wrong. +**Correct path:** Replace with `environments.JWTMiddleware` after every generation. + +### Nested Route mux.Vars Keys + +**Dead end:** Using generated handler code for nested routes without fixing variable names. +**What happens:** `mux.Vars(r)["id"]` returns empty string because the route uses `{pa_id}` or `{msg_id}`. +**Correct path:** Fix `mux.Vars` keys to match actual route variable names after generation. + +### Go SDK Streaming Endpoints + +**Dead end:** Trying to use `do()` or `doMultiStatus()` for SSE endpoints. +**What happens:** These methods unmarshal and close the response body. +**Correct path:** Use `a.client.httpClient.Do(req)` directly and return `resp.Body` as `io.ReadCloser`. + +### CLI Dependencies + +**Dead end:** Adding a new import to CLI code without running `go build` immediately. +**What happens:** `missing go.sum entry` at commit time. +**Correct path:** Run `go build ./...` after adding any new import. Fix `go.mod` before committing. + +### gRPC Port Conflict + +**Dead end:** Assuming port 9000 is available locally. +**What happens:** MinIO or another service occupies 9000. gRPC streaming fails silently. +**Correct path:** +```bash +kubectl port-forward svc/ambient-api-server 19000:9000 -n ambient-code & +export AMBIENT_GRPC_URL=127.0.0.1:19000 +``` + +### Pre-commit Hooks + +The project uses pre-commit hooks (`.pre-commit-config.yaml`). If hooks block a commit: +```bash +git commit --no-verify # skip pre-commit hooks (use sparingly) +``` +But prefer fixing the lint/format issue instead. + +--- + +## Related Skills & Context + +| Skill/Context | When to use | +|---------------|-------------| +| `.claude/skills/ambient-api-server/SKILL.md` | Working in `components/ambient-api-server/` | +| `.claude/skills/dev-cluster/SKILL.md` | Managing kind clusters for testing | +| `.claude/skills/grpc-dev/SKILL.md` | gRPC streaming, AG-UI events | +| `.claude/skills/ambient-pr-test/SKILL.md` | PR validation on MPP dev cluster | +| `.claude/context/api-server-development.md` | API server plugin architecture, OpenAPI, testing | +| `.claude/context/cli-development.md` | CLI command patterns | +| `.claude/context/sdk-development.md` | SDK generation | +| `.claude/context/control-plane-development.md` | CP fan-out, runner contract | +| `.claude/context/frontend-development.md` | Frontend build, React Query | +| `docs/internal/design/ambient-model.spec.md` | Data model spec (source of truth) | +| `docs/internal/design/ambient-model.guide.md` | Implementation guide (wave-based workflow) | + +--- + +## Self-Improvement Log + +Record every correction here with a date stamp. This section grows over time. + +### 2026-04-10 — Initial creation + +- Established devflow skill from user requirements. +- Seeded Known Pitfalls from existing context files and guide lessons learned. +- Documented TESTCONTAINERS_RYUK_DISABLED requirement (discovered in api-server-development.md). +- Documented podman `--no-cache` and `ctr import` workarounds (discovered in ambient-model.guide.md). +- Documented gRPC port 19000 workaround (discovered in ambient-model.guide.md). +- GitOps deployment step marked as TBD — will be formalized as the workflow runs. +- E2E test suite marked as TBD. From 4830f3c864b6b198cfcd851585c2f7efca66ab75 Mon Sep 17 00:00:00 2001 From: Ambient Code Bot Date: Fri, 10 Apr 2026 20:09:34 -0400 Subject: [PATCH 3/9] spec(credentials): project-scoped credentials, simplified RBAC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Credentials are now project-scoped (like K8s Secrets in Namespaces). Removed credential RBAC scope; CRUD nested under /projects/{id}/credentials. Simplified credential roles to credential:token-reader only. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- docs/internal/design/ambient-model.spec.md | 138 ++++++++++----------- 1 file changed, 63 insertions(+), 75 deletions(-) diff --git a/docs/internal/design/ambient-model.spec.md b/docs/internal/design/ambient-model.spec.md index f5b4206c0..b01186fae 100644 --- a/docs/internal/design/ambient-model.spec.md +++ b/docs/internal/design/ambient-model.spec.md @@ -2,7 +2,7 @@ **Date:** 2026-03-20 **Status:** Proposed — Pending Consensus -**Last Updated:** 2026-03-31 — added Credential Kind; extended RoleBinding.scope with `credential`; new credential roles and API endpoints +**Last Updated:** 2026-04-10 — credentials are now project-scoped; removed `credential` RBAC scope; credential CRUD nested under projects; simplified credential roles to `credential:token-reader` only **Guide:** `ambient-model.guide.md` — implementation waves, gap table, build commands, run log **Design:** `credentials-session.md` — full Credential Kind design spec and rationale @@ -17,8 +17,8 @@ The Ambient API server provides a coordination layer for orchestrating fleets of - **Session** — an ephemeral Kubernetes execution run, created exclusively via agent start. Only one active Session per Agent at a time. - **Message** — a single AG-UI event in the LLM conversation. Append-only; the canonical record of what happened in a session. - **Inbox** — a persistent message queue on an Agent. Messages survive across sessions and are drained into the start context at the next run. -- **Credential** — a platform-scoped, RBAC-owned secret. Stores a Personal Access Token or equivalent for an external provider (GitHub, GitLab, Jira, Google). Consumed by runners at session start. -- **RoleBinding** — binds a Resource to a Role at a given scope (`global`, `project`, `agent`, `session`, `credential`). Ownership and access for all Kinds is expressed through RoleBindings. +- **Credential** — a project-scoped secret. Stores a Personal Access Token or equivalent for an external provider (GitHub, GitLab, Jira, Google). Consumed by runners at session start. All agents in the project share the project's credentials automatically. +- **RoleBinding** — binds a Resource to a Role at a given scope (`global`, `project`, `agent`, `session`). Ownership and access for all Kinds is expressed through RoleBindings. The stable address of an agent is `{project_name}/{agent_name}`. It holds the inbox and links to the active session. @@ -148,18 +148,19 @@ erDiagram string ID PK string user_id FK string role_id FK - string scope "global | project | agent | session | credential" + string scope "global | project | agent | session" string scope_id "empty for global" time created_at time updated_at time deleted_at } - %% ── Credential (platform-scoped PAT/token store) ───────────────────────── + %% ── Credential (project-scoped PAT/token store) ────────────────────────── Credential { string ID PK "KSUID" - string name "human-readable" + string project_id FK + string name "human-readable; unique within project" string description string provider "github | gitlab | jira | google" string token "write-only; stored encrypted" @@ -176,11 +177,11 @@ erDiagram Project ||--o{ ProjectSettings : "has" Project ||--o{ Agent : "owns" + Project ||--o{ Credential : "owns" User ||--o{ RoleBinding : "bound_to" RoleBinding }o--o| Agent : "owns" - RoleBinding }o--o| Credential : "owns_or_accesses" Agent ||--o{ Session : "runs" Agent ||--o| Session : "current_session" @@ -319,18 +320,17 @@ The `acpctl` CLI mirrors the API 1-for-1. Every REST operation has a correspondi | `POST /sessions/{id}/messages` + `GET /sessions/{id}/events` | `acpctl session send -f --json` | ✅ implemented | | `GET /sessions/{id}/events` | `acpctl session events ` | ✅ implemented | -#### Credentials +#### Credentials (Project-Scoped) | REST API | `acpctl` Command | Status | |---|---|---| -| `GET /credentials` | `acpctl credential list` | 🔲 planned | -| `GET /credentials?provider={p}` | `acpctl credential list --provider

` | 🔲 planned | -| `POST /credentials` | `acpctl credential create --name --provider

--token [--url ] [--email ] [--description ]` | 🔲 planned | -| `GET /credentials/{id}` | `acpctl credential get ` | 🔲 planned | -| `PATCH /credentials/{id}` | `acpctl credential update [--token ] [--description ]` | 🔲 planned | -| `DELETE /credentials/{id}` | `acpctl credential delete --confirm` | 🔲 planned | -| `GET /credentials/{id}/role_bindings` | _(not yet exposed)_ | 🔲 planned | -| `GET /credentials/{id}/token` | `acpctl credential token ` | 🔲 planned | +| `GET /projects/{id}/credentials` | `acpctl credential list` | 🔲 planned | +| `GET /projects/{id}/credentials?provider={p}` | `acpctl credential list --provider

` | 🔲 planned | +| `POST /projects/{id}/credentials` | `acpctl credential create --name --provider

--token [--url ] [--email ] [--description ]` | 🔲 planned | +| `GET /projects/{id}/credentials/{cred_id}` | `acpctl credential get ` | 🔲 planned | +| `PATCH /projects/{id}/credentials/{cred_id}` | `acpctl credential update [--token ] [--description ]` | 🔲 planned | +| `DELETE /projects/{id}/credentials/{cred_id}` | `acpctl credential delete --confirm` | 🔲 planned | +| `GET /projects/{id}/credentials/{cred_id}/token` | `acpctl credential token ` | 🔲 planned | #### RBAC @@ -362,7 +362,7 @@ The `acpctl` CLI mirrors the API 1-for-1. Every REST operation has a correspondi |---|---| | `Project` | `name`, `description`, `prompt`, `labels`, `annotations` | | `Agent` | `name`, `prompt`, `labels`, `annotations`, `inbox` (seed messages) | -| `Credential` | `name`, `description`, `provider`, `token` (env var reference), `url`, `email`, `labels`, `annotations` | +| `Credential` | `name`, `description`, `provider`, `token` (env var reference), `url`, `email`, `labels`, `annotations` — created in current project context | `Agent` resources in `.ambient/teams/` files also carry an `inbox` list of seed messages. On apply, any message in the list is posted to the agent's inbox if an identical message (same `from_name` + `body`) does not already exist there. @@ -569,22 +569,21 @@ GET /api/ambient/v1/sessions/{id}/events SSE AG-UI event str GET /api/ambient/v1/sessions/{id}/role_bindings RBAC bindings ``` -### Credentials +### Credentials (Project-Scoped) ``` -GET /api/ambient/v1/credentials list credentials visible to the caller -GET /api/ambient/v1/credentials?provider={provider} filter by provider -POST /api/ambient/v1/credentials create a credential -GET /api/ambient/v1/credentials/{id} read credential (metadata only; token never returned) -PATCH /api/ambient/v1/credentials/{id} update credential -DELETE /api/ambient/v1/credentials/{id} soft delete -GET /api/ambient/v1/credentials/{id}/role_bindings RBAC bindings on this credential -GET /api/ambient/v1/credentials/{id}/token fetch raw token — restricted to credential:token-reader +GET /api/ambient/v1/projects/{id}/credentials list credentials in this project +GET /api/ambient/v1/projects/{id}/credentials?provider={provider} filter by provider +POST /api/ambient/v1/projects/{id}/credentials create a credential +GET /api/ambient/v1/projects/{id}/credentials/{cred_id} read credential (metadata only; token never returned) +PATCH /api/ambient/v1/projects/{id}/credentials/{cred_id} update credential +DELETE /api/ambient/v1/projects/{id}/credentials/{cred_id} soft delete +GET /api/ambient/v1/projects/{id}/credentials/{cred_id}/token fetch raw token — restricted to credential:token-reader ``` `token` is accepted on `POST` and `PATCH` but **never returned** by the standard read endpoints. It is stored encrypted in the database. The database row is the authoritative store; a future Vault integration can be adopted by pointing the row at a Vault path without changing the API surface. -`GET /credentials/{id}/token` is the **only** endpoint that returns the raw token. It is gated by the `credential:token-reader` role — a distinct role not implied by `credential:reader`. Runners are granted `credential:token-reader` by the platform at session start. Human users and service accounts do not hold this role by default. +`GET /projects/{id}/credentials/{cred_id}/token` is the **only** endpoint that returns the raw token. It is gated by the `credential:token-reader` role — a platform-internal role granted only to runner service accounts at session start. Human users and service accounts do not hold this role by default. Credential CRUD is governed by the caller's project-level role (e.g. `project:owner`, `project:editor`). #### Provider Enum @@ -617,33 +616,29 @@ When a runner fetches a credential, the response payload shape is consistent acr | Scope | Meaning | |---|---| | `global` | Applies across the entire platform | -| `project` | Applies to all Agents and sessions in a project | +| `project` | Applies to all resources in a project (Agents, Sessions, Credentials) | | `agent` | Applies to one Agent and all its sessions | | `session` | Applies to one session run only | -| `credential` | Applies to one Credential resource | -Effective permissions = union of all applicable bindings (global ∪ project ∪ agent ∪ session ∪ credential). No deny rules. +Effective permissions = union of all applicable bindings (global ∪ project ∪ agent ∪ session). No deny rules. -For Credential resolution at session start, the resolver walks agent → project → global and returns the most specific matching credential for the requested provider. A narrower scope always wins. +#### Credential Access — Project-Scoped by Default -#### Credential Scope — Access Granularity +Credentials belong to a project. All agents in the project share the project's credentials automatically — no explicit sharing or per-credential RoleBindings needed. At session start, the resolver lists all credentials in the agent's project and returns the matching credential for each requested provider. -A credential is a platform-level resource. What determines who and what can use it is entirely the RoleBinding scope. The same credential can be shared at any granularity: +This follows the Kubernetes resource model: -| RoleBinding scope | scope_id | Effect | -|-------------------|----------|--------| -| `credential` | `credential_id` | Ownership or explicit per-credential grant. Auto-created as `credential:owner` at creation. | -| `agent` | `agent_id` | Only one specific agent (and its sessions) can use this credential. | -| `project` | `project_id` | All agents in a project share this credential automatically. | -| `global` | _(empty)_ | Platform-wide fallback; every session resolves this credential when no narrower binding exists. | +| Ambient | Kubernetes Analogy | Relationship | +|---------|-------------------|-------------| +| Project | Namespace | Isolation boundary, owns child resources | +| Agent | Deployment | Mutable definition, runs workloads | +| Session | Pod | Ephemeral execution, created from Agent | +| Credential | Secret | Project-scoped secret, available to all workloads in the namespace | Named patterns: -- **Personal PAT** — user creates credential; `credential:owner` binding is private to them. -- **Project Robot Account** — shared credential with a `project`-scoped `credential:reader` binding; all agents in the project use it. -- **Agent-specific identity** — `agent`-scoped binding; one agent runs as a specific identity without exposing it to siblings. -- **Platform-wide credential** — `global`-scoped binding; acts as the org-wide fallback for any session on the platform. - -Users may hold many credentials and share them across many projects. RBAC expresses sharing; there is no hardcoded ownership field. +- **Project Robot Account** — credential created in a project; all agents use it automatically. +- **Multi-project credential** — create the same credential (same PAT) in multiple projects. Each project gets its own Credential record. +- **No credential** — projects without credentials simply run sessions without provider integrations. ### Built-in Roles @@ -658,26 +653,22 @@ Users may hold many credentials and share them across many projects. RBAC expres | `agent:editor` | Update prompt and metadata on a specific Agent | | `agent:observer` | Read a specific Agent and its sessions | | `agent:runner` | Minimum viable pod credential: read agent, push messages, send inbox | -| `credential:owner` | Full control of a Credential: update token, delete, manage bindings. Auto-granted at creation. | -| `credential:reader` | Read credential metadata (name, provider, url, email). Token value is never included. | -| `credential:token-reader` | Fetch the raw token via `GET /credentials/{id}/token`. Granted only to runner service accounts. Human users do not hold this role. | +| `credential:token-reader` | Fetch the raw token via `GET /projects/{id}/credentials/{cred_id}/token`. Granted only to runner service accounts at session start. Human users do not hold this role. | ### Permission Matrix -| Role | Projects | Agents | Sessions | Inbox | Home | RBAC | -|---|---|---|---|---|---|---| -| `platform:admin` | full | full | full | full | full | full | -| `platform:viewer` | read/list | read/list | read/list | — | read | read/list | -| `project:owner` | full | full | full | full | read | project+agent bindings | -| `project:editor` | read | create/update/ignite | read/list | send/read | read | — | -| `project:viewer` | read | read/list | read/list | — | read | — | -| `agent:operator` | — | update/ignite | read/list | send/read | — | — | -| `agent:editor` | — | update | — | — | — | — | -| `agent:observer` | — | read | read/list | — | — | — | -| `agent:runner` | — | read | read | send | — | — | -| `credential:owner` | — | — | — | — | — | manage bindings | metadata: full | token: — | -| `credential:reader` | — | — | — | — | — | — | metadata: read | token: — | -| `credential:token-reader` | — | — | — | — | — | — | metadata: — | token: read | +| Role | Projects | Agents | Sessions | Inbox | Credentials | Home | RBAC | +|---|---|---|---|---|---|---|---| +| `platform:admin` | full | full | full | full | full | full | full | +| `platform:viewer` | read/list | read/list | read/list | — | read/list | read | read/list | +| `project:owner` | full | full | full | full | full | read | project+agent bindings | +| `project:editor` | read | create/update/ignite | read/list | send/read | create/update/delete | read | — | +| `project:viewer` | read | read/list | read/list | — | read/list | read | — | +| `agent:operator` | — | update/ignite | read/list | send/read | — | — | — | +| `agent:editor` | — | update | — | — | — | — | — | +| `agent:observer` | — | read | read/list | — | — | — | — | +| `agent:runner` | — | read | read | send | — | — | — | +| `credential:token-reader` | — | — | — | — | token: read | — | — | ### RBAC Endpoints @@ -696,10 +687,9 @@ GET /api/ambient/v1/users/{id}/role_bindings GET /api/ambient/v1/projects/{id}/role_bindings GET /api/ambient/v1/projects/{id}/agents/{agent_id}/role_bindings GET /api/ambient/v1/sessions/{id}/role_bindings -GET /api/ambient/v1/credentials/{id}/role_bindings ``` -The `credential:token-reader` role is granted to the runner service account by the platform at session start. It is never granted via user-facing `POST /role_bindings`. It is a platform-internal binding managed by the operator. +The `credential:token-reader` role is granted to the runner service account by the platform at session start. It is never granted via user-facing `POST /role_bindings`. It is a platform-internal binding managed by the operator. Credential CRUD is governed by the caller's project-level role — `project:owner` and `project:editor` can create/update/delete credentials; `project:viewer` can list/read metadata. ``` ``` @@ -840,10 +830,10 @@ This structure means you can define and compose bespoke agent suites — entire | Agent is project-scoped, not global | Simplicity. An agent's identity and prompt are contextual to the project it serves. No indirection via a global registry. | | Agent.prompt is mutable | Prompt editing is a routine operational task. RBAC controls who can change it. No versioning overhead. | | Agent ownership via RBAC, not a hardcoded FK | Ownership is expressed as a RoleBinding (`scope=agent`, `scope_id=agent_id`). Enables multi-owner and delegated ownership consistently across all Kinds. | -| Credential ownership via RBAC, same pattern | `RoleBinding(scope=credential, scope_id=credential_id, role=credential:owner)` auto-created at credential creation. Enables shared Robot Accounts and team-wide PATs without schema changes. | -| Credential is platform-scoped, not project-scoped | Credentials (especially Robot Accounts) are shared across teams and projects. Nesting under a project would force duplication. | +| Credential is project-scoped, like a Kubernetes Secret | Credentials live inside a project. All agents in the project share them automatically. Duplication across projects is intentional and explicit — each project gets its own Credential record, same as Kubernetes Secrets in different Namespaces. | | Credential token is write-only | Prevents token exfiltration via the standard REST API. Raw token only surfaced to runners via the runtime credentials path, not to end users. | -| Five-scope RBAC (`global`, `project`, `agent`, `session`, `credential`) | `credential` scope enables per-credential access grants; combined with project/global scope it allows Robot Accounts shared at any granularity. | +| Four-scope RBAC (`global`, `project`, `agent`, `session`) | Credential access is implicit via project membership — no dedicated `credential` scope needed. Simpler model with fewer moving parts. | +| Credential CRUD governed by project roles | `project:owner` and `project:editor` can manage credentials. No separate `credential:owner` / `credential:reader` roles — project roles cover it. | | One active Session per Agent | Avoids concurrent conflicting runs; start is idempotent | | Inbox on Agent, not Session | Messages persist across re-ignitions; addressed to the agent, not the run | | Inbox drained at start | Unread messages become part of the start context; session picks up where things left off | @@ -880,10 +870,6 @@ acpctl credential list # Rotate a token acpctl credential update my-gitlab-pat --token "$GITLAB_PAT_NEW" -# Share a Robot Account with an entire project -acpctl create role-binding --user-id alice@myco.com --role-id credential:reader \ - --scope project --scope-id my-project - # Declarative apply — token sourced from env var ``` @@ -900,8 +886,9 @@ spec: ``` ```sh +acpctl project my-project acpctl apply -f credential.yaml -# credential/platform-gitlab-pat created +# credential/platform-gitlab-pat created (in project my-project) ``` --- @@ -910,12 +897,13 @@ acpctl apply -f credential.yaml | Decision | Rationale | |----------|-----------| +| Credential is project-scoped | Follows the Kubernetes Secret-in-Namespace pattern. All agents in the project share credentials implicitly. No RoleBindings needed for sharing within a project. | | Token stored in database, encrypted at rest | Single authoritative store. A future Vault integration can be adopted by pointing the DB row at a Vault path without changing the API surface. | | `google` token serialized as a string | Service Account JSON is serialized into the single `token` field. Keeps the schema uniform across all providers. | | No validation on creation | First-use error is acceptable. Avoids a network call to the provider at creation time and the failure modes that come with it. | | Credential rotation is user-managed | Users update the token via `PATCH` or `acpctl credential update`. No platform-side rotation or expiry tracking. | | No migration utility for existing K8s Secrets | Users re-enter credentials via the new API. The old Secret-based path is removed when the new API is live. | -| Users may hold many credentials, share across many projects | RBAC expresses sharing. No limit on how many credentials a user holds or how many projects a credential is shared to. | +| Dedicated tokens, not personal credentials | Users are expected to create dedicated Robot Accounts or PATs for each project, not share their personal credentials. Each project gets its own Credential records. | --- @@ -940,8 +928,8 @@ _Last updated: 2026-03-22. Use this as the authoritative index — click into co | **Projects — labels/annotations** | ✅ PATCH accepts `labels`/`annotations` | ✅ fields on `Project` type; `ProjectAPI.Update(patch map[string]any)` | ⚠️ no dedicated subcommand | | | **RBAC — roles** | ✅ | ✅ `RoleAPI` | ✅ `create role` only; list/get not exposed | | | **RBAC — role bindings** | ✅ | ✅ `RoleBindingAPI` | ✅ `create role-binding` only; list/delete not exposed | | -| **Credentials — CRUD** | 🔲 | 🔲 | 🔲 `credential list/get/create/update/delete` | New Kind; not yet implemented | -| **Credentials — token fetch (runner)** | 🔲 `GET /credentials/{id}/token` | 🔲 | n/a | Gated by `credential:token-reader`; granted to runner SA by operator | +| **Credentials — CRUD** | 🔲 | 🔲 | 🔲 `credential list/get/create/update/delete` | Project-scoped; not yet implemented | +| **Credentials — token fetch (runner)** | 🔲 `GET /projects/{id}/credentials/{cred_id}/token` | 🔲 | n/a | Gated by `credential:token-reader`; granted to runner SA by operator | | **Declarative apply** | n/a | uses SDK | ✅ `apply -f`, `apply -k` | Upsert semantics; supports inbox seeding | | **Declarative apply — Credential kind** | n/a | 🔲 | 🔲 | Planned; token sourced from env var in YAML | From d1dda9e6eadb090d117d106d2353039c00e26efd Mon Sep 17 00:00:00 2001 From: Ambient Code Bot Date: Fri, 10 Apr 2026 20:12:25 -0400 Subject: [PATCH 4/9] feat(api-server): project-scoped credential CRUD and token endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenAPI, generated client, plugin handlers, migration, and presenter updated for /projects/{id}/credentials nesting with project_id field. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../openapi/openapi.credentials.yaml | 31 +- .../ambient-api-server/openapi/openapi.yaml | 12 +- .../pkg/api/openapi/README.md | 12 +- .../pkg/api/openapi/api/openapi.yaml | 75 +- .../pkg/api/openapi/api_default.go | 1754 +++++++++-------- .../pkg/api/openapi/docs/Credential.md | 23 +- .../pkg/api/openapi/docs/DefaultAPI.md | 630 +++--- .../pkg/api/openapi/model_credential.go | 47 +- .../plugins/credentials/factory_test.go | 1 + .../plugins/credentials/handler.go | 19 +- .../plugins/credentials/integration_test.go | 37 +- .../plugins/credentials/migration.go | 24 + .../plugins/credentials/model.go | 1 + .../plugins/credentials/plugin.go | 16 +- .../plugins/credentials/presenter.go | 4 +- 15 files changed, 1448 insertions(+), 1238 deletions(-) diff --git a/components/ambient-api-server/openapi/openapi.credentials.yaml b/components/ambient-api-server/openapi/openapi.credentials.yaml index a98b1220d..71c896b68 100644 --- a/components/ambient-api-server/openapi/openapi.credentials.yaml +++ b/components/ambient-api-server/openapi/openapi.credentials.yaml @@ -1,9 +1,9 @@ paths: # NEW ENDPOINT START - /api/ambient/v1/credentials: + /api/ambient/v1/projects/{id}/credentials: # NEW ENDPOINT END get: - summary: Returns a list of credentials + summary: Returns a list of credentials in a project security: - Bearer: [] responses: @@ -45,7 +45,7 @@ paths: type: string enum: [github, gitlab, jira, google] post: - summary: Create a new credential + summary: Create a new credential in a project security: - Bearer: [] requestBody: @@ -92,11 +92,13 @@ paths: application/json: schema: $ref: 'openapi.yaml#/components/schemas/Error' + parameters: + - $ref: '#/components/parameters/id' # NEW ENDPOINT START - /api/ambient/v1/credentials/{id}: + /api/ambient/v1/projects/{id}/credentials/{cred_id}: # NEW ENDPOINT END get: - summary: Get an credential by id + summary: Get a credential by id security: - Bearer: [] responses: @@ -131,7 +133,7 @@ paths: schema: $ref: 'openapi.yaml#/components/schemas/Error' patch: - summary: Update an credential + summary: Update a credential security: - Bearer: [] requestBody: @@ -217,8 +219,9 @@ paths: $ref: 'openapi.yaml#/components/schemas/Error' parameters: - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/cred_id' # NEW ENDPOINT START - /api/ambient/v1/credentials/{id}/token: + /api/ambient/v1/projects/{id}/credentials/{cred_id}/token: # NEW ENDPOINT END get: summary: Get a decrypted token for a credential @@ -258,6 +261,7 @@ paths: $ref: 'openapi.yaml#/components/schemas/Error' parameters: - $ref: '#/components/parameters/id' + - $ref: '#/components/parameters/cred_id' components: schemas: # NEW SCHEMA START @@ -269,7 +273,11 @@ components: required: - name - provider + - project_id properties: + project_id: + type: string + description: ID of the project this credential belongs to name: type: string description: @@ -347,7 +355,14 @@ components: id: name: id in: path - description: The id of record + description: The id of the project + required: true + schema: + type: string + cred_id: + name: cred_id + in: path + description: The id of the credential required: true schema: type: string diff --git a/components/ambient-api-server/openapi/openapi.yaml b/components/ambient-api-server/openapi/openapi.yaml index 79a77734e..41922e738 100644 --- a/components/ambient-api-server/openapi/openapi.yaml +++ b/components/ambient-api-server/openapi/openapi.yaml @@ -64,12 +64,12 @@ paths: $ref: 'openapi.inbox.yaml#/paths/~1api~1ambient~1v1~1projects~1{id}~1agents~1{agent_id}~1inbox' /api/ambient/v1/projects/{id}/agents/{agent_id}/inbox/{msg_id}: $ref: 'openapi.inbox.yaml#/paths/~1api~1ambient~1v1~1projects~1{id}~1agents~1{agent_id}~1inbox~1{msg_id}' - /api/ambient/v1/credentials: - $ref: 'openapi.credentials.yaml#/paths/~1api~1ambient~1v1~1credentials' - /api/ambient/v1/credentials/{id}: - $ref: 'openapi.credentials.yaml#/paths/~1api~1ambient~1v1~1credentials~1{id}' - /api/ambient/v1/credentials/{id}/token: - $ref: 'openapi.credentials.yaml#/paths/~1api~1ambient~1v1~1credentials~1{id}~1token' + /api/ambient/v1/projects/{id}/credentials: + $ref: 'openapi.credentials.yaml#/paths/~1api~1ambient~1v1~1projects~1{id}~1credentials' + /api/ambient/v1/projects/{id}/credentials/{cred_id}: + $ref: 'openapi.credentials.yaml#/paths/~1api~1ambient~1v1~1projects~1{id}~1credentials~1{cred_id}' + /api/ambient/v1/projects/{id}/credentials/{cred_id}/token: + $ref: 'openapi.credentials.yaml#/paths/~1api~1ambient~1v1~1projects~1{id}~1credentials~1{cred_id}~1token' # AUTO-ADD NEW PATHS components: securitySchemes: diff --git a/components/ambient-api-server/pkg/api/openapi/README.md b/components/ambient-api-server/pkg/api/openapi/README.md index 0cbfb2752..9ec2643b1 100644 --- a/components/ambient-api-server/pkg/api/openapi/README.md +++ b/components/ambient-api-server/pkg/api/openapi/README.md @@ -78,12 +78,6 @@ All URIs are relative to *http://localhost:8000* Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- -*DefaultAPI* | [**ApiAmbientV1CredentialsGet**](docs/DefaultAPI.md#apiambientv1credentialsget) | **Get** /api/ambient/v1/credentials | Returns a list of credentials -*DefaultAPI* | [**ApiAmbientV1CredentialsIdDelete**](docs/DefaultAPI.md#apiambientv1credentialsiddelete) | **Delete** /api/ambient/v1/credentials/{id} | Delete a credential -*DefaultAPI* | [**ApiAmbientV1CredentialsIdGet**](docs/DefaultAPI.md#apiambientv1credentialsidget) | **Get** /api/ambient/v1/credentials/{id} | Get an credential by id -*DefaultAPI* | [**ApiAmbientV1CredentialsIdPatch**](docs/DefaultAPI.md#apiambientv1credentialsidpatch) | **Patch** /api/ambient/v1/credentials/{id} | Update an credential -*DefaultAPI* | [**ApiAmbientV1CredentialsIdTokenGet**](docs/DefaultAPI.md#apiambientv1credentialsidtokenget) | **Get** /api/ambient/v1/credentials/{id}/token | Get a decrypted token for a credential -*DefaultAPI* | [**ApiAmbientV1CredentialsPost**](docs/DefaultAPI.md#apiambientv1credentialspost) | **Post** /api/ambient/v1/credentials | Create a new credential *DefaultAPI* | [**ApiAmbientV1ProjectSettingsGet**](docs/DefaultAPI.md#apiambientv1projectsettingsget) | **Get** /api/ambient/v1/project_settings | Returns a list of project settings *DefaultAPI* | [**ApiAmbientV1ProjectSettingsIdDelete**](docs/DefaultAPI.md#apiambientv1projectsettingsiddelete) | **Delete** /api/ambient/v1/project_settings/{id} | Delete a project settings by id *DefaultAPI* | [**ApiAmbientV1ProjectSettingsIdGet**](docs/DefaultAPI.md#apiambientv1projectsettingsidget) | **Get** /api/ambient/v1/project_settings/{id} | Get a project settings by id @@ -102,6 +96,12 @@ Class | Method | HTTP request | Description *DefaultAPI* | [**ApiAmbientV1ProjectsIdAgentsAgentIdStartPost**](docs/DefaultAPI.md#apiambientv1projectsidagentsagentidstartpost) | **Post** /api/ambient/v1/projects/{id}/agents/{agent_id}/start | Start an agent — creates a Session (idempotent) *DefaultAPI* | [**ApiAmbientV1ProjectsIdAgentsGet**](docs/DefaultAPI.md#apiambientv1projectsidagentsget) | **Get** /api/ambient/v1/projects/{id}/agents | Returns a list of agents in a project *DefaultAPI* | [**ApiAmbientV1ProjectsIdAgentsPost**](docs/DefaultAPI.md#apiambientv1projectsidagentspost) | **Post** /api/ambient/v1/projects/{id}/agents | Create an agent in a project +*DefaultAPI* | [**ApiAmbientV1ProjectsIdCredentialsCredIdDelete**](docs/DefaultAPI.md#apiambientv1projectsidcredentialscrediddelete) | **Delete** /api/ambient/v1/projects/{id}/credentials/{cred_id} | Delete a credential +*DefaultAPI* | [**ApiAmbientV1ProjectsIdCredentialsCredIdGet**](docs/DefaultAPI.md#apiambientv1projectsidcredentialscredidget) | **Get** /api/ambient/v1/projects/{id}/credentials/{cred_id} | Get a credential by id +*DefaultAPI* | [**ApiAmbientV1ProjectsIdCredentialsCredIdPatch**](docs/DefaultAPI.md#apiambientv1projectsidcredentialscredidpatch) | **Patch** /api/ambient/v1/projects/{id}/credentials/{cred_id} | Update a credential +*DefaultAPI* | [**ApiAmbientV1ProjectsIdCredentialsCredIdTokenGet**](docs/DefaultAPI.md#apiambientv1projectsidcredentialscredidtokenget) | **Get** /api/ambient/v1/projects/{id}/credentials/{cred_id}/token | Get a decrypted token for a credential +*DefaultAPI* | [**ApiAmbientV1ProjectsIdCredentialsGet**](docs/DefaultAPI.md#apiambientv1projectsidcredentialsget) | **Get** /api/ambient/v1/projects/{id}/credentials | Returns a list of credentials in a project +*DefaultAPI* | [**ApiAmbientV1ProjectsIdCredentialsPost**](docs/DefaultAPI.md#apiambientv1projectsidcredentialspost) | **Post** /api/ambient/v1/projects/{id}/credentials | Create a new credential in a project *DefaultAPI* | [**ApiAmbientV1ProjectsIdDelete**](docs/DefaultAPI.md#apiambientv1projectsiddelete) | **Delete** /api/ambient/v1/projects/{id} | Delete a project by id *DefaultAPI* | [**ApiAmbientV1ProjectsIdGet**](docs/DefaultAPI.md#apiambientv1projectsidget) | **Get** /api/ambient/v1/projects/{id} | Get a project by id *DefaultAPI* | [**ApiAmbientV1ProjectsIdHomeGet**](docs/DefaultAPI.md#apiambientv1projectsidhomeget) | **Get** /api/ambient/v1/projects/{id}/home | Project home — latest status for every Agent in this project diff --git a/components/ambient-api-server/pkg/api/openapi/api/openapi.yaml b/components/ambient-api-server/pkg/api/openapi/api/openapi.yaml index 7a751a589..8c7f05820 100644 --- a/components/ambient-api-server/pkg/api/openapi/api/openapi.yaml +++ b/components/ambient-api-server/pkg/api/openapi/api/openapi.yaml @@ -2208,7 +2208,7 @@ paths: security: - Bearer: [] summary: Start an agent — creates a Session (idempotent) - /api/ambient/v1/projects/{id}/agents/{agent_id}/start/preview: + /api/ambient/v1/projects/{id}/agents/{agent_id}/ignition: get: parameters: - description: The id of record @@ -2627,9 +2627,17 @@ paths: security: - Bearer: [] summary: Mark an inbox message as read - /api/ambient/v1/credentials: + /api/ambient/v1/projects/{id}/credentials: get: parameters: + - description: The id of record + explode: false + in: path + name: id + required: true + schema: + type: string + style: simple - description: Page number of record list when record list exceeds specified page size explode: true @@ -2713,8 +2721,17 @@ paths: description: Unexpected error occurred security: - Bearer: [] - summary: Returns a list of credentials + summary: Returns a list of credentials in a project post: + parameters: + - description: The id of record + explode: false + in: path + name: id + required: true + schema: + type: string + style: simple requestBody: content: application/json: @@ -2761,8 +2778,8 @@ paths: description: An unexpected error occurred creating the credential security: - Bearer: [] - summary: Create a new credential - /api/ambient/v1/credentials/{id}: + summary: Create a new credential in a project + /api/ambient/v1/projects/{id}/credentials/{cred_id}: delete: parameters: - description: The id of record @@ -2773,6 +2790,12 @@ paths: schema: type: string style: simple + - description: The id of the credential + in: path + name: cred_id + required: true + schema: + type: string responses: "204": description: Credential deleted successfully @@ -2813,6 +2836,12 @@ paths: schema: type: string style: simple + - description: The id of the credential + in: path + name: cred_id + required: true + schema: + type: string responses: "200": content: @@ -2846,7 +2875,7 @@ paths: description: Unexpected error occurred security: - Bearer: [] - summary: Get an credential by id + summary: Get a credential by id patch: parameters: - description: The id of record @@ -2857,6 +2886,12 @@ paths: schema: type: string style: simple + - description: The id of the credential + in: path + name: cred_id + required: true + schema: + type: string requestBody: content: application/json: @@ -2909,8 +2944,8 @@ paths: description: Unexpected error updating credential security: - Bearer: [] - summary: Update an credential - /api/ambient/v1/credentials/{id}/token: + summary: Update a credential + /api/ambient/v1/projects/{id}/credentials/{cred_id}/token: get: description: Returns the decrypted token value for the given credential. Requires token-reader role. @@ -2923,6 +2958,12 @@ paths: schema: type: string style: simple + - description: The id of the credential + in: path + name: cred_id + required: true + schema: + type: string responses: "200": content: @@ -3018,6 +3059,13 @@ components: schema: type: string style: form + cred_id: + description: The id of the credential + in: path + name: cred_id + required: true + schema: + type: string schemas: ObjectReference: properties: @@ -3387,8 +3435,8 @@ components: annotations: type: string prompt: - description: Workspace-level context injected into every agent start in this - project + description: Workspace-level context injected into every agent start in + this project type: string status: type: string @@ -4182,6 +4230,9 @@ components: allOf: - $ref: "#/components/schemas/ObjectReference" - properties: + project_id: + description: ID of the project this credential belongs to + type: string name: type: string description: @@ -4208,6 +4259,7 @@ components: type: string required: - name + - project_id - provider type: object example: @@ -4219,6 +4271,7 @@ components: token: token labels: labels updated_at: 2000-01-23T04:56:07.000+00:00 + project_id: project_id provider: github name: name id: id @@ -4247,6 +4300,7 @@ components: token: token labels: labels updated_at: 2000-01-23T04:56:07.000+00:00 + project_id: project_id provider: github name: name id: id @@ -4260,6 +4314,7 @@ components: token: token labels: labels updated_at: 2000-01-23T04:56:07.000+00:00 + project_id: project_id provider: github name: name id: id diff --git a/components/ambient-api-server/pkg/api/openapi/api_default.go b/components/ambient-api-server/pkg/api/openapi/api_default.go index a5a1a0092..c11979d29 100644 --- a/components/ambient-api-server/pkg/api/openapi/api_default.go +++ b/components/ambient-api-server/pkg/api/openapi/api_default.go @@ -23,7 +23,7 @@ import ( // DefaultAPIService DefaultAPI service type DefaultAPIService service -type ApiApiAmbientV1CredentialsGetRequest struct { +type ApiApiAmbientV1ProjectSettingsGetRequest struct { ctx context.Context ApiService *DefaultAPIService page *int32 @@ -31,57 +31,50 @@ type ApiApiAmbientV1CredentialsGetRequest struct { search *string orderBy *string fields *string - provider *string } // Page number of record list when record list exceeds specified page size -func (r ApiApiAmbientV1CredentialsGetRequest) Page(page int32) ApiApiAmbientV1CredentialsGetRequest { +func (r ApiApiAmbientV1ProjectSettingsGetRequest) Page(page int32) ApiApiAmbientV1ProjectSettingsGetRequest { r.page = &page return r } // Maximum number of records to return -func (r ApiApiAmbientV1CredentialsGetRequest) Size(size int32) ApiApiAmbientV1CredentialsGetRequest { +func (r ApiApiAmbientV1ProjectSettingsGetRequest) Size(size int32) ApiApiAmbientV1ProjectSettingsGetRequest { r.size = &size return r } // Specifies the search criteria -func (r ApiApiAmbientV1CredentialsGetRequest) Search(search string) ApiApiAmbientV1CredentialsGetRequest { +func (r ApiApiAmbientV1ProjectSettingsGetRequest) Search(search string) ApiApiAmbientV1ProjectSettingsGetRequest { r.search = &search return r } // Specifies the order by criteria -func (r ApiApiAmbientV1CredentialsGetRequest) OrderBy(orderBy string) ApiApiAmbientV1CredentialsGetRequest { +func (r ApiApiAmbientV1ProjectSettingsGetRequest) OrderBy(orderBy string) ApiApiAmbientV1ProjectSettingsGetRequest { r.orderBy = &orderBy return r } // Supplies a comma-separated list of fields to be returned -func (r ApiApiAmbientV1CredentialsGetRequest) Fields(fields string) ApiApiAmbientV1CredentialsGetRequest { +func (r ApiApiAmbientV1ProjectSettingsGetRequest) Fields(fields string) ApiApiAmbientV1ProjectSettingsGetRequest { r.fields = &fields return r } -// Filter credentials by provider -func (r ApiApiAmbientV1CredentialsGetRequest) Provider(provider string) ApiApiAmbientV1CredentialsGetRequest { - r.provider = &provider - return r -} - -func (r ApiApiAmbientV1CredentialsGetRequest) Execute() (*CredentialList, *http.Response, error) { - return r.ApiService.ApiAmbientV1CredentialsGetExecute(r) +func (r ApiApiAmbientV1ProjectSettingsGetRequest) Execute() (*ProjectSettingsList, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectSettingsGetExecute(r) } /* -ApiAmbientV1CredentialsGet Returns a list of credentials +ApiAmbientV1ProjectSettingsGet Returns a list of project settings @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiApiAmbientV1CredentialsGetRequest + @return ApiApiAmbientV1ProjectSettingsGetRequest */ -func (a *DefaultAPIService) ApiAmbientV1CredentialsGet(ctx context.Context) ApiApiAmbientV1CredentialsGetRequest { - return ApiApiAmbientV1CredentialsGetRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsGet(ctx context.Context) ApiApiAmbientV1ProjectSettingsGetRequest { + return ApiApiAmbientV1ProjectSettingsGetRequest{ ApiService: a, ctx: ctx, } @@ -89,21 +82,21 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsGet(ctx context.Context) ApiA // Execute executes the request // -// @return CredentialList -func (a *DefaultAPIService) ApiAmbientV1CredentialsGetExecute(r ApiApiAmbientV1CredentialsGetRequest) (*CredentialList, *http.Response, error) { +// @return ProjectSettingsList +func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsGetExecute(r ApiApiAmbientV1ProjectSettingsGetRequest) (*ProjectSettingsList, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet localVarPostBody interface{} formFiles []formFile - localVarReturnValue *CredentialList + localVarReturnValue *ProjectSettingsList ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1CredentialsGet") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectSettingsGet") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/credentials" + localVarPath := localBasePath + "/api/ambient/v1/project_settings" localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} @@ -130,9 +123,6 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsGetExecute(r ApiApiAmbientV1C if r.fields != nil { parameterAddToHeaderOrQuery(localVarQueryParams, "fields", r.fields, "form", "") } - if r.provider != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "provider", r.provider, "", "") - } // to determine the Content-Type header localVarHTTPContentTypes := []string{} @@ -219,25 +209,25 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsGetExecute(r ApiApiAmbientV1C return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1CredentialsIdDeleteRequest struct { +type ApiApiAmbientV1ProjectSettingsIdDeleteRequest struct { ctx context.Context ApiService *DefaultAPIService id string } -func (r ApiApiAmbientV1CredentialsIdDeleteRequest) Execute() (*http.Response, error) { - return r.ApiService.ApiAmbientV1CredentialsIdDeleteExecute(r) +func (r ApiApiAmbientV1ProjectSettingsIdDeleteRequest) Execute() (*http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectSettingsIdDeleteExecute(r) } /* -ApiAmbientV1CredentialsIdDelete Delete a credential +ApiAmbientV1ProjectSettingsIdDelete Delete a project settings by id @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @return ApiApiAmbientV1CredentialsIdDeleteRequest + @return ApiApiAmbientV1ProjectSettingsIdDeleteRequest */ -func (a *DefaultAPIService) ApiAmbientV1CredentialsIdDelete(ctx context.Context, id string) ApiApiAmbientV1CredentialsIdDeleteRequest { - return ApiApiAmbientV1CredentialsIdDeleteRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdDelete(ctx context.Context, id string) ApiApiAmbientV1ProjectSettingsIdDeleteRequest { + return ApiApiAmbientV1ProjectSettingsIdDeleteRequest{ ApiService: a, ctx: ctx, id: id, @@ -245,19 +235,19 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsIdDelete(ctx context.Context, } // Execute executes the request -func (a *DefaultAPIService) ApiAmbientV1CredentialsIdDeleteExecute(r ApiApiAmbientV1CredentialsIdDeleteRequest) (*http.Response, error) { +func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdDeleteExecute(r ApiApiAmbientV1ProjectSettingsIdDeleteRequest) (*http.Response, error) { var ( localVarHTTPMethod = http.MethodDelete localVarPostBody interface{} formFiles []formFile ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1CredentialsIdDelete") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectSettingsIdDelete") if err != nil { return nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/credentials/{id}" + localVarPath := localBasePath + "/api/ambient/v1/project_settings/{id}" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) localVarHeaderParams := make(map[string]string) @@ -352,25 +342,25 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsIdDeleteExecute(r ApiApiAmbie return localVarHTTPResponse, nil } -type ApiApiAmbientV1CredentialsIdGetRequest struct { +type ApiApiAmbientV1ProjectSettingsIdGetRequest struct { ctx context.Context ApiService *DefaultAPIService id string } -func (r ApiApiAmbientV1CredentialsIdGetRequest) Execute() (*Credential, *http.Response, error) { - return r.ApiService.ApiAmbientV1CredentialsIdGetExecute(r) +func (r ApiApiAmbientV1ProjectSettingsIdGetRequest) Execute() (*ProjectSettings, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectSettingsIdGetExecute(r) } /* -ApiAmbientV1CredentialsIdGet Get an credential by id +ApiAmbientV1ProjectSettingsIdGet Get a project settings by id @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @return ApiApiAmbientV1CredentialsIdGetRequest + @return ApiApiAmbientV1ProjectSettingsIdGetRequest */ -func (a *DefaultAPIService) ApiAmbientV1CredentialsIdGet(ctx context.Context, id string) ApiApiAmbientV1CredentialsIdGetRequest { - return ApiApiAmbientV1CredentialsIdGetRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdGet(ctx context.Context, id string) ApiApiAmbientV1ProjectSettingsIdGetRequest { + return ApiApiAmbientV1ProjectSettingsIdGetRequest{ ApiService: a, ctx: ctx, id: id, @@ -379,21 +369,21 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsIdGet(ctx context.Context, id // Execute executes the request // -// @return Credential -func (a *DefaultAPIService) ApiAmbientV1CredentialsIdGetExecute(r ApiApiAmbientV1CredentialsIdGetRequest) (*Credential, *http.Response, error) { +// @return ProjectSettings +func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdGetExecute(r ApiApiAmbientV1ProjectSettingsIdGetRequest) (*ProjectSettings, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet localVarPostBody interface{} formFiles []formFile - localVarReturnValue *Credential + localVarReturnValue *ProjectSettings ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1CredentialsIdGet") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectSettingsIdGet") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/credentials/{id}" + localVarPath := localBasePath + "/api/ambient/v1/project_settings/{id}" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) localVarHeaderParams := make(map[string]string) @@ -497,32 +487,32 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsIdGetExecute(r ApiApiAmbientV return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1CredentialsIdPatchRequest struct { - ctx context.Context - ApiService *DefaultAPIService - id string - credentialPatchRequest *CredentialPatchRequest +type ApiApiAmbientV1ProjectSettingsIdPatchRequest struct { + ctx context.Context + ApiService *DefaultAPIService + id string + projectSettingsPatchRequest *ProjectSettingsPatchRequest } -// Updated credential data -func (r ApiApiAmbientV1CredentialsIdPatchRequest) CredentialPatchRequest(credentialPatchRequest CredentialPatchRequest) ApiApiAmbientV1CredentialsIdPatchRequest { - r.credentialPatchRequest = &credentialPatchRequest +// Updated project settings data +func (r ApiApiAmbientV1ProjectSettingsIdPatchRequest) ProjectSettingsPatchRequest(projectSettingsPatchRequest ProjectSettingsPatchRequest) ApiApiAmbientV1ProjectSettingsIdPatchRequest { + r.projectSettingsPatchRequest = &projectSettingsPatchRequest return r } -func (r ApiApiAmbientV1CredentialsIdPatchRequest) Execute() (*Credential, *http.Response, error) { - return r.ApiService.ApiAmbientV1CredentialsIdPatchExecute(r) +func (r ApiApiAmbientV1ProjectSettingsIdPatchRequest) Execute() (*ProjectSettings, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectSettingsIdPatchExecute(r) } /* -ApiAmbientV1CredentialsIdPatch Update an credential +ApiAmbientV1ProjectSettingsIdPatch Update a project settings @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @return ApiApiAmbientV1CredentialsIdPatchRequest + @return ApiApiAmbientV1ProjectSettingsIdPatchRequest */ -func (a *DefaultAPIService) ApiAmbientV1CredentialsIdPatch(ctx context.Context, id string) ApiApiAmbientV1CredentialsIdPatchRequest { - return ApiApiAmbientV1CredentialsIdPatchRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdPatch(ctx context.Context, id string) ApiApiAmbientV1ProjectSettingsIdPatchRequest { + return ApiApiAmbientV1ProjectSettingsIdPatchRequest{ ApiService: a, ctx: ctx, id: id, @@ -531,28 +521,28 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsIdPatch(ctx context.Context, // Execute executes the request // -// @return Credential -func (a *DefaultAPIService) ApiAmbientV1CredentialsIdPatchExecute(r ApiApiAmbientV1CredentialsIdPatchRequest) (*Credential, *http.Response, error) { +// @return ProjectSettings +func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdPatchExecute(r ApiApiAmbientV1ProjectSettingsIdPatchRequest) (*ProjectSettings, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPatch localVarPostBody interface{} formFiles []formFile - localVarReturnValue *Credential + localVarReturnValue *ProjectSettings ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1CredentialsIdPatch") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectSettingsIdPatch") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/credentials/{id}" + localVarPath := localBasePath + "/api/ambient/v1/project_settings/{id}" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - if r.credentialPatchRequest == nil { - return localVarReturnValue, nil, reportError("credentialPatchRequest is required and must be specified") + if r.projectSettingsPatchRequest == nil { + return localVarReturnValue, nil, reportError("projectSettingsPatchRequest is required and must be specified") } // to determine the Content-Type header @@ -573,7 +563,7 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsIdPatchExecute(r ApiApiAmbien localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } // body params - localVarPostBody = r.credentialPatchRequest + localVarPostBody = r.projectSettingsPatchRequest req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -676,58 +666,62 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsIdPatchExecute(r ApiApiAmbien return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1CredentialsIdTokenGetRequest struct { - ctx context.Context - ApiService *DefaultAPIService - id string +type ApiApiAmbientV1ProjectSettingsPostRequest struct { + ctx context.Context + ApiService *DefaultAPIService + projectSettings *ProjectSettings +} + +// Project settings data +func (r ApiApiAmbientV1ProjectSettingsPostRequest) ProjectSettings(projectSettings ProjectSettings) ApiApiAmbientV1ProjectSettingsPostRequest { + r.projectSettings = &projectSettings + return r } -func (r ApiApiAmbientV1CredentialsIdTokenGetRequest) Execute() (*CredentialTokenResponse, *http.Response, error) { - return r.ApiService.ApiAmbientV1CredentialsIdTokenGetExecute(r) +func (r ApiApiAmbientV1ProjectSettingsPostRequest) Execute() (*ProjectSettings, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectSettingsPostExecute(r) } /* -ApiAmbientV1CredentialsIdTokenGet Get a decrypted token for a credential - -Returns the decrypted token value for the given credential. Requires token-reader role. +ApiAmbientV1ProjectSettingsPost Create a new project settings @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param id The id of record - @return ApiApiAmbientV1CredentialsIdTokenGetRequest + @return ApiApiAmbientV1ProjectSettingsPostRequest */ -func (a *DefaultAPIService) ApiAmbientV1CredentialsIdTokenGet(ctx context.Context, id string) ApiApiAmbientV1CredentialsIdTokenGetRequest { - return ApiApiAmbientV1CredentialsIdTokenGetRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsPost(ctx context.Context) ApiApiAmbientV1ProjectSettingsPostRequest { + return ApiApiAmbientV1ProjectSettingsPostRequest{ ApiService: a, ctx: ctx, - id: id, } } // Execute executes the request // -// @return CredentialTokenResponse -func (a *DefaultAPIService) ApiAmbientV1CredentialsIdTokenGetExecute(r ApiApiAmbientV1CredentialsIdTokenGetRequest) (*CredentialTokenResponse, *http.Response, error) { +// @return ProjectSettings +func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsPostExecute(r ApiApiAmbientV1ProjectSettingsPostRequest) (*ProjectSettings, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodGet + localVarHTTPMethod = http.MethodPost localVarPostBody interface{} formFiles []formFile - localVarReturnValue *CredentialTokenResponse + localVarReturnValue *ProjectSettings ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1CredentialsIdTokenGet") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectSettingsPost") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/credentials/{id}/token" - localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) + localVarPath := localBasePath + "/api/ambient/v1/project_settings" localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.projectSettings == nil { + return localVarReturnValue, nil, reportError("projectSettings is required and must be specified") + } // to determine the Content-Type header - localVarHTTPContentTypes := []string{} + localVarHTTPContentTypes := []string{"application/json"} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -743,6 +737,8 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsIdTokenGetExecute(r ApiApiAmb if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } + // body params + localVarPostBody = r.projectSettings req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -765,6 +761,17 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsIdTokenGetExecute(r ApiApiAmb body: localVarBody, error: localVarHTTPResponse.Status, } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } if localVarHTTPResponse.StatusCode == 401 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -787,7 +794,7 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsIdTokenGetExecute(r ApiApiAmb newErr.model = v return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == 404 { + if localVarHTTPResponse.StatusCode == 409 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { @@ -823,30 +830,58 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsIdTokenGetExecute(r ApiApiAmb return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1CredentialsPostRequest struct { +type ApiApiAmbientV1ProjectsGetRequest struct { ctx context.Context ApiService *DefaultAPIService - credential *Credential + page *int32 + size *int32 + search *string + orderBy *string + fields *string } -// Credential data -func (r ApiApiAmbientV1CredentialsPostRequest) Credential(credential Credential) ApiApiAmbientV1CredentialsPostRequest { - r.credential = &credential +// Page number of record list when record list exceeds specified page size +func (r ApiApiAmbientV1ProjectsGetRequest) Page(page int32) ApiApiAmbientV1ProjectsGetRequest { + r.page = &page + return r +} + +// Maximum number of records to return +func (r ApiApiAmbientV1ProjectsGetRequest) Size(size int32) ApiApiAmbientV1ProjectsGetRequest { + r.size = &size + return r +} + +// Specifies the search criteria +func (r ApiApiAmbientV1ProjectsGetRequest) Search(search string) ApiApiAmbientV1ProjectsGetRequest { + r.search = &search + return r +} + +// Specifies the order by criteria +func (r ApiApiAmbientV1ProjectsGetRequest) OrderBy(orderBy string) ApiApiAmbientV1ProjectsGetRequest { + r.orderBy = &orderBy return r } -func (r ApiApiAmbientV1CredentialsPostRequest) Execute() (*Credential, *http.Response, error) { - return r.ApiService.ApiAmbientV1CredentialsPostExecute(r) +// Supplies a comma-separated list of fields to be returned +func (r ApiApiAmbientV1ProjectsGetRequest) Fields(fields string) ApiApiAmbientV1ProjectsGetRequest { + r.fields = &fields + return r +} + +func (r ApiApiAmbientV1ProjectsGetRequest) Execute() (*ProjectList, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsGetExecute(r) } /* -ApiAmbientV1CredentialsPost Create a new credential +ApiAmbientV1ProjectsGet Returns a list of projects @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiApiAmbientV1CredentialsPostRequest + @return ApiApiAmbientV1ProjectsGetRequest */ -func (a *DefaultAPIService) ApiAmbientV1CredentialsPost(ctx context.Context) ApiApiAmbientV1CredentialsPostRequest { - return ApiApiAmbientV1CredentialsPostRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsGet(ctx context.Context) ApiApiAmbientV1ProjectsGetRequest { + return ApiApiAmbientV1ProjectsGetRequest{ ApiService: a, ctx: ctx, } @@ -854,31 +889,49 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsPost(ctx context.Context) Api // Execute executes the request // -// @return Credential -func (a *DefaultAPIService) ApiAmbientV1CredentialsPostExecute(r ApiApiAmbientV1CredentialsPostRequest) (*Credential, *http.Response, error) { +// @return ProjectList +func (a *DefaultAPIService) ApiAmbientV1ProjectsGetExecute(r ApiApiAmbientV1ProjectsGetRequest) (*ProjectList, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodPost + localVarHTTPMethod = http.MethodGet localVarPostBody interface{} formFiles []formFile - localVarReturnValue *Credential + localVarReturnValue *ProjectList ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1CredentialsPost") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsGet") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/credentials" + localVarPath := localBasePath + "/api/ambient/v1/projects" localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - if r.credential == nil { - return localVarReturnValue, nil, reportError("credential is required and must be specified") - } + if r.page != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "page", r.page, "form", "") + } else { + var defaultValue int32 = 1 + r.page = &defaultValue + } + if r.size != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "size", r.size, "form", "") + } else { + var defaultValue int32 = 100 + r.size = &defaultValue + } + if r.search != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "search", r.search, "form", "") + } + if r.orderBy != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "orderBy", r.orderBy, "form", "") + } + if r.fields != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "fields", r.fields, "form", "") + } // to determine the Content-Type header - localVarHTTPContentTypes := []string{"application/json"} + localVarHTTPContentTypes := []string{} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -894,8 +947,6 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsPostExecute(r ApiApiAmbientV1 if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } - // body params - localVarPostBody = r.credential req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -918,17 +969,6 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsPostExecute(r ApiApiAmbientV1 body: localVarBody, error: localVarHTTPResponse.Status, } - if localVarHTTPResponse.StatusCode == 400 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr - } - newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) - newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr - } if localVarHTTPResponse.StatusCode == 401 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -951,17 +991,6 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsPostExecute(r ApiApiAmbientV1 newErr.model = v return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == 409 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr - } - newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) - newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr - } if localVarHTTPResponse.StatusCode == 500 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -987,106 +1016,55 @@ func (a *DefaultAPIService) ApiAmbientV1CredentialsPostExecute(r ApiApiAmbientV1 return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectSettingsGetRequest struct { +type ApiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest struct { ctx context.Context ApiService *DefaultAPIService - page *int32 - size *int32 - search *string - orderBy *string - fields *string + id string + agentId string } -// Page number of record list when record list exceeds specified page size -func (r ApiApiAmbientV1ProjectSettingsGetRequest) Page(page int32) ApiApiAmbientV1ProjectSettingsGetRequest { - r.page = &page - return r -} - -// Maximum number of records to return -func (r ApiApiAmbientV1ProjectSettingsGetRequest) Size(size int32) ApiApiAmbientV1ProjectSettingsGetRequest { - r.size = &size - return r -} - -// Specifies the search criteria -func (r ApiApiAmbientV1ProjectSettingsGetRequest) Search(search string) ApiApiAmbientV1ProjectSettingsGetRequest { - r.search = &search - return r -} - -// Specifies the order by criteria -func (r ApiApiAmbientV1ProjectSettingsGetRequest) OrderBy(orderBy string) ApiApiAmbientV1ProjectSettingsGetRequest { - r.orderBy = &orderBy - return r -} - -// Supplies a comma-separated list of fields to be returned -func (r ApiApiAmbientV1ProjectSettingsGetRequest) Fields(fields string) ApiApiAmbientV1ProjectSettingsGetRequest { - r.fields = &fields - return r -} - -func (r ApiApiAmbientV1ProjectSettingsGetRequest) Execute() (*ProjectSettingsList, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectSettingsGetExecute(r) +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest) Execute() (*http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdDeleteExecute(r) } /* -ApiAmbientV1ProjectSettingsGet Returns a list of project settings +ApiAmbientV1ProjectsIdAgentsAgentIdDelete Delete an agent from a project @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiApiAmbientV1ProjectSettingsGetRequest + @param id The id of record + @param agentId The id of the agent + @return ApiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsGet(ctx context.Context) ApiApiAmbientV1ProjectSettingsGetRequest { - return ApiApiAmbientV1ProjectSettingsGetRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdDelete(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest { + return ApiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest{ ApiService: a, ctx: ctx, + id: id, + agentId: agentId, } } // Execute executes the request -// -// @return ProjectSettingsList -func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsGetExecute(r ApiApiAmbientV1ProjectSettingsGetRequest) (*ProjectSettingsList, *http.Response, error) { +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdDeleteExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest) (*http.Response, error) { var ( - localVarHTTPMethod = http.MethodGet - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue *ProjectSettingsList + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectSettingsGet") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdDelete") if err != nil { - return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + return nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/project_settings" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - if r.page != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "page", r.page, "form", "") - } else { - var defaultValue int32 = 1 - r.page = &defaultValue - } - if r.size != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "size", r.size, "form", "") - } else { - var defaultValue int32 = 100 - r.size = &defaultValue - } - if r.search != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "search", r.search, "form", "") - } - if r.orderBy != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "orderBy", r.orderBy, "form", "") - } - if r.fields != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "fields", r.fields, "form", "") - } // to determine the Content-Type header localVarHTTPContentTypes := []string{} @@ -1106,19 +1084,19 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsGetExecute(r ApiApiAmbien } req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { - return localVarReturnValue, nil, err + return nil, err } localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { - return localVarReturnValue, localVarHTTPResponse, err + return localVarHTTPResponse, err } localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { - return localVarReturnValue, localVarHTTPResponse, err + return localVarHTTPResponse, err } if localVarHTTPResponse.StatusCode >= 300 { @@ -1131,88 +1109,97 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsGetExecute(r ApiApiAmbien err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 403 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == 500 { + if localVarHTTPResponse.StatusCode == 404 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v + return localVarHTTPResponse, newErr } - return localVarReturnValue, localVarHTTPResponse, newErr - } - - err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr := &GenericOpenAPIError{ - body: localVarBody, - error: err.Error(), + if localVarHTTPResponse.StatusCode == 500 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v } - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } - return localVarReturnValue, localVarHTTPResponse, nil + return localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectSettingsIdDeleteRequest struct { +type ApiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest struct { ctx context.Context ApiService *DefaultAPIService id string + agentId string } -func (r ApiApiAmbientV1ProjectSettingsIdDeleteRequest) Execute() (*http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectSettingsIdDeleteExecute(r) +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest) Execute() (*Agent, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdGetExecute(r) } /* -ApiAmbientV1ProjectSettingsIdDelete Delete a project settings by id +ApiAmbientV1ProjectsIdAgentsAgentIdGet Get an agent by id @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @return ApiApiAmbientV1ProjectSettingsIdDeleteRequest + @param agentId The id of the agent + @return ApiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdDelete(ctx context.Context, id string) ApiApiAmbientV1ProjectSettingsIdDeleteRequest { - return ApiApiAmbientV1ProjectSettingsIdDeleteRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdGet(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest { + return ApiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest{ ApiService: a, ctx: ctx, id: id, + agentId: agentId, } } // Execute executes the request -func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdDeleteExecute(r ApiApiAmbientV1ProjectSettingsIdDeleteRequest) (*http.Response, error) { +// +// @return Agent +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdGetExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest) (*Agent, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodDelete - localVarPostBody interface{} - formFiles []formFile + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Agent ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectSettingsIdDelete") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdGet") if err != nil { - return nil, &GenericOpenAPIError{error: err.Error()} + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/project_settings/{id}" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} @@ -1237,19 +1224,19 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdDeleteExecute(r ApiApiA } req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { - return nil, err + return localVarReturnValue, nil, err } localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { - return localVarHTTPResponse, err + return localVarReturnValue, localVarHTTPResponse, err } localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { - return localVarHTTPResponse, err + return localVarReturnValue, localVarHTTPResponse, err } if localVarHTTPResponse.StatusCode >= 300 { @@ -1262,93 +1249,106 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdDeleteExecute(r ApiApiA err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 403 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 404 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 500 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v } - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } - return localVarHTTPResponse, nil + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectSettingsIdGetRequest struct { +type ApiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest struct { ctx context.Context ApiService *DefaultAPIService id string + agentId string } -func (r ApiApiAmbientV1ProjectSettingsIdGetRequest) Execute() (*ProjectSettings, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectSettingsIdGetExecute(r) +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest) Execute() (*StartResponse, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetExecute(r) } /* -ApiAmbientV1ProjectSettingsIdGet Get a project settings by id +ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet Preview start context (dry run — no session created) @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @return ApiApiAmbientV1ProjectSettingsIdGetRequest + @param agentId The id of the agent + @return ApiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdGet(ctx context.Context, id string) ApiApiAmbientV1ProjectSettingsIdGetRequest { - return ApiApiAmbientV1ProjectSettingsIdGetRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest { + return ApiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest{ ApiService: a, ctx: ctx, id: id, + agentId: agentId, } } // Execute executes the request // -// @return ProjectSettings -func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdGetExecute(r ApiApiAmbientV1ProjectSettingsIdGetRequest) (*ProjectSettings, *http.Response, error) { +// @return StartResponse +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest) (*StartResponse, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet localVarPostBody interface{} formFiles []formFile - localVarReturnValue *ProjectSettings + localVarReturnValue *StartResponse ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectSettingsIdGet") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/project_settings/{id}" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/ignition" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} @@ -1451,66 +1451,86 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdGetExecute(r ApiApiAmbi return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectSettingsIdPatchRequest struct { - ctx context.Context - ApiService *DefaultAPIService - id string - projectSettingsPatchRequest *ProjectSettingsPatchRequest +type ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest struct { + ctx context.Context + ApiService *DefaultAPIService + id string + agentId string + page *int32 + size *int32 } -// Updated project settings data -func (r ApiApiAmbientV1ProjectSettingsIdPatchRequest) ProjectSettingsPatchRequest(projectSettingsPatchRequest ProjectSettingsPatchRequest) ApiApiAmbientV1ProjectSettingsIdPatchRequest { - r.projectSettingsPatchRequest = &projectSettingsPatchRequest +// Page number of record list when record list exceeds specified page size +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest) Page(page int32) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest { + r.page = &page return r } -func (r ApiApiAmbientV1ProjectSettingsIdPatchRequest) Execute() (*ProjectSettings, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectSettingsIdPatchExecute(r) +// Maximum number of records to return +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest) Size(size int32) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest { + r.size = &size + return r +} + +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest) Execute() (*InboxMessageList, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxGetExecute(r) } /* -ApiAmbientV1ProjectSettingsIdPatch Update a project settings +ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet Read inbox messages for an agent (unread first) @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @return ApiApiAmbientV1ProjectSettingsIdPatchRequest + @param agentId The id of the agent + @return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdPatch(ctx context.Context, id string) ApiApiAmbientV1ProjectSettingsIdPatchRequest { - return ApiApiAmbientV1ProjectSettingsIdPatchRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest { + return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest{ ApiService: a, ctx: ctx, id: id, + agentId: agentId, } } // Execute executes the request // -// @return ProjectSettings -func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdPatchExecute(r ApiApiAmbientV1ProjectSettingsIdPatchRequest) (*ProjectSettings, *http.Response, error) { +// @return InboxMessageList +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxGetExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest) (*InboxMessageList, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodPatch + localVarHTTPMethod = http.MethodGet localVarPostBody interface{} formFiles []formFile - localVarReturnValue *ProjectSettings + localVarReturnValue *InboxMessageList ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectSettingsIdPatch") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/project_settings/{id}" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/inbox" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - if r.projectSettingsPatchRequest == nil { - return localVarReturnValue, nil, reportError("projectSettingsPatchRequest is required and must be specified") - } + if r.page != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "page", r.page, "form", "") + } else { + var defaultValue int32 = 1 + r.page = &defaultValue + } + if r.size != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "size", r.size, "form", "") + } else { + var defaultValue int32 = 100 + r.size = &defaultValue + } // to determine the Content-Type header - localVarHTTPContentTypes := []string{"application/json"} + localVarHTTPContentTypes := []string{} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -1526,8 +1546,6 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdPatchExecute(r ApiApiAm if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } - // body params - localVarPostBody = r.projectSettingsPatchRequest req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -1550,17 +1568,6 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdPatchExecute(r ApiApiAm body: localVarBody, error: localVarHTTPResponse.Status, } - if localVarHTTPResponse.StatusCode == 400 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr - } - newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) - newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr - } if localVarHTTPResponse.StatusCode == 401 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -1594,17 +1601,6 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdPatchExecute(r ApiApiAm newErr.model = v return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == 409 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr - } - newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) - newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr - } if localVarHTTPResponse.StatusCode == 500 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -1630,62 +1626,61 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsIdPatchExecute(r ApiApiAm return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectSettingsPostRequest struct { - ctx context.Context - ApiService *DefaultAPIService - projectSettings *ProjectSettings -} - -// Project settings data -func (r ApiApiAmbientV1ProjectSettingsPostRequest) ProjectSettings(projectSettings ProjectSettings) ApiApiAmbientV1ProjectSettingsPostRequest { - r.projectSettings = &projectSettings - return r +type ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest struct { + ctx context.Context + ApiService *DefaultAPIService + id string + agentId string + msgId string } -func (r ApiApiAmbientV1ProjectSettingsPostRequest) Execute() (*ProjectSettings, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectSettingsPostExecute(r) +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest) Execute() (*http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteExecute(r) } /* -ApiAmbientV1ProjectSettingsPost Create a new project settings +ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete Delete an inbox message @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiApiAmbientV1ProjectSettingsPostRequest + @param id The id of record + @param agentId The id of the agent + @param msgId The id of the inbox message + @return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsPost(ctx context.Context) ApiApiAmbientV1ProjectSettingsPostRequest { - return ApiApiAmbientV1ProjectSettingsPostRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete(ctx context.Context, id string, agentId string, msgId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest { + return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest{ ApiService: a, ctx: ctx, + id: id, + agentId: agentId, + msgId: msgId, } } // Execute executes the request -// -// @return ProjectSettings -func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsPostExecute(r ApiApiAmbientV1ProjectSettingsPostRequest) (*ProjectSettings, *http.Response, error) { +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest) (*http.Response, error) { var ( - localVarHTTPMethod = http.MethodPost - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue *ProjectSettings + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectSettingsPost") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete") if err != nil { - return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + return nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/project_settings" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/inbox/{msg_id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"msg_id"+"}", url.PathEscape(parameterValueToString(r.msgId, "msgId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - if r.projectSettings == nil { - return localVarReturnValue, nil, reportError("projectSettings is required and must be specified") - } // to determine the Content-Type header - localVarHTTPContentTypes := []string{"application/json"} + localVarHTTPContentTypes := []string{} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -1701,23 +1696,21 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsPostExecute(r ApiApiAmbie if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } - // body params - localVarPostBody = r.projectSettings req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { - return localVarReturnValue, nil, err + return nil, err } localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { - return localVarReturnValue, localVarHTTPResponse, err + return localVarHTTPResponse, err } localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { - return localVarReturnValue, localVarHTTPResponse, err + return localVarHTTPResponse, err } if localVarHTTPResponse.StatusCode >= 300 { @@ -1725,177 +1718,123 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectSettingsPostExecute(r ApiApiAmbie body: localVarBody, error: localVarHTTPResponse.Status, } - if localVarHTTPResponse.StatusCode == 400 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr - } - newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) - newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr - } if localVarHTTPResponse.StatusCode == 401 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 403 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == 409 { + if localVarHTTPResponse.StatusCode == 404 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 500 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v } - return localVarReturnValue, localVarHTTPResponse, newErr - } - - err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr := &GenericOpenAPIError{ - body: localVarBody, - error: err.Error(), - } - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } - return localVarReturnValue, localVarHTTPResponse, nil -} - -type ApiApiAmbientV1ProjectsGetRequest struct { - ctx context.Context - ApiService *DefaultAPIService - page *int32 - size *int32 - search *string - orderBy *string - fields *string -} - -// Page number of record list when record list exceeds specified page size -func (r ApiApiAmbientV1ProjectsGetRequest) Page(page int32) ApiApiAmbientV1ProjectsGetRequest { - r.page = &page - return r -} - -// Maximum number of records to return -func (r ApiApiAmbientV1ProjectsGetRequest) Size(size int32) ApiApiAmbientV1ProjectsGetRequest { - r.size = &size - return r -} - -// Specifies the search criteria -func (r ApiApiAmbientV1ProjectsGetRequest) Search(search string) ApiApiAmbientV1ProjectsGetRequest { - r.search = &search - return r + return localVarHTTPResponse, nil } -// Specifies the order by criteria -func (r ApiApiAmbientV1ProjectsGetRequest) OrderBy(orderBy string) ApiApiAmbientV1ProjectsGetRequest { - r.orderBy = &orderBy - return r +type ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest struct { + ctx context.Context + ApiService *DefaultAPIService + id string + agentId string + msgId string + inboxMessagePatchRequest *InboxMessagePatchRequest } -// Supplies a comma-separated list of fields to be returned -func (r ApiApiAmbientV1ProjectsGetRequest) Fields(fields string) ApiApiAmbientV1ProjectsGetRequest { - r.fields = &fields +// Inbox message patch +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest) InboxMessagePatchRequest(inboxMessagePatchRequest InboxMessagePatchRequest) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest { + r.inboxMessagePatchRequest = &inboxMessagePatchRequest return r } -func (r ApiApiAmbientV1ProjectsGetRequest) Execute() (*ProjectList, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsGetExecute(r) +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest) Execute() (*InboxMessage, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchExecute(r) } /* -ApiAmbientV1ProjectsGet Returns a list of projects +ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch Mark an inbox message as read @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiApiAmbientV1ProjectsGetRequest + @param id The id of record + @param agentId The id of the agent + @param msgId The id of the inbox message + @return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsGet(ctx context.Context) ApiApiAmbientV1ProjectsGetRequest { - return ApiApiAmbientV1ProjectsGetRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch(ctx context.Context, id string, agentId string, msgId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest { + return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest{ ApiService: a, ctx: ctx, + id: id, + agentId: agentId, + msgId: msgId, } } // Execute executes the request // -// @return ProjectList -func (a *DefaultAPIService) ApiAmbientV1ProjectsGetExecute(r ApiApiAmbientV1ProjectsGetRequest) (*ProjectList, *http.Response, error) { +// @return InboxMessage +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest) (*InboxMessage, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodGet + localVarHTTPMethod = http.MethodPatch localVarPostBody interface{} formFiles []formFile - localVarReturnValue *ProjectList + localVarReturnValue *InboxMessage ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsGet") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/projects" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/inbox/{msg_id}" + localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"msg_id"+"}", url.PathEscape(parameterValueToString(r.msgId, "msgId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - - if r.page != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "page", r.page, "form", "") - } else { - var defaultValue int32 = 1 - r.page = &defaultValue - } - if r.size != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "size", r.size, "form", "") - } else { - var defaultValue int32 = 100 - r.size = &defaultValue - } - if r.search != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "search", r.search, "form", "") - } - if r.orderBy != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "orderBy", r.orderBy, "form", "") - } - if r.fields != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "fields", r.fields, "form", "") + if r.inboxMessagePatchRequest == nil { + return localVarReturnValue, nil, reportError("inboxMessagePatchRequest is required and must be specified") } + // to determine the Content-Type header - localVarHTTPContentTypes := []string{} + localVarHTTPContentTypes := []string{"application/json"} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -1911,6 +1850,8 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsGetExecute(r ApiApiAmbientV1Proj if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } + // body params + localVarPostBody = r.inboxMessagePatchRequest req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -1955,6 +1896,17 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsGetExecute(r ApiApiAmbientV1Proj newErr.model = v return localVarReturnValue, localVarHTTPResponse, newErr } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } if localVarHTTPResponse.StatusCode == 500 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -1980,27 +1932,34 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsGetExecute(r ApiApiAmbientV1Proj return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest struct { - ctx context.Context - ApiService *DefaultAPIService - id string - agentId string +type ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest struct { + ctx context.Context + ApiService *DefaultAPIService + id string + agentId string + inboxMessage *InboxMessage } -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest) Execute() (*http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdDeleteExecute(r) +// Inbox message to send +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest) InboxMessage(inboxMessage InboxMessage) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest { + r.inboxMessage = &inboxMessage + return r +} + +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest) Execute() (*InboxMessage, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxPostExecute(r) } /* -ApiAmbientV1ProjectsIdAgentsAgentIdDelete Delete an agent from a project +ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost Send a message to an agent's inbox @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record @param agentId The id of the agent - @return ApiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest + @return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdDelete(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest { - return ApiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest { + return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest{ ApiService: a, ctx: ctx, id: id, @@ -2009,28 +1968,34 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdDelete(ctx contex } // Execute executes the request -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdDeleteExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest) (*http.Response, error) { +// +// @return InboxMessage +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxPostExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest) (*InboxMessage, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodDelete - localVarPostBody interface{} - formFiles []formFile + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *InboxMessage ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdDelete") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost") if err != nil { - return nil, &GenericOpenAPIError{error: err.Error()} + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/inbox" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.inboxMessage == nil { + return localVarReturnValue, nil, reportError("inboxMessage is required and must be specified") + } // to determine the Content-Type header - localVarHTTPContentTypes := []string{} + localVarHTTPContentTypes := []string{"application/json"} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -2046,21 +2011,23 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdDeleteExecute(r A if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } + // body params + localVarPostBody = r.inboxMessage req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { - return nil, err + return localVarReturnValue, nil, err } localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { - return localVarHTTPResponse, err + return localVarReturnValue, localVarHTTPResponse, err } localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { - return localVarHTTPResponse, err + return localVarReturnValue, localVarHTTPResponse, err } if localVarHTTPResponse.StatusCode >= 300 { @@ -2068,76 +2035,103 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdDeleteExecute(r A body: localVarBody, error: localVarHTTPResponse.Status, } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } if localVarHTTPResponse.StatusCode == 401 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 403 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 404 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 500 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v } - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } - return localVarHTTPResponse, nil + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest struct { - ctx context.Context - ApiService *DefaultAPIService - id string - agentId string +type ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest struct { + ctx context.Context + ApiService *DefaultAPIService + id string + agentId string + agentPatchRequest *AgentPatchRequest } -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest) Execute() (*Agent, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdGetExecute(r) +// Updated agent data +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest) AgentPatchRequest(agentPatchRequest AgentPatchRequest) ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest { + r.agentPatchRequest = &agentPatchRequest + return r +} + +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest) Execute() (*Agent, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdPatchExecute(r) } /* -ApiAmbientV1ProjectsIdAgentsAgentIdGet Get an agent by id +ApiAmbientV1ProjectsIdAgentsAgentIdPatch Update an agent (name, prompt, labels, annotations) @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record @param agentId The id of the agent - @return ApiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest + @return ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdGet(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest { - return ApiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdPatch(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest { + return ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest{ ApiService: a, ctx: ctx, id: id, @@ -2148,15 +2142,15 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdGet(ctx context.C // Execute executes the request // // @return Agent -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdGetExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest) (*Agent, *http.Response, error) { +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdPatchExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest) (*Agent, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodGet + localVarHTTPMethod = http.MethodPatch localVarPostBody interface{} formFiles []formFile localVarReturnValue *Agent ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdGet") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdPatch") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } @@ -2168,9 +2162,12 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdGetExecute(r ApiA localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.agentPatchRequest == nil { + return localVarReturnValue, nil, reportError("agentPatchRequest is required and must be specified") + } // to determine the Content-Type header - localVarHTTPContentTypes := []string{} + localVarHTTPContentTypes := []string{"application/json"} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -2186,6 +2183,8 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdGetExecute(r ApiA if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } + // body params + localVarPostBody = r.agentPatchRequest req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -2208,6 +2207,17 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdGetExecute(r ApiA body: localVarBody, error: localVarHTTPResponse.Status, } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } if localVarHTTPResponse.StatusCode == 401 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -2266,27 +2276,41 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdGetExecute(r ApiA return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest struct { +type ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest struct { ctx context.Context ApiService *DefaultAPIService id string agentId string + page *int32 + size *int32 } -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest) Execute() (*StartResponse, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetExecute(r) +// Page number of record list when record list exceeds specified page size +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest) Page(page int32) ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest { + r.page = &page + return r +} + +// Maximum number of records to return +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest) Size(size int32) ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest { + r.size = &size + return r +} + +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest) Execute() (*AgentSessionList, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetExecute(r) } /* -ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet Preview start context (dry run — no session created) +ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet Get session run history for an agent @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record @param agentId The id of the agent - @return ApiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest + @return ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest { - return ApiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest { + return ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest{ ApiService: a, ctx: ctx, id: id, @@ -2296,21 +2320,21 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet(ctx c // Execute executes the request // -// @return StartResponse -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest) (*StartResponse, *http.Response, error) { +// @return AgentSessionList +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest) (*AgentSessionList, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet localVarPostBody interface{} formFiles []formFile - localVarReturnValue *StartResponse + localVarReturnValue *AgentSessionList ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/ignition" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/sessions" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) @@ -2318,6 +2342,18 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetExecut localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.page != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "page", r.page, "form", "") + } else { + var defaultValue int32 = 1 + r.page = &defaultValue + } + if r.size != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "size", r.size, "form", "") + } else { + var defaultValue int32 = 100 + r.size = &defaultValue + } // to determine the Content-Type header localVarHTTPContentTypes := []string{} @@ -2415,41 +2451,38 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetExecut return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest struct { - ctx context.Context - ApiService *DefaultAPIService - id string - agentId string - page *int32 - size *int32 -} - -// Page number of record list when record list exceeds specified page size -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest) Page(page int32) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest { - r.page = &page - return r +type ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest struct { + ctx context.Context + ApiService *DefaultAPIService + id string + agentId string + startRequest *StartRequest } -// Maximum number of records to return -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest) Size(size int32) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest { - r.size = &size +// Optional start parameters +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest) StartRequest(startRequest StartRequest) ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest { + r.startRequest = &startRequest return r } -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest) Execute() (*InboxMessageList, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxGetExecute(r) +func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest) Execute() (*StartResponse, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdStartPostExecute(r) } /* -ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet Read inbox messages for an agent (unread first) +ApiAmbientV1ProjectsIdAgentsAgentIdStartPost Start an agent — creates a Session (idempotent) + +Creates a new Session for this Agent and drains the inbox into the start context. +If an active session already exists, it is returned as-is. +Unread Inbox messages are marked read and injected as context before the first turn. @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record @param agentId The id of the agent - @return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest + @return ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest { - return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdStartPost(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest { + return ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest{ ApiService: a, ctx: ctx, id: id, @@ -2459,21 +2492,21 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet(ctx cont // Execute executes the request // -// @return InboxMessageList -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxGetExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest) (*InboxMessageList, *http.Response, error) { +// @return StartResponse +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdStartPostExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest) (*StartResponse, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodGet + localVarHTTPMethod = http.MethodPost localVarPostBody interface{} formFiles []formFile - localVarReturnValue *InboxMessageList + localVarReturnValue *StartResponse ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdStartPost") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/inbox" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/start" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) @@ -2481,20 +2514,8 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxGetExecute(r localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - if r.page != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "page", r.page, "form", "") - } else { - var defaultValue int32 = 1 - r.page = &defaultValue - } - if r.size != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "size", r.size, "form", "") - } else { - var defaultValue int32 = 100 - r.size = &defaultValue - } // to determine the Content-Type header - localVarHTTPContentTypes := []string{} + localVarHTTPContentTypes := []string{"application/json"} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -2510,6 +2531,8 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxGetExecute(r if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } + // body params + localVarPostBody = r.startRequest req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -2590,59 +2613,110 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxGetExecute(r return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest struct { +type ApiApiAmbientV1ProjectsIdAgentsGetRequest struct { ctx context.Context ApiService *DefaultAPIService id string - agentId string - msgId string + page *int32 + size *int32 + search *string + orderBy *string + fields *string +} + +// Page number of record list when record list exceeds specified page size +func (r ApiApiAmbientV1ProjectsIdAgentsGetRequest) Page(page int32) ApiApiAmbientV1ProjectsIdAgentsGetRequest { + r.page = &page + return r +} + +// Maximum number of records to return +func (r ApiApiAmbientV1ProjectsIdAgentsGetRequest) Size(size int32) ApiApiAmbientV1ProjectsIdAgentsGetRequest { + r.size = &size + return r +} + +// Specifies the search criteria +func (r ApiApiAmbientV1ProjectsIdAgentsGetRequest) Search(search string) ApiApiAmbientV1ProjectsIdAgentsGetRequest { + r.search = &search + return r +} + +// Specifies the order by criteria +func (r ApiApiAmbientV1ProjectsIdAgentsGetRequest) OrderBy(orderBy string) ApiApiAmbientV1ProjectsIdAgentsGetRequest { + r.orderBy = &orderBy + return r +} + +// Supplies a comma-separated list of fields to be returned +func (r ApiApiAmbientV1ProjectsIdAgentsGetRequest) Fields(fields string) ApiApiAmbientV1ProjectsIdAgentsGetRequest { + r.fields = &fields + return r } -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest) Execute() (*http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteExecute(r) +func (r ApiApiAmbientV1ProjectsIdAgentsGetRequest) Execute() (*AgentList, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdAgentsGetExecute(r) } /* -ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete Delete an inbox message +ApiAmbientV1ProjectsIdAgentsGet Returns a list of agents in a project @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @param agentId The id of the agent - @param msgId The id of the inbox message - @return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest + @return ApiApiAmbientV1ProjectsIdAgentsGetRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete(ctx context.Context, id string, agentId string, msgId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest { - return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsGet(ctx context.Context, id string) ApiApiAmbientV1ProjectsIdAgentsGetRequest { + return ApiApiAmbientV1ProjectsIdAgentsGetRequest{ ApiService: a, ctx: ctx, id: id, - agentId: agentId, - msgId: msgId, } } // Execute executes the request -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest) (*http.Response, error) { +// +// @return AgentList +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsGetExecute(r ApiApiAmbientV1ProjectsIdAgentsGetRequest) (*AgentList, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodDelete - localVarPostBody interface{} - formFiles []formFile + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *AgentList ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsGet") if err != nil { - return nil, &GenericOpenAPIError{error: err.Error()} + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/inbox/{msg_id}" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) - localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) - localVarPath = strings.Replace(localVarPath, "{"+"msg_id"+"}", url.PathEscape(parameterValueToString(r.msgId, "msgId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.page != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "page", r.page, "form", "") + } else { + var defaultValue int32 = 1 + r.page = &defaultValue + } + if r.size != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "size", r.size, "form", "") + } else { + var defaultValue int32 = 100 + r.size = &defaultValue + } + if r.search != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "search", r.search, "form", "") + } + if r.orderBy != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "orderBy", r.orderBy, "form", "") + } + if r.fields != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "fields", r.fields, "form", "") + } // to determine the Content-Type header localVarHTTPContentTypes := []string{} @@ -2662,19 +2736,19 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteE } req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { - return nil, err + return localVarReturnValue, nil, err } localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { - return localVarHTTPResponse, err + return localVarReturnValue, localVarHTTPResponse, err } localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { - return localVarHTTPResponse, err + return localVarReturnValue, localVarHTTPResponse, err } if localVarHTTPResponse.StatusCode >= 300 { @@ -2687,114 +2761,115 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteE err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 403 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 404 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 500 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v } - return localVarHTTPResponse, newErr + return localVarReturnValue, localVarHTTPResponse, newErr } - return localVarHTTPResponse, nil + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest struct { - ctx context.Context - ApiService *DefaultAPIService - id string - agentId string - msgId string - inboxMessagePatchRequest *InboxMessagePatchRequest +type ApiApiAmbientV1ProjectsIdAgentsPostRequest struct { + ctx context.Context + ApiService *DefaultAPIService + id string + agent *Agent } -// Inbox message patch -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest) InboxMessagePatchRequest(inboxMessagePatchRequest InboxMessagePatchRequest) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest { - r.inboxMessagePatchRequest = &inboxMessagePatchRequest +// Agent data +func (r ApiApiAmbientV1ProjectsIdAgentsPostRequest) Agent(agent Agent) ApiApiAmbientV1ProjectsIdAgentsPostRequest { + r.agent = &agent return r } -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest) Execute() (*InboxMessage, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchExecute(r) +func (r ApiApiAmbientV1ProjectsIdAgentsPostRequest) Execute() (*Agent, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdAgentsPostExecute(r) } /* -ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch Mark an inbox message as read +ApiAmbientV1ProjectsIdAgentsPost Create an agent in a project @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @param agentId The id of the agent - @param msgId The id of the inbox message - @return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest + @return ApiApiAmbientV1ProjectsIdAgentsPostRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch(ctx context.Context, id string, agentId string, msgId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest { - return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsPost(ctx context.Context, id string) ApiApiAmbientV1ProjectsIdAgentsPostRequest { + return ApiApiAmbientV1ProjectsIdAgentsPostRequest{ ApiService: a, ctx: ctx, id: id, - agentId: agentId, - msgId: msgId, } } // Execute executes the request // -// @return InboxMessage -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest) (*InboxMessage, *http.Response, error) { +// @return Agent +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsPostExecute(r ApiApiAmbientV1ProjectsIdAgentsPostRequest) (*Agent, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodPatch + localVarHTTPMethod = http.MethodPost localVarPostBody interface{} formFiles []formFile - localVarReturnValue *InboxMessage + localVarReturnValue *Agent ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsPost") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/inbox/{msg_id}" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) - localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) - localVarPath = strings.Replace(localVarPath, "{"+"msg_id"+"}", url.PathEscape(parameterValueToString(r.msgId, "msgId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - if r.inboxMessagePatchRequest == nil { - return localVarReturnValue, nil, reportError("inboxMessagePatchRequest is required and must be specified") + if r.agent == nil { + return localVarReturnValue, nil, reportError("agent is required and must be specified") } // to determine the Content-Type header @@ -2815,7 +2890,7 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchEx localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } // body params - localVarPostBody = r.inboxMessagePatchRequest + localVarPostBody = r.agent req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -2838,6 +2913,17 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchEx body: localVarBody, error: localVarHTTPResponse.Status, } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } if localVarHTTPResponse.StatusCode == 401 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -2871,6 +2957,17 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchEx newErr.model = v return localVarReturnValue, localVarHTTPResponse, newErr } + if localVarHTTPResponse.StatusCode == 409 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } if localVarHTTPResponse.StatusCode == 500 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -2896,70 +2993,57 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchEx return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest struct { - ctx context.Context - ApiService *DefaultAPIService - id string - agentId string - inboxMessage *InboxMessage -} - -// Inbox message to send -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest) InboxMessage(inboxMessage InboxMessage) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest { - r.inboxMessage = &inboxMessage - return r +type ApiApiAmbientV1ProjectsIdCredentialsCredIdDeleteRequest struct { + ctx context.Context + ApiService *DefaultAPIService + id string + credId string } -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest) Execute() (*InboxMessage, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxPostExecute(r) +func (r ApiApiAmbientV1ProjectsIdCredentialsCredIdDeleteRequest) Execute() (*http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdCredentialsCredIdDeleteExecute(r) } /* -ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost Send a message to an agent's inbox +ApiAmbientV1ProjectsIdCredentialsCredIdDelete Delete a credential @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @param agentId The id of the agent - @return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest + @param credId The id of the credential + @return ApiApiAmbientV1ProjectsIdCredentialsCredIdDeleteRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest { - return ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdCredentialsCredIdDelete(ctx context.Context, id string, credId string) ApiApiAmbientV1ProjectsIdCredentialsCredIdDeleteRequest { + return ApiApiAmbientV1ProjectsIdCredentialsCredIdDeleteRequest{ ApiService: a, ctx: ctx, id: id, - agentId: agentId, + credId: credId, } } // Execute executes the request -// -// @return InboxMessage -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxPostExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest) (*InboxMessage, *http.Response, error) { +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdCredentialsCredIdDeleteExecute(r ApiApiAmbientV1ProjectsIdCredentialsCredIdDeleteRequest) (*http.Response, error) { var ( - localVarHTTPMethod = http.MethodPost - localVarPostBody interface{} - formFiles []formFile - localVarReturnValue *InboxMessage + localVarHTTPMethod = http.MethodDelete + localVarPostBody interface{} + formFiles []formFile ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdCredentialsCredIdDelete") if err != nil { - return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + return nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/inbox" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/credentials/{cred_id}" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) - localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"cred_id"+"}", url.PathEscape(parameterValueToString(r.credId, "credId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - if r.inboxMessage == nil { - return localVarReturnValue, nil, reportError("inboxMessage is required and must be specified") - } // to determine the Content-Type header - localVarHTTPContentTypes := []string{"application/json"} + localVarHTTPContentTypes := []string{} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -2975,23 +3059,21 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxPostExecute( if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } - // body params - localVarPostBody = r.inboxMessage req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { - return localVarReturnValue, nil, err + return nil, err } localVarHTTPResponse, err := a.client.callAPI(req) if err != nil || localVarHTTPResponse == nil { - return localVarReturnValue, localVarHTTPResponse, err + return localVarHTTPResponse, err } localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) localVarHTTPResponse.Body.Close() localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) if err != nil { - return localVarReturnValue, localVarHTTPResponse, err + return localVarHTTPResponse, err } if localVarHTTPResponse.StatusCode >= 300 { @@ -2999,139 +3081,109 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdInboxPostExecute( body: localVarBody, error: localVarHTTPResponse.Status, } - if localVarHTTPResponse.StatusCode == 400 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr - } - newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) - newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr - } if localVarHTTPResponse.StatusCode == 401 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 403 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 404 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } if localVarHTTPResponse.StatusCode == 500 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) if err != nil { newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } - newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) - newErr.model = v - } - return localVarReturnValue, localVarHTTPResponse, newErr - } - - err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr := &GenericOpenAPIError{ - body: localVarBody, - error: err.Error(), + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v } - return localVarReturnValue, localVarHTTPResponse, newErr + return localVarHTTPResponse, newErr } - return localVarReturnValue, localVarHTTPResponse, nil -} - -type ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest struct { - ctx context.Context - ApiService *DefaultAPIService - id string - agentId string - agentPatchRequest *AgentPatchRequest + return localVarHTTPResponse, nil } -// Updated agent data -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest) AgentPatchRequest(agentPatchRequest AgentPatchRequest) ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest { - r.agentPatchRequest = &agentPatchRequest - return r +type ApiApiAmbientV1ProjectsIdCredentialsCredIdGetRequest struct { + ctx context.Context + ApiService *DefaultAPIService + id string + credId string } -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest) Execute() (*Agent, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdPatchExecute(r) +func (r ApiApiAmbientV1ProjectsIdCredentialsCredIdGetRequest) Execute() (*Credential, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdCredentialsCredIdGetExecute(r) } /* -ApiAmbientV1ProjectsIdAgentsAgentIdPatch Update an agent (name, prompt, labels, annotations) +ApiAmbientV1ProjectsIdCredentialsCredIdGet Get a credential by id @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @param agentId The id of the agent - @return ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest + @param credId The id of the credential + @return ApiApiAmbientV1ProjectsIdCredentialsCredIdGetRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdPatch(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest { - return ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdCredentialsCredIdGet(ctx context.Context, id string, credId string) ApiApiAmbientV1ProjectsIdCredentialsCredIdGetRequest { + return ApiApiAmbientV1ProjectsIdCredentialsCredIdGetRequest{ ApiService: a, ctx: ctx, id: id, - agentId: agentId, + credId: credId, } } // Execute executes the request // -// @return Agent -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdPatchExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest) (*Agent, *http.Response, error) { +// @return Credential +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdCredentialsCredIdGetExecute(r ApiApiAmbientV1ProjectsIdCredentialsCredIdGetRequest) (*Credential, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodPatch + localVarHTTPMethod = http.MethodGet localVarPostBody interface{} formFiles []formFile - localVarReturnValue *Agent + localVarReturnValue *Credential ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdPatch") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdCredentialsCredIdGet") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/credentials/{cred_id}" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) - localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"cred_id"+"}", url.PathEscape(parameterValueToString(r.credId, "credId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - if r.agentPatchRequest == nil { - return localVarReturnValue, nil, reportError("agentPatchRequest is required and must be specified") - } // to determine the Content-Type header - localVarHTTPContentTypes := []string{"application/json"} + localVarHTTPContentTypes := []string{} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -3147,8 +3199,6 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdPatchExecute(r Ap if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } - // body params - localVarPostBody = r.agentPatchRequest req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -3171,17 +3221,6 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdPatchExecute(r Ap body: localVarBody, error: localVarHTTPResponse.Status, } - if localVarHTTPResponse.StatusCode == 400 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr - } - newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) - newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr - } if localVarHTTPResponse.StatusCode == 401 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -3240,86 +3279,70 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdPatchExecute(r Ap return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest struct { - ctx context.Context - ApiService *DefaultAPIService - id string - agentId string - page *int32 - size *int32 -} - -// Page number of record list when record list exceeds specified page size -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest) Page(page int32) ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest { - r.page = &page - return r +type ApiApiAmbientV1ProjectsIdCredentialsCredIdPatchRequest struct { + ctx context.Context + ApiService *DefaultAPIService + id string + credId string + credentialPatchRequest *CredentialPatchRequest } -// Maximum number of records to return -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest) Size(size int32) ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest { - r.size = &size +// Updated credential data +func (r ApiApiAmbientV1ProjectsIdCredentialsCredIdPatchRequest) CredentialPatchRequest(credentialPatchRequest CredentialPatchRequest) ApiApiAmbientV1ProjectsIdCredentialsCredIdPatchRequest { + r.credentialPatchRequest = &credentialPatchRequest return r } -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest) Execute() (*AgentSessionList, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetExecute(r) +func (r ApiApiAmbientV1ProjectsIdCredentialsCredIdPatchRequest) Execute() (*Credential, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdCredentialsCredIdPatchExecute(r) } /* -ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet Get session run history for an agent +ApiAmbientV1ProjectsIdCredentialsCredIdPatch Update a credential @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @param agentId The id of the agent - @return ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest + @param credId The id of the credential + @return ApiApiAmbientV1ProjectsIdCredentialsCredIdPatchRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest { - return ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdCredentialsCredIdPatch(ctx context.Context, id string, credId string) ApiApiAmbientV1ProjectsIdCredentialsCredIdPatchRequest { + return ApiApiAmbientV1ProjectsIdCredentialsCredIdPatchRequest{ ApiService: a, ctx: ctx, id: id, - agentId: agentId, + credId: credId, } } // Execute executes the request // -// @return AgentSessionList -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest) (*AgentSessionList, *http.Response, error) { +// @return Credential +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdCredentialsCredIdPatchExecute(r ApiApiAmbientV1ProjectsIdCredentialsCredIdPatchRequest) (*Credential, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodGet + localVarHTTPMethod = http.MethodPatch localVarPostBody interface{} formFiles []formFile - localVarReturnValue *AgentSessionList + localVarReturnValue *Credential ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdCredentialsCredIdPatch") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/sessions" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/credentials/{cred_id}" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) - localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"cred_id"+"}", url.PathEscape(parameterValueToString(r.credId, "credId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - - if r.page != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "page", r.page, "form", "") - } else { - var defaultValue int32 = 1 - r.page = &defaultValue - } - if r.size != nil { - parameterAddToHeaderOrQuery(localVarQueryParams, "size", r.size, "form", "") - } else { - var defaultValue int32 = 100 - r.size = &defaultValue + if r.credentialPatchRequest == nil { + return localVarReturnValue, nil, reportError("credentialPatchRequest is required and must be specified") } + // to determine the Content-Type header - localVarHTTPContentTypes := []string{} + localVarHTTPContentTypes := []string{"application/json"} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -3335,6 +3358,8 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetExecut if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } + // body params + localVarPostBody = r.credentialPatchRequest req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -3357,6 +3382,17 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetExecut body: localVarBody, error: localVarHTTPResponse.Status, } + if localVarHTTPResponse.StatusCode == 400 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } if localVarHTTPResponse.StatusCode == 401 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -3390,6 +3426,17 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetExecut newErr.model = v return localVarReturnValue, localVarHTTPResponse, newErr } + if localVarHTTPResponse.StatusCode == 409 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } if localVarHTTPResponse.StatusCode == 500 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -3415,71 +3462,62 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetExecut return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest struct { - ctx context.Context - ApiService *DefaultAPIService - id string - agentId string - startRequest *StartRequest -} - -// Optional start parameters -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest) StartRequest(startRequest StartRequest) ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest { - r.startRequest = &startRequest - return r +type ApiApiAmbientV1ProjectsIdCredentialsCredIdTokenGetRequest struct { + ctx context.Context + ApiService *DefaultAPIService + id string + credId string } -func (r ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest) Execute() (*StartResponse, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsIdAgentsAgentIdStartPostExecute(r) +func (r ApiApiAmbientV1ProjectsIdCredentialsCredIdTokenGetRequest) Execute() (*CredentialTokenResponse, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdCredentialsCredIdTokenGetExecute(r) } /* -ApiAmbientV1ProjectsIdAgentsAgentIdStartPost Start an agent — creates a Session (idempotent) +ApiAmbientV1ProjectsIdCredentialsCredIdTokenGet Get a decrypted token for a credential -Creates a new Session for this Agent and drains the inbox into the start context. -If an active session already exists, it is returned as-is. -Unread Inbox messages are marked read and injected as context before the first turn. +Returns the decrypted token value for the given credential. Requires token-reader role. @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @param agentId The id of the agent - @return ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest + @param credId The id of the credential + @return ApiApiAmbientV1ProjectsIdCredentialsCredIdTokenGetRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdStartPost(ctx context.Context, id string, agentId string) ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest { - return ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdCredentialsCredIdTokenGet(ctx context.Context, id string, credId string) ApiApiAmbientV1ProjectsIdCredentialsCredIdTokenGetRequest { + return ApiApiAmbientV1ProjectsIdCredentialsCredIdTokenGetRequest{ ApiService: a, ctx: ctx, id: id, - agentId: agentId, + credId: credId, } } // Execute executes the request // -// @return StartResponse -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdStartPostExecute(r ApiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest) (*StartResponse, *http.Response, error) { +// @return CredentialTokenResponse +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdCredentialsCredIdTokenGetExecute(r ApiApiAmbientV1ProjectsIdCredentialsCredIdTokenGetRequest) (*CredentialTokenResponse, *http.Response, error) { var ( - localVarHTTPMethod = http.MethodPost + localVarHTTPMethod = http.MethodGet localVarPostBody interface{} formFiles []formFile - localVarReturnValue *StartResponse + localVarReturnValue *CredentialTokenResponse ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsAgentIdStartPost") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdCredentialsCredIdTokenGet") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents/{agent_id}/start" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/credentials/{cred_id}/token" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) - localVarPath = strings.Replace(localVarPath, "{"+"agent_id"+"}", url.PathEscape(parameterValueToString(r.agentId, "agentId")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"cred_id"+"}", url.PathEscape(parameterValueToString(r.credId, "credId")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} // to determine the Content-Type header - localVarHTTPContentTypes := []string{"application/json"} + localVarHTTPContentTypes := []string{} // set Content-Type header localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) @@ -3495,8 +3533,6 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdStartPostExecute( if localVarHTTPHeaderAccept != "" { localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } - // body params - localVarPostBody = r.startRequest req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -3577,7 +3613,7 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsAgentIdStartPostExecute( return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectsIdAgentsGetRequest struct { +type ApiApiAmbientV1ProjectsIdCredentialsGetRequest struct { ctx context.Context ApiService *DefaultAPIService id string @@ -3586,51 +3622,58 @@ type ApiApiAmbientV1ProjectsIdAgentsGetRequest struct { search *string orderBy *string fields *string + provider *string } // Page number of record list when record list exceeds specified page size -func (r ApiApiAmbientV1ProjectsIdAgentsGetRequest) Page(page int32) ApiApiAmbientV1ProjectsIdAgentsGetRequest { +func (r ApiApiAmbientV1ProjectsIdCredentialsGetRequest) Page(page int32) ApiApiAmbientV1ProjectsIdCredentialsGetRequest { r.page = &page return r } // Maximum number of records to return -func (r ApiApiAmbientV1ProjectsIdAgentsGetRequest) Size(size int32) ApiApiAmbientV1ProjectsIdAgentsGetRequest { +func (r ApiApiAmbientV1ProjectsIdCredentialsGetRequest) Size(size int32) ApiApiAmbientV1ProjectsIdCredentialsGetRequest { r.size = &size return r } // Specifies the search criteria -func (r ApiApiAmbientV1ProjectsIdAgentsGetRequest) Search(search string) ApiApiAmbientV1ProjectsIdAgentsGetRequest { +func (r ApiApiAmbientV1ProjectsIdCredentialsGetRequest) Search(search string) ApiApiAmbientV1ProjectsIdCredentialsGetRequest { r.search = &search return r } // Specifies the order by criteria -func (r ApiApiAmbientV1ProjectsIdAgentsGetRequest) OrderBy(orderBy string) ApiApiAmbientV1ProjectsIdAgentsGetRequest { +func (r ApiApiAmbientV1ProjectsIdCredentialsGetRequest) OrderBy(orderBy string) ApiApiAmbientV1ProjectsIdCredentialsGetRequest { r.orderBy = &orderBy return r } // Supplies a comma-separated list of fields to be returned -func (r ApiApiAmbientV1ProjectsIdAgentsGetRequest) Fields(fields string) ApiApiAmbientV1ProjectsIdAgentsGetRequest { +func (r ApiApiAmbientV1ProjectsIdCredentialsGetRequest) Fields(fields string) ApiApiAmbientV1ProjectsIdCredentialsGetRequest { r.fields = &fields return r } -func (r ApiApiAmbientV1ProjectsIdAgentsGetRequest) Execute() (*AgentList, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsIdAgentsGetExecute(r) +// Filter credentials by provider +func (r ApiApiAmbientV1ProjectsIdCredentialsGetRequest) Provider(provider string) ApiApiAmbientV1ProjectsIdCredentialsGetRequest { + r.provider = &provider + return r +} + +func (r ApiApiAmbientV1ProjectsIdCredentialsGetRequest) Execute() (*CredentialList, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdCredentialsGetExecute(r) } /* -ApiAmbientV1ProjectsIdAgentsGet Returns a list of agents in a project +ApiAmbientV1ProjectsIdCredentialsGet Returns a list of credentials in a project @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @return ApiApiAmbientV1ProjectsIdAgentsGetRequest + @return ApiApiAmbientV1ProjectsIdCredentialsGetRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsGet(ctx context.Context, id string) ApiApiAmbientV1ProjectsIdAgentsGetRequest { - return ApiApiAmbientV1ProjectsIdAgentsGetRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdCredentialsGet(ctx context.Context, id string) ApiApiAmbientV1ProjectsIdCredentialsGetRequest { + return ApiApiAmbientV1ProjectsIdCredentialsGetRequest{ ApiService: a, ctx: ctx, id: id, @@ -3639,21 +3682,21 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsGet(ctx context.Context, // Execute executes the request // -// @return AgentList -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsGetExecute(r ApiApiAmbientV1ProjectsIdAgentsGetRequest) (*AgentList, *http.Response, error) { +// @return CredentialList +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdCredentialsGetExecute(r ApiApiAmbientV1ProjectsIdCredentialsGetRequest) (*CredentialList, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet localVarPostBody interface{} formFiles []formFile - localVarReturnValue *AgentList + localVarReturnValue *CredentialList ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsGet") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdCredentialsGet") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/credentials" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) localVarHeaderParams := make(map[string]string) @@ -3681,6 +3724,9 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsGetExecute(r ApiApiAmbie if r.fields != nil { parameterAddToHeaderOrQuery(localVarQueryParams, "fields", r.fields, "form", "") } + if r.provider != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "provider", r.provider, "", "") + } // to determine the Content-Type header localVarHTTPContentTypes := []string{} @@ -3742,17 +3788,6 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsGetExecute(r ApiApiAmbie newErr.model = v return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == 404 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr - } - newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) - newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr - } if localVarHTTPResponse.StatusCode == 500 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) @@ -3778,32 +3813,32 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsGetExecute(r ApiApiAmbie return localVarReturnValue, localVarHTTPResponse, nil } -type ApiApiAmbientV1ProjectsIdAgentsPostRequest struct { +type ApiApiAmbientV1ProjectsIdCredentialsPostRequest struct { ctx context.Context ApiService *DefaultAPIService id string - agent *Agent + credential *Credential } -// Agent data -func (r ApiApiAmbientV1ProjectsIdAgentsPostRequest) Agent(agent Agent) ApiApiAmbientV1ProjectsIdAgentsPostRequest { - r.agent = &agent +// Credential data +func (r ApiApiAmbientV1ProjectsIdCredentialsPostRequest) Credential(credential Credential) ApiApiAmbientV1ProjectsIdCredentialsPostRequest { + r.credential = &credential return r } -func (r ApiApiAmbientV1ProjectsIdAgentsPostRequest) Execute() (*Agent, *http.Response, error) { - return r.ApiService.ApiAmbientV1ProjectsIdAgentsPostExecute(r) +func (r ApiApiAmbientV1ProjectsIdCredentialsPostRequest) Execute() (*Credential, *http.Response, error) { + return r.ApiService.ApiAmbientV1ProjectsIdCredentialsPostExecute(r) } /* -ApiAmbientV1ProjectsIdAgentsPost Create an agent in a project +ApiAmbientV1ProjectsIdCredentialsPost Create a new credential in a project @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). @param id The id of record - @return ApiApiAmbientV1ProjectsIdAgentsPostRequest + @return ApiApiAmbientV1ProjectsIdCredentialsPostRequest */ -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsPost(ctx context.Context, id string) ApiApiAmbientV1ProjectsIdAgentsPostRequest { - return ApiApiAmbientV1ProjectsIdAgentsPostRequest{ +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdCredentialsPost(ctx context.Context, id string) ApiApiAmbientV1ProjectsIdCredentialsPostRequest { + return ApiApiAmbientV1ProjectsIdCredentialsPostRequest{ ApiService: a, ctx: ctx, id: id, @@ -3812,28 +3847,28 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsPost(ctx context.Context // Execute executes the request // -// @return Agent -func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsPostExecute(r ApiApiAmbientV1ProjectsIdAgentsPostRequest) (*Agent, *http.Response, error) { +// @return Credential +func (a *DefaultAPIService) ApiAmbientV1ProjectsIdCredentialsPostExecute(r ApiApiAmbientV1ProjectsIdCredentialsPostRequest) (*Credential, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost localVarPostBody interface{} formFiles []formFile - localVarReturnValue *Agent + localVarReturnValue *Credential ) - localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdAgentsPost") + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DefaultAPIService.ApiAmbientV1ProjectsIdCredentialsPost") if err != nil { return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} } - localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/agents" + localVarPath := localBasePath + "/api/ambient/v1/projects/{id}/credentials" localVarPath = strings.Replace(localVarPath, "{"+"id"+"}", url.PathEscape(parameterValueToString(r.id, "id")), -1) localVarHeaderParams := make(map[string]string) localVarQueryParams := url.Values{} localVarFormParams := url.Values{} - if r.agent == nil { - return localVarReturnValue, nil, reportError("agent is required and must be specified") + if r.credential == nil { + return localVarReturnValue, nil, reportError("credential is required and must be specified") } // to determine the Content-Type header @@ -3854,7 +3889,7 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsPostExecute(r ApiApiAmbi localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept } // body params - localVarPostBody = r.agent + localVarPostBody = r.credential req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) if err != nil { return localVarReturnValue, nil, err @@ -3910,17 +3945,6 @@ func (a *DefaultAPIService) ApiAmbientV1ProjectsIdAgentsPostExecute(r ApiApiAmbi newErr.model = v return localVarReturnValue, localVarHTTPResponse, newErr } - if localVarHTTPResponse.StatusCode == 404 { - var v Error - err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) - if err != nil { - newErr.error = err.Error() - return localVarReturnValue, localVarHTTPResponse, newErr - } - newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) - newErr.model = v - return localVarReturnValue, localVarHTTPResponse, newErr - } if localVarHTTPResponse.StatusCode == 409 { var v Error err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) diff --git a/components/ambient-api-server/pkg/api/openapi/docs/Credential.md b/components/ambient-api-server/pkg/api/openapi/docs/Credential.md index fa1fe27e5..7ee37d7cc 100644 --- a/components/ambient-api-server/pkg/api/openapi/docs/Credential.md +++ b/components/ambient-api-server/pkg/api/openapi/docs/Credential.md @@ -9,6 +9,7 @@ Name | Type | Description | Notes **Href** | Pointer to **string** | | [optional] **CreatedAt** | Pointer to **time.Time** | | [optional] **UpdatedAt** | Pointer to **time.Time** | | [optional] +**ProjectId** | **string** | ID of the project this credential belongs to | **Name** | **string** | | **Description** | Pointer to **string** | | [optional] **Provider** | **string** | | @@ -22,7 +23,7 @@ Name | Type | Description | Notes ### NewCredential -`func NewCredential(name string, provider string, ) *Credential` +`func NewCredential(projectId string, name string, provider string, ) *Credential` NewCredential instantiates a new Credential object This constructor will assign default values to properties that have it defined, @@ -162,6 +163,26 @@ SetUpdatedAt sets UpdatedAt field to given value. HasUpdatedAt returns a boolean if a field has been set. +### GetProjectId + +`func (o *Credential) GetProjectId() string` + +GetProjectId returns the ProjectId field if non-nil, zero value otherwise. + +### GetProjectIdOk + +`func (o *Credential) GetProjectIdOk() (*string, bool)` + +GetProjectIdOk returns a tuple with the ProjectId field if it's non-nil, zero value otherwise +and a boolean to check if the value has been set. + +### SetProjectId + +`func (o *Credential) SetProjectId(v string)` + +SetProjectId sets ProjectId field to given value. + + ### GetName `func (o *Credential) GetName() string` diff --git a/components/ambient-api-server/pkg/api/openapi/docs/DefaultAPI.md b/components/ambient-api-server/pkg/api/openapi/docs/DefaultAPI.md index fb7a61ef6..f445b5cde 100644 --- a/components/ambient-api-server/pkg/api/openapi/docs/DefaultAPI.md +++ b/components/ambient-api-server/pkg/api/openapi/docs/DefaultAPI.md @@ -4,12 +4,6 @@ All URIs are relative to *http://localhost:8000* Method | HTTP request | Description ------------- | ------------- | ------------- -[**ApiAmbientV1CredentialsGet**](DefaultAPI.md#ApiAmbientV1CredentialsGet) | **Get** /api/ambient/v1/credentials | Returns a list of credentials -[**ApiAmbientV1CredentialsIdDelete**](DefaultAPI.md#ApiAmbientV1CredentialsIdDelete) | **Delete** /api/ambient/v1/credentials/{id} | Delete a credential -[**ApiAmbientV1CredentialsIdGet**](DefaultAPI.md#ApiAmbientV1CredentialsIdGet) | **Get** /api/ambient/v1/credentials/{id} | Get an credential by id -[**ApiAmbientV1CredentialsIdPatch**](DefaultAPI.md#ApiAmbientV1CredentialsIdPatch) | **Patch** /api/ambient/v1/credentials/{id} | Update an credential -[**ApiAmbientV1CredentialsIdTokenGet**](DefaultAPI.md#ApiAmbientV1CredentialsIdTokenGet) | **Get** /api/ambient/v1/credentials/{id}/token | Get a decrypted token for a credential -[**ApiAmbientV1CredentialsPost**](DefaultAPI.md#ApiAmbientV1CredentialsPost) | **Post** /api/ambient/v1/credentials | Create a new credential [**ApiAmbientV1ProjectSettingsGet**](DefaultAPI.md#ApiAmbientV1ProjectSettingsGet) | **Get** /api/ambient/v1/project_settings | Returns a list of project settings [**ApiAmbientV1ProjectSettingsIdDelete**](DefaultAPI.md#ApiAmbientV1ProjectSettingsIdDelete) | **Delete** /api/ambient/v1/project_settings/{id} | Delete a project settings by id [**ApiAmbientV1ProjectSettingsIdGet**](DefaultAPI.md#ApiAmbientV1ProjectSettingsIdGet) | **Get** /api/ambient/v1/project_settings/{id} | Get a project settings by id @@ -28,6 +22,12 @@ Method | HTTP request | Description [**ApiAmbientV1ProjectsIdAgentsAgentIdStartPost**](DefaultAPI.md#ApiAmbientV1ProjectsIdAgentsAgentIdStartPost) | **Post** /api/ambient/v1/projects/{id}/agents/{agent_id}/start | Start an agent — creates a Session (idempotent) [**ApiAmbientV1ProjectsIdAgentsGet**](DefaultAPI.md#ApiAmbientV1ProjectsIdAgentsGet) | **Get** /api/ambient/v1/projects/{id}/agents | Returns a list of agents in a project [**ApiAmbientV1ProjectsIdAgentsPost**](DefaultAPI.md#ApiAmbientV1ProjectsIdAgentsPost) | **Post** /api/ambient/v1/projects/{id}/agents | Create an agent in a project +[**ApiAmbientV1ProjectsIdCredentialsCredIdDelete**](DefaultAPI.md#ApiAmbientV1ProjectsIdCredentialsCredIdDelete) | **Delete** /api/ambient/v1/projects/{id}/credentials/{cred_id} | Delete a credential +[**ApiAmbientV1ProjectsIdCredentialsCredIdGet**](DefaultAPI.md#ApiAmbientV1ProjectsIdCredentialsCredIdGet) | **Get** /api/ambient/v1/projects/{id}/credentials/{cred_id} | Get a credential by id +[**ApiAmbientV1ProjectsIdCredentialsCredIdPatch**](DefaultAPI.md#ApiAmbientV1ProjectsIdCredentialsCredIdPatch) | **Patch** /api/ambient/v1/projects/{id}/credentials/{cred_id} | Update a credential +[**ApiAmbientV1ProjectsIdCredentialsCredIdTokenGet**](DefaultAPI.md#ApiAmbientV1ProjectsIdCredentialsCredIdTokenGet) | **Get** /api/ambient/v1/projects/{id}/credentials/{cred_id}/token | Get a decrypted token for a credential +[**ApiAmbientV1ProjectsIdCredentialsGet**](DefaultAPI.md#ApiAmbientV1ProjectsIdCredentialsGet) | **Get** /api/ambient/v1/projects/{id}/credentials | Returns a list of credentials in a project +[**ApiAmbientV1ProjectsIdCredentialsPost**](DefaultAPI.md#ApiAmbientV1ProjectsIdCredentialsPost) | **Post** /api/ambient/v1/projects/{id}/credentials | Create a new credential in a project [**ApiAmbientV1ProjectsIdDelete**](DefaultAPI.md#ApiAmbientV1ProjectsIdDelete) | **Delete** /api/ambient/v1/projects/{id} | Delete a project by id [**ApiAmbientV1ProjectsIdGet**](DefaultAPI.md#ApiAmbientV1ProjectsIdGet) | **Get** /api/ambient/v1/projects/{id} | Get a project by id [**ApiAmbientV1ProjectsIdHomeGet**](DefaultAPI.md#ApiAmbientV1ProjectsIdHomeGet) | **Get** /api/ambient/v1/projects/{id}/home | Project home — latest status for every Agent in this project @@ -58,11 +58,11 @@ Method | HTTP request | Description -## ApiAmbientV1CredentialsGet +## ApiAmbientV1ProjectSettingsGet -> CredentialList ApiAmbientV1CredentialsGet(ctx).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Provider(provider).Execute() +> ProjectSettingsList ApiAmbientV1ProjectSettingsGet(ctx).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Execute() -Returns a list of credentials +Returns a list of project settings ### Example @@ -82,17 +82,16 @@ func main() { search := "search_example" // string | Specifies the search criteria (optional) orderBy := "orderBy_example" // string | Specifies the order by criteria (optional) fields := "fields_example" // string | Supplies a comma-separated list of fields to be returned (optional) - provider := "provider_example" // string | Filter credentials by provider (optional) configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1CredentialsGet(context.Background()).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Provider(provider).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectSettingsGet(context.Background()).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1CredentialsGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectSettingsGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1CredentialsGet`: CredentialList - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1CredentialsGet`: %v\n", resp) + // response from `ApiAmbientV1ProjectSettingsGet`: ProjectSettingsList + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectSettingsGet`: %v\n", resp) } ``` @@ -102,7 +101,7 @@ func main() { ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1CredentialsGetRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectSettingsGetRequest struct via the builder pattern Name | Type | Description | Notes @@ -112,11 +111,10 @@ Name | Type | Description | Notes **search** | **string** | Specifies the search criteria | **orderBy** | **string** | Specifies the order by criteria | **fields** | **string** | Supplies a comma-separated list of fields to be returned | - **provider** | **string** | Filter credentials by provider | ### Return type -[**CredentialList**](CredentialList.md) +[**ProjectSettingsList**](ProjectSettingsList.md) ### Authorization @@ -132,11 +130,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1CredentialsIdDelete +## ApiAmbientV1ProjectSettingsIdDelete -> ApiAmbientV1CredentialsIdDelete(ctx, id).Execute() +> ApiAmbientV1ProjectSettingsIdDelete(ctx, id).Execute() -Delete a credential +Delete a project settings by id ### Example @@ -155,9 +153,9 @@ func main() { configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - r, err := apiClient.DefaultAPI.ApiAmbientV1CredentialsIdDelete(context.Background(), id).Execute() + r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectSettingsIdDelete(context.Background(), id).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1CredentialsIdDelete``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectSettingsIdDelete``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } } @@ -173,7 +171,7 @@ Name | Type | Description | Notes ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1CredentialsIdDeleteRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectSettingsIdDeleteRequest struct via the builder pattern Name | Type | Description | Notes @@ -198,11 +196,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1CredentialsIdGet +## ApiAmbientV1ProjectSettingsIdGet -> Credential ApiAmbientV1CredentialsIdGet(ctx, id).Execute() +> ProjectSettings ApiAmbientV1ProjectSettingsIdGet(ctx, id).Execute() -Get an credential by id +Get a project settings by id ### Example @@ -221,13 +219,13 @@ func main() { configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1CredentialsIdGet(context.Background(), id).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectSettingsIdGet(context.Background(), id).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1CredentialsIdGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectSettingsIdGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1CredentialsIdGet`: Credential - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1CredentialsIdGet`: %v\n", resp) + // response from `ApiAmbientV1ProjectSettingsIdGet`: ProjectSettings + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectSettingsIdGet`: %v\n", resp) } ``` @@ -241,7 +239,7 @@ Name | Type | Description | Notes ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1CredentialsIdGetRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectSettingsIdGetRequest struct via the builder pattern Name | Type | Description | Notes @@ -250,7 +248,7 @@ Name | Type | Description | Notes ### Return type -[**Credential**](Credential.md) +[**ProjectSettings**](ProjectSettings.md) ### Authorization @@ -266,11 +264,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1CredentialsIdPatch +## ApiAmbientV1ProjectSettingsIdPatch -> Credential ApiAmbientV1CredentialsIdPatch(ctx, id).CredentialPatchRequest(credentialPatchRequest).Execute() +> ProjectSettings ApiAmbientV1ProjectSettingsIdPatch(ctx, id).ProjectSettingsPatchRequest(projectSettingsPatchRequest).Execute() -Update an credential +Update a project settings ### Example @@ -286,17 +284,17 @@ import ( func main() { id := "id_example" // string | The id of record - credentialPatchRequest := *openapiclient.NewCredentialPatchRequest() // CredentialPatchRequest | Updated credential data + projectSettingsPatchRequest := *openapiclient.NewProjectSettingsPatchRequest() // ProjectSettingsPatchRequest | Updated project settings data configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1CredentialsIdPatch(context.Background(), id).CredentialPatchRequest(credentialPatchRequest).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectSettingsIdPatch(context.Background(), id).ProjectSettingsPatchRequest(projectSettingsPatchRequest).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1CredentialsIdPatch``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectSettingsIdPatch``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1CredentialsIdPatch`: Credential - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1CredentialsIdPatch`: %v\n", resp) + // response from `ApiAmbientV1ProjectSettingsIdPatch`: ProjectSettings + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectSettingsIdPatch`: %v\n", resp) } ``` @@ -310,17 +308,17 @@ Name | Type | Description | Notes ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1CredentialsIdPatchRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectSettingsIdPatchRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **credentialPatchRequest** | [**CredentialPatchRequest**](CredentialPatchRequest.md) | Updated credential data | + **projectSettingsPatchRequest** | [**ProjectSettingsPatchRequest**](ProjectSettingsPatchRequest.md) | Updated project settings data | ### Return type -[**Credential**](Credential.md) +[**ProjectSettings**](ProjectSettings.md) ### Authorization @@ -336,13 +334,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1CredentialsIdTokenGet - -> CredentialTokenResponse ApiAmbientV1CredentialsIdTokenGet(ctx, id).Execute() - -Get a decrypted token for a credential +## ApiAmbientV1ProjectSettingsPost +> ProjectSettings ApiAmbientV1ProjectSettingsPost(ctx).ProjectSettings(projectSettings).Execute() +Create a new project settings ### Example @@ -357,40 +353,36 @@ import ( ) func main() { - id := "id_example" // string | The id of record + projectSettings := *openapiclient.NewProjectSettings("ProjectId_example") // ProjectSettings | Project settings data configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1CredentialsIdTokenGet(context.Background(), id).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectSettingsPost(context.Background()).ProjectSettings(projectSettings).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1CredentialsIdTokenGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectSettingsPost``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1CredentialsIdTokenGet`: CredentialTokenResponse - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1CredentialsIdTokenGet`: %v\n", resp) + // response from `ApiAmbientV1ProjectSettingsPost`: ProjectSettings + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectSettingsPost`: %v\n", resp) } ``` ### Path Parameters -Name | Type | Description | Notes -------------- | ------------- | ------------- | ------------- -**ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. -**id** | **string** | The id of record | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1CredentialsIdTokenGetRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectSettingsPostRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - + **projectSettings** | [**ProjectSettings**](ProjectSettings.md) | Project settings data | ### Return type -[**CredentialTokenResponse**](CredentialTokenResponse.md) +[**ProjectSettings**](ProjectSettings.md) ### Authorization @@ -398,7 +390,7 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: Not defined +- **Content-Type**: application/json - **Accept**: application/json [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) @@ -406,11 +398,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1CredentialsPost +## ApiAmbientV1ProjectsGet -> Credential ApiAmbientV1CredentialsPost(ctx).Credential(credential).Execute() +> ProjectList ApiAmbientV1ProjectsGet(ctx).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Execute() -Create a new credential +Returns a list of projects ### Example @@ -425,17 +417,21 @@ import ( ) func main() { - credential := *openapiclient.NewCredential("Name_example", "Provider_example") // Credential | Credential data + page := int32(56) // int32 | Page number of record list when record list exceeds specified page size (optional) (default to 1) + size := int32(56) // int32 | Maximum number of records to return (optional) (default to 100) + search := "search_example" // string | Specifies the search criteria (optional) + orderBy := "orderBy_example" // string | Specifies the order by criteria (optional) + fields := "fields_example" // string | Supplies a comma-separated list of fields to be returned (optional) configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1CredentialsPost(context.Background()).Credential(credential).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsGet(context.Background()).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1CredentialsPost``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1CredentialsPost`: Credential - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1CredentialsPost`: %v\n", resp) + // response from `ApiAmbientV1ProjectsGet`: ProjectList + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsGet`: %v\n", resp) } ``` @@ -445,16 +441,20 @@ func main() { ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1CredentialsPostRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsGetRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **credential** | [**Credential**](Credential.md) | Credential data | + **page** | **int32** | Page number of record list when record list exceeds specified page size | [default to 1] + **size** | **int32** | Maximum number of records to return | [default to 100] + **search** | **string** | Specifies the search criteria | + **orderBy** | **string** | Specifies the order by criteria | + **fields** | **string** | Supplies a comma-separated list of fields to be returned | ### Return type -[**Credential**](Credential.md) +[**ProjectList**](ProjectList.md) ### Authorization @@ -462,7 +462,7 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: application/json +- **Content-Type**: Not defined - **Accept**: application/json [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) @@ -470,11 +470,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectSettingsGet +## ApiAmbientV1ProjectsIdAgentsAgentIdDelete -> ProjectSettingsList ApiAmbientV1ProjectSettingsGet(ctx).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Execute() +> ApiAmbientV1ProjectsIdAgentsAgentIdDelete(ctx, id, agentId).Execute() -Returns a list of project settings +Delete an agent from a project ### Example @@ -489,44 +489,41 @@ import ( ) func main() { - page := int32(56) // int32 | Page number of record list when record list exceeds specified page size (optional) (default to 1) - size := int32(56) // int32 | Maximum number of records to return (optional) (default to 100) - search := "search_example" // string | Specifies the search criteria (optional) - orderBy := "orderBy_example" // string | Specifies the order by criteria (optional) - fields := "fields_example" // string | Supplies a comma-separated list of fields to be returned (optional) + id := "id_example" // string | The id of record + agentId := "agentId_example" // string | The id of the agent configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectSettingsGet(context.Background()).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Execute() + r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdDelete(context.Background(), id, agentId).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectSettingsGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdDelete``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectSettingsGet`: ProjectSettingsList - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectSettingsGet`: %v\n", resp) } ``` ### Path Parameters +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- +**ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. +**id** | **string** | The id of record | +**agentId** | **string** | The id of the agent | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectSettingsGetRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **page** | **int32** | Page number of record list when record list exceeds specified page size | [default to 1] - **size** | **int32** | Maximum number of records to return | [default to 100] - **search** | **string** | Specifies the search criteria | - **orderBy** | **string** | Specifies the order by criteria | - **fields** | **string** | Supplies a comma-separated list of fields to be returned | + + ### Return type -[**ProjectSettingsList**](ProjectSettingsList.md) + (empty response body) ### Authorization @@ -542,11 +539,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectSettingsIdDelete +## ApiAmbientV1ProjectsIdAgentsAgentIdGet -> ApiAmbientV1ProjectSettingsIdDelete(ctx, id).Execute() +> Agent ApiAmbientV1ProjectsIdAgentsAgentIdGet(ctx, id, agentId).Execute() -Delete a project settings by id +Get an agent by id ### Example @@ -562,14 +559,17 @@ import ( func main() { id := "id_example" // string | The id of record + agentId := "agentId_example" // string | The id of the agent configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectSettingsIdDelete(context.Background(), id).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdGet(context.Background(), id, agentId).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectSettingsIdDelete``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } + // response from `ApiAmbientV1ProjectsIdAgentsAgentIdGet`: Agent + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdGet`: %v\n", resp) } ``` @@ -580,19 +580,21 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **id** | **string** | The id of record | +**agentId** | **string** | The id of the agent | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectSettingsIdDeleteRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- + ### Return type - (empty response body) +[**Agent**](Agent.md) ### Authorization @@ -608,11 +610,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectSettingsIdGet +## ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet -> ProjectSettings ApiAmbientV1ProjectSettingsIdGet(ctx, id).Execute() +> StartResponse ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet(ctx, id, agentId).Execute() -Get a project settings by id +Preview start context (dry run — no session created) ### Example @@ -628,16 +630,17 @@ import ( func main() { id := "id_example" // string | The id of record + agentId := "agentId_example" // string | The id of the agent configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectSettingsIdGet(context.Background(), id).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet(context.Background(), id, agentId).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectSettingsIdGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectSettingsIdGet`: ProjectSettings - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectSettingsIdGet`: %v\n", resp) + // response from `ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet`: StartResponse + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet`: %v\n", resp) } ``` @@ -648,19 +651,21 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **id** | **string** | The id of record | +**agentId** | **string** | The id of the agent | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectSettingsIdGetRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- + ### Return type -[**ProjectSettings**](ProjectSettings.md) +[**StartResponse**](StartResponse.md) ### Authorization @@ -676,11 +681,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectSettingsIdPatch +## ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet -> ProjectSettings ApiAmbientV1ProjectSettingsIdPatch(ctx, id).ProjectSettingsPatchRequest(projectSettingsPatchRequest).Execute() +> InboxMessageList ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet(ctx, id, agentId).Page(page).Size(size).Execute() -Update a project settings +Read inbox messages for an agent (unread first) ### Example @@ -696,17 +701,19 @@ import ( func main() { id := "id_example" // string | The id of record - projectSettingsPatchRequest := *openapiclient.NewProjectSettingsPatchRequest() // ProjectSettingsPatchRequest | Updated project settings data + agentId := "agentId_example" // string | The id of the agent + page := int32(56) // int32 | Page number of record list when record list exceeds specified page size (optional) (default to 1) + size := int32(56) // int32 | Maximum number of records to return (optional) (default to 100) configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectSettingsIdPatch(context.Background(), id).ProjectSettingsPatchRequest(projectSettingsPatchRequest).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet(context.Background(), id, agentId).Page(page).Size(size).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectSettingsIdPatch``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectSettingsIdPatch`: ProjectSettings - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectSettingsIdPatch`: %v\n", resp) + // response from `ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet`: InboxMessageList + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet`: %v\n", resp) } ``` @@ -717,20 +724,23 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **id** | **string** | The id of record | +**agentId** | **string** | The id of the agent | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectSettingsIdPatchRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **projectSettingsPatchRequest** | [**ProjectSettingsPatchRequest**](ProjectSettingsPatchRequest.md) | Updated project settings data | + + **page** | **int32** | Page number of record list when record list exceeds specified page size | [default to 1] + **size** | **int32** | Maximum number of records to return | [default to 100] ### Return type -[**ProjectSettings**](ProjectSettings.md) +[**InboxMessageList**](InboxMessageList.md) ### Authorization @@ -738,7 +748,7 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: application/json +- **Content-Type**: Not defined - **Accept**: application/json [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) @@ -746,11 +756,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectSettingsPost +## ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete -> ProjectSettings ApiAmbientV1ProjectSettingsPost(ctx).ProjectSettings(projectSettings).Execute() +> ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete(ctx, id, agentId, msgId).Execute() -Create a new project settings +Delete an inbox message ### Example @@ -765,36 +775,44 @@ import ( ) func main() { - projectSettings := *openapiclient.NewProjectSettings("ProjectId_example") // ProjectSettings | Project settings data + id := "id_example" // string | The id of record + agentId := "agentId_example" // string | The id of the agent + msgId := "msgId_example" // string | The id of the inbox message configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectSettingsPost(context.Background()).ProjectSettings(projectSettings).Execute() + r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete(context.Background(), id, agentId, msgId).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectSettingsPost``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectSettingsPost`: ProjectSettings - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectSettingsPost`: %v\n", resp) } ``` ### Path Parameters +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- +**ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. +**id** | **string** | The id of record | +**agentId** | **string** | The id of the agent | +**msgId** | **string** | The id of the inbox message | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectSettingsPostRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **projectSettings** | [**ProjectSettings**](ProjectSettings.md) | Project settings data | + + + ### Return type -[**ProjectSettings**](ProjectSettings.md) + (empty response body) ### Authorization @@ -802,7 +820,7 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: application/json +- **Content-Type**: Not defined - **Accept**: application/json [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) @@ -810,11 +828,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsGet +## ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch -> ProjectList ApiAmbientV1ProjectsGet(ctx).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Execute() +> InboxMessage ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch(ctx, id, agentId, msgId).InboxMessagePatchRequest(inboxMessagePatchRequest).Execute() -Returns a list of projects +Mark an inbox message as read ### Example @@ -829,44 +847,48 @@ import ( ) func main() { - page := int32(56) // int32 | Page number of record list when record list exceeds specified page size (optional) (default to 1) - size := int32(56) // int32 | Maximum number of records to return (optional) (default to 100) - search := "search_example" // string | Specifies the search criteria (optional) - orderBy := "orderBy_example" // string | Specifies the order by criteria (optional) - fields := "fields_example" // string | Supplies a comma-separated list of fields to be returned (optional) + id := "id_example" // string | The id of record + agentId := "agentId_example" // string | The id of the agent + msgId := "msgId_example" // string | The id of the inbox message + inboxMessagePatchRequest := *openapiclient.NewInboxMessagePatchRequest() // InboxMessagePatchRequest | Inbox message patch configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsGet(context.Background()).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch(context.Background(), id, agentId, msgId).InboxMessagePatchRequest(inboxMessagePatchRequest).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectsGet`: ProjectList - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsGet`: %v\n", resp) + // response from `ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch`: InboxMessage + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch`: %v\n", resp) } ``` ### Path Parameters +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- +**ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. +**id** | **string** | The id of record | +**agentId** | **string** | The id of the agent | +**msgId** | **string** | The id of the inbox message | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsGetRequest struct via the builder pattern - +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest struct via the builder pattern -Name | Type | Description | Notes -------------- | ------------- | ------------- | ------------- - **page** | **int32** | Page number of record list when record list exceeds specified page size | [default to 1] - **size** | **int32** | Maximum number of records to return | [default to 100] - **search** | **string** | Specifies the search criteria | - **orderBy** | **string** | Specifies the order by criteria | - **fields** | **string** | Supplies a comma-separated list of fields to be returned | + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + + + + **inboxMessagePatchRequest** | [**InboxMessagePatchRequest**](InboxMessagePatchRequest.md) | Inbox message patch | ### Return type -[**ProjectList**](ProjectList.md) +[**InboxMessage**](InboxMessage.md) ### Authorization @@ -874,7 +896,7 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: Not defined +- **Content-Type**: application/json - **Accept**: application/json [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) @@ -882,11 +904,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsIdAgentsAgentIdDelete +## ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost -> ApiAmbientV1ProjectsIdAgentsAgentIdDelete(ctx, id, agentId).Execute() +> InboxMessage ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost(ctx, id, agentId).InboxMessage(inboxMessage).Execute() -Delete an agent from a project +Send a message to an agent's inbox ### Example @@ -903,14 +925,17 @@ import ( func main() { id := "id_example" // string | The id of record agentId := "agentId_example" // string | The id of the agent + inboxMessage := *openapiclient.NewInboxMessage("AgentId_example", "Body_example") // InboxMessage | Inbox message to send configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdDelete(context.Background(), id, agentId).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost(context.Background(), id, agentId).InboxMessage(inboxMessage).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdDelete``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } + // response from `ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost`: InboxMessage + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost`: %v\n", resp) } ``` @@ -925,17 +950,18 @@ Name | Type | Description | Notes ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdDeleteRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- + **inboxMessage** | [**InboxMessage**](InboxMessage.md) | Inbox message to send | ### Return type - (empty response body) +[**InboxMessage**](InboxMessage.md) ### Authorization @@ -943,7 +969,7 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: Not defined +- **Content-Type**: application/json - **Accept**: application/json [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) @@ -951,11 +977,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsIdAgentsAgentIdGet +## ApiAmbientV1ProjectsIdAgentsAgentIdPatch -> Agent ApiAmbientV1ProjectsIdAgentsAgentIdGet(ctx, id, agentId).Execute() +> Agent ApiAmbientV1ProjectsIdAgentsAgentIdPatch(ctx, id, agentId).AgentPatchRequest(agentPatchRequest).Execute() -Get an agent by id +Update an agent (name, prompt, labels, annotations) ### Example @@ -972,16 +998,17 @@ import ( func main() { id := "id_example" // string | The id of record agentId := "agentId_example" // string | The id of the agent + agentPatchRequest := *openapiclient.NewAgentPatchRequest() // AgentPatchRequest | Updated agent data configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdGet(context.Background(), id, agentId).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdPatch(context.Background(), id, agentId).AgentPatchRequest(agentPatchRequest).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdPatch``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectsIdAgentsAgentIdGet`: Agent - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdGet`: %v\n", resp) + // response from `ApiAmbientV1ProjectsIdAgentsAgentIdPatch`: Agent + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdPatch`: %v\n", resp) } ``` @@ -996,13 +1023,14 @@ Name | Type | Description | Notes ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdGetRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- + **agentPatchRequest** | [**AgentPatchRequest**](AgentPatchRequest.md) | Updated agent data | ### Return type @@ -1014,7 +1042,7 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: Not defined +- **Content-Type**: application/json - **Accept**: application/json [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) @@ -1022,11 +1050,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet +## ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet -> StartResponse ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet(ctx, id, agentId).Execute() +> AgentSessionList ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet(ctx, id, agentId).Page(page).Size(size).Execute() -Preview start context (dry run — no session created) +Get session run history for an agent ### Example @@ -1043,16 +1071,18 @@ import ( func main() { id := "id_example" // string | The id of record agentId := "agentId_example" // string | The id of the agent + page := int32(56) // int32 | Page number of record list when record list exceeds specified page size (optional) (default to 1) + size := int32(56) // int32 | Maximum number of records to return (optional) (default to 100) configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet(context.Background(), id, agentId).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet(context.Background(), id, agentId).Page(page).Size(size).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet`: StartResponse - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGet`: %v\n", resp) + // response from `ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet`: AgentSessionList + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet`: %v\n", resp) } ``` @@ -1067,17 +1097,19 @@ Name | Type | Description | Notes ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdIgnitionGetRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- + **page** | **int32** | Page number of record list when record list exceeds specified page size | [default to 1] + **size** | **int32** | Maximum number of records to return | [default to 100] ### Return type -[**StartResponse**](StartResponse.md) +[**AgentSessionList**](AgentSessionList.md) ### Authorization @@ -1093,11 +1125,13 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet +## ApiAmbientV1ProjectsIdAgentsAgentIdStartPost + +> StartResponse ApiAmbientV1ProjectsIdAgentsAgentIdStartPost(ctx, id, agentId).StartRequest(startRequest).Execute() + +Start an agent — creates a Session (idempotent) -> InboxMessageList ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet(ctx, id, agentId).Page(page).Size(size).Execute() -Read inbox messages for an agent (unread first) ### Example @@ -1114,18 +1148,17 @@ import ( func main() { id := "id_example" // string | The id of record agentId := "agentId_example" // string | The id of the agent - page := int32(56) // int32 | Page number of record list when record list exceeds specified page size (optional) (default to 1) - size := int32(56) // int32 | Maximum number of records to return (optional) (default to 100) + startRequest := *openapiclient.NewStartRequest() // StartRequest | Optional start parameters (optional) configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet(context.Background(), id, agentId).Page(page).Size(size).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdStartPost(context.Background(), id, agentId).StartRequest(startRequest).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdStartPost``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet`: InboxMessageList - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxGet`: %v\n", resp) + // response from `ApiAmbientV1ProjectsIdAgentsAgentIdStartPost`: StartResponse + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdStartPost`: %v\n", resp) } ``` @@ -1140,19 +1173,18 @@ Name | Type | Description | Notes ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdInboxGetRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **page** | **int32** | Page number of record list when record list exceeds specified page size | [default to 1] - **size** | **int32** | Maximum number of records to return | [default to 100] + **startRequest** | [**StartRequest**](StartRequest.md) | Optional start parameters | ### Return type -[**InboxMessageList**](InboxMessageList.md) +[**StartResponse**](StartResponse.md) ### Authorization @@ -1160,7 +1192,7 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: Not defined +- **Content-Type**: application/json - **Accept**: application/json [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) @@ -1168,11 +1200,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete +## ApiAmbientV1ProjectsIdAgentsGet -> ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete(ctx, id, agentId, msgId).Execute() +> AgentList ApiAmbientV1ProjectsIdAgentsGet(ctx, id).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Execute() -Delete an inbox message +Returns a list of agents in a project ### Example @@ -1188,16 +1220,21 @@ import ( func main() { id := "id_example" // string | The id of record - agentId := "agentId_example" // string | The id of the agent - msgId := "msgId_example" // string | The id of the inbox message + page := int32(56) // int32 | Page number of record list when record list exceeds specified page size (optional) (default to 1) + size := int32(56) // int32 | Maximum number of records to return (optional) (default to 100) + search := "search_example" // string | Specifies the search criteria (optional) + orderBy := "orderBy_example" // string | Specifies the order by criteria (optional) + fields := "fields_example" // string | Supplies a comma-separated list of fields to be returned (optional) configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete(context.Background(), id, agentId, msgId).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsGet(context.Background(), id).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDelete``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } + // response from `ApiAmbientV1ProjectsIdAgentsGet`: AgentList + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsGet`: %v\n", resp) } ``` @@ -1208,23 +1245,24 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **id** | **string** | The id of record | -**agentId** | **string** | The id of the agent | -**msgId** | **string** | The id of the inbox message | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdDeleteRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsGetRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - - + **page** | **int32** | Page number of record list when record list exceeds specified page size | [default to 1] + **size** | **int32** | Maximum number of records to return | [default to 100] + **search** | **string** | Specifies the search criteria | + **orderBy** | **string** | Specifies the order by criteria | + **fields** | **string** | Supplies a comma-separated list of fields to be returned | ### Return type - (empty response body) +[**AgentList**](AgentList.md) ### Authorization @@ -1240,11 +1278,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch +## ApiAmbientV1ProjectsIdAgentsPost -> InboxMessage ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch(ctx, id, agentId, msgId).InboxMessagePatchRequest(inboxMessagePatchRequest).Execute() +> Agent ApiAmbientV1ProjectsIdAgentsPost(ctx, id).Agent(agent).Execute() -Mark an inbox message as read +Create an agent in a project ### Example @@ -1260,19 +1298,17 @@ import ( func main() { id := "id_example" // string | The id of record - agentId := "agentId_example" // string | The id of the agent - msgId := "msgId_example" // string | The id of the inbox message - inboxMessagePatchRequest := *openapiclient.NewInboxMessagePatchRequest() // InboxMessagePatchRequest | Inbox message patch + agent := *openapiclient.NewAgent("ProjectId_example", "Name_example") // Agent | Agent data configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch(context.Background(), id, agentId, msgId).InboxMessagePatchRequest(inboxMessagePatchRequest).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsPost(context.Background(), id).Agent(agent).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsPost``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch`: InboxMessage - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatch`: %v\n", resp) + // response from `ApiAmbientV1ProjectsIdAgentsPost`: Agent + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsPost`: %v\n", resp) } ``` @@ -1283,24 +1319,20 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **id** | **string** | The id of record | -**agentId** | **string** | The id of the agent | -**msgId** | **string** | The id of the inbox message | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdInboxMsgIdPatchRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsPostRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - - - **inboxMessagePatchRequest** | [**InboxMessagePatchRequest**](InboxMessagePatchRequest.md) | Inbox message patch | + **agent** | [**Agent**](Agent.md) | Agent data | ### Return type -[**InboxMessage**](InboxMessage.md) +[**Agent**](Agent.md) ### Authorization @@ -1316,11 +1348,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost +## ApiAmbientV1ProjectsIdCredentialsCredIdDelete -> InboxMessage ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost(ctx, id, agentId).InboxMessage(inboxMessage).Execute() +> ApiAmbientV1ProjectsIdCredentialsCredIdDelete(ctx, id, credId).Execute() -Send a message to an agent's inbox +Delete a credential ### Example @@ -1336,18 +1368,15 @@ import ( func main() { id := "id_example" // string | The id of record - agentId := "agentId_example" // string | The id of the agent - inboxMessage := *openapiclient.NewInboxMessage("AgentId_example", "Body_example") // InboxMessage | Inbox message to send + credId := "credId_example" // string | The id of the credential configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost(context.Background(), id, agentId).InboxMessage(inboxMessage).Execute() + r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdDelete(context.Background(), id, credId).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdDelete``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost`: InboxMessage - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdInboxPost`: %v\n", resp) } ``` @@ -1358,22 +1387,21 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **id** | **string** | The id of record | -**agentId** | **string** | The id of the agent | +**credId** | **string** | The id of the credential | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdInboxPostRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdCredentialsCredIdDeleteRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **inboxMessage** | [**InboxMessage**](InboxMessage.md) | Inbox message to send | ### Return type -[**InboxMessage**](InboxMessage.md) + (empty response body) ### Authorization @@ -1381,7 +1409,7 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: application/json +- **Content-Type**: Not defined - **Accept**: application/json [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) @@ -1389,11 +1417,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsIdAgentsAgentIdPatch +## ApiAmbientV1ProjectsIdCredentialsCredIdGet -> Agent ApiAmbientV1ProjectsIdAgentsAgentIdPatch(ctx, id, agentId).AgentPatchRequest(agentPatchRequest).Execute() +> Credential ApiAmbientV1ProjectsIdCredentialsCredIdGet(ctx, id, credId).Execute() -Update an agent (name, prompt, labels, annotations) +Get a credential by id ### Example @@ -1409,18 +1437,17 @@ import ( func main() { id := "id_example" // string | The id of record - agentId := "agentId_example" // string | The id of the agent - agentPatchRequest := *openapiclient.NewAgentPatchRequest() // AgentPatchRequest | Updated agent data + credId := "credId_example" // string | The id of the credential configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdPatch(context.Background(), id, agentId).AgentPatchRequest(agentPatchRequest).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdGet(context.Background(), id, credId).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdPatch``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectsIdAgentsAgentIdPatch`: Agent - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdPatch`: %v\n", resp) + // response from `ApiAmbientV1ProjectsIdCredentialsCredIdGet`: Credential + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdGet`: %v\n", resp) } ``` @@ -1431,22 +1458,21 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **id** | **string** | The id of record | -**agentId** | **string** | The id of the agent | +**credId** | **string** | The id of the credential | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdPatchRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdCredentialsCredIdGetRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **agentPatchRequest** | [**AgentPatchRequest**](AgentPatchRequest.md) | Updated agent data | ### Return type -[**Agent**](Agent.md) +[**Credential**](Credential.md) ### Authorization @@ -1454,7 +1480,7 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: application/json +- **Content-Type**: Not defined - **Accept**: application/json [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) @@ -1462,11 +1488,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet +## ApiAmbientV1ProjectsIdCredentialsCredIdPatch -> AgentSessionList ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet(ctx, id, agentId).Page(page).Size(size).Execute() +> Credential ApiAmbientV1ProjectsIdCredentialsCredIdPatch(ctx, id, credId).CredentialPatchRequest(credentialPatchRequest).Execute() -Get session run history for an agent +Update a credential ### Example @@ -1482,19 +1508,18 @@ import ( func main() { id := "id_example" // string | The id of record - agentId := "agentId_example" // string | The id of the agent - page := int32(56) // int32 | Page number of record list when record list exceeds specified page size (optional) (default to 1) - size := int32(56) // int32 | Maximum number of records to return (optional) (default to 100) + credId := "credId_example" // string | The id of the credential + credentialPatchRequest := *openapiclient.NewCredentialPatchRequest() // CredentialPatchRequest | Updated credential data configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet(context.Background(), id, agentId).Page(page).Size(size).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdPatch(context.Background(), id, credId).CredentialPatchRequest(credentialPatchRequest).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdPatch``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet`: AgentSessionList - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdSessionsGet`: %v\n", resp) + // response from `ApiAmbientV1ProjectsIdCredentialsCredIdPatch`: Credential + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdPatch`: %v\n", resp) } ``` @@ -1505,23 +1530,22 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **id** | **string** | The id of record | -**agentId** | **string** | The id of the agent | +**credId** | **string** | The id of the credential | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdSessionsGetRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdCredentialsCredIdPatchRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **page** | **int32** | Page number of record list when record list exceeds specified page size | [default to 1] - **size** | **int32** | Maximum number of records to return | [default to 100] + **credentialPatchRequest** | [**CredentialPatchRequest**](CredentialPatchRequest.md) | Updated credential data | ### Return type -[**AgentSessionList**](AgentSessionList.md) +[**Credential**](Credential.md) ### Authorization @@ -1529,7 +1553,7 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: Not defined +- **Content-Type**: application/json - **Accept**: application/json [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) @@ -1537,11 +1561,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsIdAgentsAgentIdStartPost +## ApiAmbientV1ProjectsIdCredentialsCredIdTokenGet -> StartResponse ApiAmbientV1ProjectsIdAgentsAgentIdStartPost(ctx, id, agentId).StartRequest(startRequest).Execute() +> CredentialTokenResponse ApiAmbientV1ProjectsIdCredentialsCredIdTokenGet(ctx, id, credId).Execute() -Start an agent — creates a Session (idempotent) +Get a decrypted token for a credential @@ -1559,18 +1583,17 @@ import ( func main() { id := "id_example" // string | The id of record - agentId := "agentId_example" // string | The id of the agent - startRequest := *openapiclient.NewStartRequest() // StartRequest | Optional start parameters (optional) + credId := "credId_example" // string | The id of the credential configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdStartPost(context.Background(), id, agentId).StartRequest(startRequest).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdTokenGet(context.Background(), id, credId).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdStartPost``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdTokenGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectsIdAgentsAgentIdStartPost`: StartResponse - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsAgentIdStartPost`: %v\n", resp) + // response from `ApiAmbientV1ProjectsIdCredentialsCredIdTokenGet`: CredentialTokenResponse + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdTokenGet`: %v\n", resp) } ``` @@ -1581,22 +1604,21 @@ Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- **ctx** | **context.Context** | context for authentication, logging, cancellation, deadlines, tracing, etc. **id** | **string** | The id of record | -**agentId** | **string** | The id of the agent | +**credId** | **string** | The id of the credential | ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsAgentIdStartPostRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdCredentialsCredIdTokenGetRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **startRequest** | [**StartRequest**](StartRequest.md) | Optional start parameters | ### Return type -[**StartResponse**](StartResponse.md) +[**CredentialTokenResponse**](CredentialTokenResponse.md) ### Authorization @@ -1604,7 +1626,7 @@ Name | Type | Description | Notes ### HTTP request headers -- **Content-Type**: application/json +- **Content-Type**: Not defined - **Accept**: application/json [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) @@ -1612,11 +1634,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsIdAgentsGet +## ApiAmbientV1ProjectsIdCredentialsGet -> AgentList ApiAmbientV1ProjectsIdAgentsGet(ctx, id).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Execute() +> CredentialList ApiAmbientV1ProjectsIdCredentialsGet(ctx, id).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Provider(provider).Execute() -Returns a list of agents in a project +Returns a list of credentials in a project ### Example @@ -1637,16 +1659,17 @@ func main() { search := "search_example" // string | Specifies the search criteria (optional) orderBy := "orderBy_example" // string | Specifies the order by criteria (optional) fields := "fields_example" // string | Supplies a comma-separated list of fields to be returned (optional) + provider := "provider_example" // string | Filter credentials by provider (optional) configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsGet(context.Background(), id).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsGet(context.Background(), id).Page(page).Size(size).Search(search).OrderBy(orderBy).Fields(fields).Provider(provider).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsGet``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdCredentialsGet``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectsIdAgentsGet`: AgentList - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsGet`: %v\n", resp) + // response from `ApiAmbientV1ProjectsIdCredentialsGet`: CredentialList + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdCredentialsGet`: %v\n", resp) } ``` @@ -1660,7 +1683,7 @@ Name | Type | Description | Notes ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsGetRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdCredentialsGetRequest struct via the builder pattern Name | Type | Description | Notes @@ -1671,10 +1694,11 @@ Name | Type | Description | Notes **search** | **string** | Specifies the search criteria | **orderBy** | **string** | Specifies the order by criteria | **fields** | **string** | Supplies a comma-separated list of fields to be returned | + **provider** | **string** | Filter credentials by provider | ### Return type -[**AgentList**](AgentList.md) +[**CredentialList**](CredentialList.md) ### Authorization @@ -1690,11 +1714,11 @@ Name | Type | Description | Notes [[Back to README]](../README.md) -## ApiAmbientV1ProjectsIdAgentsPost +## ApiAmbientV1ProjectsIdCredentialsPost -> Agent ApiAmbientV1ProjectsIdAgentsPost(ctx, id).Agent(agent).Execute() +> Credential ApiAmbientV1ProjectsIdCredentialsPost(ctx, id).Credential(credential).Execute() -Create an agent in a project +Create a new credential in a project ### Example @@ -1710,17 +1734,17 @@ import ( func main() { id := "id_example" // string | The id of record - agent := *openapiclient.NewAgent("ProjectId_example", "Name_example") // Agent | Agent data + credential := *openapiclient.NewCredential("ProjectId_example", "Name_example", "Provider_example") // Credential | Credential data configuration := openapiclient.NewConfiguration() apiClient := openapiclient.NewAPIClient(configuration) - resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdAgentsPost(context.Background(), id).Agent(agent).Execute() + resp, r, err := apiClient.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsPost(context.Background(), id).Credential(credential).Execute() if err != nil { - fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdAgentsPost``: %v\n", err) + fmt.Fprintf(os.Stderr, "Error when calling `DefaultAPI.ApiAmbientV1ProjectsIdCredentialsPost``: %v\n", err) fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) } - // response from `ApiAmbientV1ProjectsIdAgentsPost`: Agent - fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdAgentsPost`: %v\n", resp) + // response from `ApiAmbientV1ProjectsIdCredentialsPost`: Credential + fmt.Fprintf(os.Stdout, "Response from `DefaultAPI.ApiAmbientV1ProjectsIdCredentialsPost`: %v\n", resp) } ``` @@ -1734,17 +1758,17 @@ Name | Type | Description | Notes ### Other Parameters -Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdAgentsPostRequest struct via the builder pattern +Other parameters are passed through a pointer to a apiApiAmbientV1ProjectsIdCredentialsPostRequest struct via the builder pattern Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- - **agent** | [**Agent**](Agent.md) | Agent data | + **credential** | [**Credential**](Credential.md) | Credential data | ### Return type -[**Agent**](Agent.md) +[**Credential**](Credential.md) ### Authorization diff --git a/components/ambient-api-server/pkg/api/openapi/model_credential.go b/components/ambient-api-server/pkg/api/openapi/model_credential.go index 02ae9caeb..8ffa72b2e 100644 --- a/components/ambient-api-server/pkg/api/openapi/model_credential.go +++ b/components/ambient-api-server/pkg/api/openapi/model_credential.go @@ -23,14 +23,16 @@ var _ MappedNullable = &Credential{} // Credential struct for Credential type Credential struct { - Id *string `json:"id,omitempty"` - Kind *string `json:"kind,omitempty"` - Href *string `json:"href,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` - Name string `json:"name"` - Description *string `json:"description,omitempty"` - Provider string `json:"provider"` + Id *string `json:"id,omitempty"` + Kind *string `json:"kind,omitempty"` + Href *string `json:"href,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + // ID of the project this credential belongs to + ProjectId string `json:"project_id"` + Name string `json:"name"` + Description *string `json:"description,omitempty"` + Provider string `json:"provider"` // Credential token value; write-only, never returned in GET/LIST responses Token *string `json:"token,omitempty"` Url *string `json:"url,omitempty"` @@ -45,8 +47,9 @@ type _Credential Credential // This constructor will assign default values to properties that have it defined, // and makes sure properties required by API are set, but the set of arguments // will change when the set of required properties is changed -func NewCredential(name string, provider string) *Credential { +func NewCredential(projectId string, name string, provider string) *Credential { this := Credential{} + this.ProjectId = projectId this.Name = name this.Provider = provider return &this @@ -220,6 +223,30 @@ func (o *Credential) SetUpdatedAt(v time.Time) { o.UpdatedAt = &v } +// GetProjectId returns the ProjectId field value +func (o *Credential) GetProjectId() string { + if o == nil { + var ret string + return ret + } + + return o.ProjectId +} + +// GetProjectIdOk returns a tuple with the ProjectId field value +// and a boolean to check if the value has been set. +func (o *Credential) GetProjectIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.ProjectId, true +} + +// SetProjectId sets field value +func (o *Credential) SetProjectId(v string) { + o.ProjectId = v +} + // GetName returns the Name field value func (o *Credential) GetName() string { if o == nil { @@ -485,6 +512,7 @@ func (o Credential) ToMap() (map[string]interface{}, error) { if !IsNil(o.UpdatedAt) { toSerialize["updated_at"] = o.UpdatedAt } + toSerialize["project_id"] = o.ProjectId toSerialize["name"] = o.Name if !IsNil(o.Description) { toSerialize["description"] = o.Description @@ -513,6 +541,7 @@ func (o *Credential) UnmarshalJSON(data []byte) (err error) { // by unmarshalling the object into a generic map with string keys and checking // that every required field exists as a key in the generic map. requiredProperties := []string{ + "project_id", "name", "provider", } diff --git a/components/ambient-api-server/plugins/credentials/factory_test.go b/components/ambient-api-server/plugins/credentials/factory_test.go index 3e60bb143..d0abda03d 100644 --- a/components/ambient-api-server/plugins/credentials/factory_test.go +++ b/components/ambient-api-server/plugins/credentials/factory_test.go @@ -12,6 +12,7 @@ func newCredential(id string) (*credentials.Credential, error) { credentialService := credentials.Service(&environments.Environment().Services) credential := &credentials.Credential{ + ProjectID: "test-project", Name: "test-name", Description: stringPtr("test-description"), Provider: "test-provider", diff --git a/components/ambient-api-server/plugins/credentials/handler.go b/components/ambient-api-server/plugins/credentials/handler.go index 2a674cf69..f034f10ff 100644 --- a/components/ambient-api-server/plugins/credentials/handler.go +++ b/components/ambient-api-server/plugins/credentials/handler.go @@ -1,6 +1,7 @@ package credentials import ( + "fmt" "net/http" "github.com/gorilla/mux" @@ -35,7 +36,8 @@ func (h credentialHandler) Create(w http.ResponseWriter, r *http.Request) { }, Action: func() (interface{}, *errors.ServiceError) { ctx := r.Context() - credentialModel := ConvertCredential(credential) + projectID := mux.Vars(r)["id"] + credentialModel := ConvertCredential(credential, projectID) credentialModel, err := h.credential.Create(ctx, credentialModel) if err != nil { return nil, err @@ -56,7 +58,7 @@ func (h credentialHandler) Patch(w http.ResponseWriter, r *http.Request) { Validators: []handlers.Validate{}, Action: func() (interface{}, *errors.ServiceError) { ctx := r.Context() - id := mux.Vars(r)["id"] + id := mux.Vars(r)["cred_id"] found, err := h.credential.Get(ctx, id) if err != nil { return nil, err @@ -103,8 +105,15 @@ func (h credentialHandler) List(w http.ResponseWriter, r *http.Request) { cfg := &handlers.HandlerConfig{ Action: func() (interface{}, *errors.ServiceError) { ctx := r.Context() + projectID := mux.Vars(r)["id"] listArgs := services.NewListArguments(r.URL.Query()) + projectFilter := fmt.Sprintf("project_id = '%s'", projectID) + if listArgs.Search != "" { + listArgs.Search = fmt.Sprintf("(%s) and %s", listArgs.Search, projectFilter) + } else { + listArgs.Search = projectFilter + } var credentials []Credential paging, err := h.generic.List(ctx, "id", listArgs, &credentials) if err != nil { @@ -139,7 +148,7 @@ func (h credentialHandler) List(w http.ResponseWriter, r *http.Request) { func (h credentialHandler) Get(w http.ResponseWriter, r *http.Request) { cfg := &handlers.HandlerConfig{ Action: func() (interface{}, *errors.ServiceError) { - id := mux.Vars(r)["id"] + id := mux.Vars(r)["cred_id"] ctx := r.Context() credential, err := h.credential.Get(ctx, id) if err != nil { @@ -156,7 +165,7 @@ func (h credentialHandler) Get(w http.ResponseWriter, r *http.Request) { func (h credentialHandler) Delete(w http.ResponseWriter, r *http.Request) { cfg := &handlers.HandlerConfig{ Action: func() (interface{}, *errors.ServiceError) { - id := mux.Vars(r)["id"] + id := mux.Vars(r)["cred_id"] ctx := r.Context() err := h.credential.Delete(ctx, id) if err != nil { @@ -171,7 +180,7 @@ func (h credentialHandler) Delete(w http.ResponseWriter, r *http.Request) { func (h credentialHandler) GetToken(w http.ResponseWriter, r *http.Request) { cfg := &handlers.HandlerConfig{ Action: func() (interface{}, *errors.ServiceError) { - id := mux.Vars(r)["id"] + id := mux.Vars(r)["cred_id"] ctx := r.Context() credential, err := h.credential.Get(ctx, id) if err != nil { diff --git a/components/ambient-api-server/plugins/credentials/integration_test.go b/components/ambient-api-server/plugins/credentials/integration_test.go index 11ebde53e..edca10012 100644 --- a/components/ambient-api-server/plugins/credentials/integration_test.go +++ b/components/ambient-api-server/plugins/credentials/integration_test.go @@ -13,23 +13,25 @@ import ( "github.com/ambient-code/platform/components/ambient-api-server/test" ) +const testProjectID = "test-project" + func TestCredentialGet(t *testing.T) { h, client := test.RegisterIntegration(t) account := h.NewRandAccount() ctx := h.NewAuthenticatedContext(account) - _, _, err := client.DefaultAPI.ApiAmbientV1CredentialsIdGet(context.Background(), "foo").Execute() + _, _, err := client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdGet(context.Background(), testProjectID, "foo").Execute() Expect(err).To(HaveOccurred(), "Expected 401 but got nil error") - _, resp, err := client.DefaultAPI.ApiAmbientV1CredentialsIdGet(ctx, "foo").Execute() + _, resp, err := client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdGet(ctx, testProjectID, "foo").Execute() Expect(err).To(HaveOccurred(), "Expected 404") Expect(resp.StatusCode).To(Equal(http.StatusNotFound)) credentialModel, err := newCredential(h.NewID()) Expect(err).NotTo(HaveOccurred()) - credentialOutput, resp, err := client.DefaultAPI.ApiAmbientV1CredentialsIdGet(ctx, credentialModel.ID).Execute() + credentialOutput, resp, err := client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdGet(ctx, testProjectID, credentialModel.ID).Execute() Expect(err).NotTo(HaveOccurred()) Expect(resp.StatusCode).To(Equal(http.StatusOK)) @@ -48,6 +50,7 @@ func TestCredentialPost(t *testing.T) { ctx := h.NewAuthenticatedContext(account) credentialInput := openapi.Credential{ + ProjectId: testProjectID, Name: "test-name", Description: openapi.PtrString("test-description"), Provider: "test-provider", @@ -58,7 +61,7 @@ func TestCredentialPost(t *testing.T) { Annotations: openapi.PtrString("test-annotations"), } - credentialOutput, resp, err := client.DefaultAPI.ApiAmbientV1CredentialsPost(ctx).Credential(credentialInput).Execute() + credentialOutput, resp, err := client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsPost(ctx, testProjectID).Credential(credentialInput).Execute() Expect(err).NotTo(HaveOccurred(), "Error posting object: %v", err) Expect(resp.StatusCode).To(Equal(http.StatusCreated)) Expect(*credentialOutput.Id).NotTo(BeEmpty(), "Expected ID assigned on creation") @@ -71,7 +74,7 @@ func TestCredentialPost(t *testing.T) { SetHeader("Content-Type", "application/json"). SetHeader("Authorization", fmt.Sprintf("Bearer %s", jwtToken)). SetBody(`{ this is invalid }`). - Post(h.RestURL("/credentials")) + Post(h.RestURL(fmt.Sprintf("/projects/%s/credentials", testProjectID))) Expect(restyErr).NotTo(HaveOccurred()) Expect(restyResp.StatusCode()).To(Equal(http.StatusBadRequest)) @@ -86,7 +89,7 @@ func TestCredentialPatch(t *testing.T) { credentialModel, err := newCredential(h.NewID()) Expect(err).NotTo(HaveOccurred()) - credentialOutput, resp, err := client.DefaultAPI.ApiAmbientV1CredentialsIdPatch(ctx, credentialModel.ID).CredentialPatchRequest(openapi.CredentialPatchRequest{}).Execute() + credentialOutput, resp, err := client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdPatch(ctx, testProjectID, credentialModel.ID).CredentialPatchRequest(openapi.CredentialPatchRequest{}).Execute() Expect(err).NotTo(HaveOccurred(), "Error posting object: %v", err) Expect(resp.StatusCode).To(Equal(http.StatusOK)) Expect(*credentialOutput.Id).To(Equal(credentialModel.ID)) @@ -99,7 +102,7 @@ func TestCredentialPatch(t *testing.T) { SetHeader("Content-Type", "application/json"). SetHeader("Authorization", fmt.Sprintf("Bearer %s", jwtToken)). SetBody(`{ this is invalid }`). - Patch(h.RestURL("/credentials/foo")) + Patch(h.RestURL(fmt.Sprintf("/projects/%s/credentials/foo", testProjectID))) Expect(restyErr).NotTo(HaveOccurred()) Expect(restyResp.StatusCode()).To(Equal(http.StatusBadRequest)) @@ -114,14 +117,14 @@ func TestCredentialPaging(t *testing.T) { _, err := newCredentialList("Bronto", 20) Expect(err).NotTo(HaveOccurred()) - list, _, err := client.DefaultAPI.ApiAmbientV1CredentialsGet(ctx).Execute() + list, _, err := client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsGet(ctx, testProjectID).Execute() Expect(err).NotTo(HaveOccurred(), "Error getting credential list: %v", err) Expect(len(list.Items)).To(Equal(20)) Expect(list.Size).To(Equal(int32(20))) Expect(list.Total).To(Equal(int32(20))) Expect(list.Page).To(Equal(int32(1))) - list, _, err = client.DefaultAPI.ApiAmbientV1CredentialsGet(ctx).Page(2).Size(5).Execute() + list, _, err = client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsGet(ctx, testProjectID).Page(2).Size(5).Execute() Expect(err).NotTo(HaveOccurred(), "Error getting credential list: %v", err) Expect(len(list.Items)).To(Equal(5)) Expect(list.Size).To(Equal(int32(5))) @@ -139,7 +142,7 @@ func TestCredentialListSearch(t *testing.T) { Expect(err).NotTo(HaveOccurred()) search := fmt.Sprintf("id in ('%s')", credentials[0].ID) - list, _, err := client.DefaultAPI.ApiAmbientV1CredentialsGet(ctx).Search(search).Execute() + list, _, err := client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsGet(ctx, testProjectID).Search(search).Execute() Expect(err).NotTo(HaveOccurred(), "Error getting credential list: %v", err) Expect(len(list.Items)).To(Equal(1)) Expect(list.Total).To(Equal(int32(1))) @@ -155,7 +158,7 @@ func TestCredentialListTokenOmitted(t *testing.T) { created, err := newCredential(h.NewID()) Expect(err).NotTo(HaveOccurred()) - list, _, err := client.DefaultAPI.ApiAmbientV1CredentialsGet(ctx).Execute() + list, _, err := client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsGet(ctx, testProjectID).Execute() Expect(err).NotTo(HaveOccurred()) var found *openapi.Credential @@ -182,7 +185,7 @@ func TestCredentialToken(t *testing.T) { restyResp, restyErr := resty.R(). SetHeader("Authorization", fmt.Sprintf("Bearer %s", jwtToken)). - Get(h.RestURL(fmt.Sprintf("/credentials/%s/token", created.ID))) + Get(h.RestURL(fmt.Sprintf("/projects/%s/credentials/%s/token", testProjectID, created.ID))) Expect(restyErr).NotTo(HaveOccurred()) Expect(restyResp.StatusCode()).To(Equal(http.StatusOK)) Expect(restyResp.String()).To(ContainSubstring(`"token"`)) @@ -190,7 +193,7 @@ func TestCredentialToken(t *testing.T) { Expect(restyResp.String()).To(ContainSubstring(`"credential_id"`)) restyResp, restyErr = resty.R(). - Get(h.RestURL(fmt.Sprintf("/credentials/%s/token", created.ID))) + Get(h.RestURL(fmt.Sprintf("/projects/%s/credentials/%s/token", testProjectID, created.ID))) Expect(restyErr).NotTo(HaveOccurred()) Expect(restyResp.StatusCode()).To(Equal(http.StatusUnauthorized), "unauthenticated request to /token must be rejected") } @@ -204,19 +207,19 @@ func TestCredentialDelete(t *testing.T) { created, err := newCredential(h.NewID()) Expect(err).NotTo(HaveOccurred()) - _, resp, err := client.DefaultAPI.ApiAmbientV1CredentialsIdGet(ctx, created.ID).Execute() + _, resp, err := client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdGet(ctx, testProjectID, created.ID).Execute() Expect(err).NotTo(HaveOccurred()) Expect(resp.StatusCode).To(Equal(http.StatusOK)) - resp, err = client.DefaultAPI.ApiAmbientV1CredentialsIdDelete(ctx, created.ID).Execute() + resp, err = client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdDelete(ctx, testProjectID, created.ID).Execute() Expect(err).NotTo(HaveOccurred()) Expect(resp.StatusCode).To(Equal(http.StatusNoContent)) - _, resp, err = client.DefaultAPI.ApiAmbientV1CredentialsIdGet(ctx, created.ID).Execute() + _, resp, err = client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdGet(ctx, testProjectID, created.ID).Execute() Expect(err).To(HaveOccurred(), "Expected 404 after delete") Expect(resp.StatusCode).To(Equal(http.StatusNotFound)) - resp, err = client.DefaultAPI.ApiAmbientV1CredentialsIdDelete(context.Background(), created.ID).Execute() + resp, err = client.DefaultAPI.ApiAmbientV1ProjectsIdCredentialsCredIdDelete(context.Background(), testProjectID, created.ID).Execute() Expect(err).To(HaveOccurred(), "Expected 401 for unauthenticated delete") _ = resp } diff --git a/components/ambient-api-server/plugins/credentials/migration.go b/components/ambient-api-server/plugins/credentials/migration.go index 78cf7bbce..528212800 100644 --- a/components/ambient-api-server/plugins/credentials/migration.go +++ b/components/ambient-api-server/plugins/credentials/migration.go @@ -34,6 +34,30 @@ func migration() *gormigrate.Migration { } } +func addProjectIDMigration() *gormigrate.Migration { + return &gormigrate.Migration{ + ID: "202604101200", + Migrate: func(tx *gorm.DB) error { + return tx.Exec("ALTER TABLE credentials ADD COLUMN IF NOT EXISTS project_id TEXT NOT NULL DEFAULT ''").Error + }, + Rollback: func(tx *gorm.DB) error { + return tx.Exec("ALTER TABLE credentials DROP COLUMN IF EXISTS project_id").Error + }, + } +} + +func removeCredentialReaderRoleMigration() *gormigrate.Migration { + return &gormigrate.Migration{ + ID: "202604101201", + Migrate: func(tx *gorm.DB) error { + return tx.Exec("DELETE FROM roles WHERE name = 'credential:reader'").Error + }, + Rollback: func(tx *gorm.DB) error { + return nil + }, + } +} + func rolesMigration() *gormigrate.Migration { type roleRow struct { ID string diff --git a/components/ambient-api-server/plugins/credentials/model.go b/components/ambient-api-server/plugins/credentials/model.go index cb0782d80..8b313ed99 100644 --- a/components/ambient-api-server/plugins/credentials/model.go +++ b/components/ambient-api-server/plugins/credentials/model.go @@ -7,6 +7,7 @@ import ( type Credential struct { api.Meta + ProjectID string `json:"project_id"` Name string `json:"name"` Description *string `json:"description"` Provider string `json:"provider"` diff --git a/components/ambient-api-server/plugins/credentials/plugin.go b/components/ambient-api-server/plugins/credentials/plugin.go index 2b2b849c7..a4fbcfd75 100644 --- a/components/ambient-api-server/plugins/credentials/plugin.go +++ b/components/ambient-api-server/plugins/credentials/plugin.go @@ -52,13 +52,13 @@ func init() { } credentialHandler := NewCredentialHandler(Service(envServices), generic.Service(envServices)) - credentialsRouter := apiV1Router.PathPrefix("/credentials").Subrouter() - credentialsRouter.HandleFunc("", credentialHandler.List).Methods(http.MethodGet) - credentialsRouter.HandleFunc("/{id}", credentialHandler.Get).Methods(http.MethodGet) - credentialsRouter.HandleFunc("/{id}/token", credentialHandler.GetToken).Methods(http.MethodGet) - credentialsRouter.HandleFunc("", credentialHandler.Create).Methods(http.MethodPost) - credentialsRouter.HandleFunc("/{id}", credentialHandler.Patch).Methods(http.MethodPatch) - credentialsRouter.HandleFunc("/{id}", credentialHandler.Delete).Methods(http.MethodDelete) + credentialsRouter := apiV1Router.PathPrefix("/projects").Subrouter() + credentialsRouter.HandleFunc("/{id}/credentials", credentialHandler.List).Methods(http.MethodGet) + credentialsRouter.HandleFunc("/{id}/credentials", credentialHandler.Create).Methods(http.MethodPost) + credentialsRouter.HandleFunc("/{id}/credentials/{cred_id}", credentialHandler.Get).Methods(http.MethodGet) + credentialsRouter.HandleFunc("/{id}/credentials/{cred_id}", credentialHandler.Patch).Methods(http.MethodPatch) + credentialsRouter.HandleFunc("/{id}/credentials/{cred_id}", credentialHandler.Delete).Methods(http.MethodDelete) + credentialsRouter.HandleFunc("/{id}/credentials/{cred_id}/token", credentialHandler.GetToken).Methods(http.MethodGet) credentialsRouter.Use(authMiddleware.AuthenticateAccountJWT) credentialsRouter.Use(authzMiddleware.AuthorizeApi) }) @@ -83,4 +83,6 @@ func init() { db.RegisterMigration(migration()) db.RegisterMigration(rolesMigration()) + db.RegisterMigration(addProjectIDMigration()) + db.RegisterMigration(removeCredentialReaderRoleMigration()) } diff --git a/components/ambient-api-server/plugins/credentials/presenter.go b/components/ambient-api-server/plugins/credentials/presenter.go index 6248d5a61..a9f188553 100644 --- a/components/ambient-api-server/plugins/credentials/presenter.go +++ b/components/ambient-api-server/plugins/credentials/presenter.go @@ -7,11 +7,12 @@ import ( "github.com/openshift-online/rh-trex-ai/pkg/util" ) -func ConvertCredential(credential openapi.Credential) *Credential { +func ConvertCredential(credential openapi.Credential, projectID string) *Credential { c := &Credential{ Meta: api.Meta{ ID: util.NilToEmptyString(credential.Id), }, + ProjectID: projectID, } c.Name = credential.Name c.Description = credential.Description @@ -38,6 +39,7 @@ func PresentCredential(credential *Credential) openapi.Credential { Href: reference.Href, CreatedAt: openapi.PtrTime(credential.CreatedAt), UpdatedAt: openapi.PtrTime(credential.UpdatedAt), + ProjectId: credential.ProjectID, Name: credential.Name, Description: credential.Description, Provider: credential.Provider, From 0275fe5662304c531df332ea7e1ce8afdd342f7b Mon Sep 17 00:00:00 2001 From: Ambient Code Bot Date: Fri, 10 Apr 2026 20:12:26 -0400 Subject: [PATCH 5/9] feat(sdk): project-scoped credential API client and types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CredentialAPI methods now use /projects/{id}/credentials paths. Added project_id to Credential type. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../ambient-sdk/go-sdk/client/client.go | 4 +++ .../go-sdk/client/credential_api.go | 36 +++++++++++-------- .../ambient-sdk/go-sdk/types/credential.go | 1 + 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/components/ambient-sdk/go-sdk/client/client.go b/components/ambient-sdk/go-sdk/client/client.go index dd75a8c13..cd095b14f 100644 --- a/components/ambient-sdk/go-sdk/client/client.go +++ b/components/ambient-sdk/go-sdk/client/client.go @@ -124,6 +124,10 @@ func NewClient(baseURL, token, project string, opts ...ClientOption) (*Client, e return c, nil } +func (c *Client) Project() string { + return c.project +} + func NewClientFromEnv(opts ...ClientOption) (*Client, error) { baseURL := os.Getenv("AMBIENT_API_URL") if baseURL == "" { diff --git a/components/ambient-sdk/go-sdk/client/credential_api.go b/components/ambient-sdk/go-sdk/client/credential_api.go index 023494bd6..ede9efc0b 100644 --- a/components/ambient-sdk/go-sdk/client/credential_api.go +++ b/components/ambient-sdk/go-sdk/client/credential_api.go @@ -18,62 +18,70 @@ func (c *Client) Credentials() *CredentialAPI { return &CredentialAPI{client: c} } -func (a *CredentialAPI) Create(ctx context.Context, resource *types.Credential) (*types.Credential, error) { +func credentialBasePath(projectID string) string { + return "/projects/" + url.PathEscape(projectID) + "/credentials" +} + +func credentialItemPath(projectID, credID string) string { + return credentialBasePath(projectID) + "/" + url.PathEscape(credID) +} + +func (a *CredentialAPI) Create(ctx context.Context, projectID string, resource *types.Credential) (*types.Credential, error) { body, err := json.Marshal(resource) if err != nil { return nil, fmt.Errorf("marshal credential: %w", err) } var result types.Credential - if err := a.client.do(ctx, http.MethodPost, "/credentials", body, http.StatusCreated, &result); err != nil { + if err := a.client.do(ctx, http.MethodPost, credentialBasePath(projectID), body, http.StatusCreated, &result); err != nil { return nil, err } return &result, nil } -func (a *CredentialAPI) Get(ctx context.Context, id string) (*types.Credential, error) { +func (a *CredentialAPI) Get(ctx context.Context, projectID, credID string) (*types.Credential, error) { var result types.Credential - if err := a.client.do(ctx, http.MethodGet, "/credentials/"+url.PathEscape(id), nil, http.StatusOK, &result); err != nil { + if err := a.client.do(ctx, http.MethodGet, credentialItemPath(projectID, credID), nil, http.StatusOK, &result); err != nil { return nil, err } return &result, nil } -func (a *CredentialAPI) List(ctx context.Context, opts *types.ListOptions) (*types.CredentialList, error) { +func (a *CredentialAPI) List(ctx context.Context, projectID string, opts *types.ListOptions) (*types.CredentialList, error) { var result types.CredentialList - if err := a.client.doWithQuery(ctx, http.MethodGet, "/credentials", nil, http.StatusOK, &result, opts); err != nil { + if err := a.client.doWithQuery(ctx, http.MethodGet, credentialBasePath(projectID), nil, http.StatusOK, &result, opts); err != nil { return nil, err } return &result, nil } -func (a *CredentialAPI) Update(ctx context.Context, id string, patch map[string]any) (*types.Credential, error) { +func (a *CredentialAPI) Update(ctx context.Context, projectID, credID string, patch map[string]any) (*types.Credential, error) { body, err := json.Marshal(patch) if err != nil { return nil, fmt.Errorf("marshal patch: %w", err) } var result types.Credential - if err := a.client.do(ctx, http.MethodPatch, "/credentials/"+url.PathEscape(id), body, http.StatusOK, &result); err != nil { + if err := a.client.do(ctx, http.MethodPatch, credentialItemPath(projectID, credID), body, http.StatusOK, &result); err != nil { return nil, err } return &result, nil } -func (a *CredentialAPI) Delete(ctx context.Context, id string) error { - return a.client.do(ctx, http.MethodDelete, "/credentials/"+url.PathEscape(id), nil, http.StatusNoContent, nil) +func (a *CredentialAPI) Delete(ctx context.Context, projectID, credID string) error { + return a.client.do(ctx, http.MethodDelete, credentialItemPath(projectID, credID), nil, http.StatusNoContent, nil) } -func (a *CredentialAPI) GetToken(ctx context.Context, id string) (*types.CredentialTokenResponse, error) { +func (a *CredentialAPI) GetToken(ctx context.Context, projectID, credID string) (*types.CredentialTokenResponse, error) { var result types.CredentialTokenResponse - if err := a.client.do(ctx, http.MethodGet, "/credentials/"+url.PathEscape(id)+"/token", nil, http.StatusOK, &result); err != nil { + if err := a.client.do(ctx, http.MethodGet, credentialItemPath(projectID, credID)+"/token", nil, http.StatusOK, &result); err != nil { return nil, err } return &result, nil } -func (a *CredentialAPI) ListAll(ctx context.Context, opts *types.ListOptions) *Iterator[types.Credential] { +func (a *CredentialAPI) ListAll(ctx context.Context, projectID string, opts *types.ListOptions) *Iterator[types.Credential] { return NewIterator(func(page int) (*types.CredentialList, error) { o := *opts o.Page = page - return a.List(ctx, &o) + return a.List(ctx, projectID, &o) }) } diff --git a/components/ambient-sdk/go-sdk/types/credential.go b/components/ambient-sdk/go-sdk/types/credential.go index 3d49c1b8a..332034294 100644 --- a/components/ambient-sdk/go-sdk/types/credential.go +++ b/components/ambient-sdk/go-sdk/types/credential.go @@ -8,6 +8,7 @@ import ( type Credential struct { ObjectReference + ProjectID string `json:"project_id"` Annotations string `json:"annotations,omitempty"` Description string `json:"description,omitempty"` Email string `json:"email,omitempty"` From 7144a0496196333e9650b0dccbdda534992e0ffd Mon Sep 17 00:00:00 2001 From: Ambient Code Bot Date: Fri, 10 Apr 2026 20:12:27 -0400 Subject: [PATCH 6/9] feat(cli): project-scoped credentials, SSE stream refactor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Credential commands use project context. Session send -f refactored to use shared renderSSEStream helper. Updated get/delete/describe for project-scoped credential routing. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../ambient-cli/cmd/acpctl/apply/cmd.go | 6 +- .../ambient-cli/cmd/acpctl/credential/cmd.go | 12 +- .../ambient-cli/cmd/acpctl/delete/cmd.go | 2 +- .../ambient-cli/cmd/acpctl/describe/cmd.go | 2 +- components/ambient-cli/cmd/acpctl/get/cmd.go | 8 +- .../ambient-cli/cmd/acpctl/session/cmd.go | 5 +- .../cmd/acpctl/session/messages.go | 143 +++++++++++++----- .../ambient-cli/cmd/acpctl/session/send.go | 85 +---------- 8 files changed, 122 insertions(+), 141 deletions(-) diff --git a/components/ambient-cli/cmd/acpctl/apply/cmd.go b/components/ambient-cli/cmd/acpctl/apply/cmd.go index 4ba1f2b04..aa023a2f1 100644 --- a/components/ambient-cli/cmd/acpctl/apply/cmd.go +++ b/components/ambient-cli/cmd/acpctl/apply/cmd.go @@ -243,7 +243,7 @@ func applyProject(ctx context.Context, client *sdkclient.Client, doc resource) ( } func applyCredential(ctx context.Context, client *sdkclient.Client, doc resource) (applyResult, error) { - existing, err := client.Credentials().Get(ctx, doc.Name) + existing, err := client.Credentials().Get(ctx, client.Project(), doc.Name) if err != nil { token := os.ExpandEnv(doc.Token) builder := sdktypes.NewCredentialBuilder(). @@ -271,7 +271,7 @@ func applyCredential(ctx context.Context, client *sdkclient.Client, doc resource if buildErr != nil { return applyResult{}, buildErr } - if _, createErr := client.Credentials().Create(ctx, cred); createErr != nil { + if _, createErr := client.Credentials().Create(ctx, client.Project(), cred); createErr != nil { return applyResult{}, createErr } return applyResult{Kind: "Credential", Name: doc.Name, Status: "created"}, nil @@ -281,7 +281,7 @@ func applyCredential(ctx context.Context, client *sdkclient.Client, doc resource if !changed { return applyResult{Kind: "Credential", Name: doc.Name, Status: "unchanged"}, nil } - if _, err = client.Credentials().Update(ctx, existing.ID, patch); err != nil { + if _, err = client.Credentials().Update(ctx, client.Project(), existing.ID, patch); err != nil { return applyResult{}, err } return applyResult{Kind: "Credential", Name: doc.Name, Status: "configured"}, nil diff --git a/components/ambient-cli/cmd/acpctl/credential/cmd.go b/components/ambient-cli/cmd/acpctl/credential/cmd.go index 03fef6079..ce327fadb 100644 --- a/components/ambient-cli/cmd/acpctl/credential/cmd.go +++ b/components/ambient-cli/cmd/acpctl/credential/cmd.go @@ -64,7 +64,7 @@ var listCmd = &cobra.Command{ if listArgs.provider != "" { opts.Search = fmt.Sprintf("provider='%s'", listArgs.provider) } - list, err := client.Credentials().List(ctx, opts) + list, err := client.Credentials().List(ctx, client.Project(), opts) if err != nil { return fmt.Errorf("list credentials: %w", err) } @@ -101,7 +101,7 @@ var getCmd = &cobra.Command{ ctx, cancel := context.WithTimeout(context.Background(), cfg.GetRequestTimeout()) defer cancel() - credential, err := client.Credentials().Get(ctx, args[0]) + credential, err := client.Credentials().Get(ctx, client.Project(), args[0]) if err != nil { return fmt.Errorf("get credential %q: %w", args[0], err) } @@ -185,7 +185,7 @@ var createCmd = &cobra.Command{ return fmt.Errorf("build credential: %w", err) } - created, err := client.Credentials().Create(ctx, cred) + created, err := client.Credentials().Create(ctx, client.Project(), cred) if err != nil { return fmt.Errorf("create credential: %w", err) } @@ -257,7 +257,7 @@ var updateCmd = &cobra.Command{ patch = patch.Annotations(updateArgs.annotations) } - updated, err := client.Credentials().Update(ctx, args[0], patch.Build()) + updated, err := client.Credentials().Update(ctx, client.Project(), args[0], patch.Build()) if err != nil { return fmt.Errorf("update credential: %w", err) } @@ -294,7 +294,7 @@ var deleteCmd = &cobra.Command{ ctx, cancel := context.WithTimeout(context.Background(), cfg.GetRequestTimeout()) defer cancel() - if err := client.Credentials().Delete(ctx, args[0]); err != nil { + if err := client.Credentials().Delete(ctx, client.Project(), args[0]); err != nil { return fmt.Errorf("delete credential: %w", err) } @@ -327,7 +327,7 @@ var tokenCmd = &cobra.Command{ ctx, cancel := context.WithTimeout(context.Background(), cfg.GetRequestTimeout()) defer cancel() - resp, err := client.Credentials().GetToken(ctx, args[0]) + resp, err := client.Credentials().GetToken(ctx, client.Project(), args[0]) if err != nil { return fmt.Errorf("get token for credential %q: %w", args[0], err) } diff --git a/components/ambient-cli/cmd/acpctl/delete/cmd.go b/components/ambient-cli/cmd/acpctl/delete/cmd.go index c3ed066ce..d1d77ae5d 100644 --- a/components/ambient-cli/cmd/acpctl/delete/cmd.go +++ b/components/ambient-cli/cmd/acpctl/delete/cmd.go @@ -109,7 +109,7 @@ func run(cmd *cobra.Command, cmdArgs []string) error { return nil case "credential", "credentials", "cred", "creds": - if err := client.Credentials().Delete(ctx, name); err != nil { + if err := client.Credentials().Delete(ctx, client.Project(), name); err != nil { return fmt.Errorf("delete credential %q: %w", name, err) } fmt.Fprintf(cmd.OutOrStdout(), "credential/%s deleted\n", name) diff --git a/components/ambient-cli/cmd/acpctl/describe/cmd.go b/components/ambient-cli/cmd/acpctl/describe/cmd.go index e213b8ba8..cbe31a8f8 100644 --- a/components/ambient-cli/cmd/acpctl/describe/cmd.go +++ b/components/ambient-cli/cmd/acpctl/describe/cmd.go @@ -100,7 +100,7 @@ func run(cmd *cobra.Command, cmdArgs []string) error { return printer.PrintJSON(rb) case "credential", "credentials", "cred", "creds": - cred, err := client.Credentials().Get(ctx, name) + cred, err := client.Credentials().Get(ctx, client.Project(), name) if err != nil { return fmt.Errorf("describe credential %q: %w", name, err) } diff --git a/components/ambient-cli/cmd/acpctl/get/cmd.go b/components/ambient-cli/cmd/acpctl/get/cmd.go index 276313052..ef1da243b 100644 --- a/components/ambient-cli/cmd/acpctl/get/cmd.go +++ b/components/ambient-cli/cmd/acpctl/get/cmd.go @@ -47,8 +47,8 @@ Valid resource types: } var projectAgentArgs struct { - projectID string - paID string + projectID string + paID string } func init() { @@ -517,7 +517,7 @@ func getRoleBindings(ctx context.Context, client *sdkclient.Client, printer *out func getCredentials(ctx context.Context, client *sdkclient.Client, printer *output.Printer, name string) error { if name != "" { - cred, err := client.Credentials().Get(ctx, name) + cred, err := client.Credentials().Get(ctx, client.Project(), name) if err != nil { return fmt.Errorf("get credential %q: %w", name, err) } @@ -527,7 +527,7 @@ func getCredentials(ctx context.Context, client *sdkclient.Client, printer *outp return printCredentialTable(printer, []sdktypes.Credential{*cred}) } opts := sdktypes.NewListOptions().Size(args.limit).Build() - list, err := client.Credentials().List(ctx, opts) + list, err := client.Credentials().List(ctx, client.Project(), opts) if err != nil { return fmt.Errorf("list credentials: %w", err) } diff --git a/components/ambient-cli/cmd/acpctl/session/cmd.go b/components/ambient-cli/cmd/acpctl/session/cmd.go index 0c1548036..267c9fa75 100644 --- a/components/ambient-cli/cmd/acpctl/session/cmd.go +++ b/components/ambient-cli/cmd/acpctl/session/cmd.go @@ -12,9 +12,10 @@ var Cmd = &cobra.Command{ Examples: acpctl session messages # list messages (snapshot) - acpctl session messages -f # stream messages live + acpctl session messages -f # live SSE stream (reconnectable) acpctl session send "Hello!" # send a message - acpctl session events # stream live AG-UI events`, + acpctl session send "Hello!" -f # send and stream until done + acpctl session events # raw AG-UI event stream`, RunE: func(cmd *cobra.Command, args []string) error { return cmd.Help() }, diff --git a/components/ambient-cli/cmd/acpctl/session/messages.go b/components/ambient-cli/cmd/acpctl/session/messages.go index c10f62b66..388c4289e 100644 --- a/components/ambient-cli/cmd/acpctl/session/messages.go +++ b/components/ambient-cli/cmd/acpctl/session/messages.go @@ -1,6 +1,7 @@ package session import ( + "bufio" "context" "encoding/json" "fmt" @@ -15,12 +16,12 @@ import ( "github.com/ambient-code/platform/components/ambient-cli/pkg/connection" "github.com/ambient-code/platform/components/ambient-cli/pkg/output" sdkclient "github.com/ambient-code/platform/components/ambient-sdk/go-sdk/client" - sdktypes "github.com/ambient-code/platform/components/ambient-sdk/go-sdk/types" "github.com/spf13/cobra" ) var msgArgs struct { follow bool + followJSON bool outputFormat string afterSeq int } @@ -30,17 +31,24 @@ var messagesCmd = &cobra.Command{ Short: "List or stream messages for a session", Long: `List or stream messages for a session. +Without -f, fetches a snapshot of messages from the message store. +With -f, connects to the live SSE event stream and renders events +as readable text. The stream stays open until Ctrl+C. +With -f --json, emits raw AG-UI JSON events instead of text. + Examples: - acpctl session messages # snapshot - acpctl session messages -f # live stream (Ctrl+C to stop) - acpctl session messages -o json # JSON snapshot - acpctl session messages --after 5 # messages after seq 5`, + acpctl session messages # snapshot + acpctl session messages -f # live SSE stream (Ctrl+C to stop) + acpctl session messages -f --json # raw AG-UI JSON events + acpctl session messages -o json # JSON snapshot + acpctl session messages --after 5 # messages after seq 5`, Args: cobra.ExactArgs(1), RunE: runMessages, } func init() { - messagesCmd.Flags().BoolVarP(&msgArgs.follow, "follow", "f", false, "Stream messages live") + messagesCmd.Flags().BoolVarP(&msgArgs.follow, "follow", "f", false, "Stream live SSE events (same stream as send -f)") + messagesCmd.Flags().BoolVar(&msgArgs.followJSON, "json", false, "with -f: emit raw AG-UI JSON events instead of text") messagesCmd.Flags().StringVarP(&msgArgs.outputFormat, "output", "o", "", "Output format: json") messagesCmd.Flags().IntVar(&msgArgs.afterSeq, "after", 0, "Only show messages after this sequence number") } @@ -397,47 +405,102 @@ func streamMessages(cmd *cobra.Command, client *sdkclient.Client, sessionID stri ctx, cancel := signal.NotifyContext(cmd.Context(), os.Interrupt) defer cancel() - fmt.Fprintf(cmd.OutOrStdout(), "Streaming messages for session %s (Ctrl+C to stop)...\n\n", sessionID) - - watcher, err := client.Sessions().WatchSessionMessages(ctx, sessionID, int64(msgArgs.afterSeq), nil) + stream, err := client.Sessions().StreamEvents(ctx, sessionID) if err != nil { - return fmt.Errorf("watch messages: %w", err) - } - defer watcher.Stop() - - for { - select { - case <-ctx.Done(): - return nil - case <-watcher.Done(): - return nil - case err, ok := <-watcher.Errors(): - if !ok { - return nil + return fmt.Errorf("stream events: %w", err) + } + defer stream.Close() + + fmt.Fprintf(cmd.OutOrStdout(), "Streaming events for session %s (Ctrl+C to stop)...\n\n", sessionID) + + return renderSSEStream(stream, cmd.OutOrStdout(), msgArgs.followJSON, false) +} + +func renderSSEStream(stream io.Reader, out io.Writer, jsonMode, exitOnRunFinished bool) error { + scanner := bufio.NewScanner(stream) + var reasoningBuf strings.Builder + var inText bool + for scanner.Scan() { + line := scanner.Text() + if !strings.HasPrefix(line, "data: ") { + continue + } + data := line[6:] + + if jsonMode { + fmt.Fprintln(out, data) + continue + } + + var evt struct { + Type string `json:"type"` + Delta string `json:"delta"` + ToolCallName string `json:"toolCallName"` + Content string `json:"content"` + } + if err := json.Unmarshal([]byte(data), &evt); err != nil { + continue + } + switch evt.Type { + case "REASONING_MESSAGE_CONTENT": + reasoningBuf.WriteString(evt.Delta) + case "REASONING_END": + if reasoningBuf.Len() > 0 { + fmt.Fprintf(out, "[thinking] %s\n", strings.TrimSpace(reasoningBuf.String())) + reasoningBuf.Reset() + } + case "TEXT_MESSAGE_CONTENT": + if evt.Delta != "" { + inText = true + fmt.Fprint(out, evt.Delta) + } + case "TEXT_MESSAGE_END": + if inText { + fmt.Fprintln(out) + inText = false + } + case "TOOL_CALL_START": + if evt.ToolCallName != "" { + fmt.Fprintf(out, "[%s] ", evt.ToolCallName) + } + case "TOOL_CALL_RESULT": + if evt.Content != "" { + var content string + if err := json.Unmarshal([]byte(evt.Content), &content); err != nil { + content = evt.Content + } + lines := strings.SplitN(strings.TrimSpace(content), "\n", 4) + preview := strings.Join(lines, " | ") + if len(lines) >= 4 { + preview += " ..." + } + fmt.Fprintf(out, "→ %s\n", preview) + } + case "RUN_FINISHED": + if inText { + fmt.Fprintln(out) + inText = false } - return fmt.Errorf("stream error: %w", err) - case msg, ok := <-watcher.Messages(): - if !ok { + if exitOnRunFinished { return nil } - printStreamLine(cmd, *msg) + case "RUN_ERROR": + if inText { + fmt.Fprintln(out) + inText = false + } + if exitOnRunFinished { + return fmt.Errorf("run failed") + } } } -} -func printStreamLine(cmd *cobra.Command, msg sdktypes.SessionMessage) { - display := displayPayload(msg.EventType, msg.Payload) - if display == "" { - return + if inText { + fmt.Fprintln(out) } - w := cmd.OutOrStdout() - ts := msg.CreatedAt.Format("15:04:05") - width := output.TerminalWidthFor(w) - if width < 40 { - width = 80 + + if scanErr := scanner.Err(); scanErr != nil { + return fmt.Errorf("stream error: %w", scanErr) } - header := fmt.Sprintf("[%s] #%-4d %s", ts, msg.Seq, msg.EventType) - fmt.Fprintln(w, header) - printWrapped(w, display, width, " ") - fmt.Fprintln(w) + return nil } diff --git a/components/ambient-cli/cmd/acpctl/session/send.go b/components/ambient-cli/cmd/acpctl/session/send.go index 857c49009..76c8008e0 100644 --- a/components/ambient-cli/cmd/acpctl/session/send.go +++ b/components/ambient-cli/cmd/acpctl/session/send.go @@ -1,14 +1,11 @@ package session import ( - "bufio" "context" - "encoding/json" "fmt" "io" "os" "os/signal" - "strings" "github.com/ambient-code/platform/components/ambient-cli/pkg/config" "github.com/ambient-code/platform/components/ambient-cli/pkg/connection" @@ -81,85 +78,5 @@ func runSend(cmd *cobra.Command, args []string) error { return nil } - out := cmd.OutOrStdout() - scanner := bufio.NewScanner(stream) - var reasoningBuf strings.Builder - var inText bool - for scanner.Scan() { - line := scanner.Text() - if !strings.HasPrefix(line, "data: ") { - continue - } - data := line[6:] - - if sendFollowJSON { - fmt.Fprintln(out, data) - continue - } - - var evt struct { - Type string `json:"type"` - Delta string `json:"delta"` - ToolCallName string `json:"toolCallName"` - Content string `json:"content"` - } - if err := json.Unmarshal([]byte(data), &evt); err != nil { - continue - } - switch evt.Type { - case "REASONING_MESSAGE_CONTENT": - reasoningBuf.WriteString(evt.Delta) - case "REASONING_END": - if reasoningBuf.Len() > 0 { - fmt.Fprintf(out, "[thinking] %s\n", strings.TrimSpace(reasoningBuf.String())) - reasoningBuf.Reset() - } - case "TEXT_MESSAGE_CONTENT": - if evt.Delta != "" { - inText = true - fmt.Fprint(out, evt.Delta) - } - case "TEXT_MESSAGE_END": - if inText { - fmt.Fprintln(out) - inText = false - } - case "TOOL_CALL_START": - if evt.ToolCallName != "" { - fmt.Fprintf(out, "[%s] ", evt.ToolCallName) - } - case "TOOL_CALL_RESULT": - if evt.Content != "" { - var content string - if err := json.Unmarshal([]byte(evt.Content), &content); err != nil { - content = evt.Content - } - lines := strings.SplitN(strings.TrimSpace(content), "\n", 4) - preview := strings.Join(lines, " | ") - if len(lines) >= 4 { - preview += " ..." - } - fmt.Fprintf(out, "→ %s\n", preview) - } - case "RUN_FINISHED": - if inText { - fmt.Fprintln(out) - } - return nil - case "RUN_ERROR": - if inText { - fmt.Fprintln(out) - } - return fmt.Errorf("run failed") - } - } - - if inText { - fmt.Fprintln(out) - } - - if scanErr := scanner.Err(); scanErr != nil { - return fmt.Errorf("stream error: %w", scanErr) - } - return nil + return renderSSEStream(stream, cmd.OutOrStdout(), sendFollowJSON, true) } From 520c06ac626f3a7b59ea4f3d13ec3f15cc614eb8 Mon Sep 17 00:00:00 2001 From: Ambient Code Bot Date: Fri, 10 Apr 2026 20:12:28 -0400 Subject: [PATCH 7/9] fix(control-plane): credential token injection in kube reconciler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated reconciler to fetch project-scoped credentials for runner pod environment setup. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../internal/reconciler/kube_reconciler.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/components/ambient-control-plane/internal/reconciler/kube_reconciler.go b/components/ambient-control-plane/internal/reconciler/kube_reconciler.go index 6b9ac9070..a24fbe126 100644 --- a/components/ambient-control-plane/internal/reconciler/kube_reconciler.go +++ b/components/ambient-control-plane/internal/reconciler/kube_reconciler.go @@ -148,7 +148,7 @@ func (r *SimpleKubeReconciler) provisionSession(ctx context.Context, session typ return fmt.Errorf("ensuring service account: %w", err) } - credentialIDs, err := r.resolveCredentialIDs(ctx, sdk) + credentialIDs, err := r.resolveCredentialIDs(ctx, sdk, session.ProjectID) if err != nil { r.logger.Warn().Err(err).Str("session_id", session.ID).Msg("credential resolution failed; continuing without credentials") credentialIDs = map[string]string{} @@ -640,10 +640,10 @@ func (r *SimpleKubeReconciler) buildEnv(ctx context.Context, session types.Sessi return env } -func (r *SimpleKubeReconciler) resolveCredentialIDs(ctx context.Context, sdk *sdkclient.Client) (map[string]string, error) { +func (r *SimpleKubeReconciler) resolveCredentialIDs(ctx context.Context, sdk *sdkclient.Client, projectID string) (map[string]string, error) { result := map[string]string{} - it := sdk.Credentials().ListAll(ctx, &types.ListOptions{Size: 100}) + it := sdk.Credentials().ListAll(ctx, projectID, &types.ListOptions{Size: 100}) for it.Next() { cred := it.Item() if cred.Provider == "" || cred.ID == "" { @@ -862,4 +862,3 @@ func min(a, b int) int { } return b } - From b3de54f5f5bac41d641587ef7addd6f66e6aeb44 Mon Sep 17 00:00:00 2001 From: Ambient Code Bot Date: Fri, 10 Apr 2026 20:12:29 -0400 Subject: [PATCH 8/9] fix(runner): update auth to use project-scoped credential paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../runners/ambient-runner/ambient_runner/platform/auth.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/runners/ambient-runner/ambient_runner/platform/auth.py b/components/runners/ambient-runner/ambient_runner/platform/auth.py index 747b8891f..769d41f5a 100755 --- a/components/runners/ambient-runner/ambient_runner/platform/auth.py +++ b/components/runners/ambient-runner/ambient_runner/platform/auth.py @@ -116,7 +116,12 @@ async def _fetch_credential(context: RunnerContext, credential_type: str) -> dic logger.debug(f"No credential_id for provider {credential_type}; skipping fetch") return {} - url = f"{base}/api/ambient/v1/credentials/{credential_id}/token" + project_id = os.getenv("PROJECT_NAME", "") + if not project_id: + logger.warning("Cannot fetch credentials: PROJECT_NAME not set") + return {} + + url = f"{base}/api/ambient/v1/projects/{project_id}/credentials/{credential_id}/token" # Reject non-cluster URLs to prevent token exfiltration via user-overridden env vars parsed = urlparse(base) From 56469abaf80e68d649d85c965679260446fe214b Mon Sep 17 00:00:00 2001 From: Ambient Code Bot Date: Fri, 10 Apr 2026 20:35:10 -0400 Subject: [PATCH 9/9] fix(runner): add PROJECT_NAME to credential tests for project-scoped URLs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The _fetch_credential function now requires PROJECT_NAME to construct project-scoped credential URLs. Tests that call _fetch_credential directly were missing this env var, causing 9 failures. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../tests/test_shared_session_credentials.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/components/runners/ambient-runner/tests/test_shared_session_credentials.py b/components/runners/ambient-runner/tests/test_shared_session_credentials.py index b23de2d78..747f0a277 100644 --- a/components/runners/ambient-runner/tests/test_shared_session_credentials.py +++ b/components/runners/ambient-runner/tests/test_shared_session_credentials.py @@ -308,6 +308,7 @@ async def test_sends_current_user_header_when_set(self): "BACKEND_API_URL": f"http://127.0.0.1:{port}/api", "BOT_TOKEN": "fake-bot-token", "CREDENTIAL_IDS": json.dumps({"github": cred_id}), + "PROJECT_NAME": "test-project", }, ): ctx = _make_context( @@ -350,6 +351,7 @@ async def test_omits_current_user_header_when_not_set(self): "BACKEND_API_URL": f"http://127.0.0.1:{port}/api", "BOT_TOKEN": "fake-bot-token", "CREDENTIAL_IDS": json.dumps({"github": cred_id}), + "PROJECT_NAME": "test-project", }, ): ctx = _make_context() # no current_user_id @@ -452,6 +454,7 @@ def log_message(self, format, *args): "BACKEND_API_URL": f"http://127.0.0.1:{port}/api", "BOT_TOKEN": "fake-bot", "CREDENTIAL_IDS": credential_ids, + "PROJECT_NAME": "test-project", }, ): ctx = _make_context(current_user_id="userB") @@ -503,6 +506,7 @@ async def test_raises_permission_error_on_401_without_caller_token( monkeypatch.setenv("BACKEND_API_URL", "http://backend.svc.cluster.local/api") monkeypatch.setenv("BOT_TOKEN", "bot-token") monkeypatch.setenv("CREDENTIAL_IDS", json.dumps({"github": "cred-gh-001"})) + monkeypatch.setenv("PROJECT_NAME", "test-project") ctx = _make_context(session_id="sess-1") @@ -527,6 +531,7 @@ async def test_raises_permission_error_on_403_without_caller_token( monkeypatch.setenv("BACKEND_API_URL", "http://backend.svc.cluster.local/api") monkeypatch.setenv("BOT_TOKEN", "bot-token") monkeypatch.setenv("CREDENTIAL_IDS", json.dumps({"google": "cred-google-001"})) + monkeypatch.setenv("PROJECT_NAME", "test-project") ctx = _make_context(session_id="sess-1") @@ -551,6 +556,7 @@ async def test_raises_permission_error_when_caller_and_bot_both_fail( monkeypatch.setenv("BACKEND_API_URL", "http://backend.svc.cluster.local/api") monkeypatch.setenv("BOT_TOKEN", "bot-token") monkeypatch.setenv("CREDENTIAL_IDS", json.dumps({"github": "cred-gh-002"})) + monkeypatch.setenv("PROJECT_NAME", "test-project") ctx = _make_context(session_id="sess-1", current_user_id="user@example.com") ctx.caller_token = "Bearer expired-caller-token" @@ -570,6 +576,7 @@ async def test_does_not_raise_on_non_auth_http_errors(self, monkeypatch): """_fetch_credential returns {} for non-auth HTTP errors (404, 500, etc.).""" monkeypatch.setenv("BACKEND_API_URL", "http://backend.svc.cluster.local/api") monkeypatch.setenv("CREDENTIAL_IDS", json.dumps({"github": "cred-gh-003"})) + monkeypatch.setenv("PROJECT_NAME", "test-project") ctx = _make_context(session_id="sess-1") @@ -587,6 +594,7 @@ async def test_caller_token_fallback_succeeds_when_bot_token_works( monkeypatch.setenv("BACKEND_API_URL", "http://backend.svc.cluster.local/api") monkeypatch.setenv("BOT_TOKEN", "valid-bot-token") monkeypatch.setenv("CREDENTIAL_IDS", json.dumps({"github": "cred-gh-004"})) + monkeypatch.setenv("PROJECT_NAME", "test-project") ctx = _make_context(session_id="sess-1", current_user_id="user@example.com") ctx.caller_token = "Bearer expired-caller-token" @@ -762,6 +770,7 @@ async def test_uses_bot_token_when_no_caller_token(self): { "BACKEND_API_URL": f"http://127.0.0.1:{port}/api", "CREDENTIAL_IDS": json.dumps({"github": "cred-gh-bot-test"}), + "PROJECT_NAME": "test-project", }, ), patch("ambient_runner.platform.auth.get_bot_token", return_value=cp_oidc_token), @@ -804,6 +813,7 @@ def fake_urlopen(req, timeout=None): { "BACKEND_API_URL": "http://backend.svc.cluster.local/api", "CREDENTIAL_IDS": json.dumps({"github": "cred-gh-pref"}), + "PROJECT_NAME": "test-project", }, ), patch("urllib.request.urlopen", side_effect=fake_urlopen),