diff --git a/components/ambient-api-server/pkg/api/openapi/.openapi-generator/FILES b/components/ambient-api-server/pkg/api/openapi/.openapi-generator/FILES index 144bee9da..2ce954859 100644 --- a/components/ambient-api-server/pkg/api/openapi/.openapi-generator/FILES +++ b/components/ambient-api-server/pkg/api/openapi/.openapi-generator/FILES @@ -10,6 +10,7 @@ docs/Agent.md docs/AgentList.md docs/AgentPatchRequest.md docs/AgentSessionList.md +docs/ApiAmbientV1ProjectsIdScheduledSessionsSsIdTriggerPost200Response.md docs/Credential.md docs/CredentialList.md docs/CredentialPatchRequest.md @@ -35,6 +36,9 @@ docs/RoleBindingList.md docs/RoleBindingPatchRequest.md docs/RoleList.md docs/RolePatchRequest.md +docs/ScheduledSession.md +docs/ScheduledSessionList.md +docs/ScheduledSessionPatchRequest.md docs/Session.md docs/SessionList.md docs/SessionMessage.md @@ -49,6 +53,7 @@ docs/UserPatchRequest.md git_push.sh go.mod go.sum +model__api_ambient_v1_projects__id__scheduled_sessions__ss_id__trigger_post_200_response.go model_agent.go model_agent_list.go model_agent_patch_request.go @@ -77,6 +82,9 @@ model_role_binding_list.go model_role_binding_patch_request.go model_role_list.go model_role_patch_request.go +model_scheduled_session.go +model_scheduled_session_list.go +model_scheduled_session_patch_request.go model_session.go model_session_list.go model_session_message.go diff --git a/components/ambient-cli/cmd/acpctl/agent/cmd.go b/components/ambient-cli/cmd/acpctl/agent/cmd.go index 4b5d373ed..ac4cc672c 100644 --- a/components/ambient-cli/cmd/acpctl/agent/cmd.go +++ b/components/ambient-cli/cmd/acpctl/agent/cmd.go @@ -435,7 +435,7 @@ This operation is idempotent — calling it multiple times is safe.`, } func startSingleAgent(ctx context.Context, cmd *cobra.Command, client *sdkclient.Client, projectID, agentID, displayName string) error { - resp, err := client.Agents().Start(ctx, projectID, agentID, agentStartArgs.prompt) + resp, err := client.Agents().StartInProject(ctx, projectID, agentID, agentStartArgs.prompt) if err != nil { return fmt.Errorf("start agent: %w", err) } diff --git a/components/ambient-cli/cmd/acpctl/ambient/tui/client.go b/components/ambient-cli/cmd/acpctl/ambient/tui/client.go index f18c6961b..884749004 100644 --- a/components/ambient-cli/cmd/acpctl/ambient/tui/client.go +++ b/components/ambient-cli/cmd/acpctl/ambient/tui/client.go @@ -468,7 +468,7 @@ func (tc *TUIClient) StartAgent(projectID, agentID, prompt string) tea.Cmd { return StartAgentMsg{Err: err} } - resp, err := client.Agents().Start(ctx, projectID, agentID, prompt) + resp, err := client.Agents().StartInProject(ctx, projectID, agentID, prompt) if err != nil { return StartAgentMsg{Err: err} } @@ -837,7 +837,7 @@ func (tc *TUIClient) FetchScheduledSessions(projectID string) tea.Cmd { return ScheduledSessionsMsg{Err: err} } - list, err := client.ScheduledSessions().List(ctx, projectID, defaultListOpts()) + list, err := client.ScheduledSessions().ListByProject(ctx, projectID, defaultListOpts()) if err != nil { return ScheduledSessionsMsg{Err: err} } @@ -856,7 +856,7 @@ func (tc *TUIClient) DeleteScheduledSession(projectID, id string) tea.Cmd { return DeleteScheduledSessionMsg{Err: err} } - err = client.ScheduledSessions().Delete(ctx, projectID, id) + err = client.ScheduledSessions().DeleteInProject(ctx, projectID, id) return DeleteScheduledSessionMsg{Err: err} } } @@ -936,7 +936,7 @@ func (tc *TUIClient) CreateScheduledSession(projectID, name, agentID, schedule, Enabled: true, } - result, err := client.ScheduledSessions().Create(ctx, projectID, ss) + result, err := client.ScheduledSessions().CreateInProject(ctx, projectID, ss) if err != nil { return CreateScheduledSessionMsg{Err: err} } @@ -955,16 +955,7 @@ func (tc *TUIClient) UpdateScheduledSession(projectID, id string, patch map[stri return UpdateScheduledSessionMsg{Err: err} } - patchJSON, err := json.Marshal(patch) - if err != nil { - return UpdateScheduledSessionMsg{Err: fmt.Errorf("marshal patch: %w", err)} - } - var typedPatch sdktypes.ScheduledSessionPatch - if err := json.Unmarshal(patchJSON, &typedPatch); err != nil { - return UpdateScheduledSessionMsg{Err: fmt.Errorf("unmarshal patch: %w", err)} - } - - result, err := client.ScheduledSessions().Update(ctx, projectID, id, &typedPatch) + result, err := client.ScheduledSessions().UpdateInProject(ctx, projectID, id, patch) if err != nil { return UpdateScheduledSessionMsg{Err: err} } diff --git a/components/ambient-cli/cmd/acpctl/ambient/tui/views/scheduledsessions.go b/components/ambient-cli/cmd/acpctl/ambient/tui/views/scheduledsessions.go index eb69fc940..bcf9baa0f 100755 --- a/components/ambient-cli/cmd/acpctl/ambient/tui/views/scheduledsessions.go +++ b/components/ambient-cli/cmd/acpctl/ambient/tui/views/scheduledsessions.go @@ -87,20 +87,9 @@ func ScheduledSessionDetail(ss sdktypes.ScheduledSession) []DetailLine { updatedAt = ss.UpdatedAt.Format(time.RFC3339) } - timeout := "" - if ss.Timeout != nil { - timeout = fmt.Sprintf("%d", *ss.Timeout) - } - - inactivityTimeout := "" - if ss.InactivityTimeout != nil { - inactivityTimeout = fmt.Sprintf("%d", *ss.InactivityTimeout) - } - - stopOnRunFinished := "" - if ss.StopOnRunFinished != nil { - stopOnRunFinished = fmt.Sprintf("%v", *ss.StopOnRunFinished) - } + timeout := fmt.Sprintf("%d", ss.Timeout) + inactivityTimeout := fmt.Sprintf("%d", ss.InactivityTimeout) + stopOnRunFinished := fmt.Sprintf("%v", ss.StopOnRunFinished) return []DetailLine{ {Key: "ID", Value: ss.ID}, diff --git a/components/ambient-cli/cmd/acpctl/scheduledsession/cmd.go b/components/ambient-cli/cmd/acpctl/scheduledsession/cmd.go index 5426b1682..33a0cecc1 100755 --- a/components/ambient-cli/cmd/acpctl/scheduledsession/cmd.go +++ b/components/ambient-cli/cmd/acpctl/scheduledsession/cmd.go @@ -53,7 +53,7 @@ func resolveScheduledSession(ctx context.Context, projectID, arg string) (string if err != nil { return "", err } - ss, err := client.ScheduledSessions().Get(ctx, projectID, arg) + ss, err := client.ScheduledSessions().GetByProject(ctx, projectID, arg) if err != nil { ss, err = client.ScheduledSessions().GetByName(ctx, projectID, arg) if err != nil { @@ -98,7 +98,7 @@ var listCmd = &cobra.Command{ defer cancel() opts := sdktypes.NewListOptions().Size(listArgs.limit).Build() - list, err := client.ScheduledSessions().List(ctx, projectID, opts) + list, err := client.ScheduledSessions().ListByProject(ctx, projectID, opts) if err != nil { return fmt.Errorf("list scheduled sessions: %w", err) } @@ -150,7 +150,7 @@ var getCmd = &cobra.Command{ ctx, cancel := context.WithTimeout(context.Background(), cfg.GetRequestTimeout()) defer cancel() - ss, err := client.ScheduledSessions().Get(ctx, projectID, args[0]) + ss, err := client.ScheduledSessions().GetByProject(ctx, projectID, args[0]) if err != nil { ss, err = client.ScheduledSessions().GetByName(ctx, projectID, args[0]) if err != nil { @@ -250,7 +250,7 @@ var createCmd = &cobra.Command{ return fmt.Errorf("build scheduled session: %w", err) } - created, err := client.ScheduledSessions().Create(ctx, projectID, ss) + created, err := client.ScheduledSessions().CreateInProject(ctx, projectID, ss) if err != nil { return fmt.Errorf("create scheduled session: %w", err) } @@ -349,7 +349,7 @@ var updateCmd = &cobra.Command{ patch = patch.RunnerType(updateArgs.runnerType) } - updated, err := client.ScheduledSessions().Update(ctx, projectID, id, patch.Build()) + updated, err := client.ScheduledSessions().UpdateInProject(ctx, projectID, id, patch.Build()) if err != nil { return fmt.Errorf("update scheduled session: %w", err) } @@ -401,7 +401,7 @@ var deleteCmd = &cobra.Command{ return err } - if err := client.ScheduledSessions().Delete(ctx, projectID, id); err != nil { + if err := client.ScheduledSessions().DeleteInProject(ctx, projectID, id); err != nil { return fmt.Errorf("delete scheduled session: %w", err) } diff --git a/components/ambient-cli/cmd/acpctl/start/cmd.go b/components/ambient-cli/cmd/acpctl/start/cmd.go index 0618ac048..5056b5fe5 100644 --- a/components/ambient-cli/cmd/acpctl/start/cmd.go +++ b/components/ambient-cli/cmd/acpctl/start/cmd.go @@ -48,7 +48,7 @@ func run(cmd *cobra.Command, cmdArgs []string) error { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - resp, err := client.Agents().Start(ctx, startArgs.projectID, paID, startArgs.prompt) + resp, err := client.Agents().StartInProject(ctx, startArgs.projectID, paID, startArgs.prompt) if err != nil { return fmt.Errorf("start agent %q: %w", paID, err) } diff --git a/components/ambient-sdk/generator/templates/go/http_client.go.tmpl b/components/ambient-sdk/generator/templates/go/http_client.go.tmpl index d453246b2..b05f64d19 100644 --- a/components/ambient-sdk/generator/templates/go/http_client.go.tmpl +++ b/components/ambient-sdk/generator/templates/go/http_client.go.tmpl @@ -25,6 +25,7 @@ import ( type Client struct { httpClient *http.Client + streamingClient *http.Client baseURL string token string project string @@ -44,17 +45,21 @@ func WithTimeout(timeout time.Duration) ClientOption { func WithInsecureSkipVerify() ClientOption { return func(c *Client) { c.insecureSkipVerify = true - t, ok := c.httpClient.Transport.(*http.Transport) - if !ok || t == nil { - t = http.DefaultTransport.(*http.Transport).Clone() - } else { - t = t.Clone() + applyInsecure := func(hc *http.Client) { + t, ok := hc.Transport.(*http.Transport) + if !ok || t == nil { + t = http.DefaultTransport.(*http.Transport).Clone() + } else { + t = t.Clone() + } + if t.TLSClientConfig == nil { + t.TLSClientConfig = &tls.Config{MinVersion: tls.VersionTLS12} + } + t.TLSClientConfig.InsecureSkipVerify = true //nolint:gosec + hc.Transport = t } - if t.TLSClientConfig == nil { - t.TLSClientConfig = &tls.Config{MinVersion: tls.VersionTLS12} - } - t.TLSClientConfig.InsecureSkipVerify = true //nolint:gosec - c.httpClient.Transport = t + applyInsecure(c.httpClient) + applyInsecure(c.streamingClient) } } @@ -95,15 +100,19 @@ func NewClient(baseURL, token, project string, opts ...ClientOption) (*Client, e return nil, fmt.Errorf("invalid base URL: %w", err) } + streamingTransport := http.DefaultTransport.(*http.Transport).Clone() + streamingTransport.DisableCompression = true + c := &Client{ httpClient: &http.Client{ Timeout: 30 * time.Second, }, - baseURL: strings.TrimSuffix(baseURL, "/"), - token: token, - project: project, - logger: slog.Default(), - userAgent: "ambient-go-sdk/1.0.0", + streamingClient: &http.Client{Transport: streamingTransport}, + baseURL: strings.TrimSuffix(baseURL, "/"), + token: token, + project: project, + logger: slog.Default(), + userAgent: "ambient-go-sdk/1.0.0", } for _, opt := range opts { @@ -115,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 == "" { @@ -135,6 +148,10 @@ func NewClientFromEnv(opts ...ClientOption) (*Client, error) { } func (c *Client) do(ctx context.Context, method, path string, body []byte, expectedStatus int, result interface{}) error { + return c.doMultiStatus(ctx, method, path, body, result, expectedStatus) +} + +func (c *Client) doMultiStatus(ctx context.Context, method, path string, body []byte, result interface{}, expectedStatuses ...int) error { url := c.baseURL + "{{.Spec.BasePath}}" + path req, err := http.NewRequestWithContext(ctx, method, url, nil) @@ -175,7 +192,14 @@ func (c *Client) do(ctx context.Context, method, path string, body []byte, expec slog.Int("body_len", len(respBody)), ) - if resp.StatusCode != expectedStatus { + statusOK := false + for _, s := range expectedStatuses { + if resp.StatusCode == s { + statusOK = true + break + } + } + if !statusOK { var apiErr types.APIError if json.Unmarshal(respBody, &apiErr) == nil && apiErr.Code != "" { apiErr.StatusCode = resp.StatusCode diff --git a/components/ambient-sdk/generator/templates/ts/ambient_client.ts.tmpl b/components/ambient-sdk/generator/templates/ts/ambient_client.ts.tmpl index 03c038232..45acf7239 100644 --- a/components/ambient-sdk/generator/templates/ts/ambient_client.ts.tmpl +++ b/components/ambient-sdk/generator/templates/ts/ambient_client.ts.tmpl @@ -17,25 +17,29 @@ export class AmbientClient { if (!config.baseUrl) { throw new Error('baseUrl is required'); } - if (!config.token) { - throw new Error('token is required'); + if (config.token) { + if (config.token.length < 20) { + throw new Error('token is too short (minimum 20 characters)'); + } + if (config.token === 'YOUR_TOKEN_HERE' || config.token === 'PLACEHOLDER_TOKEN') { + throw new Error('placeholder token is not allowed'); + } } - if (config.token.length < 20) { - throw new Error('token is too short (minimum 20 characters)'); - } - if (config.token === 'YOUR_TOKEN_HERE' || config.token === 'PLACEHOLDER_TOKEN') { - throw new Error('placeholder token is not allowed'); - } - if (!config.project) { - throw new Error('project is required'); - } - if (config.project.length > 63) { + if (config.project && config.project.length > 63) { throw new Error('project name cannot exceed 63 characters'); } - const url = new URL(config.baseUrl); - if (url.protocol !== 'http:' && url.protocol !== 'https:') { - throw new Error('only HTTP and HTTPS schemes are supported'); + // Reject protocol-relative URLs (e.g. "//evil.com/path") + if (config.baseUrl.startsWith('//')) { + throw new Error('Protocol-relative URLs are not allowed for baseUrl'); + } + + // Skip URL parsing for relative paths (e.g. "/api/proxy") + if (!config.baseUrl.startsWith('/')) { + const url = new URL(config.baseUrl); + if (url.protocol !== 'http:' && url.protocol !== 'https:') { + throw new Error('only HTTP and HTTPS schemes are supported'); + } } this.config = { @@ -54,10 +58,7 @@ export class AmbientClient { if (!token) { throw new Error('AMBIENT_TOKEN environment variable is required'); } - if (!project) { - throw new Error('AMBIENT_PROJECT environment variable is required'); - } - return new AmbientClient({ baseUrl, token, project }); + return new AmbientClient({ baseUrl, token, ...(project ? { project } : {}) }); } } diff --git a/components/ambient-sdk/generator/templates/ts/base.ts.tmpl b/components/ambient-sdk/generator/templates/ts/base.ts.tmpl index ba0ae525d..376edc44e 100644 --- a/components/ambient-sdk/generator/templates/ts/base.ts.tmpl +++ b/components/ambient-sdk/generator/templates/ts/base.ts.tmpl @@ -70,8 +70,8 @@ export type RequestOptions = { export type AmbientClientConfig = { baseUrl: string; - token: string; - project: string; + token?: string; + project?: string; }; export async function ambientFetch( @@ -83,8 +83,8 @@ export async function ambientFetch( ): Promise { const url = `${config.baseUrl}{{.Spec.BasePath}}${path}`; const headers: Record = { - 'Authorization': `Bearer ${config.token}`, - 'X-Ambient-Project': config.project, + ...(config.token ? { 'Authorization': `Bearer ${config.token}` } : {}), + ...(config.project ? { 'X-Ambient-Project': config.project } : {}), }; if (body !== undefined) { headers['Content-Type'] = 'application/json'; diff --git a/components/ambient-sdk/generator/templates/ts/client.ts.tmpl b/components/ambient-sdk/generator/templates/ts/client.ts.tmpl index e99d175b2..36fb73839 100644 --- a/components/ambient-sdk/generator/templates/ts/client.ts.tmpl +++ b/components/ambient-sdk/generator/templates/ts/client.ts.tmpl @@ -12,6 +12,9 @@ export class {{.Resource.Name}}API { {{- if .Resource.IsSubResource}} private basePath(): string { + if (!this.config.project) { + throw new Error('project is required for {{.Resource.Name}} operations'); + } return '/{{.Resource.PathSegment}}'.replace('{id}', encodeURIComponent(this.config.project)); } {{end}} diff --git a/components/ambient-sdk/go-sdk/client/agent_api.go b/components/ambient-sdk/go-sdk/client/agent_api.go index 84f549622..6e9451ad1 100644 --- a/components/ambient-sdk/go-sdk/client/agent_api.go +++ b/components/ambient-sdk/go-sdk/client/agent_api.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package client @@ -70,6 +70,14 @@ func (a *AgentAPI) Delete(ctx context.Context, id string) error { return a.client.do(ctx, http.MethodDelete, a.basePath()+"/"+url.PathEscape(id), nil, http.StatusNoContent, nil) } +func (a *AgentAPI) Start(ctx context.Context, id string) (*types.Agent, error) { + var result types.Agent + if err := a.client.do(ctx, http.MethodPost, a.basePath()+"/"+url.PathEscape(id)+"/start", nil, http.StatusOK, &result); err != nil { + return nil, err + } + return &result, nil +} + func (a *AgentAPI) ListAll(ctx context.Context, opts *types.ListOptions) *Iterator[types.Agent] { return NewIterator(func(page int) (*types.AgentList, error) { o := *opts diff --git a/components/ambient-sdk/go-sdk/client/agent_extensions.go b/components/ambient-sdk/go-sdk/client/agent_extensions.go index 6e6a3b47c..fb1ae0766 100644 --- a/components/ambient-sdk/go-sdk/client/agent_extensions.go +++ b/components/ambient-sdk/go-sdk/client/agent_extensions.go @@ -59,7 +59,7 @@ func (a *AgentAPI) DeleteInProject(ctx context.Context, projectID, agentID strin return a.client.do(ctx, http.MethodDelete, path, nil, http.StatusNoContent, nil) } -func (a *AgentAPI) Start(ctx context.Context, projectID, agentID, prompt string) (*types.StartResponse, error) { +func (a *AgentAPI) StartInProject(ctx context.Context, projectID, agentID, prompt string) (*types.StartResponse, error) { req := types.StartRequest{Prompt: prompt} body, err := json.Marshal(req) if err != nil { diff --git a/components/ambient-sdk/go-sdk/client/client.go b/components/ambient-sdk/go-sdk/client/client.go index cd095b14f..fe695c316 100644 --- a/components/ambient-sdk/go-sdk/client/client.go +++ b/components/ambient-sdk/go-sdk/client/client.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -// Generated: 2026-03-21T21:30:53Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package client diff --git a/components/ambient-sdk/go-sdk/client/credential_api.go b/components/ambient-sdk/go-sdk/client/credential_api.go index 558b5ec2d..8a8f81aeb 100644 --- a/components/ambient-sdk/go-sdk/client/credential_api.go +++ b/components/ambient-sdk/go-sdk/client/credential_api.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package client @@ -70,14 +70,6 @@ func (a *CredentialAPI) Delete(ctx context.Context, id string) error { return a.client.do(ctx, http.MethodDelete, a.basePath()+"/"+url.PathEscape(id), nil, http.StatusNoContent, nil) } -func (a *CredentialAPI) GetToken(ctx context.Context, id string) (*types.CredentialTokenResponse, error) { - var result types.CredentialTokenResponse - if err := a.client.do(ctx, http.MethodGet, a.basePath()+"/"+url.PathEscape(id)+"/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] { return NewIterator(func(page int) (*types.CredentialList, error) { o := *opts diff --git a/components/ambient-sdk/go-sdk/client/credential_extensions.go b/components/ambient-sdk/go-sdk/client/credential_extensions.go new file mode 100644 index 000000000..7e41304f4 --- /dev/null +++ b/components/ambient-sdk/go-sdk/client/credential_extensions.go @@ -0,0 +1,17 @@ +package client + +import ( + "context" + "net/http" + "net/url" + + "github.com/ambient-code/platform/components/ambient-sdk/go-sdk/types" +) + +func (a *CredentialAPI) GetToken(ctx context.Context, id string) (*types.CredentialTokenResponse, error) { + var result types.CredentialTokenResponse + if err := a.client.do(ctx, http.MethodGet, a.basePath()+"/"+url.PathEscape(id)+"/token", nil, http.StatusOK, &result); err != nil { + return nil, err + } + return &result, nil +} diff --git a/components/ambient-sdk/go-sdk/client/extensions_test.go b/components/ambient-sdk/go-sdk/client/extensions_test.go new file mode 100644 index 000000000..10bbdb7dd --- /dev/null +++ b/components/ambient-sdk/go-sdk/client/extensions_test.go @@ -0,0 +1,599 @@ +package client + +import ( + "context" + "encoding/json" + "io" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/ambient-code/platform/components/ambient-sdk/go-sdk/types" +) + +// --------------------------------------------------------------------------- +// ScheduledSession extensions +// --------------------------------------------------------------------------- + +func TestScheduledSessionListByProject(t *testing.T) { + want := &types.ScheduledSessionList{ + ListMeta: types.ListMeta{Kind: "ScheduledSessionList", Page: 1, Size: 10, Total: 1}, + Items: []types.ScheduledSession{{ObjectReference: types.ObjectReference{ID: "ss-1"}, Name: "nightly"}}, + } + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if !strings.Contains(r.URL.Path, "/projects/proj-a/scheduled-sessions") { + t.Errorf("unexpected path: %s", r.URL.Path) + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(marshalJSON(t, want)) + })) + defer srv.Close() + + c := newTestClient(t, srv) + got, err := c.ScheduledSessions().ListByProject(context.Background(), "proj-a", &types.ListOptions{}) + if err != nil { + t.Fatalf("ListByProject: %v", err) + } + if len(got.Items) != 1 || got.Items[0].ID != "ss-1" { + t.Errorf("unexpected items: %+v", got.Items) + } +} + +func TestScheduledSessionGetByProject(t *testing.T) { + want := &types.ScheduledSession{ + ObjectReference: types.ObjectReference{ID: "ss-abc"}, + Name: "daily-build", + } + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if !strings.Contains(r.URL.Path, "/projects/proj-a/scheduled-sessions/ss-abc") { + t.Errorf("unexpected path: %s", r.URL.Path) + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(marshalJSON(t, want)) + })) + defer srv.Close() + + c := newTestClient(t, srv) + got, err := c.ScheduledSessions().GetByProject(context.Background(), "proj-a", "ss-abc") + if err != nil { + t.Fatalf("GetByProject: %v", err) + } + if got.ID != "ss-abc" || got.Name != "daily-build" { + t.Errorf("unexpected result: %+v", got) + } +} + +func TestScheduledSessionCreateInProject(t *testing.T) { + want := &types.ScheduledSession{ + ObjectReference: types.ObjectReference{ID: "ss-new"}, + Name: "new-schedule", + } + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + t.Errorf("expected POST, got %s", r.Method) + } + if !strings.Contains(r.URL.Path, "/projects/proj-a/scheduled-sessions") { + t.Errorf("unexpected path: %s", r.URL.Path) + } + if r.Header.Get("Content-Type") != "application/json" { + t.Errorf("expected Content-Type: application/json") + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + _, _ = w.Write(marshalJSON(t, want)) + })) + defer srv.Close() + + c := newTestClient(t, srv) + got, err := c.ScheduledSessions().CreateInProject(context.Background(), "proj-a", &types.ScheduledSession{Name: "new-schedule"}) + if err != nil { + t.Fatalf("CreateInProject: %v", err) + } + if got.ID != "ss-new" { + t.Errorf("unexpected result: %+v", got) + } +} + +func TestScheduledSessionUpdateInProject(t *testing.T) { + want := &types.ScheduledSession{ + ObjectReference: types.ObjectReference{ID: "ss-upd"}, + Name: "updated", + } + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPatch { + t.Errorf("expected PATCH, got %s", r.Method) + } + if !strings.Contains(r.URL.Path, "/projects/proj-a/scheduled-sessions/ss-upd") { + t.Errorf("unexpected path: %s", r.URL.Path) + } + body, _ := io.ReadAll(r.Body) + var patch map[string]any + if err := json.Unmarshal(body, &patch); err != nil { + t.Fatalf("unmarshal body: %v", err) + } + if patch["name"] != "updated" { + t.Errorf("expected name=updated in patch, got %v", patch["name"]) + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(marshalJSON(t, want)) + })) + defer srv.Close() + + c := newTestClient(t, srv) + got, err := c.ScheduledSessions().UpdateInProject(context.Background(), "proj-a", "ss-upd", map[string]any{"name": "updated"}) + if err != nil { + t.Fatalf("UpdateInProject: %v", err) + } + if got.ID != "ss-upd" || got.Name != "updated" { + t.Errorf("unexpected result: %+v", got) + } +} + +func TestScheduledSessionDeleteInProject(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodDelete { + t.Errorf("expected DELETE, got %s", r.Method) + } + if !strings.Contains(r.URL.Path, "/projects/proj-a/scheduled-sessions/ss-del") { + t.Errorf("unexpected path: %s", r.URL.Path) + } + w.WriteHeader(http.StatusNoContent) + })) + defer srv.Close() + + c := newTestClient(t, srv) + if err := c.ScheduledSessions().DeleteInProject(context.Background(), "proj-a", "ss-del"); err != nil { + t.Fatalf("DeleteInProject: %v", err) + } +} + +func TestScheduledSessionSuspend(t *testing.T) { + want := &types.ScheduledSession{ + ObjectReference: types.ObjectReference{ID: "ss-sus"}, + Enabled: false, + } + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + t.Errorf("expected POST, got %s", r.Method) + } + if !strings.HasSuffix(r.URL.Path, "/scheduled-sessions/ss-sus/suspend") { + t.Errorf("unexpected path: %s", r.URL.Path) + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(marshalJSON(t, want)) + })) + defer srv.Close() + + c := newTestClient(t, srv) + got, err := c.ScheduledSessions().Suspend(context.Background(), "proj-a", "ss-sus") + if err != nil { + t.Fatalf("Suspend: %v", err) + } + if got.ID != "ss-sus" { + t.Errorf("unexpected result: %+v", got) + } +} + +func TestScheduledSessionResume(t *testing.T) { + want := &types.ScheduledSession{ + ObjectReference: types.ObjectReference{ID: "ss-res"}, + Enabled: true, + } + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + t.Errorf("expected POST, got %s", r.Method) + } + if !strings.HasSuffix(r.URL.Path, "/scheduled-sessions/ss-res/resume") { + t.Errorf("unexpected path: %s", r.URL.Path) + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(marshalJSON(t, want)) + })) + defer srv.Close() + + c := newTestClient(t, srv) + got, err := c.ScheduledSessions().Resume(context.Background(), "proj-a", "ss-res") + if err != nil { + t.Fatalf("Resume: %v", err) + } + if got.ID != "ss-res" || !got.Enabled { + t.Errorf("unexpected result: %+v", got) + } +} + +func TestScheduledSessionTrigger(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + t.Errorf("expected POST, got %s", r.Method) + } + if !strings.HasSuffix(r.URL.Path, "/scheduled-sessions/ss-trig/trigger") { + t.Errorf("unexpected path: %s", r.URL.Path) + } + w.WriteHeader(http.StatusOK) + })) + defer srv.Close() + + c := newTestClient(t, srv) + if err := c.ScheduledSessions().Trigger(context.Background(), "proj-a", "ss-trig"); err != nil { + t.Fatalf("Trigger: %v", err) + } +} + +func TestScheduledSessionGetByName(t *testing.T) { + want := &types.ScheduledSessionList{ + ListMeta: types.ListMeta{Kind: "ScheduledSessionList", Page: 1, Size: 10, Total: 1}, + Items: []types.ScheduledSession{{ObjectReference: types.ObjectReference{ID: "ss-named"}, Name: "nightly-build"}}, + } + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if r.URL.Query().Get("search") == "" { + t.Error("expected search query param for GetByName") + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(marshalJSON(t, want)) + })) + defer srv.Close() + + c := newTestClient(t, srv) + got, err := c.ScheduledSessions().GetByName(context.Background(), "proj-a", "nightly-build") + if err != nil { + t.Fatalf("GetByName: %v", err) + } + if got.ID != "ss-named" || got.Name != "nightly-build" { + t.Errorf("unexpected result: %+v", got) + } +} + +func TestScheduledSessionGetByName_NotFound(t *testing.T) { + want := &types.ScheduledSessionList{ + ListMeta: types.ListMeta{Kind: "ScheduledSessionList", Page: 1, Size: 10, Total: 0}, + Items: []types.ScheduledSession{}, + } + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(marshalJSON(t, want)) + })) + defer srv.Close() + + c := newTestClient(t, srv) + _, err := c.ScheduledSessions().GetByName(context.Background(), "proj-a", "nonexistent") + if err == nil { + t.Fatal("expected error for not-found name") + } +} + +// --------------------------------------------------------------------------- +// Agent StartInProject (multi-status) +// --------------------------------------------------------------------------- + +func TestAgentStartInProject(t *testing.T) { + want := &types.StartResponse{ + Session: &types.Session{ObjectReference: types.ObjectReference{ID: "sess-started"}}, + StartingPrompt: "do the thing", + } + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + t.Errorf("expected POST, got %s", r.Method) + } + if !strings.Contains(r.URL.Path, "/projects/proj-a/agents/agent-1/start") { + t.Errorf("unexpected path: %s", r.URL.Path) + } + body, _ := io.ReadAll(r.Body) + var req types.StartRequest + if err := json.Unmarshal(body, &req); err != nil { + t.Fatalf("unmarshal body: %v", err) + } + if req.Prompt != "do the thing" { + t.Errorf("expected prompt 'do the thing', got %q", req.Prompt) + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + _, _ = w.Write(marshalJSON(t, want)) + })) + defer srv.Close() + + c := newTestClient(t, srv) + got, err := c.Agents().StartInProject(context.Background(), "proj-a", "agent-1", "do the thing") + if err != nil { + t.Fatalf("StartInProject: %v", err) + } + if got.Session == nil || got.Session.ID != "sess-started" { + t.Errorf("unexpected result: %+v", got) + } +} + +// --------------------------------------------------------------------------- +// Credential GetToken +// --------------------------------------------------------------------------- + +func TestCredentialGetToken(t *testing.T) { + want := &types.CredentialTokenResponse{ + CredentialID: "cred-1", + Provider: "github", + Token: "ghp_test123", + } + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if !strings.HasSuffix(r.URL.Path, "/credentials/cred-1/token") { + t.Errorf("unexpected path: %s", r.URL.Path) + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(marshalJSON(t, want)) + })) + defer srv.Close() + + c := newTestClient(t, srv) + got, err := c.Credentials().GetToken(context.Background(), "cred-1") + if err != nil { + t.Fatalf("GetToken: %v", err) + } + if got.CredentialID != "cred-1" || got.Provider != "github" || got.Token != "ghp_test123" { + t.Errorf("unexpected result: %+v", got) + } +} + +// --------------------------------------------------------------------------- +// doMultiStatus +// --------------------------------------------------------------------------- + +func TestDoMultiStatus_AcceptsMultipleStatuses(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + _, _ = w.Write([]byte(`{"id":"test"}`)) + })) + defer srv.Close() + + c := newTestClient(t, srv) + var result map[string]string + err := c.doMultiStatus(context.Background(), http.MethodPost, "/test", nil, &result, http.StatusOK, http.StatusCreated) + if err != nil { + t.Fatalf("doMultiStatus should accept 201 when 200,201 expected: %v", err) + } + if result["id"] != "test" { + t.Errorf("unexpected result: %+v", result) + } +} + +func TestDoMultiStatus_RejectsUnexpectedStatus(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusForbidden) + })) + defer srv.Close() + + c := newTestClient(t, srv) + err := c.doMultiStatus(context.Background(), http.MethodPost, "/test", nil, nil, http.StatusOK, http.StatusCreated) + if err == nil { + t.Fatal("expected error for 403 when 200,201 expected") + } +} + +// --------------------------------------------------------------------------- +// Project() accessor +// --------------------------------------------------------------------------- + +func TestClientProjectAccessor(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + defer srv.Close() + + c := newTestClient(t, srv) + if c.Project() != testProject { + t.Errorf("expected project %q, got %q", testProject, c.Project()) + } +} + +// --------------------------------------------------------------------------- +// ScheduledSession Runs +// --------------------------------------------------------------------------- + +func TestScheduledSessionRuns(t *testing.T) { + want := &types.SessionList{ + ListMeta: types.ListMeta{Kind: "SessionList", Page: 1, Size: 10, Total: 2}, + Items: []types.Session{ + {ObjectReference: types.ObjectReference{ID: "sess-run-1"}, Name: "run-1"}, + {ObjectReference: types.ObjectReference{ID: "sess-run-2"}, Name: "run-2"}, + }, + } + + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + t.Errorf("expected GET, got %s", r.Method) + } + if !strings.HasSuffix(r.URL.Path, "/scheduled-sessions/ss-runs/runs") { + t.Errorf("unexpected path: %s", r.URL.Path) + } + if !strings.Contains(r.URL.Path, "/projects/proj-a/") { + t.Errorf("expected project in path: %s", r.URL.Path) + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(marshalJSON(t, want)) + })) + defer srv.Close() + + c := newTestClient(t, srv) + got, err := c.ScheduledSessions().Runs(context.Background(), "proj-a", "ss-runs", &types.ListOptions{}) + if err != nil { + t.Fatalf("Runs: %v", err) + } + if len(got.Items) != 2 { + t.Errorf("expected 2 runs, got %d", len(got.Items)) + } + if got.Items[0].ID != "sess-run-1" { + t.Errorf("unexpected first run: %+v", got.Items[0]) + } +} + +// --------------------------------------------------------------------------- +// streamingClient initialization +// --------------------------------------------------------------------------- + +func TestNewClient_StreamingClientCreated(t *testing.T) { + c, err := NewClient("http://localhost:8080", testToken, testProject) + if err != nil { + t.Fatalf("NewClient: %v", err) + } + if c.streamingClient == nil { + t.Fatal("expected streamingClient to be initialized") + } + tr, ok := c.streamingClient.Transport.(*http.Transport) + if !ok { + t.Fatal("expected streamingClient transport to be *http.Transport") + } + if !tr.DisableCompression { + t.Error("expected streamingClient transport to have DisableCompression=true") + } +} + +// --------------------------------------------------------------------------- +// WithInsecureSkipVerify applies to both clients +// --------------------------------------------------------------------------- + +func TestWithInsecureSkipVerify_BothClients(t *testing.T) { + c, err := NewClient("http://localhost:8080", testToken, testProject, WithInsecureSkipVerify()) + if err != nil { + t.Fatalf("NewClient: %v", err) + } + if !c.insecureSkipVerify { + t.Error("expected insecureSkipVerify=true") + } + + checkInsecure := func(name string, hc *http.Client) { + t.Helper() + tr, ok := hc.Transport.(*http.Transport) + if !ok || tr == nil { + t.Fatalf("%s: expected *http.Transport, got %T", name, hc.Transport) + } + if tr.TLSClientConfig == nil { + t.Fatalf("%s: expected TLSClientConfig to be set", name) + } + if !tr.TLSClientConfig.InsecureSkipVerify { + t.Errorf("%s: expected InsecureSkipVerify=true", name) + } + } + checkInsecure("httpClient", c.httpClient) + checkInsecure("streamingClient", c.streamingClient) +} + +// --------------------------------------------------------------------------- +// ScheduledSessionPatch JSON round-trip +// --------------------------------------------------------------------------- + +func TestScheduledSessionPatch_JSONRoundTrip(t *testing.T) { + enabled := true + timeout := int32(3600) + inactivity := int32(300) + stopOnRun := false + + patch := types.ScheduledSessionPatch{ + AgentID: strPtr("agent-1"), + Description: strPtr("nightly build"), + Enabled: &enabled, + InactivityTimeout: &inactivity, + Name: strPtr("nightly"), + RunnerType: strPtr("claude"), + Schedule: strPtr("0 2 * * *"), + SessionPrompt: strPtr("run tests"), + StopOnRunFinished: &stopOnRun, + Timeout: &timeout, + Timezone: strPtr("UTC"), + } + + b, err := json.Marshal(patch) + if err != nil { + t.Fatalf("marshal: %v", err) + } + + var m map[string]any + if err := json.Unmarshal(b, &m); err != nil { + t.Fatalf("unmarshal to map: %v", err) + } + + expectedKeys := []string{ + "agent_id", "description", "enabled", "inactivity_timeout", + "name", "runner_type", "schedule", "session_prompt", + "stop_on_run_finished", "timeout", "timezone", + } + for _, k := range expectedKeys { + if _, ok := m[k]; !ok { + t.Errorf("missing key %q in marshaled JSON", k) + } + } + if len(m) != len(expectedKeys) { + t.Errorf("expected %d keys, got %d: %v", len(expectedKeys), len(m), m) + } + + // Verify false bool is NOT omitted (pointer semantics) + if m["stop_on_run_finished"] != false { + t.Errorf("expected stop_on_run_finished=false, got %v", m["stop_on_run_finished"]) + } + + // Round-trip back to struct + var decoded types.ScheduledSessionPatch + if err := json.Unmarshal(b, &decoded); err != nil { + t.Fatalf("unmarshal to struct: %v", err) + } + if *decoded.AgentID != "agent-1" { + t.Errorf("agent_id mismatch: %v", decoded.AgentID) + } + if *decoded.Timeout != 3600 { + t.Errorf("timeout mismatch: %v", decoded.Timeout) + } +} + +// Omitted fields should not appear in JSON +func TestScheduledSessionPatch_OmitEmpty(t *testing.T) { + patch := types.ScheduledSessionPatch{ + Name: strPtr("only-name"), + } + + b, err := json.Marshal(patch) + if err != nil { + t.Fatalf("marshal: %v", err) + } + + var m map[string]any + if err := json.Unmarshal(b, &m); err != nil { + t.Fatalf("unmarshal: %v", err) + } + + if len(m) != 1 { + t.Errorf("expected 1 key (name only), got %d: %v", len(m), m) + } + if m["name"] != "only-name" { + t.Errorf("expected name=only-name, got %v", m["name"]) + } +} + +func strPtr(s string) *string { return &s } diff --git a/components/ambient-sdk/go-sdk/client/inbox_message_api.go b/components/ambient-sdk/go-sdk/client/inbox_message_api.go index 23d8b635b..b8322d2e9 100644 --- a/components/ambient-sdk/go-sdk/client/inbox_message_api.go +++ b/components/ambient-sdk/go-sdk/client/inbox_message_api.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package client diff --git a/components/ambient-sdk/go-sdk/client/iterator.go b/components/ambient-sdk/go-sdk/client/iterator.go index da5030716..11f033c95 100644 --- a/components/ambient-sdk/go-sdk/client/iterator.go +++ b/components/ambient-sdk/go-sdk/client/iterator.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package client diff --git a/components/ambient-sdk/go-sdk/client/project_api.go b/components/ambient-sdk/go-sdk/client/project_api.go index 1aefbb740..f720c67ea 100644 --- a/components/ambient-sdk/go-sdk/client/project_api.go +++ b/components/ambient-sdk/go-sdk/client/project_api.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package client diff --git a/components/ambient-sdk/go-sdk/client/project_settings_api.go b/components/ambient-sdk/go-sdk/client/project_settings_api.go index 47660e350..aed0fb1d9 100644 --- a/components/ambient-sdk/go-sdk/client/project_settings_api.go +++ b/components/ambient-sdk/go-sdk/client/project_settings_api.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package client diff --git a/components/ambient-sdk/go-sdk/client/role_api.go b/components/ambient-sdk/go-sdk/client/role_api.go index 1e19ae5c4..56e2e5bda 100644 --- a/components/ambient-sdk/go-sdk/client/role_api.go +++ b/components/ambient-sdk/go-sdk/client/role_api.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package client diff --git a/components/ambient-sdk/go-sdk/client/role_binding_api.go b/components/ambient-sdk/go-sdk/client/role_binding_api.go index ad3e628e6..2ea9211aa 100644 --- a/components/ambient-sdk/go-sdk/client/role_binding_api.go +++ b/components/ambient-sdk/go-sdk/client/role_binding_api.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package client diff --git a/components/ambient-sdk/go-sdk/client/scheduled_session_api.go b/components/ambient-sdk/go-sdk/client/scheduled_session_api.go index daa07bdf9..ef5aa2add 100644 --- a/components/ambient-sdk/go-sdk/client/scheduled_session_api.go +++ b/components/ambient-sdk/go-sdk/client/scheduled_session_api.go @@ -1,3 +1,8 @@ +// Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. +// Source: ../../ambient-api-server/openapi/openapi.yaml +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z + package client import ( @@ -6,6 +11,7 @@ import ( "fmt" "net/http" "net/url" + "strings" "github.com/ambient-code/platform/components/ambient-sdk/go-sdk/types" ) @@ -17,98 +23,57 @@ type ScheduledSessionAPI struct { func (c *Client) ScheduledSessions() *ScheduledSessionAPI { return &ScheduledSessionAPI{client: c} } - -func (a *ScheduledSessionAPI) basePath(projectID string) string { - return "/projects/" + url.PathEscape(projectID) + "/scheduled-sessions" -} - -func (a *ScheduledSessionAPI) List(ctx context.Context, projectID string, opts *types.ListOptions) (*types.ScheduledSessionList, error) { - var result types.ScheduledSessionList - if err := a.client.doWithQuery(ctx, http.MethodGet, a.basePath(projectID), nil, http.StatusOK, &result, opts); err != nil { - return nil, err - } - return &result, nil -} - -func (a *ScheduledSessionAPI) Get(ctx context.Context, projectID, id string) (*types.ScheduledSession, error) { - var result types.ScheduledSession - path := a.basePath(projectID) + "/" + url.PathEscape(id) - if err := a.client.do(ctx, http.MethodGet, path, nil, http.StatusOK, &result); err != nil { - return nil, err - } - return &result, nil +func (a *ScheduledSessionAPI) basePath() string { + return strings.NewReplacer("{id}", url.PathEscape(a.client.project)).Replace("/projects/{id}/scheduled-sessions") } -func (a *ScheduledSessionAPI) Create(ctx context.Context, projectID string, resource *types.ScheduledSession) (*types.ScheduledSession, error) { +func (a *ScheduledSessionAPI) Create(ctx context.Context, resource *types.ScheduledSession) (*types.ScheduledSession, error) { body, err := json.Marshal(resource) if err != nil { - return nil, fmt.Errorf("marshal scheduled session: %w", err) + return nil, fmt.Errorf("marshal scheduled_session: %w", err) } var result types.ScheduledSession - if err := a.client.do(ctx, http.MethodPost, a.basePath(projectID), body, http.StatusCreated, &result); err != nil { + if err := a.client.do(ctx, http.MethodPost, a.basePath(), body, http.StatusCreated, &result); err != nil { return nil, err } return &result, nil } -func (a *ScheduledSessionAPI) Update(ctx context.Context, projectID, id string, patch *types.ScheduledSessionPatch) (*types.ScheduledSession, error) { - body, err := json.Marshal(patch) - if err != nil { - return nil, fmt.Errorf("marshal patch: %w", err) - } +func (a *ScheduledSessionAPI) Get(ctx context.Context, id string) (*types.ScheduledSession, error) { var result types.ScheduledSession - path := a.basePath(projectID) + "/" + url.PathEscape(id) - if err := a.client.do(ctx, http.MethodPatch, path, body, http.StatusOK, &result); err != nil { + if err := a.client.do(ctx, http.MethodGet, a.basePath()+"/"+url.PathEscape(id), nil, http.StatusOK, &result); err != nil { return nil, err } return &result, nil } -func (a *ScheduledSessionAPI) Delete(ctx context.Context, projectID, id string) error { - return a.client.do(ctx, http.MethodDelete, a.basePath(projectID)+"/"+url.PathEscape(id), nil, http.StatusNoContent, nil) -} - -func (a *ScheduledSessionAPI) Suspend(ctx context.Context, projectID, id string) (*types.ScheduledSession, error) { - var result types.ScheduledSession - path := a.basePath(projectID) + "/" + url.PathEscape(id) + "/suspend" - if err := a.client.do(ctx, http.MethodPost, path, nil, http.StatusOK, &result); err != nil { +func (a *ScheduledSessionAPI) List(ctx context.Context, opts *types.ListOptions) (*types.ScheduledSessionList, error) { + var result types.ScheduledSessionList + if err := a.client.doWithQuery(ctx, http.MethodGet, a.basePath(), nil, http.StatusOK, &result, opts); err != nil { return nil, err } return &result, nil } - -func (a *ScheduledSessionAPI) Resume(ctx context.Context, projectID, id string) (*types.ScheduledSession, error) { +func (a *ScheduledSessionAPI) Update(ctx context.Context, id string, patch map[string]any) (*types.ScheduledSession, error) { + body, err := json.Marshal(patch) + if err != nil { + return nil, fmt.Errorf("marshal patch: %w", err) + } var result types.ScheduledSession - path := a.basePath(projectID) + "/" + url.PathEscape(id) + "/resume" - if err := a.client.do(ctx, http.MethodPost, path, nil, http.StatusOK, &result); err != nil { + if err := a.client.do(ctx, http.MethodPatch, a.basePath()+"/"+url.PathEscape(id), body, http.StatusOK, &result); err != nil { return nil, err } return &result, nil } -func (a *ScheduledSessionAPI) Trigger(ctx context.Context, projectID, id string) error { - path := a.basePath(projectID) + "/" + url.PathEscape(id) + "/trigger" - return a.client.do(ctx, http.MethodPost, path, nil, http.StatusOK, nil) +func (a *ScheduledSessionAPI) Delete(ctx context.Context, id string) error { + return a.client.do(ctx, http.MethodDelete, a.basePath()+"/"+url.PathEscape(id), nil, http.StatusNoContent, nil) } -func (a *ScheduledSessionAPI) Runs(ctx context.Context, projectID, id string, opts *types.ListOptions) (*types.SessionList, error) { - var result types.SessionList - path := a.basePath(projectID) + "/" + url.PathEscape(id) + "/runs" - if err := a.client.doWithQuery(ctx, http.MethodGet, path, nil, http.StatusOK, &result, opts); err != nil { - return nil, err - } - return &result, nil -} - -func (a *ScheduledSessionAPI) GetByName(ctx context.Context, projectID, name string) (*types.ScheduledSession, error) { - list, err := a.List(ctx, projectID, &types.ListOptions{Search: "name = '" + name + "'"}) - if err != nil { - return nil, err - } - for i := range list.Items { - if list.Items[i].Name == name { - return &list.Items[i], nil - } - } - return nil, fmt.Errorf("scheduled session %q not found in project %q", name, projectID) +func (a *ScheduledSessionAPI) ListAll(ctx context.Context, opts *types.ListOptions) *Iterator[types.ScheduledSession] { + return NewIterator(func(page int) (*types.ScheduledSessionList, error) { + o := *opts + o.Page = page + return a.List(ctx, &o) + }) } diff --git a/components/ambient-sdk/go-sdk/client/scheduled_session_extensions.go b/components/ambient-sdk/go-sdk/client/scheduled_session_extensions.go new file mode 100644 index 000000000..3647ac5d4 --- /dev/null +++ b/components/ambient-sdk/go-sdk/client/scheduled_session_extensions.go @@ -0,0 +1,106 @@ +package client + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "net/url" + + "github.com/ambient-code/platform/components/ambient-sdk/go-sdk/types" +) + +func (a *ScheduledSessionAPI) projectPath(projectID string) string { + return "/projects/" + url.PathEscape(projectID) + "/scheduled-sessions" +} + +func (a *ScheduledSessionAPI) ListByProject(ctx context.Context, projectID string, opts *types.ListOptions) (*types.ScheduledSessionList, error) { + var result types.ScheduledSessionList + if err := a.client.doWithQuery(ctx, http.MethodGet, a.projectPath(projectID), nil, http.StatusOK, &result, opts); err != nil { + return nil, err + } + return &result, nil +} + +func (a *ScheduledSessionAPI) GetByProject(ctx context.Context, projectID, id string) (*types.ScheduledSession, error) { + var result types.ScheduledSession + path := a.projectPath(projectID) + "/" + url.PathEscape(id) + if err := a.client.do(ctx, http.MethodGet, path, nil, http.StatusOK, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (a *ScheduledSessionAPI) CreateInProject(ctx context.Context, projectID string, resource *types.ScheduledSession) (*types.ScheduledSession, error) { + body, err := json.Marshal(resource) + if err != nil { + return nil, fmt.Errorf("marshal scheduled session: %w", err) + } + var result types.ScheduledSession + if err := a.client.do(ctx, http.MethodPost, a.projectPath(projectID), body, http.StatusCreated, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (a *ScheduledSessionAPI) UpdateInProject(ctx context.Context, projectID, id string, patch map[string]any) (*types.ScheduledSession, error) { + body, err := json.Marshal(patch) + if err != nil { + return nil, fmt.Errorf("marshal patch: %w", err) + } + var result types.ScheduledSession + path := a.projectPath(projectID) + "/" + url.PathEscape(id) + if err := a.client.do(ctx, http.MethodPatch, path, body, http.StatusOK, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (a *ScheduledSessionAPI) DeleteInProject(ctx context.Context, projectID, id string) error { + return a.client.do(ctx, http.MethodDelete, a.projectPath(projectID)+"/"+url.PathEscape(id), nil, http.StatusNoContent, nil) +} + +func (a *ScheduledSessionAPI) Suspend(ctx context.Context, projectID, id string) (*types.ScheduledSession, error) { + var result types.ScheduledSession + path := a.projectPath(projectID) + "/" + url.PathEscape(id) + "/suspend" + if err := a.client.do(ctx, http.MethodPost, path, nil, http.StatusOK, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (a *ScheduledSessionAPI) Resume(ctx context.Context, projectID, id string) (*types.ScheduledSession, error) { + var result types.ScheduledSession + path := a.projectPath(projectID) + "/" + url.PathEscape(id) + "/resume" + if err := a.client.do(ctx, http.MethodPost, path, nil, http.StatusOK, &result); err != nil { + return nil, err + } + return &result, nil +} + +func (a *ScheduledSessionAPI) Trigger(ctx context.Context, projectID, id string) error { + path := a.projectPath(projectID) + "/" + url.PathEscape(id) + "/trigger" + return a.client.do(ctx, http.MethodPost, path, nil, http.StatusOK, nil) +} + +func (a *ScheduledSessionAPI) Runs(ctx context.Context, projectID, id string, opts *types.ListOptions) (*types.SessionList, error) { + var result types.SessionList + path := a.projectPath(projectID) + "/" + url.PathEscape(id) + "/runs" + if err := a.client.doWithQuery(ctx, http.MethodGet, path, nil, http.StatusOK, &result, opts); err != nil { + return nil, err + } + return &result, nil +} + +func (a *ScheduledSessionAPI) GetByName(ctx context.Context, projectID, name string) (*types.ScheduledSession, error) { + list, err := a.ListByProject(ctx, projectID, &types.ListOptions{Search: "name = '" + name + "'"}) + if err != nil { + return nil, err + } + for i := range list.Items { + if list.Items[i].Name == name { + return &list.Items[i], nil + } + } + return nil, fmt.Errorf("scheduled session %q not found in project %q", name, projectID) +} diff --git a/components/ambient-sdk/go-sdk/client/session_api.go b/components/ambient-sdk/go-sdk/client/session_api.go index 2e3afb192..27726fd55 100644 --- a/components/ambient-sdk/go-sdk/client/session_api.go +++ b/components/ambient-sdk/go-sdk/client/session_api.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package client diff --git a/components/ambient-sdk/go-sdk/client/session_message_api.go b/components/ambient-sdk/go-sdk/client/session_message_api.go index 0f0e43c80..c4e27b867 100644 --- a/components/ambient-sdk/go-sdk/client/session_message_api.go +++ b/components/ambient-sdk/go-sdk/client/session_message_api.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package client diff --git a/components/ambient-sdk/go-sdk/client/user_api.go b/components/ambient-sdk/go-sdk/client/user_api.go index c78f7cbb8..923e96645 100644 --- a/components/ambient-sdk/go-sdk/client/user_api.go +++ b/components/ambient-sdk/go-sdk/client/user_api.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package client diff --git a/components/ambient-sdk/go-sdk/types/agent.go b/components/ambient-sdk/go-sdk/types/agent.go index e880327d4..a965c10fd 100644 --- a/components/ambient-sdk/go-sdk/types/agent.go +++ b/components/ambient-sdk/go-sdk/types/agent.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package types diff --git a/components/ambient-sdk/go-sdk/types/base.go b/components/ambient-sdk/go-sdk/types/base.go index b3a3734ba..471d6e91a 100644 --- a/components/ambient-sdk/go-sdk/types/base.go +++ b/components/ambient-sdk/go-sdk/types/base.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package types diff --git a/components/ambient-sdk/go-sdk/types/credential.go b/components/ambient-sdk/go-sdk/types/credential.go index 2c2429be3..546c2be30 100644 --- a/components/ambient-sdk/go-sdk/types/credential.go +++ b/components/ambient-sdk/go-sdk/types/credential.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package types @@ -155,9 +155,3 @@ func (b *CredentialPatchBuilder) URL(v string) *CredentialPatchBuilder { func (b *CredentialPatchBuilder) Build() map[string]any { return b.patch } - -type CredentialTokenResponse struct { - CredentialID string `json:"credential_id"` - Provider string `json:"provider"` - Token string `json:"token"` -} diff --git a/components/ambient-sdk/go-sdk/types/credential_extensions.go b/components/ambient-sdk/go-sdk/types/credential_extensions.go new file mode 100644 index 000000000..f358179e7 --- /dev/null +++ b/components/ambient-sdk/go-sdk/types/credential_extensions.go @@ -0,0 +1,7 @@ +package types + +type CredentialTokenResponse struct { + CredentialID string `json:"credential_id"` + Provider string `json:"provider"` + Token string `json:"token"` +} diff --git a/components/ambient-sdk/go-sdk/types/inbox_message.go b/components/ambient-sdk/go-sdk/types/inbox_message.go index eb851499d..81f9c43e8 100644 --- a/components/ambient-sdk/go-sdk/types/inbox_message.go +++ b/components/ambient-sdk/go-sdk/types/inbox_message.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package types diff --git a/components/ambient-sdk/go-sdk/types/list_options.go b/components/ambient-sdk/go-sdk/types/list_options.go index bf7d638d6..287ca0b3d 100644 --- a/components/ambient-sdk/go-sdk/types/list_options.go +++ b/components/ambient-sdk/go-sdk/types/list_options.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package types diff --git a/components/ambient-sdk/go-sdk/types/project.go b/components/ambient-sdk/go-sdk/types/project.go index d22837b1c..91b709f4c 100644 --- a/components/ambient-sdk/go-sdk/types/project.go +++ b/components/ambient-sdk/go-sdk/types/project.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package types diff --git a/components/ambient-sdk/go-sdk/types/project_settings.go b/components/ambient-sdk/go-sdk/types/project_settings.go index 1a5a07d61..5b0a7bdd9 100644 --- a/components/ambient-sdk/go-sdk/types/project_settings.go +++ b/components/ambient-sdk/go-sdk/types/project_settings.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package types diff --git a/components/ambient-sdk/go-sdk/types/role.go b/components/ambient-sdk/go-sdk/types/role.go index 3bc87ba6b..081457fae 100644 --- a/components/ambient-sdk/go-sdk/types/role.go +++ b/components/ambient-sdk/go-sdk/types/role.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package types diff --git a/components/ambient-sdk/go-sdk/types/role_binding.go b/components/ambient-sdk/go-sdk/types/role_binding.go index 37a09d474..99863b9de 100644 --- a/components/ambient-sdk/go-sdk/types/role_binding.go +++ b/components/ambient-sdk/go-sdk/types/role_binding.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package types diff --git a/components/ambient-sdk/go-sdk/types/scheduled_session.go b/components/ambient-sdk/go-sdk/types/scheduled_session.go index 2b3f9d2ce..8090ed23a 100755 --- a/components/ambient-sdk/go-sdk/types/scheduled_session.go +++ b/components/ambient-sdk/go-sdk/types/scheduled_session.go @@ -1,3 +1,8 @@ +// Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. +// Source: ../../ambient-api-server/openapi/openapi.yaml +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z + package types import ( @@ -12,16 +17,16 @@ type ScheduledSession struct { AgentID string `json:"agent_id,omitempty"` Description string `json:"description,omitempty"` Enabled bool `json:"enabled,omitempty"` - InactivityTimeout *int32 `json:"inactivity_timeout,omitempty"` + InactivityTimeout int32 `json:"inactivity_timeout,omitempty"` LastRunAt *time.Time `json:"last_run_at,omitempty"` Name string `json:"name"` NextRunAt *time.Time `json:"next_run_at,omitempty"` - ProjectID string `json:"project_id,omitempty"` + ProjectID string `json:"project_id"` RunnerType string `json:"runner_type,omitempty"` - Schedule string `json:"schedule,omitempty"` + Schedule string `json:"schedule"` SessionPrompt string `json:"session_prompt,omitempty"` - StopOnRunFinished *bool `json:"stop_on_run_finished,omitempty"` - Timeout *int32 `json:"timeout,omitempty"` + StopOnRunFinished bool `json:"stop_on_run_finished,omitempty"` + Timeout int32 `json:"timeout,omitempty"` Timezone string `json:"timezone,omitempty"` } @@ -35,164 +40,164 @@ func (l *ScheduledSessionList) GetTotal() int { return l.Total } func (l *ScheduledSessionList) GetPage() int { return l.Page } func (l *ScheduledSessionList) GetSize() int { return l.Size } -// ScheduledSessionPatch is the request body for a PATCH operation. -// Only set fields that should be changed; omitted (nil) fields are left unchanged. -type ScheduledSessionPatch struct { - Name *string `json:"name,omitempty"` - Description *string `json:"description,omitempty"` - AgentID *string `json:"agent_id,omitempty"` - Schedule *string `json:"schedule,omitempty"` - Timezone *string `json:"timezone,omitempty"` - Enabled *bool `json:"enabled,omitempty"` - SessionPrompt *string `json:"session_prompt,omitempty"` - Timeout *int32 `json:"timeout,omitempty"` - InactivityTimeout *int32 `json:"inactivity_timeout,omitempty"` - StopOnRunFinished *bool `json:"stop_on_run_finished,omitempty"` - RunnerType *string `json:"runner_type,omitempty"` -} - -// ScheduledSessionBuilder builds a ScheduledSession for creation. type ScheduledSessionBuilder struct { resource ScheduledSession - errs []error + errors []error } func NewScheduledSessionBuilder() *ScheduledSessionBuilder { return &ScheduledSessionBuilder{} } -func (b *ScheduledSessionBuilder) Name(v string) *ScheduledSessionBuilder { - b.resource.Name = v +func (b *ScheduledSessionBuilder) AgentID(v string) *ScheduledSessionBuilder { + b.resource.AgentID = v return b } -func (b *ScheduledSessionBuilder) ProjectID(v string) *ScheduledSessionBuilder { - b.resource.ProjectID = v +func (b *ScheduledSessionBuilder) Description(v string) *ScheduledSessionBuilder { + b.resource.Description = v return b } -func (b *ScheduledSessionBuilder) AgentID(v string) *ScheduledSessionBuilder { - b.resource.AgentID = v +func (b *ScheduledSessionBuilder) Enabled(v bool) *ScheduledSessionBuilder { + b.resource.Enabled = v return b } -func (b *ScheduledSessionBuilder) Schedule(v string) *ScheduledSessionBuilder { - b.resource.Schedule = v +func (b *ScheduledSessionBuilder) InactivityTimeout(v int32) *ScheduledSessionBuilder { + b.resource.InactivityTimeout = v return b } -func (b *ScheduledSessionBuilder) Timezone(v string) *ScheduledSessionBuilder { - b.resource.Timezone = v +func (b *ScheduledSessionBuilder) LastRunAt(v *time.Time) *ScheduledSessionBuilder { + b.resource.LastRunAt = v return b } -func (b *ScheduledSessionBuilder) SessionPrompt(v string) *ScheduledSessionBuilder { - b.resource.SessionPrompt = v +func (b *ScheduledSessionBuilder) Name(v string) *ScheduledSessionBuilder { + b.resource.Name = v return b } -func (b *ScheduledSessionBuilder) Description(v string) *ScheduledSessionBuilder { - b.resource.Description = v +func (b *ScheduledSessionBuilder) NextRunAt(v *time.Time) *ScheduledSessionBuilder { + b.resource.NextRunAt = v return b } -func (b *ScheduledSessionBuilder) Timeout(v int32) *ScheduledSessionBuilder { - b.resource.Timeout = &v +func (b *ScheduledSessionBuilder) ProjectID(v string) *ScheduledSessionBuilder { + b.resource.ProjectID = v return b } -func (b *ScheduledSessionBuilder) InactivityTimeout(v int32) *ScheduledSessionBuilder { - b.resource.InactivityTimeout = &v +func (b *ScheduledSessionBuilder) RunnerType(v string) *ScheduledSessionBuilder { + b.resource.RunnerType = v + return b +} + +func (b *ScheduledSessionBuilder) Schedule(v string) *ScheduledSessionBuilder { + b.resource.Schedule = v + return b +} + +func (b *ScheduledSessionBuilder) SessionPrompt(v string) *ScheduledSessionBuilder { + b.resource.SessionPrompt = v return b } func (b *ScheduledSessionBuilder) StopOnRunFinished(v bool) *ScheduledSessionBuilder { - b.resource.StopOnRunFinished = &v + b.resource.StopOnRunFinished = v return b } -func (b *ScheduledSessionBuilder) RunnerType(v string) *ScheduledSessionBuilder { - b.resource.RunnerType = v +func (b *ScheduledSessionBuilder) Timeout(v int32) *ScheduledSessionBuilder { + b.resource.Timeout = v + return b +} + +func (b *ScheduledSessionBuilder) Timezone(v string) *ScheduledSessionBuilder { + b.resource.Timezone = v return b } func (b *ScheduledSessionBuilder) Build() (*ScheduledSession, error) { if b.resource.Name == "" { - b.errs = append(b.errs, fmt.Errorf("name is required")) + b.errors = append(b.errors, fmt.Errorf("name is required")) + } + if b.resource.ProjectID == "" { + b.errors = append(b.errors, fmt.Errorf("project_id is required")) } if b.resource.Schedule == "" { - b.errs = append(b.errs, fmt.Errorf("schedule is required")) + b.errors = append(b.errors, fmt.Errorf("schedule is required")) } - if len(b.errs) > 0 { - return nil, fmt.Errorf("validation failed: %w", errors.Join(b.errs...)) + if len(b.errors) > 0 { + return nil, fmt.Errorf("validation failed: %w", errors.Join(b.errors...)) } return &b.resource, nil } -// ScheduledSessionPatchBuilder builds a ScheduledSessionPatch for update operations. type ScheduledSessionPatchBuilder struct { - patch ScheduledSessionPatch + patch map[string]any } func NewScheduledSessionPatchBuilder() *ScheduledSessionPatchBuilder { - return &ScheduledSessionPatchBuilder{} + return &ScheduledSessionPatchBuilder{patch: make(map[string]any)} } -func (b *ScheduledSessionPatchBuilder) Name(v string) *ScheduledSessionPatchBuilder { - b.patch.Name = &v +func (b *ScheduledSessionPatchBuilder) AgentID(v string) *ScheduledSessionPatchBuilder { + b.patch["agent_id"] = v return b } func (b *ScheduledSessionPatchBuilder) Description(v string) *ScheduledSessionPatchBuilder { - b.patch.Description = &v + b.patch["description"] = v return b } -func (b *ScheduledSessionPatchBuilder) Schedule(v string) *ScheduledSessionPatchBuilder { - b.patch.Schedule = &v +func (b *ScheduledSessionPatchBuilder) Enabled(v bool) *ScheduledSessionPatchBuilder { + b.patch["enabled"] = v return b } -func (b *ScheduledSessionPatchBuilder) Timezone(v string) *ScheduledSessionPatchBuilder { - b.patch.Timezone = &v +func (b *ScheduledSessionPatchBuilder) InactivityTimeout(v int32) *ScheduledSessionPatchBuilder { + b.patch["inactivity_timeout"] = v return b } -func (b *ScheduledSessionPatchBuilder) Enabled(v bool) *ScheduledSessionPatchBuilder { - b.patch.Enabled = &v +func (b *ScheduledSessionPatchBuilder) Name(v string) *ScheduledSessionPatchBuilder { + b.patch["name"] = v return b } -func (b *ScheduledSessionPatchBuilder) SessionPrompt(v string) *ScheduledSessionPatchBuilder { - b.patch.SessionPrompt = &v +func (b *ScheduledSessionPatchBuilder) RunnerType(v string) *ScheduledSessionPatchBuilder { + b.patch["runner_type"] = v return b } -func (b *ScheduledSessionPatchBuilder) AgentID(v string) *ScheduledSessionPatchBuilder { - b.patch.AgentID = &v +func (b *ScheduledSessionPatchBuilder) Schedule(v string) *ScheduledSessionPatchBuilder { + b.patch["schedule"] = v return b } -func (b *ScheduledSessionPatchBuilder) Timeout(v int32) *ScheduledSessionPatchBuilder { - b.patch.Timeout = &v +func (b *ScheduledSessionPatchBuilder) SessionPrompt(v string) *ScheduledSessionPatchBuilder { + b.patch["session_prompt"] = v return b } -func (b *ScheduledSessionPatchBuilder) InactivityTimeout(v int32) *ScheduledSessionPatchBuilder { - b.patch.InactivityTimeout = &v +func (b *ScheduledSessionPatchBuilder) StopOnRunFinished(v bool) *ScheduledSessionPatchBuilder { + b.patch["stop_on_run_finished"] = v return b } -func (b *ScheduledSessionPatchBuilder) StopOnRunFinished(v bool) *ScheduledSessionPatchBuilder { - b.patch.StopOnRunFinished = &v +func (b *ScheduledSessionPatchBuilder) Timeout(v int32) *ScheduledSessionPatchBuilder { + b.patch["timeout"] = v return b } -func (b *ScheduledSessionPatchBuilder) RunnerType(v string) *ScheduledSessionPatchBuilder { - b.patch.RunnerType = &v +func (b *ScheduledSessionPatchBuilder) Timezone(v string) *ScheduledSessionPatchBuilder { + b.patch["timezone"] = v return b } -func (b *ScheduledSessionPatchBuilder) Build() *ScheduledSessionPatch { - return &b.patch +func (b *ScheduledSessionPatchBuilder) Build() map[string]any { + return b.patch } diff --git a/components/ambient-sdk/go-sdk/types/scheduled_session_extensions.go b/components/ambient-sdk/go-sdk/types/scheduled_session_extensions.go new file mode 100644 index 000000000..324ed2cda --- /dev/null +++ b/components/ambient-sdk/go-sdk/types/scheduled_session_extensions.go @@ -0,0 +1,15 @@ +package types + +type ScheduledSessionPatch struct { + AgentID *string `json:"agent_id,omitempty"` + Description *string `json:"description,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + InactivityTimeout *int32 `json:"inactivity_timeout,omitempty"` + Name *string `json:"name,omitempty"` + RunnerType *string `json:"runner_type,omitempty"` + Schedule *string `json:"schedule,omitempty"` + SessionPrompt *string `json:"session_prompt,omitempty"` + StopOnRunFinished *bool `json:"stop_on_run_finished,omitempty"` + Timeout *int32 `json:"timeout,omitempty"` + Timezone *string `json:"timezone,omitempty"` +} diff --git a/components/ambient-sdk/go-sdk/types/session.go b/components/ambient-sdk/go-sdk/types/session.go index 98459dd05..814798554 100644 --- a/components/ambient-sdk/go-sdk/types/session.go +++ b/components/ambient-sdk/go-sdk/types/session.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package types diff --git a/components/ambient-sdk/go-sdk/types/session_message.go b/components/ambient-sdk/go-sdk/types/session_message.go index 82b37c603..add587d2b 100644 --- a/components/ambient-sdk/go-sdk/types/session_message.go +++ b/components/ambient-sdk/go-sdk/types/session_message.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package types diff --git a/components/ambient-sdk/go-sdk/types/user.go b/components/ambient-sdk/go-sdk/types/user.go index 35682b8e6..a275fe1f6 100644 --- a/components/ambient-sdk/go-sdk/types/user.go +++ b/components/ambient-sdk/go-sdk/types/user.go @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z package types diff --git a/components/ambient-sdk/python-sdk/ambient_platform/__init__.py b/components/ambient-sdk/python-sdk/ambient_platform/__init__.py index 57b230f4e..f79498c76 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/__init__.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/__init__.py @@ -1,18 +1,20 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -# Generated: 2026-03-21T21:30:53Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z """Ambient Platform SDK for Python.""" from .client import AmbientClient from ._base import APIError, ListOptions -from .inbox_message import InboxMessage +from .agent import Agent, AgentPatch +from .credential import Credential, CredentialPatch +from .inbox_message import InboxMessage, InboxMessagePatch from .project import Project, ProjectPatch -from .agent import Agent from .project_settings import ProjectSettings, ProjectSettingsPatch from .role import Role, RolePatch from .role_binding import RoleBinding, RoleBindingPatch +from .scheduled_session import ScheduledSession, ScheduledSessionPatch from .session import Session, SessionPatch, SessionStatusPatch from .session_message import SessionMessage from .user import User, UserPatch @@ -23,16 +25,22 @@ "AmbientClient", "APIError", "ListOptions", + "Agent", + "AgentPatch", + "Credential", + "CredentialPatch", "InboxMessage", + "InboxMessagePatch", "Project", "ProjectPatch", - "Agent", "ProjectSettings", "ProjectSettingsPatch", "Role", "RolePatch", "RoleBinding", "RoleBindingPatch", + "ScheduledSession", + "ScheduledSessionPatch", "Session", "SessionPatch", "SessionStatusPatch", diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_agent_api.py b/components/ambient-sdk/python-sdk/ambient_platform/_agent_api.py index 531a9a926..74876e405 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/_agent_api.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/_agent_api.py @@ -1,11 +1,12 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 404b5671af96841f4a876b6192afc6358b4fb8e082ca2b6da499efcf3f72c781 -# Generated: 2026-03-20T16:48:23Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations from typing import Any, Iterator, Optional, TYPE_CHECKING +from urllib.parse import quote from ._base import ListOptions from .agent import Agent, AgentList @@ -17,22 +18,32 @@ class AgentAPI: def __init__(self, client: AmbientClient) -> None: self._client = client + def _base_path(self) -> str: + return "/projects/{id}/agents".replace("{id}", quote(self._client._project, safe="")) + def create(self, data: dict) -> Agent: - resp = self._client._request("POST", "/agents", json=data) + resp = self._client._request("POST", self._base_path(), json=data) return Agent.from_dict(resp) def get(self, resource_id: str) -> Agent: - resp = self._client._request("GET", f"/agents/{resource_id}") + resp = self._client._request("GET", f"{self._base_path()}/{resource_id}") return Agent.from_dict(resp) def list(self, opts: Optional[ListOptions] = None) -> AgentList: params = opts.to_params() if opts else None - resp = self._client._request("GET", "/agents", params=params) + resp = self._client._request("GET", self._base_path(), params=params) return AgentList.from_dict(resp) def update(self, resource_id: str, patch: Any) -> Agent: data = patch.to_dict() if hasattr(patch, "to_dict") else patch - resp = self._client._request("PATCH", f"/agents/{resource_id}", json=data) + resp = self._client._request("PATCH", f"{self._base_path()}/{resource_id}", json=data) + return Agent.from_dict(resp) + + def delete(self, resource_id: str) -> None: + self._client._request("DELETE", f"{self._base_path()}/{resource_id}", expect_json=False) + + def start(self, resource_id: str) -> Agent: + resp = self._client._request("POST", f"{self._base_path()}/{resource_id}/start") return Agent.from_dict(resp) def list_all(self, size: int = 100, **kwargs: Any) -> Iterator[Agent]: diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_base.py b/components/ambient-sdk/python-sdk/ambient_platform/_base.py index 89dd7058a..9ec92c722 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/_base.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/_base.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_credential_api.py b/components/ambient-sdk/python-sdk/ambient_platform/_credential_api.py new file mode 100644 index 000000000..55579aad7 --- /dev/null +++ b/components/ambient-sdk/python-sdk/ambient_platform/_credential_api.py @@ -0,0 +1,52 @@ +# Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. +# Source: ../../ambient-api-server/openapi/openapi.yaml +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z + +from __future__ import annotations + +from typing import Any, Iterator, Optional, TYPE_CHECKING +from urllib.parse import quote + +from ._base import ListOptions +from .credential import Credential, CredentialList + +if TYPE_CHECKING: + from .client import AmbientClient + + +class CredentialAPI: + def __init__(self, client: AmbientClient) -> None: + self._client = client + def _base_path(self) -> str: + return "/projects/{id}/credentials".replace("{id}", quote(self._client._project, safe="")) + + + def create(self, data: dict) -> Credential: + resp = self._client._request("POST", self._base_path(), json=data) + return Credential.from_dict(resp) + + def get(self, resource_id: str) -> Credential: + resp = self._client._request("GET", f"{self._base_path()}/{resource_id}") + return Credential.from_dict(resp) + + def list(self, opts: Optional[ListOptions] = None) -> CredentialList: + params = opts.to_params() if opts else None + resp = self._client._request("GET", self._base_path(), params=params) + return CredentialList.from_dict(resp) + def update(self, resource_id: str, patch: Any) -> Credential: + data = patch.to_dict() if hasattr(patch, "to_dict") else patch + resp = self._client._request("PATCH", f"{self._base_path()}/{resource_id}", json=data) + return Credential.from_dict(resp) + + def delete(self, resource_id: str) -> None: + self._client._request("DELETE", f"{self._base_path()}/{resource_id}", expect_json=False) + + def list_all(self, size: int = 100, **kwargs: Any) -> Iterator[Credential]: + page = 1 + while True: + result = self.list(ListOptions().page(page).size(size)) + yield from result.items + if page * size >= result.total: + break + page += 1 diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_inbox_message_api.py b/components/ambient-sdk/python-sdk/ambient_platform/_inbox_message_api.py index 7fb6582f5..1048fe8a0 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/_inbox_message_api.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/_inbox_message_api.py @@ -1,11 +1,12 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -# Generated: 2026-03-21T21:30:53Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations from typing import Any, Iterator, Optional, TYPE_CHECKING +from urllib.parse import quote from ._base import ListOptions from .inbox_message import InboxMessage, InboxMessageList @@ -17,19 +18,30 @@ class InboxMessageAPI: def __init__(self, client: AmbientClient) -> None: self._client = client + def _base_path(self) -> str: + return "/projects/{id}/agents/{agent_id}/inbox".replace("{id}", quote(self._client._project, safe="")) + def create(self, data: dict) -> InboxMessage: - resp = self._client._request("POST", "/projects", json=data) + resp = self._client._request("POST", self._base_path(), json=data) return InboxMessage.from_dict(resp) def get(self, resource_id: str) -> InboxMessage: - resp = self._client._request("GET", f"/projects/{resource_id}") + resp = self._client._request("GET", f"{self._base_path()}/{resource_id}") return InboxMessage.from_dict(resp) def list(self, opts: Optional[ListOptions] = None) -> InboxMessageList: params = opts.to_params() if opts else None - resp = self._client._request("GET", "/projects", params=params) + resp = self._client._request("GET", self._base_path(), params=params) return InboxMessageList.from_dict(resp) + def update(self, resource_id: str, patch: Any) -> InboxMessage: + data = patch.to_dict() if hasattr(patch, "to_dict") else patch + resp = self._client._request("PATCH", f"{self._base_path()}/{resource_id}", json=data) + return InboxMessage.from_dict(resp) + + def delete(self, resource_id: str) -> None: + self._client._request("DELETE", f"{self._base_path()}/{resource_id}", expect_json=False) + def list_all(self, size: int = 100, **kwargs: Any) -> Iterator[InboxMessage]: page = 1 while True: diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_iterator.py b/components/ambient-sdk/python-sdk/ambient_platform/_iterator.py index 920933d38..1353bfc0d 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/_iterator.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/_iterator.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_project_api.py b/components/ambient-sdk/python-sdk/ambient_platform/_project_api.py index 31054debe..15434448b 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/_project_api.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/_project_api.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_project_settings_api.py b/components/ambient-sdk/python-sdk/ambient_platform/_project_settings_api.py index fcb507970..f99a6abfd 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/_project_settings_api.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/_project_settings_api.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_role_api.py b/components/ambient-sdk/python-sdk/ambient_platform/_role_api.py index 611bcffc5..de253af9a 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/_role_api.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/_role_api.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -# Generated: 2026-03-21T21:30:53Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations @@ -35,6 +35,9 @@ def update(self, resource_id: str, patch: Any) -> Role: resp = self._client._request("PATCH", f"/roles/{resource_id}", json=data) return Role.from_dict(resp) + def delete(self, resource_id: str) -> None: + self._client._request("DELETE", f"/roles/{resource_id}", expect_json=False) + def list_all(self, size: int = 100, **kwargs: Any) -> Iterator[Role]: page = 1 while True: diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_role_binding_api.py b/components/ambient-sdk/python-sdk/ambient_platform/_role_binding_api.py index 391c6d536..ec4161dfb 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/_role_binding_api.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/_role_binding_api.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -# Generated: 2026-03-21T21:30:53Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations @@ -35,6 +35,9 @@ def update(self, resource_id: str, patch: Any) -> RoleBinding: resp = self._client._request("PATCH", f"/role_bindings/{resource_id}", json=data) return RoleBinding.from_dict(resp) + def delete(self, resource_id: str) -> None: + self._client._request("DELETE", f"/role_bindings/{resource_id}", expect_json=False) + def list_all(self, size: int = 100, **kwargs: Any) -> Iterator[RoleBinding]: page = 1 while True: diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_scheduled_session_api.py b/components/ambient-sdk/python-sdk/ambient_platform/_scheduled_session_api.py new file mode 100644 index 000000000..a9b6515a6 --- /dev/null +++ b/components/ambient-sdk/python-sdk/ambient_platform/_scheduled_session_api.py @@ -0,0 +1,52 @@ +# Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. +# Source: ../../ambient-api-server/openapi/openapi.yaml +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z + +from __future__ import annotations + +from typing import Any, Iterator, Optional, TYPE_CHECKING +from urllib.parse import quote + +from ._base import ListOptions +from .scheduled_session import ScheduledSession, ScheduledSessionList + +if TYPE_CHECKING: + from .client import AmbientClient + + +class ScheduledSessionAPI: + def __init__(self, client: AmbientClient) -> None: + self._client = client + def _base_path(self) -> str: + return "/projects/{id}/scheduled-sessions".replace("{id}", quote(self._client._project, safe="")) + + + def create(self, data: dict) -> ScheduledSession: + resp = self._client._request("POST", self._base_path(), json=data) + return ScheduledSession.from_dict(resp) + + def get(self, resource_id: str) -> ScheduledSession: + resp = self._client._request("GET", f"{self._base_path()}/{resource_id}") + return ScheduledSession.from_dict(resp) + + def list(self, opts: Optional[ListOptions] = None) -> ScheduledSessionList: + params = opts.to_params() if opts else None + resp = self._client._request("GET", self._base_path(), params=params) + return ScheduledSessionList.from_dict(resp) + def update(self, resource_id: str, patch: Any) -> ScheduledSession: + data = patch.to_dict() if hasattr(patch, "to_dict") else patch + resp = self._client._request("PATCH", f"{self._base_path()}/{resource_id}", json=data) + return ScheduledSession.from_dict(resp) + + def delete(self, resource_id: str) -> None: + self._client._request("DELETE", f"{self._base_path()}/{resource_id}", expect_json=False) + + def list_all(self, size: int = 100, **kwargs: Any) -> Iterator[ScheduledSession]: + page = 1 + while True: + result = self.list(ListOptions().page(page).size(size)) + yield from result.items + if page * size >= result.total: + break + page += 1 diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_session_api.py b/components/ambient-sdk/python-sdk/ambient_platform/_session_api.py index c006ab923..6d295de2a 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/_session_api.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/_session_api.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_session_message_api.py b/components/ambient-sdk/python-sdk/ambient_platform/_session_message_api.py index 0e1bd918f..c08812c0b 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/_session_message_api.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/_session_message_api.py @@ -1,11 +1,12 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -# Generated: 2026-03-21T21:30:53Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations from typing import Any, Iterator, Optional, TYPE_CHECKING +from urllib.parse import quote from ._base import ListOptions from .session_message import SessionMessage, SessionMessageList @@ -17,18 +18,21 @@ class SessionMessageAPI: def __init__(self, client: AmbientClient) -> None: self._client = client + def _base_path(self) -> str: + return "/sessions/{id}/messages".replace("{id}", quote(self._client._project, safe="")) + def create(self, data: dict) -> SessionMessage: - resp = self._client._request("POST", "/sessions", json=data) + resp = self._client._request("POST", self._base_path(), json=data) return SessionMessage.from_dict(resp) def get(self, resource_id: str) -> SessionMessage: - resp = self._client._request("GET", f"/sessions/{resource_id}") + resp = self._client._request("GET", f"{self._base_path()}/{resource_id}") return SessionMessage.from_dict(resp) def list(self, opts: Optional[ListOptions] = None) -> SessionMessageList: params = opts.to_params() if opts else None - resp = self._client._request("GET", "/sessions", params=params) + resp = self._client._request("GET", self._base_path(), params=params) return SessionMessageList.from_dict(resp) def list_all(self, size: int = 100, **kwargs: Any) -> Iterator[SessionMessage]: page = 1 diff --git a/components/ambient-sdk/python-sdk/ambient_platform/_user_api.py b/components/ambient-sdk/python-sdk/ambient_platform/_user_api.py index 9d00255e6..785ff338a 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/_user_api.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/_user_api.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/python-sdk/ambient_platform/agent.py b/components/ambient-sdk/python-sdk/ambient_platform/agent.py index 207c8669c..8bbf1515d 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/agent.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/agent.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 404b5671af96841f4a876b6192afc6358b4fb8e082ca2b6da499efcf3f72c781 -# Generated: 2026-03-20T16:48:23Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations @@ -19,10 +19,24 @@ class Agent: href: str = "" created_at: Optional[datetime] = None updated_at: Optional[datetime] = None + annotations: str = "" + bot_account_name: str = "" + current_session_id: str = "" + description: str = "" + display_name: str = "" + environment_variables: str = "" + labels: str = "" + llm_max_tokens: int = 0 + llm_model: str = "" + llm_temperature: float = 0.0 name: str = "" owner_user_id: str = "" + parent_agent_id: str = "" + project_id: str = "" prompt: str = "" - version: int = 0 + repo_url: str = "" + resource_overrides: str = "" + workflow_id: str = "" @classmethod def from_dict(cls, data: dict) -> Agent: @@ -32,10 +46,24 @@ def from_dict(cls, data: dict) -> Agent: href=data.get("href", ""), created_at=_parse_datetime(data.get("created_at")), updated_at=_parse_datetime(data.get("updated_at")), + annotations=data.get("annotations", ""), + bot_account_name=data.get("bot_account_name", ""), + current_session_id=data.get("current_session_id", ""), + description=data.get("description", ""), + display_name=data.get("display_name", ""), + environment_variables=data.get("environment_variables", ""), + labels=data.get("labels", ""), + llm_max_tokens=data.get("llm_max_tokens", 0), + llm_model=data.get("llm_model", ""), + llm_temperature=data.get("llm_temperature", 0.0), name=data.get("name", ""), owner_user_id=data.get("owner_user_id", ""), + parent_agent_id=data.get("parent_agent_id", ""), + project_id=data.get("project_id", ""), prompt=data.get("prompt", ""), - version=data.get("version", 0), + repo_url=data.get("repo_url", ""), + resource_overrides=data.get("resource_overrides", ""), + workflow_id=data.get("workflow_id", ""), ) @classmethod @@ -67,6 +95,42 @@ def __init__(self) -> None: self._data: dict[str, Any] = {} + def annotations(self, value: str) -> AgentBuilder: + self._data["annotations"] = value + return self + + def bot_account_name(self, value: str) -> AgentBuilder: + self._data["bot_account_name"] = value + return self + + def description(self, value: str) -> AgentBuilder: + self._data["description"] = value + return self + + def display_name(self, value: str) -> AgentBuilder: + self._data["display_name"] = value + return self + + def environment_variables(self, value: str) -> AgentBuilder: + self._data["environment_variables"] = value + return self + + def labels(self, value: str) -> AgentBuilder: + self._data["labels"] = value + return self + + def llm_max_tokens(self, value: int) -> AgentBuilder: + self._data["llm_max_tokens"] = value + return self + + def llm_model(self, value: str) -> AgentBuilder: + self._data["llm_model"] = value + return self + + def llm_temperature(self, value: float) -> AgentBuilder: + self._data["llm_temperature"] = value + return self + def name(self, value: str) -> AgentBuilder: self._data["name"] = value return self @@ -75,15 +139,35 @@ def owner_user_id(self, value: str) -> AgentBuilder: self._data["owner_user_id"] = value return self + def parent_agent_id(self, value: str) -> AgentBuilder: + self._data["parent_agent_id"] = value + return self + + def project_id(self, value: str) -> AgentBuilder: + self._data["project_id"] = value + return self + def prompt(self, value: str) -> AgentBuilder: self._data["prompt"] = value return self + def repo_url(self, value: str) -> AgentBuilder: + self._data["repo_url"] = value + return self + + def resource_overrides(self, value: str) -> AgentBuilder: + self._data["resource_overrides"] = value + return self + + def workflow_id(self, value: str) -> AgentBuilder: + self._data["workflow_id"] = value + return self + def build(self) -> dict: if "name" not in self._data: raise ValueError("name is required") - if "owner_user_id" not in self._data: - raise ValueError("owner_user_id is required") + if "project_id" not in self._data: + raise ValueError("project_id is required") return dict(self._data) @@ -92,9 +176,45 @@ def __init__(self) -> None: self._data: dict[str, Any] = {} + def annotations(self, value: str) -> AgentPatch: + self._data["annotations"] = value + return self + + def description(self, value: str) -> AgentPatch: + self._data["description"] = value + return self + + def display_name(self, value: str) -> AgentPatch: + self._data["display_name"] = value + return self + + def labels(self, value: str) -> AgentPatch: + self._data["labels"] = value + return self + + def llm_max_tokens(self, value: int) -> AgentPatch: + self._data["llm_max_tokens"] = value + return self + + def llm_model(self, value: str) -> AgentPatch: + self._data["llm_model"] = value + return self + + def llm_temperature(self, value: float) -> AgentPatch: + self._data["llm_temperature"] = value + return self + + def name(self, value: str) -> AgentPatch: + self._data["name"] = value + return self + def prompt(self, value: str) -> AgentPatch: self._data["prompt"] = value return self + def repo_url(self, value: str) -> AgentPatch: + self._data["repo_url"] = value + return self + def to_dict(self) -> dict: return dict(self._data) diff --git a/components/ambient-sdk/python-sdk/ambient_platform/client.py b/components/ambient-sdk/python-sdk/ambient_platform/client.py index 39dd3f037..16ca6968e 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/client.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/client.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -# Generated: 2026-03-21T21:30:53Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations @@ -16,12 +16,14 @@ from ._base import APIError, ListOptions if TYPE_CHECKING: + from ._agent_api import AgentAPI + from ._credential_api import CredentialAPI from ._inbox_message_api import InboxMessageAPI from ._project_api import ProjectAPI - from ._agent_api import AgentAPI from ._project_settings_api import ProjectSettingsAPI from ._role_api import RoleAPI from ._role_binding_api import RoleBindingAPI + from ._scheduled_session_api import ScheduledSessionAPI from ._session_api import SessionAPI from ._session_message_api import SessionMessageAPI from ._user_api import UserAPI @@ -58,12 +60,14 @@ def __init__( ) # Initialize API interfaces + self._agent_api: Optional[AgentAPI] = None + self._credential_api: Optional[CredentialAPI] = None self._inbox_message_api: Optional[InboxMessageAPI] = None self._project_api: Optional[ProjectAPI] = None - self._agent_api: Optional[AgentAPI] = None self._project_settings_api: Optional[ProjectSettingsAPI] = None self._role_api: Optional[RoleAPI] = None self._role_binding_api: Optional[RoleBindingAPI] = None + self._scheduled_session_api: Optional[ScheduledSessionAPI] = None self._session_api: Optional[SessionAPI] = None self._session_message_api: Optional[SessionMessageAPI] = None self._user_api: Optional[UserAPI] = None @@ -180,6 +184,20 @@ def __enter__(self) -> AmbientClient: def __exit__(self, *args: Any) -> None: self.close() @property + def agents(self) -> AgentAPI: + """Get the Agent API interface.""" + if self._agent_api is None: + from ._agent_api import AgentAPI + self._agent_api = AgentAPI(self) + return self._agent_api + @property + def credentials(self) -> CredentialAPI: + """Get the Credential API interface.""" + if self._credential_api is None: + from ._credential_api import CredentialAPI + self._credential_api = CredentialAPI(self) + return self._credential_api + @property def inbox_messages(self) -> InboxMessageAPI: """Get the InboxMessage API interface.""" if self._inbox_message_api is None: @@ -194,13 +212,6 @@ def projects(self) -> ProjectAPI: self._project_api = ProjectAPI(self) return self._project_api @property - def agents(self) -> AgentAPI: - """Get the Agent API interface.""" - if self._agent_api is None: - from ._agent_api import AgentAPI - self._agent_api = AgentAPI(self) - return self._agent_api - @property def project_settings(self) -> ProjectSettingsAPI: """Get the ProjectSettings API interface.""" if self._project_settings_api is None: @@ -222,6 +233,13 @@ def role_bindings(self) -> RoleBindingAPI: self._role_binding_api = RoleBindingAPI(self) return self._role_binding_api @property + def scheduled_sessions(self) -> ScheduledSessionAPI: + """Get the ScheduledSession API interface.""" + if self._scheduled_session_api is None: + from ._scheduled_session_api import ScheduledSessionAPI + self._scheduled_session_api = ScheduledSessionAPI(self) + return self._scheduled_session_api + @property def sessions(self) -> SessionAPI: """Get the Session API interface.""" if self._session_api is None: diff --git a/components/ambient-sdk/python-sdk/ambient_platform/credential.py b/components/ambient-sdk/python-sdk/ambient_platform/credential.py new file mode 100644 index 000000000..94db48d00 --- /dev/null +++ b/components/ambient-sdk/python-sdk/ambient_platform/credential.py @@ -0,0 +1,164 @@ +# Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. +# Source: ../../ambient-api-server/openapi/openapi.yaml +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import Any, Optional + +from ._base import ListMeta, _parse_datetime + + +@dataclass(frozen=True) +class Credential: + id: str = "" + kind: str = "" + href: str = "" + created_at: Optional[datetime] = None + updated_at: Optional[datetime] = None + annotations: str = "" + description: str = "" + email: str = "" + labels: str = "" + name: str = "" + project_id: str = "" + provider: str = "" + token: str = "" + url: str = "" + + @classmethod + def from_dict(cls, data: dict) -> Credential: + return cls( + id=data.get("id", ""), + kind=data.get("kind", ""), + href=data.get("href", ""), + created_at=_parse_datetime(data.get("created_at")), + updated_at=_parse_datetime(data.get("updated_at")), + annotations=data.get("annotations", ""), + description=data.get("description", ""), + email=data.get("email", ""), + labels=data.get("labels", ""), + name=data.get("name", ""), + project_id=data.get("project_id", ""), + provider=data.get("provider", ""), + token=data.get("token", ""), + url=data.get("url", ""), + ) + + @classmethod + def builder(cls) -> CredentialBuilder: + return CredentialBuilder() + + +@dataclass(frozen=True) +class CredentialList: + kind: str = "" + page: int = 0 + size: int = 0 + total: int = 0 + items: list[Credential] = () + + @classmethod + def from_dict(cls, data: dict) -> CredentialList: + return cls( + kind=data.get("kind", ""), + page=data.get("page", 0), + size=data.get("size", 0), + total=data.get("total", 0), + items=[Credential.from_dict(item) for item in data.get("items", [])], + ) + + +class CredentialBuilder: + def __init__(self) -> None: + self._data: dict[str, Any] = {} + + + def annotations(self, value: str) -> CredentialBuilder: + self._data["annotations"] = value + return self + + def description(self, value: str) -> CredentialBuilder: + self._data["description"] = value + return self + + def email(self, value: str) -> CredentialBuilder: + self._data["email"] = value + return self + + def labels(self, value: str) -> CredentialBuilder: + self._data["labels"] = value + return self + + def name(self, value: str) -> CredentialBuilder: + self._data["name"] = value + return self + + def project_id(self, value: str) -> CredentialBuilder: + self._data["project_id"] = value + return self + + def provider(self, value: str) -> CredentialBuilder: + self._data["provider"] = value + return self + + def token(self, value: str) -> CredentialBuilder: + self._data["token"] = value + return self + + def url(self, value: str) -> CredentialBuilder: + self._data["url"] = value + return self + + def build(self) -> dict: + if "name" not in self._data: + raise ValueError("name is required") + if "project_id" not in self._data: + raise ValueError("project_id is required") + if "provider" not in self._data: + raise ValueError("provider is required") + return dict(self._data) + + +class CredentialPatch: + def __init__(self) -> None: + self._data: dict[str, Any] = {} + + + def annotations(self, value: str) -> CredentialPatch: + self._data["annotations"] = value + return self + + def description(self, value: str) -> CredentialPatch: + self._data["description"] = value + return self + + def email(self, value: str) -> CredentialPatch: + self._data["email"] = value + return self + + def labels(self, value: str) -> CredentialPatch: + self._data["labels"] = value + return self + + def name(self, value: str) -> CredentialPatch: + self._data["name"] = value + return self + + def provider(self, value: str) -> CredentialPatch: + self._data["provider"] = value + return self + + def token(self, value: str) -> CredentialPatch: + self._data["token"] = value + return self + + def url(self, value: str) -> CredentialPatch: + self._data["url"] = value + return self + + def to_dict(self) -> dict: + return dict(self._data) diff --git a/components/ambient-sdk/python-sdk/ambient_platform/inbox_message.py b/components/ambient-sdk/python-sdk/ambient_platform/inbox_message.py index a6bdf6cce..26ebe9315 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/inbox_message.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/inbox_message.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/python-sdk/ambient_platform/project.py b/components/ambient-sdk/python-sdk/ambient_platform/project.py index b8b6a3053..30950ea2a 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/project.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/project.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -# Generated: 2026-03-21T21:30:53Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations @@ -21,6 +21,7 @@ class Project: updated_at: Optional[datetime] = None annotations: str = "" description: str = "" + display_name: str = "" labels: str = "" name: str = "" prompt: str = "" @@ -36,6 +37,7 @@ def from_dict(cls, data: dict) -> Project: updated_at=_parse_datetime(data.get("updated_at")), annotations=data.get("annotations", ""), description=data.get("description", ""), + display_name=data.get("display_name", ""), labels=data.get("labels", ""), name=data.get("name", ""), prompt=data.get("prompt", ""), @@ -79,6 +81,10 @@ def description(self, value: str) -> ProjectBuilder: self._data["description"] = value return self + def display_name(self, value: str) -> ProjectBuilder: + self._data["display_name"] = value + return self + def labels(self, value: str) -> ProjectBuilder: self._data["labels"] = value return self @@ -114,6 +120,10 @@ def description(self, value: str) -> ProjectPatch: self._data["description"] = value return self + def display_name(self, value: str) -> ProjectPatch: + self._data["display_name"] = value + return self + def labels(self, value: str) -> ProjectPatch: self._data["labels"] = value return self diff --git a/components/ambient-sdk/python-sdk/ambient_platform/project_settings.py b/components/ambient-sdk/python-sdk/ambient_platform/project_settings.py index 2e405b190..3eb1d133e 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/project_settings.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/project_settings.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/python-sdk/ambient_platform/role.py b/components/ambient-sdk/python-sdk/ambient_platform/role.py index f258bd4ab..a89be540d 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/role.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/role.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/python-sdk/ambient_platform/role_binding.py b/components/ambient-sdk/python-sdk/ambient_platform/role_binding.py index 23b5fdc8b..5edc7f4c9 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/role_binding.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/role_binding.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/python-sdk/ambient_platform/scheduled_session.py b/components/ambient-sdk/python-sdk/ambient_platform/scheduled_session.py new file mode 100644 index 000000000..54953fafd --- /dev/null +++ b/components/ambient-sdk/python-sdk/ambient_platform/scheduled_session.py @@ -0,0 +1,206 @@ +# Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. +# Source: ../../ambient-api-server/openapi/openapi.yaml +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z + +from __future__ import annotations + +from dataclasses import dataclass +from datetime import datetime +from typing import Any, Optional + +from ._base import ListMeta, _parse_datetime + + +@dataclass(frozen=True) +class ScheduledSession: + id: str = "" + kind: str = "" + href: str = "" + created_at: Optional[datetime] = None + updated_at: Optional[datetime] = None + agent_id: str = "" + description: str = "" + enabled: bool = False + inactivity_timeout: int = 0 + last_run_at: Optional[datetime] = None + name: str = "" + next_run_at: Optional[datetime] = None + project_id: str = "" + runner_type: str = "" + schedule: str = "" + session_prompt: str = "" + stop_on_run_finished: bool = False + timeout: int = 0 + timezone: str = "" + + @classmethod + def from_dict(cls, data: dict) -> ScheduledSession: + return cls( + id=data.get("id", ""), + kind=data.get("kind", ""), + href=data.get("href", ""), + created_at=_parse_datetime(data.get("created_at")), + updated_at=_parse_datetime(data.get("updated_at")), + agent_id=data.get("agent_id", ""), + description=data.get("description", ""), + enabled=data.get("enabled", False), + inactivity_timeout=data.get("inactivity_timeout", 0), + last_run_at=_parse_datetime(data.get("last_run_at")), + name=data.get("name", ""), + next_run_at=_parse_datetime(data.get("next_run_at")), + project_id=data.get("project_id", ""), + runner_type=data.get("runner_type", ""), + schedule=data.get("schedule", ""), + session_prompt=data.get("session_prompt", ""), + stop_on_run_finished=data.get("stop_on_run_finished", False), + timeout=data.get("timeout", 0), + timezone=data.get("timezone", ""), + ) + + @classmethod + def builder(cls) -> ScheduledSessionBuilder: + return ScheduledSessionBuilder() + + +@dataclass(frozen=True) +class ScheduledSessionList: + kind: str = "" + page: int = 0 + size: int = 0 + total: int = 0 + items: list[ScheduledSession] = () + + @classmethod + def from_dict(cls, data: dict) -> ScheduledSessionList: + return cls( + kind=data.get("kind", ""), + page=data.get("page", 0), + size=data.get("size", 0), + total=data.get("total", 0), + items=[ScheduledSession.from_dict(item) for item in data.get("items", [])], + ) + + +class ScheduledSessionBuilder: + def __init__(self) -> None: + self._data: dict[str, Any] = {} + + + def agent_id(self, value: str) -> ScheduledSessionBuilder: + self._data["agent_id"] = value + return self + + def description(self, value: str) -> ScheduledSessionBuilder: + self._data["description"] = value + return self + + def enabled(self, value: bool) -> ScheduledSessionBuilder: + self._data["enabled"] = value + return self + + def inactivity_timeout(self, value: int) -> ScheduledSessionBuilder: + self._data["inactivity_timeout"] = value + return self + + def last_run_at(self, value: Optional[datetime]) -> ScheduledSessionBuilder: + self._data["last_run_at"] = value + return self + + def name(self, value: str) -> ScheduledSessionBuilder: + self._data["name"] = value + return self + + def next_run_at(self, value: Optional[datetime]) -> ScheduledSessionBuilder: + self._data["next_run_at"] = value + return self + + def project_id(self, value: str) -> ScheduledSessionBuilder: + self._data["project_id"] = value + return self + + def runner_type(self, value: str) -> ScheduledSessionBuilder: + self._data["runner_type"] = value + return self + + def schedule(self, value: str) -> ScheduledSessionBuilder: + self._data["schedule"] = value + return self + + def session_prompt(self, value: str) -> ScheduledSessionBuilder: + self._data["session_prompt"] = value + return self + + def stop_on_run_finished(self, value: bool) -> ScheduledSessionBuilder: + self._data["stop_on_run_finished"] = value + return self + + def timeout(self, value: int) -> ScheduledSessionBuilder: + self._data["timeout"] = value + return self + + def timezone(self, value: str) -> ScheduledSessionBuilder: + self._data["timezone"] = value + return self + + def build(self) -> dict: + if "name" not in self._data: + raise ValueError("name is required") + if "project_id" not in self._data: + raise ValueError("project_id is required") + if "schedule" not in self._data: + raise ValueError("schedule is required") + return dict(self._data) + + +class ScheduledSessionPatch: + def __init__(self) -> None: + self._data: dict[str, Any] = {} + + + def agent_id(self, value: str) -> ScheduledSessionPatch: + self._data["agent_id"] = value + return self + + def description(self, value: str) -> ScheduledSessionPatch: + self._data["description"] = value + return self + + def enabled(self, value: bool) -> ScheduledSessionPatch: + self._data["enabled"] = value + return self + + def inactivity_timeout(self, value: int) -> ScheduledSessionPatch: + self._data["inactivity_timeout"] = value + return self + + def name(self, value: str) -> ScheduledSessionPatch: + self._data["name"] = value + return self + + def runner_type(self, value: str) -> ScheduledSessionPatch: + self._data["runner_type"] = value + return self + + def schedule(self, value: str) -> ScheduledSessionPatch: + self._data["schedule"] = value + return self + + def session_prompt(self, value: str) -> ScheduledSessionPatch: + self._data["session_prompt"] = value + return self + + def stop_on_run_finished(self, value: bool) -> ScheduledSessionPatch: + self._data["stop_on_run_finished"] = value + return self + + def timeout(self, value: int) -> ScheduledSessionPatch: + self._data["timeout"] = value + return self + + def timezone(self, value: str) -> ScheduledSessionPatch: + self._data["timezone"] = value + return self + + def to_dict(self) -> dict: + return dict(self._data) diff --git a/components/ambient-sdk/python-sdk/ambient_platform/session.py b/components/ambient-sdk/python-sdk/ambient_platform/session.py index ef7b62db5..a2b614553 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/session.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/session.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/python-sdk/ambient_platform/session_message.py b/components/ambient-sdk/python-sdk/ambient_platform/session_message.py index 383cbd634..a34f79e8e 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/session_message.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/session_message.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/python-sdk/ambient_platform/user.py b/components/ambient-sdk/python-sdk/ambient_platform/user.py index da72aaecc..fc435e956 100644 --- a/components/ambient-sdk/python-sdk/ambient_platform/user.py +++ b/components/ambient-sdk/python-sdk/ambient_platform/user.py @@ -1,7 +1,7 @@ # Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. # Source: ../../ambient-api-server/openapi/openapi.yaml -# Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -# Generated: 2026-04-18T21:11:11Z +# Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +# Generated: 2026-05-05T18:24:54Z from __future__ import annotations diff --git a/components/ambient-sdk/ts-sdk/src/agent.ts b/components/ambient-sdk/ts-sdk/src/agent.ts index a4788819d..8b995edde 100644 --- a/components/ambient-sdk/ts-sdk/src/agent.ts +++ b/components/ambient-sdk/ts-sdk/src/agent.ts @@ -1,19 +1,29 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 404b5671af96841f4a876b6192afc6358b4fb8e082ca2b6da499efcf3f72c781 -// Generated: 2026-03-20T16:48:23Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { ObjectReference, ListMeta } from './base'; export type Agent = ObjectReference & { - annotations?: string; - current_session_id?: string; - labels?: string; + annotations: string; + bot_account_name: string; + current_session_id: string; + description: string; + display_name: string; + environment_variables: string; + labels: string; + llm_max_tokens: number; + llm_model: string; + llm_temperature: number; name: string; - owner_user_id?: string; - project_id?: string; - prompt?: string; - version?: number; + owner_user_id: string; + parent_agent_id: string; + project_id: string; + prompt: string; + repo_url: string; + resource_overrides: string; + workflow_id: string; }; export type AgentList = ListMeta & { @@ -22,33 +32,86 @@ export type AgentList = ListMeta & { export type AgentCreateRequest = { annotations?: string; + bot_account_name?: string; + description?: string; + display_name?: string; + environment_variables?: string; labels?: string; + llm_max_tokens?: number; + llm_model?: string; + llm_temperature?: number; name: string; owner_user_id?: string; - project_id?: string; + parent_agent_id?: string; + project_id: string; prompt?: string; + repo_url?: string; + resource_overrides?: string; + workflow_id?: string; }; export type AgentPatchRequest = { annotations?: string; + description?: string; + display_name?: string; labels?: string; + llm_max_tokens?: number; + llm_model?: string; + llm_temperature?: number; name?: string; prompt?: string; + repo_url?: string; }; export class AgentBuilder { private data: Record = {}; + annotations(value: string): this { this.data['annotations'] = value; return this; } + botAccountName(value: string): this { + this.data['bot_account_name'] = value; + return this; + } + + description(value: string): this { + this.data['description'] = value; + return this; + } + + displayName(value: string): this { + this.data['display_name'] = value; + return this; + } + + environmentVariables(value: string): this { + this.data['environment_variables'] = value; + return this; + } + labels(value: string): this { this.data['labels'] = value; return this; } + llmMaxTokens(value: number): this { + this.data['llm_max_tokens'] = value; + return this; + } + + llmModel(value: string): this { + this.data['llm_model'] = value; + return this; + } + + llmTemperature(value: number): this { + this.data['llm_temperature'] = value; + return this; + } + name(value: string): this { this.data['name'] = value; return this; @@ -59,6 +122,11 @@ export class AgentBuilder { return this; } + parentAgentId(value: string): this { + this.data['parent_agent_id'] = value; + return this; + } + projectId(value: string): this { this.data['project_id'] = value; return this; @@ -69,10 +137,28 @@ export class AgentBuilder { return this; } + repoUrl(value: string): this { + this.data['repo_url'] = value; + return this; + } + + resourceOverrides(value: string): this { + this.data['resource_overrides'] = value; + return this; + } + + workflowId(value: string): this { + this.data['workflow_id'] = value; + return this; + } + build(): AgentCreateRequest { if (!this.data['name']) { throw new Error('name is required'); } + if (!this.data['project_id']) { + throw new Error('project_id is required'); + } return this.data as AgentCreateRequest; } } @@ -80,16 +166,42 @@ export class AgentBuilder { export class AgentPatchBuilder { private data: Record = {}; + annotations(value: string): this { this.data['annotations'] = value; return this; } + description(value: string): this { + this.data['description'] = value; + return this; + } + + displayName(value: string): this { + this.data['display_name'] = value; + return this; + } + labels(value: string): this { this.data['labels'] = value; return this; } + llmMaxTokens(value: number): this { + this.data['llm_max_tokens'] = value; + return this; + } + + llmModel(value: string): this { + this.data['llm_model'] = value; + return this; + } + + llmTemperature(value: number): this { + this.data['llm_temperature'] = value; + return this; + } + name(value: string): this { this.data['name'] = value; return this; @@ -100,6 +212,11 @@ export class AgentPatchBuilder { return this; } + repoUrl(value: string): this { + this.data['repo_url'] = value; + return this; + } + build(): AgentPatchRequest { return this.data as AgentPatchRequest; } diff --git a/components/ambient-sdk/ts-sdk/src/agent_api.ts b/components/ambient-sdk/ts-sdk/src/agent_api.ts index e90a05cec..17d358c93 100644 --- a/components/ambient-sdk/ts-sdk/src/agent_api.ts +++ b/components/ambient-sdk/ts-sdk/src/agent_api.ts @@ -1,42 +1,44 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 404b5671af96841f4a876b6192afc6358b4fb8e082ca2b6da499efcf3f72c781 -// Generated: 2026-03-20T16:48:23Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z -import type { AmbientClientConfig, ListOptions, RequestOptions, ListMeta } from './base'; +import type { AmbientClientConfig, ListOptions, RequestOptions } from './base'; import { ambientFetch, buildQueryString } from './base'; import type { Agent, AgentList, AgentCreateRequest, AgentPatchRequest } from './agent'; -import type { Session } from './session'; - -export type AgentSessionList = ListMeta & { items: Session[] }; - -export type StartRequest = { - prompt?: string; -}; - -export type StartResponse = { - session?: Session; - starting_prompt?: string; -}; export class AgentAPI { constructor(private readonly config: AmbientClientConfig) {} + private basePath(): string { + if (!this.config.project) { + throw new Error('project is required for Agent operations'); + } + return '/projects/{id}/agents'.replace('{id}', encodeURIComponent(this.config.project)); + } + async create(data: AgentCreateRequest, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'POST', '/agents', data, opts); + return ambientFetch(this.config, 'POST', this.basePath(), data, opts); } async get(id: string, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'GET', `/agents/${id}`, undefined, opts); + return ambientFetch(this.config, 'GET', `${this.basePath()}/${id}`, undefined, opts); } async list(listOpts?: ListOptions, opts?: RequestOptions): Promise { const qs = buildQueryString(listOpts); - return ambientFetch(this.config, 'GET', `/agents${qs}`, undefined, opts); + return ambientFetch(this.config, 'GET', `${this.basePath()}${qs}`, undefined, opts); } - async update(id: string, patch: AgentPatchRequest, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'PATCH', `/agents/${id}`, patch, opts); + return ambientFetch(this.config, 'PATCH', `${this.basePath()}/${id}`, patch, opts); + } + + async delete(id: string, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'DELETE', `${this.basePath()}/${id}`, undefined, opts); + } + + async start(id: string, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'POST', `${this.basePath()}/${id}/start`, undefined, opts); } async *listAll(size: number = 100, opts?: RequestOptions): AsyncGenerator { @@ -52,38 +54,4 @@ export class AgentAPI { page++; } } - - async listByProject(projectId: string, listOpts?: ListOptions, opts?: RequestOptions): Promise { - const qs = buildQueryString(listOpts); - return ambientFetch(this.config, 'GET', `/projects/${encodeURIComponent(projectId)}/agents${qs}`, undefined, opts); - } - - async getByProject(projectId: string, agentId: string, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'GET', `/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentId)}`, undefined, opts); - } - - async createInProject(projectId: string, data: AgentCreateRequest, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'POST', `/projects/${encodeURIComponent(projectId)}/agents`, data, opts); - } - - async updateInProject(projectId: string, agentId: string, patch: AgentPatchRequest, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'PATCH', `/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentId)}`, patch, opts); - } - - async deleteInProject(projectId: string, agentId: string, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'DELETE', `/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentId)}`, undefined, opts); - } - - async start(projectId: string, agentId: string, prompt?: string, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'POST', `/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentId)}/start`, { prompt }, opts); - } - - async getStartPreview(projectId: string, agentId: string, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'GET', `/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentId)}/start`, undefined, opts); - } - - async sessions(projectId: string, agentId: string, listOpts?: ListOptions, opts?: RequestOptions): Promise { - const qs = buildQueryString(listOpts); - return ambientFetch(this.config, 'GET', `/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentId)}/sessions${qs}`, undefined, opts); - } } diff --git a/components/ambient-sdk/ts-sdk/src/base.ts b/components/ambient-sdk/ts-sdk/src/base.ts index 5994cb43b..8fb335a0c 100644 --- a/components/ambient-sdk/ts-sdk/src/base.ts +++ b/components/ambient-sdk/ts-sdk/src/base.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -// Generated: 2026-03-21T21:30:53Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z export type ObjectReference = { id: string; @@ -70,7 +70,7 @@ export type RequestOptions = { export type AmbientClientConfig = { baseUrl: string; - token: string; + token?: string; project?: string; }; @@ -83,7 +83,7 @@ export async function ambientFetch( ): Promise { const url = `${config.baseUrl}/api/ambient/v1${path}`; const headers: Record = { - 'Authorization': `Bearer ${config.token}`, + ...(config.token ? { 'Authorization': `Bearer ${config.token}` } : {}), ...(config.project ? { 'X-Ambient-Project': config.project } : {}), }; if (body !== undefined) { diff --git a/components/ambient-sdk/ts-sdk/src/client.ts b/components/ambient-sdk/ts-sdk/src/client.ts index 941a077ea..e9c590d59 100644 --- a/components/ambient-sdk/ts-sdk/src/client.ts +++ b/components/ambient-sdk/ts-sdk/src/client.ts @@ -1,15 +1,17 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -// Generated: 2026-03-21T21:30:53Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { AmbientClientConfig } from './base'; +import { AgentAPI } from './agent_api'; +import { CredentialAPI } from './credential_api'; import { InboxMessageAPI } from './inbox_message_api'; import { ProjectAPI } from './project_api'; -import { AgentAPI } from './agent_api'; import { ProjectSettingsAPI } from './project_settings_api'; import { RoleAPI } from './role_api'; import { RoleBindingAPI } from './role_binding_api'; +import { ScheduledSessionAPI } from './scheduled_session_api'; import { SessionAPI } from './session_api'; import { SessionMessageAPI } from './session_message_api'; import { UserAPI } from './user_api'; @@ -18,12 +20,14 @@ import { UserAPI } from './user_api'; export class AmbientClient { private readonly config: AmbientClientConfig; + readonly agents: AgentAPI; + readonly credentials: CredentialAPI; readonly inboxMessages: InboxMessageAPI; readonly projects: ProjectAPI; - readonly agents: AgentAPI; readonly projectSettings: ProjectSettingsAPI; readonly roles: RoleAPI; readonly roleBindings: RoleBindingAPI; + readonly scheduledSessions: ScheduledSessionAPI; readonly sessions: SessionAPI; readonly sessionMessages: SessionMessageAPI; readonly users: UserAPI; @@ -32,22 +36,29 @@ export class AmbientClient { if (!config.baseUrl) { throw new Error('baseUrl is required'); } - if (!config.token) { - throw new Error('token is required'); - } - if (config.token.length < 20) { - throw new Error('token is too short (minimum 20 characters)'); - } - if (config.token === 'YOUR_TOKEN_HERE' || config.token === 'PLACEHOLDER_TOKEN') { - throw new Error('placeholder token is not allowed'); + if (config.token) { + if (config.token.length < 20) { + throw new Error('token is too short (minimum 20 characters)'); + } + if (config.token === 'YOUR_TOKEN_HERE' || config.token === 'PLACEHOLDER_TOKEN') { + throw new Error('placeholder token is not allowed'); + } } if (config.project && config.project.length > 63) { throw new Error('project name cannot exceed 63 characters'); } - const url = new URL(config.baseUrl); - if (url.protocol !== 'http:' && url.protocol !== 'https:') { - throw new Error('only HTTP and HTTPS schemes are supported'); + // Reject protocol-relative URLs (e.g. "//evil.com/path") + if (config.baseUrl.startsWith('//')) { + throw new Error('Protocol-relative URLs are not allowed for baseUrl'); + } + + // Skip URL parsing for relative paths (e.g. "/api/proxy") + if (!config.baseUrl.startsWith('/')) { + const url = new URL(config.baseUrl); + if (url.protocol !== 'http:' && url.protocol !== 'https:') { + throw new Error('only HTTP and HTTPS schemes are supported'); + } } this.config = { @@ -55,12 +66,14 @@ export class AmbientClient { baseUrl: config.baseUrl.replace(/\/+$/, ''), }; + this.agents = new AgentAPI(this.config); + this.credentials = new CredentialAPI(this.config); this.inboxMessages = new InboxMessageAPI(this.config); this.projects = new ProjectAPI(this.config); - this.agents = new AgentAPI(this.config); this.projectSettings = new ProjectSettingsAPI(this.config); this.roles = new RoleAPI(this.config); this.roleBindings = new RoleBindingAPI(this.config); + this.scheduledSessions = new ScheduledSessionAPI(this.config); this.sessions = new SessionAPI(this.config); this.sessionMessages = new SessionMessageAPI(this.config); this.users = new UserAPI(this.config); @@ -74,6 +87,7 @@ export class AmbientClient { if (!token) { throw new Error('AMBIENT_TOKEN environment variable is required'); } + return new AmbientClient({ baseUrl, token, ...(project ? { project } : {}) }); } } diff --git a/components/ambient-sdk/ts-sdk/src/credential.ts b/components/ambient-sdk/ts-sdk/src/credential.ts new file mode 100644 index 000000000..44f41d284 --- /dev/null +++ b/components/ambient-sdk/ts-sdk/src/credential.ts @@ -0,0 +1,157 @@ +// Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. +// Source: ../../ambient-api-server/openapi/openapi.yaml +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z + +import type { ObjectReference, ListMeta } from './base'; + +export type Credential = ObjectReference & { + annotations: string; + description: string; + email: string; + labels: string; + name: string; + project_id: string; + provider: string; + token: string; + url: string; +}; + +export type CredentialList = ListMeta & { + items: Credential[]; +}; + +export type CredentialCreateRequest = { + annotations?: string; + description?: string; + email?: string; + labels?: string; + name: string; + project_id: string; + provider: string; + token?: string; + url?: string; +}; + +export type CredentialPatchRequest = { + annotations?: string; + description?: string; + email?: string; + labels?: string; + name?: string; + provider?: string; + token?: string; + url?: string; +}; + +export class CredentialBuilder { + private data: Record = {}; + + + annotations(value: string): this { + this.data['annotations'] = value; + return this; + } + + description(value: string): this { + this.data['description'] = value; + return this; + } + + email(value: string): this { + this.data['email'] = value; + return this; + } + + labels(value: string): this { + this.data['labels'] = value; + return this; + } + + name(value: string): this { + this.data['name'] = value; + return this; + } + + projectId(value: string): this { + this.data['project_id'] = value; + return this; + } + + provider(value: string): this { + this.data['provider'] = value; + return this; + } + + token(value: string): this { + this.data['token'] = value; + return this; + } + + url(value: string): this { + this.data['url'] = value; + return this; + } + + build(): CredentialCreateRequest { + if (!this.data['name']) { + throw new Error('name is required'); + } + if (!this.data['project_id']) { + throw new Error('project_id is required'); + } + if (!this.data['provider']) { + throw new Error('provider is required'); + } + return this.data as CredentialCreateRequest; + } +} + +export class CredentialPatchBuilder { + private data: Record = {}; + + + annotations(value: string): this { + this.data['annotations'] = value; + return this; + } + + description(value: string): this { + this.data['description'] = value; + return this; + } + + email(value: string): this { + this.data['email'] = value; + return this; + } + + labels(value: string): this { + this.data['labels'] = value; + return this; + } + + name(value: string): this { + this.data['name'] = value; + return this; + } + + provider(value: string): this { + this.data['provider'] = value; + return this; + } + + token(value: string): this { + this.data['token'] = value; + return this; + } + + url(value: string): this { + this.data['url'] = value; + return this; + } + + build(): CredentialPatchRequest { + return this.data as CredentialPatchRequest; + } +} diff --git a/components/ambient-sdk/ts-sdk/src/credential_api.ts b/components/ambient-sdk/ts-sdk/src/credential_api.ts new file mode 100644 index 000000000..f1adeb10f --- /dev/null +++ b/components/ambient-sdk/ts-sdk/src/credential_api.ts @@ -0,0 +1,53 @@ +// Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. +// Source: ../../ambient-api-server/openapi/openapi.yaml +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z + +import type { AmbientClientConfig, ListOptions, RequestOptions } from './base'; +import { ambientFetch, buildQueryString } from './base'; +import type { Credential, CredentialList, CredentialCreateRequest, CredentialPatchRequest } from './credential'; + +export class CredentialAPI { + constructor(private readonly config: AmbientClientConfig) {} + private basePath(): string { + if (!this.config.project) { + throw new Error('project is required for Credential operations'); + } + return '/projects/{id}/credentials'.replace('{id}', encodeURIComponent(this.config.project)); + } + + + async create(data: CredentialCreateRequest, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'POST', this.basePath(), data, opts); + } + + async get(id: string, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'GET', `${this.basePath()}/${id}`, undefined, opts); + } + + async list(listOpts?: ListOptions, opts?: RequestOptions): Promise { + const qs = buildQueryString(listOpts); + return ambientFetch(this.config, 'GET', `${this.basePath()}${qs}`, undefined, opts); + } + async update(id: string, patch: CredentialPatchRequest, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'PATCH', `${this.basePath()}/${id}`, patch, opts); + } + + async delete(id: string, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'DELETE', `${this.basePath()}/${id}`, undefined, opts); + } + + async *listAll(size: number = 100, opts?: RequestOptions): AsyncGenerator { + let page = 1; + while (true) { + const result = await this.list({ page, size }, opts); + for (const item of result.items) { + yield item; + } + if (page * size >= result.total) { + break; + } + page++; + } + } +} diff --git a/components/ambient-sdk/ts-sdk/src/inbox_message.ts b/components/ambient-sdk/ts-sdk/src/inbox_message.ts index 59a119948..01353cd25 100644 --- a/components/ambient-sdk/ts-sdk/src/inbox_message.ts +++ b/components/ambient-sdk/ts-sdk/src/inbox_message.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { ObjectReference, ListMeta } from './base'; diff --git a/components/ambient-sdk/ts-sdk/src/inbox_message_api.ts b/components/ambient-sdk/ts-sdk/src/inbox_message_api.ts index dce744c32..bf361a8d2 100644 --- a/components/ambient-sdk/ts-sdk/src/inbox_message_api.ts +++ b/components/ambient-sdk/ts-sdk/src/inbox_message_api.ts @@ -1,26 +1,53 @@ -import type { AmbientClientConfig, ListOptions, RequestOptions, ListMeta } from './base'; -import { ambientFetch, buildQueryString } from './base'; -import type { InboxMessage, InboxMessageCreateRequest } from './inbox_message'; +// Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. +// Source: ../../ambient-api-server/openapi/openapi.yaml +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z -export type InboxMessageList = ListMeta & { items: InboxMessage[] }; +import type { AmbientClientConfig, ListOptions, RequestOptions } from './base'; +import { ambientFetch, buildQueryString } from './base'; +import type { InboxMessage, InboxMessageList, InboxMessageCreateRequest, InboxMessagePatchRequest } from './inbox_message'; export class InboxMessageAPI { constructor(private readonly config: AmbientClientConfig) {} + private basePath(): string { + if (!this.config.project) { + throw new Error('project is required for InboxMessage operations'); + } + return '/projects/{id}/agents/{agent_id}/inbox'.replace('{id}', encodeURIComponent(this.config.project)); + } + - async send(projectId: string, agentId: string, data: InboxMessageCreateRequest, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'POST', `/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentId)}/inbox`, data, opts); + async create(data: InboxMessageCreateRequest, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'POST', this.basePath(), data, opts); } - async listByAgent(projectId: string, agentId: string, listOpts?: ListOptions, opts?: RequestOptions): Promise { + async get(id: string, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'GET', `${this.basePath()}/${id}`, undefined, opts); + } + + async list(listOpts?: ListOptions, opts?: RequestOptions): Promise { const qs = buildQueryString(listOpts); - return ambientFetch(this.config, 'GET', `/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentId)}/inbox${qs}`, undefined, opts); + return ambientFetch(this.config, 'GET', `${this.basePath()}${qs}`, undefined, opts); + } + async update(id: string, patch: InboxMessagePatchRequest, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'PATCH', `${this.basePath()}/${id}`, patch, opts); } - async markRead(projectId: string, agentId: string, msgId: string, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'PATCH', `/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentId)}/inbox/${encodeURIComponent(msgId)}`, { read: true }, opts); + async delete(id: string, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'DELETE', `${this.basePath()}/${id}`, undefined, opts); } - async deleteMessage(projectId: string, agentId: string, msgId: string, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'DELETE', `/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentId)}/inbox/${encodeURIComponent(msgId)}`, undefined, opts); + async *listAll(size: number = 100, opts?: RequestOptions): AsyncGenerator { + let page = 1; + while (true) { + const result = await this.list({ page, size }, opts); + for (const item of result.items) { + yield item; + } + if (page * size >= result.total) { + break; + } + page++; + } } } diff --git a/components/ambient-sdk/ts-sdk/src/index.ts b/components/ambient-sdk/ts-sdk/src/index.ts index 73f97681d..defb4c9a1 100644 --- a/components/ambient-sdk/ts-sdk/src/index.ts +++ b/components/ambient-sdk/ts-sdk/src/index.ts @@ -1,26 +1,28 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -// Generated: 2026-03-21T21:30:53Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z export { AmbientClient } from './client'; export type { AmbientClientConfig, ListOptions, RequestOptions, ObjectReference, ListMeta, APIError } from './base'; export { AmbientAPIError, buildQueryString } from './base'; -export type { InboxMessage, InboxMessageCreateRequest, InboxMessagePatchRequest } from './inbox_message'; +export type { Agent, AgentList, AgentCreateRequest, AgentPatchRequest } from './agent'; +export { AgentBuilder, AgentPatchBuilder } from './agent'; +export { AgentAPI } from './agent_api'; + +export type { Credential, CredentialList, CredentialCreateRequest, CredentialPatchRequest } from './credential'; +export { CredentialBuilder, CredentialPatchBuilder } from './credential'; +export { CredentialAPI } from './credential_api'; + +export type { InboxMessage, InboxMessageList, InboxMessageCreateRequest, InboxMessagePatchRequest } from './inbox_message'; export { InboxMessageBuilder, InboxMessagePatchBuilder } from './inbox_message'; export { InboxMessageAPI } from './inbox_message_api'; -export type { InboxMessageList } from './inbox_message_api'; export type { Project, ProjectList, ProjectCreateRequest, ProjectPatchRequest } from './project'; export { ProjectBuilder, ProjectPatchBuilder } from './project'; export { ProjectAPI } from './project_api'; -export type { Agent, AgentList, AgentCreateRequest, AgentPatchRequest } from './agent'; -export { AgentBuilder, AgentPatchBuilder } from './agent'; -export { AgentAPI } from './agent_api'; -export type { AgentSessionList, StartRequest, StartResponse } from './agent_api'; - export type { ProjectSettings, ProjectSettingsList, ProjectSettingsCreateRequest, ProjectSettingsPatchRequest } from './project_settings'; export { ProjectSettingsBuilder, ProjectSettingsPatchBuilder } from './project_settings'; export { ProjectSettingsAPI } from './project_settings_api'; @@ -33,6 +35,10 @@ export type { RoleBinding, RoleBindingList, RoleBindingCreateRequest, RoleBindin export { RoleBindingBuilder, RoleBindingPatchBuilder } from './role_binding'; export { RoleBindingAPI } from './role_binding_api'; +export type { ScheduledSession, ScheduledSessionList, ScheduledSessionCreateRequest, ScheduledSessionPatchRequest } from './scheduled_session'; +export { ScheduledSessionBuilder, ScheduledSessionPatchBuilder } from './scheduled_session'; +export { ScheduledSessionAPI } from './scheduled_session_api'; + export type { Session, SessionList, SessionCreateRequest, SessionPatchRequest, SessionStatusPatchRequest } from './session'; export { SessionBuilder, SessionPatchBuilder, SessionStatusPatchBuilder } from './session'; export { SessionAPI } from './session_api'; diff --git a/components/ambient-sdk/ts-sdk/src/project.ts b/components/ambient-sdk/ts-sdk/src/project.ts index 6a999a583..276616f46 100644 --- a/components/ambient-sdk/ts-sdk/src/project.ts +++ b/components/ambient-sdk/ts-sdk/src/project.ts @@ -1,13 +1,14 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -// Generated: 2026-03-21T21:30:53Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { ObjectReference, ListMeta } from './base'; export type Project = ObjectReference & { annotations: string; description: string; + display_name: string; labels: string; name: string; prompt: string; @@ -21,6 +22,7 @@ export type ProjectList = ListMeta & { export type ProjectCreateRequest = { annotations?: string; description?: string; + display_name?: string; labels?: string; name: string; prompt?: string; @@ -30,6 +32,7 @@ export type ProjectCreateRequest = { export type ProjectPatchRequest = { annotations?: string; description?: string; + display_name?: string; labels?: string; name?: string; prompt?: string; @@ -50,6 +53,11 @@ export class ProjectBuilder { return this; } + displayName(value: string): this { + this.data['display_name'] = value; + return this; + } + labels(value: string): this { this.data['labels'] = value; return this; @@ -92,6 +100,11 @@ export class ProjectPatchBuilder { return this; } + displayName(value: string): this { + this.data['display_name'] = value; + return this; + } + labels(value: string): this { this.data['labels'] = value; return this; diff --git a/components/ambient-sdk/ts-sdk/src/project_api.ts b/components/ambient-sdk/ts-sdk/src/project_api.ts index 2fc1dc0fc..b7565a863 100644 --- a/components/ambient-sdk/ts-sdk/src/project_api.ts +++ b/components/ambient-sdk/ts-sdk/src/project_api.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { AmbientClientConfig, ListOptions, RequestOptions } from './base'; import { ambientFetch, buildQueryString } from './base'; diff --git a/components/ambient-sdk/ts-sdk/src/project_settings.ts b/components/ambient-sdk/ts-sdk/src/project_settings.ts index d231fa40f..a53a7a4f6 100644 --- a/components/ambient-sdk/ts-sdk/src/project_settings.ts +++ b/components/ambient-sdk/ts-sdk/src/project_settings.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { ObjectReference, ListMeta } from './base'; diff --git a/components/ambient-sdk/ts-sdk/src/project_settings_api.ts b/components/ambient-sdk/ts-sdk/src/project_settings_api.ts index 11cae5345..b6d184d84 100644 --- a/components/ambient-sdk/ts-sdk/src/project_settings_api.ts +++ b/components/ambient-sdk/ts-sdk/src/project_settings_api.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { AmbientClientConfig, ListOptions, RequestOptions } from './base'; import { ambientFetch, buildQueryString } from './base'; diff --git a/components/ambient-sdk/ts-sdk/src/role.ts b/components/ambient-sdk/ts-sdk/src/role.ts index b6952464a..77845a082 100644 --- a/components/ambient-sdk/ts-sdk/src/role.ts +++ b/components/ambient-sdk/ts-sdk/src/role.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { ObjectReference, ListMeta } from './base'; diff --git a/components/ambient-sdk/ts-sdk/src/role_api.ts b/components/ambient-sdk/ts-sdk/src/role_api.ts index b5350904f..135fd29ad 100644 --- a/components/ambient-sdk/ts-sdk/src/role_api.ts +++ b/components/ambient-sdk/ts-sdk/src/role_api.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -// Generated: 2026-03-21T21:30:53Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { AmbientClientConfig, ListOptions, RequestOptions } from './base'; import { ambientFetch, buildQueryString } from './base'; @@ -26,6 +26,10 @@ export class RoleAPI { return ambientFetch(this.config, 'PATCH', `/roles/${id}`, patch, opts); } + async delete(id: string, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'DELETE', `/roles/${id}`, undefined, opts); + } + async *listAll(size: number = 100, opts?: RequestOptions): AsyncGenerator { let page = 1; while (true) { diff --git a/components/ambient-sdk/ts-sdk/src/role_binding.ts b/components/ambient-sdk/ts-sdk/src/role_binding.ts index 5dcc33816..ebccb185d 100644 --- a/components/ambient-sdk/ts-sdk/src/role_binding.ts +++ b/components/ambient-sdk/ts-sdk/src/role_binding.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { ObjectReference, ListMeta } from './base'; diff --git a/components/ambient-sdk/ts-sdk/src/role_binding_api.ts b/components/ambient-sdk/ts-sdk/src/role_binding_api.ts index 94261dcb8..80512362f 100644 --- a/components/ambient-sdk/ts-sdk/src/role_binding_api.ts +++ b/components/ambient-sdk/ts-sdk/src/role_binding_api.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -// Generated: 2026-03-21T21:30:53Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { AmbientClientConfig, ListOptions, RequestOptions } from './base'; import { ambientFetch, buildQueryString } from './base'; @@ -26,6 +26,10 @@ export class RoleBindingAPI { return ambientFetch(this.config, 'PATCH', `/role_bindings/${id}`, patch, opts); } + async delete(id: string, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'DELETE', `/role_bindings/${id}`, undefined, opts); + } + async *listAll(size: number = 100, opts?: RequestOptions): AsyncGenerator { let page = 1; while (true) { diff --git a/components/ambient-sdk/ts-sdk/src/scheduled_session.ts b/components/ambient-sdk/ts-sdk/src/scheduled_session.ts new file mode 100644 index 000000000..d82dcb82d --- /dev/null +++ b/components/ambient-sdk/ts-sdk/src/scheduled_session.ts @@ -0,0 +1,210 @@ +// Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. +// Source: ../../ambient-api-server/openapi/openapi.yaml +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z + +import type { ObjectReference, ListMeta } from './base'; + +export type ScheduledSession = ObjectReference & { + agent_id: string; + description: string; + enabled: boolean; + inactivity_timeout: number; + last_run_at: string; + name: string; + next_run_at: string; + project_id: string; + runner_type: string; + schedule: string; + session_prompt: string; + stop_on_run_finished: boolean; + timeout: number; + timezone: string; +}; + +export type ScheduledSessionList = ListMeta & { + items: ScheduledSession[]; +}; + +export type ScheduledSessionCreateRequest = { + agent_id?: string; + description?: string; + enabled?: boolean; + inactivity_timeout?: number; + last_run_at?: string; + name: string; + next_run_at?: string; + project_id: string; + runner_type?: string; + schedule: string; + session_prompt?: string; + stop_on_run_finished?: boolean; + timeout?: number; + timezone?: string; +}; + +export type ScheduledSessionPatchRequest = { + agent_id?: string; + description?: string; + enabled?: boolean; + inactivity_timeout?: number; + name?: string; + runner_type?: string; + schedule?: string; + session_prompt?: string; + stop_on_run_finished?: boolean; + timeout?: number; + timezone?: string; +}; + +export class ScheduledSessionBuilder { + private data: Record = {}; + + + agentId(value: string): this { + this.data['agent_id'] = value; + return this; + } + + description(value: string): this { + this.data['description'] = value; + return this; + } + + enabled(value: boolean): this { + this.data['enabled'] = value; + return this; + } + + inactivityTimeout(value: number): this { + this.data['inactivity_timeout'] = value; + return this; + } + + lastRunAt(value: string): this { + this.data['last_run_at'] = value; + return this; + } + + name(value: string): this { + this.data['name'] = value; + return this; + } + + nextRunAt(value: string): this { + this.data['next_run_at'] = value; + return this; + } + + projectId(value: string): this { + this.data['project_id'] = value; + return this; + } + + runnerType(value: string): this { + this.data['runner_type'] = value; + return this; + } + + schedule(value: string): this { + this.data['schedule'] = value; + return this; + } + + sessionPrompt(value: string): this { + this.data['session_prompt'] = value; + return this; + } + + stopOnRunFinished(value: boolean): this { + this.data['stop_on_run_finished'] = value; + return this; + } + + timeout(value: number): this { + this.data['timeout'] = value; + return this; + } + + timezone(value: string): this { + this.data['timezone'] = value; + return this; + } + + build(): ScheduledSessionCreateRequest { + if (!this.data['name']) { + throw new Error('name is required'); + } + if (!this.data['project_id']) { + throw new Error('project_id is required'); + } + if (!this.data['schedule']) { + throw new Error('schedule is required'); + } + return this.data as ScheduledSessionCreateRequest; + } +} + +export class ScheduledSessionPatchBuilder { + private data: Record = {}; + + + agentId(value: string): this { + this.data['agent_id'] = value; + return this; + } + + description(value: string): this { + this.data['description'] = value; + return this; + } + + enabled(value: boolean): this { + this.data['enabled'] = value; + return this; + } + + inactivityTimeout(value: number): this { + this.data['inactivity_timeout'] = value; + return this; + } + + name(value: string): this { + this.data['name'] = value; + return this; + } + + runnerType(value: string): this { + this.data['runner_type'] = value; + return this; + } + + schedule(value: string): this { + this.data['schedule'] = value; + return this; + } + + sessionPrompt(value: string): this { + this.data['session_prompt'] = value; + return this; + } + + stopOnRunFinished(value: boolean): this { + this.data['stop_on_run_finished'] = value; + return this; + } + + timeout(value: number): this { + this.data['timeout'] = value; + return this; + } + + timezone(value: string): this { + this.data['timezone'] = value; + return this; + } + + build(): ScheduledSessionPatchRequest { + return this.data as ScheduledSessionPatchRequest; + } +} diff --git a/components/ambient-sdk/ts-sdk/src/scheduled_session_api.ts b/components/ambient-sdk/ts-sdk/src/scheduled_session_api.ts new file mode 100644 index 000000000..a6f9c05af --- /dev/null +++ b/components/ambient-sdk/ts-sdk/src/scheduled_session_api.ts @@ -0,0 +1,53 @@ +// Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. +// Source: ../../ambient-api-server/openapi/openapi.yaml +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z + +import type { AmbientClientConfig, ListOptions, RequestOptions } from './base'; +import { ambientFetch, buildQueryString } from './base'; +import type { ScheduledSession, ScheduledSessionList, ScheduledSessionCreateRequest, ScheduledSessionPatchRequest } from './scheduled_session'; + +export class ScheduledSessionAPI { + constructor(private readonly config: AmbientClientConfig) {} + private basePath(): string { + if (!this.config.project) { + throw new Error('project is required for ScheduledSession operations'); + } + return '/projects/{id}/scheduled-sessions'.replace('{id}', encodeURIComponent(this.config.project)); + } + + + async create(data: ScheduledSessionCreateRequest, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'POST', this.basePath(), data, opts); + } + + async get(id: string, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'GET', `${this.basePath()}/${id}`, undefined, opts); + } + + async list(listOpts?: ListOptions, opts?: RequestOptions): Promise { + const qs = buildQueryString(listOpts); + return ambientFetch(this.config, 'GET', `${this.basePath()}${qs}`, undefined, opts); + } + async update(id: string, patch: ScheduledSessionPatchRequest, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'PATCH', `${this.basePath()}/${id}`, patch, opts); + } + + async delete(id: string, opts?: RequestOptions): Promise { + return ambientFetch(this.config, 'DELETE', `${this.basePath()}/${id}`, undefined, opts); + } + + async *listAll(size: number = 100, opts?: RequestOptions): AsyncGenerator { + let page = 1; + while (true) { + const result = await this.list({ page, size }, opts); + for (const item of result.items) { + yield item; + } + if (page * size >= result.total) { + break; + } + page++; + } + } +} diff --git a/components/ambient-sdk/ts-sdk/src/session.ts b/components/ambient-sdk/ts-sdk/src/session.ts index 626a80f2f..ec76c8209 100644 --- a/components/ambient-sdk/ts-sdk/src/session.ts +++ b/components/ambient-sdk/ts-sdk/src/session.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { ObjectReference, ListMeta } from './base'; diff --git a/components/ambient-sdk/ts-sdk/src/session_api.ts b/components/ambient-sdk/ts-sdk/src/session_api.ts index ce29e8c01..ccc1aa488 100644 --- a/components/ambient-sdk/ts-sdk/src/session_api.ts +++ b/components/ambient-sdk/ts-sdk/src/session_api.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { AmbientClientConfig, ListOptions, RequestOptions } from './base'; import { ambientFetch, buildQueryString } from './base'; diff --git a/components/ambient-sdk/ts-sdk/src/session_message.ts b/components/ambient-sdk/ts-sdk/src/session_message.ts index 14bfcef6c..527ab896d 100644 --- a/components/ambient-sdk/ts-sdk/src/session_message.ts +++ b/components/ambient-sdk/ts-sdk/src/session_message.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { ObjectReference, ListMeta } from './base'; diff --git a/components/ambient-sdk/ts-sdk/src/session_message_api.ts b/components/ambient-sdk/ts-sdk/src/session_message_api.ts index f81a74647..65eb307ce 100644 --- a/components/ambient-sdk/ts-sdk/src/session_message_api.ts +++ b/components/ambient-sdk/ts-sdk/src/session_message_api.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 9a8e623edcfae33acf56edf974d1859a127c22915d4831cb786daba2b398ca37 -// Generated: 2026-03-21T21:30:53Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { AmbientClientConfig, ListOptions, RequestOptions } from './base'; import { ambientFetch, buildQueryString } from './base'; @@ -9,18 +9,25 @@ import type { SessionMessage, SessionMessageList, SessionMessageCreateRequest } export class SessionMessageAPI { constructor(private readonly config: AmbientClientConfig) {} + private basePath(): string { + if (!this.config.project) { + throw new Error('project is required for SessionMessage operations'); + } + return '/sessions/{id}/messages'.replace('{id}', encodeURIComponent(this.config.project)); + } + async create(data: SessionMessageCreateRequest, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'POST', '/sessions', data, opts); + return ambientFetch(this.config, 'POST', this.basePath(), data, opts); } async get(id: string, opts?: RequestOptions): Promise { - return ambientFetch(this.config, 'GET', `/sessions/${id}`, undefined, opts); + return ambientFetch(this.config, 'GET', `${this.basePath()}/${id}`, undefined, opts); } async list(listOpts?: ListOptions, opts?: RequestOptions): Promise { const qs = buildQueryString(listOpts); - return ambientFetch(this.config, 'GET', `/sessions${qs}`, undefined, opts); + return ambientFetch(this.config, 'GET', `${this.basePath()}${qs}`, undefined, opts); } async *listAll(size: number = 100, opts?: RequestOptions): AsyncGenerator { let page = 1; diff --git a/components/ambient-sdk/ts-sdk/src/user.ts b/components/ambient-sdk/ts-sdk/src/user.ts index 58648586f..8fcd31c96 100644 --- a/components/ambient-sdk/ts-sdk/src/user.ts +++ b/components/ambient-sdk/ts-sdk/src/user.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { ObjectReference, ListMeta } from './base'; diff --git a/components/ambient-sdk/ts-sdk/src/user_api.ts b/components/ambient-sdk/ts-sdk/src/user_api.ts index 564ad1cd3..ad374c760 100644 --- a/components/ambient-sdk/ts-sdk/src/user_api.ts +++ b/components/ambient-sdk/ts-sdk/src/user_api.ts @@ -1,7 +1,7 @@ // Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT. // Source: ../../ambient-api-server/openapi/openapi.yaml -// Spec SHA256: 97773951f427a0271532ec5ed2e18c6441b246989b0aebbe755b544b47e2e702 -// Generated: 2026-04-18T21:11:11Z +// Spec SHA256: c9d4494778eb0a006db1f289630460fb9b5dc58df1895903c42735b4f56b0314 +// Generated: 2026-05-05T18:24:54Z import type { AmbientClientConfig, ListOptions, RequestOptions } from './base'; import { ambientFetch, buildQueryString } from './base'; diff --git a/components/ambient-sdk/ts-sdk/tests/client.test.ts b/components/ambient-sdk/ts-sdk/tests/client.test.ts index 77dd509a3..587cf4279 100644 --- a/components/ambient-sdk/ts-sdk/tests/client.test.ts +++ b/components/ambient-sdk/ts-sdk/tests/client.test.ts @@ -22,20 +22,31 @@ describe('AmbientClient construction', () => { })).toThrow('baseUrl is required'); }); - it('throws when token is missing', () => { - expect(() => new AmbientClient({ + it('creates client without token (browser mode)', () => { + const client = new AmbientClient({ baseUrl: 'https://api.ambient-platform.com', - token: '', - project: 'test-project', - })).toThrow('token is required'); + }); + expect(client).toBeDefined(); + expect(client.sessions).toBeDefined(); }); - it('throws when project is missing', () => { - expect(() => new AmbientClient({ + it('creates client without project', () => { + const client = new AmbientClient({ baseUrl: 'https://api.ambient-platform.com', token: 'sha256~abcdefghijklmnopqrstuvwxyz1234567890', - project: '', - })).toThrow('project is required'); + }); + expect(client).toBeDefined(); + expect(client.sessions).toBeDefined(); + }); + + it('creates client with relative baseUrl', () => { + const client = new AmbientClient({ + baseUrl: '/api/proxy', + token: 'sha256~abcdefghijklmnopqrstuvwxyz1234567890', + project: 'test-project', + }); + expect(client).toBeDefined(); + expect(client.sessions).toBeDefined(); }); it('strips trailing slashes from baseUrl', () => { @@ -46,6 +57,14 @@ describe('AmbientClient construction', () => { }); expect(client).toBeDefined(); }); + + it('rejects protocol-relative URLs', () => { + expect(() => new AmbientClient({ + baseUrl: '//evil.com/path', + token: 'sha256~abcdefghijklmnopqrstuvwxyz1234567890', + project: 'test-project', + })).toThrow('Protocol-relative URLs are not allowed for baseUrl'); + }); }); describe('AmbientClient.fromEnv', () => { @@ -61,7 +80,7 @@ describe('AmbientClient.fromEnv', () => { it('creates client from environment variables', () => { process.env.AMBIENT_API_URL = 'https://api.test.com'; - process.env.AMBIENT_TOKEN = 'sha256~testtoken123'; + process.env.AMBIENT_TOKEN = 'sha256~abcdefghijklmnopqrstuvwxyz1234567890'; process.env.AMBIENT_PROJECT = 'my-project'; const client = AmbientClient.fromEnv(); expect(client).toBeDefined(); @@ -74,10 +93,12 @@ describe('AmbientClient.fromEnv', () => { expect(() => AmbientClient.fromEnv()).toThrow('AMBIENT_TOKEN environment variable is required'); }); - it('throws when AMBIENT_PROJECT is missing', () => { + it('creates client when AMBIENT_PROJECT is missing', () => { process.env.AMBIENT_TOKEN = 'sha256~abcdefghijklmnopqrstuvwxyz1234567890'; delete process.env.AMBIENT_PROJECT; - expect(() => AmbientClient.fromEnv()).toThrow('AMBIENT_PROJECT environment variable is required'); + const client = AmbientClient.fromEnv(); + expect(client).toBeDefined(); + expect(client.sessions).toBeDefined(); }); });