Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions components/ambient-sdk/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ ambient-sdk/
The API server owns the canonical OpenAPI spec at `../ambient-api-server/openapi/openapi.yaml`. The SDK does **not** maintain its own copy — it derives types and client behavior from the API server's spec.

- **Spec location**: `../ambient-api-server/openapi/` (split by resource: sessions, agents, tasks, workflows, etc.)
- **Session endpoints**: `GET /api/ambient-api-server/v1/sessions`, `POST ...`, `GET .../sessions/{id}`
- **Session endpoints**: `GET /api/ambient/v1/sessions`, `POST ...`, `GET .../sessions/{id}`
- **Auth**: `Authorization: Bearer <token>` header (project scoping via `X-Ambient-Project`)
- **Statuses**: `pending` → `running` → `completed` | `failed`
- Update the API server's spec before changing SDK types or client behavior
Expand All @@ -111,7 +111,7 @@ The API server owns the canonical OpenAPI spec at `../ambient-api-server/openapi

## Smoke Test

Run `cd go-sdk && go run examples/main.go` until it passes. This is the SDK's end-to-end smoke test against the live API server. It currently returns 404 because the API server has not been migrated to serve `/api/ambient-api-server/v1/sessions` yet. Once the full migration (api-server + control-plane + deployment) is complete, this test will pass. Keep running it — when it stops returning 404, the platform is wired up.
Run `cd go-sdk && go run examples/main.go` until it passes. This is the SDK's end-to-end smoke test against the live API server. It currently returns 404 because the API server has not been migrated to serve `/api/ambient/v1/sessions` yet. Once the full migration (api-server + control-plane + deployment) is complete, this test will pass. Keep running it — when it stops returning 404, the platform is wired up.

## Loadable Context

Expand Down
10 changes: 5 additions & 5 deletions components/ambient-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The Ambient Platform SDK provides Go, Python, and TypeScript client libraries fo
## Supported Languages

- **Go SDK** - `go-sdk/` - Go 1.21+ with standard library only
- **Python SDK** - `python-sdk/` - Python 3.8+ with minimal dependencies
- **Python SDK** - `python-sdk/` - Python 3.8+ with minimal dependencies
- **TypeScript SDK** - `ts-sdk/` - Modern TypeScript with proper type safety

## Quick Start
Expand All @@ -35,7 +35,7 @@ from ambient_platform.client import AmbientClient

client = AmbientClient.from_env()
session = client.sessions.create({
"name": "My Analysis Session",
"name": "My Analysis Session",
"prompt": "Analyze this codebase"
})
```
Expand Down Expand Up @@ -71,7 +71,7 @@ All SDKs support these environment variables:
The SDK provides access to 4 core resources:

- **Sessions** - Create and manage AI agentic sessions
- **Users** - User management and authentication
- **Users** - User management and authentication
- **Projects** - Project configuration and settings
- **ProjectSettings** - Project-specific configuration

Expand All @@ -82,7 +82,7 @@ The SDK provides access to 4 core resources:
make generate-sdk

# Verify all SDKs build correctly
make verify-sdk
make verify-sdk

# Build generator binary
make build-generator
Expand All @@ -96,4 +96,4 @@ For detailed documentation, see:
- `docs/architecture.md` - Design decisions and platform integration
- `docs/authentication.md` - Auth flows and token formats
- `go-sdk/README.md` - Go-specific usage
- `python-sdk/README.md` - Python-specific usage
- `python-sdk/README.md` - Python-specific usage
43 changes: 43 additions & 0 deletions components/ambient-sdk/bin/templates/go/base.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT.
// Source: {{.Header.SpecPath}}
// Spec SHA256: {{.Header.SpecHash}}
// Generated: {{.Header.Timestamp}}

package types

import (
"strconv"
"time"
)

type ObjectReference struct {
ID string `json:"id,omitempty"`
Kind string `json:"kind,omitempty"`
Href string `json:"href,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
}

type ListMeta struct {
Kind string `json:"kind"`
Page int `json:"page"`
Size int `json:"size"`
Total int `json:"total"`
}

type APIError struct {
ID string `json:"id,omitempty"`
Kind string `json:"kind,omitempty"`
Href string `json:"href,omitempty"`
Code string `json:"code"`
Reason string `json:"reason"`
OperationID string `json:"operation_id,omitempty"`
StatusCode int `json:"-"`
}

func (e *APIError) Error() string {
if e.StatusCode > 0 {
return "ambient API error " + strconv.Itoa(e.StatusCode) + ": " + e.Code + " — " + e.Reason
}
return "ambient API error: " + e.Code + " — " + e.Reason
}
100 changes: 100 additions & 0 deletions components/ambient-sdk/bin/templates/go/client.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Code generated by ambient-sdk-generator from openapi.yaml — DO NOT EDIT.
// Source: {{.Header.SpecPath}}
// Spec SHA256: {{.Header.SpecHash}}
// Generated: {{.Header.Timestamp}}

package client

import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"

"github.com/ambient-code/platform/components/ambient-sdk/go-sdk/types"
)

type {{.Resource.Name}}API struct {
client *Client
}

func (c *Client) {{.Resource.Plural}}() *{{.Resource.Name}}API {
return &{{.Resource.Name}}API{client: c}
}

func (a *{{.Resource.Name}}API) Create(ctx context.Context, resource *types.{{.Resource.Name}}) (*types.{{.Resource.Name}}, error) {
body, err := json.Marshal(resource)
if err != nil {
return nil, fmt.Errorf("marshal {{.Resource.Name | snakeCase}}: %w", err)
}
var result types.{{.Resource.Name}}
if err := a.client.do(ctx, http.MethodPost, "/{{.Resource.PathSegment}}", body, http.StatusCreated, &result); err != nil {
return nil, err
}
return &result, nil
}

func (a *{{.Resource.Name}}API) Get(ctx context.Context, id string) (*types.{{.Resource.Name}}, error) {
var result types.{{.Resource.Name}}
if err := a.client.do(ctx, http.MethodGet, "/{{.Resource.PathSegment}}/"+url.PathEscape(id), nil, http.StatusOK, &result); err != nil {
return nil, err
}
return &result, nil
}

func (a *{{.Resource.Name}}API) List(ctx context.Context, opts *types.ListOptions) (*types.{{.Resource.Name}}List, error) {
var result types.{{.Resource.Name}}List
if err := a.client.doWithQuery(ctx, http.MethodGet, "/{{.Resource.PathSegment}}", nil, http.StatusOK, &result, opts); err != nil {
return nil, err
}
return &result, nil
}

{{- if .Resource.HasPatch}}
func (a *{{.Resource.Name}}API) Update(ctx context.Context, id string, patch map[string]any) (*types.{{.Resource.Name}}, error) {
body, err := json.Marshal(patch)
if err != nil {
return nil, fmt.Errorf("marshal patch: %w", err)
}
var result types.{{.Resource.Name}}
if err := a.client.do(ctx, http.MethodPatch, "/{{.Resource.PathSegment}}/"+url.PathEscape(id), body, http.StatusOK, &result); err != nil {
return nil, err
}
return &result, nil
}
{{end}}
{{- if .Resource.HasDelete}}
func (a *{{.Resource.Name}}API) Delete(ctx context.Context, id string) error {
return a.client.do(ctx, http.MethodDelete, "/{{.Resource.PathSegment}}/"+url.PathEscape(id), nil, http.StatusNoContent, nil)
}
{{end}}
{{- if .Resource.HasStatusPatch}}
func (a *{{.Resource.Name}}API) UpdateStatus(ctx context.Context, id string, patch map[string]any) (*types.{{.Resource.Name}}, error) {
body, err := json.Marshal(patch)
if err != nil {
return nil, fmt.Errorf("marshal status patch: %w", err)
}
var result types.{{.Resource.Name}}
if err := a.client.do(ctx, http.MethodPatch, "/{{.Resource.PathSegment}}/"+url.PathEscape(id)+"/status", body, http.StatusOK, &result); err != nil {
return nil, err
}
return &result, nil
}
{{end}}
{{- range .Resource.Actions}}
func (a *{{$.Resource.Name}}API) {{. | title}}(ctx context.Context, id string) (*types.{{$.Resource.Name}}, error) {
var result types.{{$.Resource.Name}}
if err := a.client.do(ctx, http.MethodPost, "/{{$.Resource.PathSegment}}/"+url.PathEscape(id)+"/{{.}}", nil, http.StatusOK, &result); err != nil {
return nil, err
}
return &result, nil
}
{{end}}
func (a *{{.Resource.Name}}API) ListAll(ctx context.Context, opts *types.ListOptions) *Iterator[types.{{.Resource.Name}}] {
return NewIterator(func(page int) (*types.{{.Resource.Name}}List, error) {
o := *opts
o.Page = page
return a.List(ctx, &o)
})
}
Loading
Loading