Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a643ead036 | ||
|
|
99b0948da9 | ||
|
|
75c2095f30 | ||
|
|
3683bd28dc |
No files matched your search
@@ -108,15 +108,15 @@ client, err := elydora.NewClient(&elydora.Config{
|
|||||||
BaseURL: "https://...", // API base URL (default: https://api.elydora.com)
|
BaseURL: "https://...", // API base URL (default: https://api.elydora.com)
|
||||||
TTLMs: 30000, // Operation TTL in ms (default: 30000)
|
TTLMs: 30000, // Operation TTL in ms (default: 30000)
|
||||||
MaxRetries: 3, // Max retries on transient failures (default: 3)
|
MaxRetries: 3, // Max retries on transient failures (default: 3)
|
||||||
Token: "<jwt>", // JWT token for authenticated requests
|
Token: "<token>", // API token for authenticated requests
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
### Client Methods
|
### Client Methods
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Update the JWT token at runtime
|
// Update the API token at runtime
|
||||||
client.SetToken("new-jwt-token")
|
client.SetToken("new-api-token")
|
||||||
```
|
```
|
||||||
|
|
||||||
### Authentication
|
### Authentication
|
||||||
@@ -128,7 +128,7 @@ reg, err := elydora.Register(baseURL, email, password,
|
|||||||
elydora.WithOrgName("Acme Corp"),
|
elydora.WithOrgName("Acme Corp"),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Login and receive a JWT
|
// Login and receive a session token
|
||||||
auth, err := elydora.Login(baseURL, email, password)
|
auth, err := elydora.Login(baseURL, email, password)
|
||||||
|
|
||||||
// Get current authenticated user profile
|
// Get current authenticated user profile
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package elydora
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// ListAdminEvents retrieves recent administrative events for the organization.
|
||||||
|
// An optional limit (1–100) may be provided; pass 0 to use the server default (20).
|
||||||
|
func (c *Client) ListAdminEvents(limit int) (*ListAdminEventsResponse, error) {
|
||||||
|
path := "/v1/admin/events"
|
||||||
|
if limit > 0 {
|
||||||
|
path = fmt.Sprintf("%s?limit=%d", path, limit)
|
||||||
|
}
|
||||||
|
var result ListAdminEventsResponse
|
||||||
|
if err := c.doGet(path, &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
@@ -24,10 +24,14 @@ func (c *Client) GetAgent(agentID string) (*GetAgentResponse, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FreezeAgent freezes an agent, preventing it from submitting operations.
|
// FreezeAgent freezes an agent, preventing it from submitting operations.
|
||||||
func (c *Client) FreezeAgent(agentID, reason string) error {
|
func (c *Client) FreezeAgent(agentID, reason string) (*FreezeAgentResponse, error) {
|
||||||
return c.doPost(fmt.Sprintf("/v1/agents/%s/freeze", agentID), &FreezeAgentRequest{
|
var result FreezeAgentResponse
|
||||||
|
if err := c.doPost(fmt.Sprintf("/v1/agents/%s/freeze", agentID), &FreezeAgentRequest{
|
||||||
Reason: reason,
|
Reason: reason,
|
||||||
}, nil)
|
}, &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RevokeKey revokes a specific key for an agent.
|
// RevokeKey revokes a specific key for an agent.
|
||||||
@@ -48,10 +52,25 @@ func (c *Client) ListAgents() (*ListAgentsResponse, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UnfreezeAgent unfreezes a previously frozen agent.
|
// UnfreezeAgent unfreezes a previously frozen agent.
|
||||||
func (c *Client) UnfreezeAgent(agentID, reason string) error {
|
func (c *Client) UnfreezeAgent(agentID, reason string) (*UnfreezeAgentResponse, error) {
|
||||||
return c.doPost(fmt.Sprintf("/v1/agents/%s/unfreeze", agentID), &UnfreezeAgentRequest{
|
var result UnfreezeAgentResponse
|
||||||
|
if err := c.doPost(fmt.Sprintf("/v1/agents/%s/unfreeze", agentID), &UnfreezeAgentRequest{
|
||||||
Reason: reason,
|
Reason: reason,
|
||||||
}, nil)
|
}, &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateAgent updates an agent's integration type.
|
||||||
|
func (c *Client) UpdateAgent(agentID string, integrationType IntegrationType) (*UpdateAgentResponse, error) {
|
||||||
|
var result UpdateAgentResponse
|
||||||
|
if err := c.doRequest(http.MethodPatch, fmt.Sprintf("/v1/agents/%s", agentID), &UpdateAgentRequest{
|
||||||
|
IntegrationType: integrationType,
|
||||||
|
}, &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAgent permanently deletes an agent and all associated data.
|
// DeleteAgent permanently deletes an agent and all associated data.
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ func WithOrgName(name string) RegisterOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register creates a new user and organization.
|
// Register creates a new user and organization.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Better Auth endpoints directly. See docs.
|
||||||
func Register(baseURL, email, password string, opts ...RegisterOption) (*AuthRegisterResponse, error) {
|
func Register(baseURL, email, password string, opts ...RegisterOption) (*AuthRegisterResponse, error) {
|
||||||
if baseURL == "" {
|
if baseURL == "" {
|
||||||
baseURL = defaultBaseURL
|
baseURL = defaultBaseURL
|
||||||
@@ -49,7 +51,9 @@ func Register(baseURL, email, password string, opts ...RegisterOption) (*AuthReg
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login authenticates a user and returns a JWT token.
|
// Login authenticates a user and returns a session token.
|
||||||
|
//
|
||||||
|
// Deprecated: Use Better Auth endpoints directly. See docs.
|
||||||
func Login(baseURL, email, password string) (*AuthLoginResponse, error) {
|
func Login(baseURL, email, password string) (*AuthLoginResponse, error) {
|
||||||
if baseURL == "" {
|
if baseURL == "" {
|
||||||
baseURL = defaultBaseURL
|
baseURL = defaultBaseURL
|
||||||
@@ -140,3 +144,13 @@ func (c *Client) IssueApiToken(req *IssueApiTokenRequest) (*IssueApiTokenRespons
|
|||||||
}
|
}
|
||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RotateApiToken rotates the current API token and leaves the old token
|
||||||
|
// valid for a 24h grace window.
|
||||||
|
func (c *Client) RotateApiToken() (*RotateApiTokenResponse, error) {
|
||||||
|
var result RotateApiTokenResponse
|
||||||
|
if err := c.doPost("/v1/auth/rotate", map[string]interface{}{}, &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
@@ -24,7 +24,7 @@ type Config struct {
|
|||||||
BaseURL string // defaults to "https://api.elydora.com"
|
BaseURL string // defaults to "https://api.elydora.com"
|
||||||
TTLMs int // defaults to 30000
|
TTLMs int // defaults to 30000
|
||||||
MaxRetries int // defaults to 3
|
MaxRetries int // defaults to 3
|
||||||
Token string // JWT token for authenticated requests
|
Token string // API token for authenticated requests
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client is the Elydora SDK client.
|
// Client is the Elydora SDK client.
|
||||||
@@ -172,7 +172,7 @@ func (c *Client) doPost(path string, body interface{}, result interface{}) error
|
|||||||
return c.doRequest(http.MethodPost, path, body, result)
|
return c.doRequest(http.MethodPost, path, body, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetToken sets the JWT token used for authenticated API requests.
|
// SetToken sets the API token used for authenticated API requests.
|
||||||
func (c *Client) SetToken(token string) {
|
func (c *Client) SetToken(token string) {
|
||||||
c.token = token
|
c.token = token
|
||||||
}
|
}
|
||||||
+2
-2
@@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/Elydora-Infrastructure/Elydora-Go-SDK/cmd/elydora/plugins"
|
"github.com/Elydora-Infrastructure/Elydora-Go-SDK/cmd/elydora/plugins"
|
||||||
)
|
)
|
||||||
|
|
||||||
const version = "1.2.0"
|
const version = "1.2.1"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
@@ -69,7 +69,7 @@ func cmdInstall(args []string) {
|
|||||||
agentID := fs.String("agent-id", "", "Agent ID (required)")
|
agentID := fs.String("agent-id", "", "Agent ID (required)")
|
||||||
privateKey := fs.String("private-key", "", "Base64url-encoded Ed25519 private key seed (required)")
|
privateKey := fs.String("private-key", "", "Base64url-encoded Ed25519 private key seed (required)")
|
||||||
kid := fs.String("kid", "", "Key ID (defaults to <agent-id>-key-1)")
|
kid := fs.String("kid", "", "Key ID (defaults to <agent-id>-key-1)")
|
||||||
token := fs.String("token", "", "JWT token for authenticated requests (optional)")
|
token := fs.String("token", "", "API token for authenticated requests (optional)")
|
||||||
baseURL := fs.String("base-url", "https://api.elydora.com", "Elydora API base URL")
|
baseURL := fs.String("base-url", "https://api.elydora.com", "Elydora API base URL")
|
||||||
|
|
||||||
fs.Parse(args)
|
fs.Parse(args)
|
||||||
|
|||||||
@@ -60,3 +60,57 @@ func Health(baseURL string) (*HealthResponse, error) {
|
|||||||
Message: string(respBody),
|
Message: string(respBody),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepHealth checks the deep health of the Elydora API, including its backend
|
||||||
|
// dependencies (D1, R2, KV). This is a public endpoint that does not require
|
||||||
|
// authentication.
|
||||||
|
func DeepHealth(baseURL string) (*DeepHealthResponse, error) {
|
||||||
|
if baseURL == "" {
|
||||||
|
baseURL = defaultBaseURL
|
||||||
|
}
|
||||||
|
baseURL = strings.TrimRight(baseURL, "/")
|
||||||
|
|
||||||
|
client := &http.Client{Timeout: 30 * time.Second}
|
||||||
|
req, err := http.NewRequest(http.MethodGet, baseURL+"/v1/health/deep", nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("elydora: create request: %w", err)
|
||||||
|
}
|
||||||
|
req.Header.Set("Accept", "application/json")
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("elydora: http request: %w", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
respBody, err := io.ReadAll(io.LimitReader(resp.Body, 10<<20))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("elydora: read response body: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept both 200 (healthy) and 503 (degraded) as valid deep-health responses.
|
||||||
|
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusServiceUnavailable {
|
||||||
|
var result DeepHealthResponse
|
||||||
|
if err := json.Unmarshal(respBody, &result); err != nil {
|
||||||
|
return nil, fmt.Errorf("elydora: unmarshal response: %w", err)
|
||||||
|
}
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var errResp errorResponse
|
||||||
|
if err := json.Unmarshal(respBody, &errResp); err == nil && errResp.Error.Code != "" {
|
||||||
|
return nil, &ElydoraError{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
Code: errResp.Error.Code,
|
||||||
|
Message: errResp.Error.Message,
|
||||||
|
RequestID: errResp.Error.RequestID,
|
||||||
|
Details: errResp.Error.Details,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, &ElydoraError{
|
||||||
|
StatusCode: resp.StatusCode,
|
||||||
|
Code: ErrorCodeInternalError,
|
||||||
|
Message: string(respBody),
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package elydora
|
||||||
|
|
||||||
|
// ListMembers retrieves all members of the organization.
|
||||||
|
func (c *Client) ListMembers() (*ListMembersResponse, error) {
|
||||||
|
var result ListMembersResponse
|
||||||
|
if err := c.doGet("/v1/members", &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
+5
-1
@@ -88,7 +88,11 @@ func (c *Client) GetOperation(operationID string) (*GetOperationResponse, error)
|
|||||||
// VerifyOperation verifies the integrity of an operation.
|
// VerifyOperation verifies the integrity of an operation.
|
||||||
func (c *Client) VerifyOperation(operationID string) (*VerifyOperationResponse, error) {
|
func (c *Client) VerifyOperation(operationID string) (*VerifyOperationResponse, error) {
|
||||||
var result VerifyOperationResponse
|
var result VerifyOperationResponse
|
||||||
if err := c.doPost(fmt.Sprintf("/v1/operations/%s/verify", operationID), nil, &result); err != nil {
|
if err := c.doPost(
|
||||||
|
fmt.Sprintf("/v1/operations/%s/verify", operationID),
|
||||||
|
map[string]interface{}{},
|
||||||
|
&result,
|
||||||
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &result, nil
|
return &result, nil
|
||||||
|
|||||||
@@ -0,0 +1,155 @@
|
|||||||
|
package elydora_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ed25519"
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
elydora "github.com/Elydora-Infrastructure/Elydora-Go-SDK"
|
||||||
|
)
|
||||||
|
|
||||||
|
func randomHex(n int) string {
|
||||||
|
buf := make([]byte, n)
|
||||||
|
_, _ = rand.Read(buf)
|
||||||
|
return hex.EncodeToString(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomSeedBase64url(t *testing.T) (seedB64 string, pubB64 string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
seed := make([]byte, ed25519.SeedSize)
|
||||||
|
if _, err := rand.Read(seed); err != nil {
|
||||||
|
t.Fatalf("read random seed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey := ed25519.NewKeyFromSeed(seed)
|
||||||
|
publicKey := privateKey.Public().(ed25519.PublicKey)
|
||||||
|
|
||||||
|
return base64.RawURLEncoding.EncodeToString(seed), base64.RawURLEncoding.EncodeToString(publicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSDKCompatibilityAgainstLatestAPI(t *testing.T) {
|
||||||
|
baseURL := os.Getenv("API_BASE_URL")
|
||||||
|
if baseURL == "" {
|
||||||
|
t.Skip("API_BASE_URL is not set; skipping SDK compatibility integration test")
|
||||||
|
}
|
||||||
|
suffix := randomHex(6)
|
||||||
|
email := fmt.Sprintf("go-sdk-%s@elydora.test", suffix)
|
||||||
|
password := fmt.Sprintf("Go-%s-Password!", suffix)
|
||||||
|
agentID := fmt.Sprintf("go-agent-%s", randomHex(8))
|
||||||
|
kid := fmt.Sprintf("go-kid-%s", randomHex(8))
|
||||||
|
privateKey, publicKey := randomSeedBase64url(t)
|
||||||
|
|
||||||
|
if _, err := elydora.Register(baseURL, email, password, elydora.WithDisplayName("go-sdk-user"), elydora.WithOrgName("go-org-"+suffix)); err != nil {
|
||||||
|
t.Fatalf("register failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
login, err := elydora.Login(baseURL, email, password)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("login failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := elydora.NewClient(&elydora.Config{
|
||||||
|
OrgID: login.User.OrgID,
|
||||||
|
AgentID: agentID,
|
||||||
|
PrivateKey: privateKey,
|
||||||
|
BaseURL: baseURL,
|
||||||
|
TTLMs: 120000,
|
||||||
|
MaxRetries: 1,
|
||||||
|
Token: login.Token,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("new client failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ttl := 1800
|
||||||
|
tokenResp, err := client.IssueApiToken(&elydora.IssueApiTokenRequest{TTLSeconds: &ttl})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("issue api token failed: %v", err)
|
||||||
|
}
|
||||||
|
if tokenResp.TokenID == "" {
|
||||||
|
t.Fatalf("issue api token: token_id missing")
|
||||||
|
}
|
||||||
|
|
||||||
|
oldToken := tokenResp.Token
|
||||||
|
client.SetToken(oldToken)
|
||||||
|
meWithAPI, err := client.GetMe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("api token auth failed: %v", err)
|
||||||
|
}
|
||||||
|
if meWithAPI.User.OrgID != login.User.OrgID {
|
||||||
|
t.Fatalf("api token org mismatch: got %s want %s", meWithAPI.User.OrgID, login.User.OrgID)
|
||||||
|
}
|
||||||
|
|
||||||
|
rotateResp, err := client.RotateApiToken()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("rotate api token failed: %v", err)
|
||||||
|
}
|
||||||
|
if rotateResp.Token == "" {
|
||||||
|
t.Fatalf("rotate response missing token: %+v", rotateResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
client.SetToken(rotateResp.Token)
|
||||||
|
meWithRotated, err := client.GetMe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("rotated token auth failed: %v", err)
|
||||||
|
}
|
||||||
|
if meWithRotated.User.OrgID != login.User.OrgID {
|
||||||
|
t.Fatalf("rotated token org mismatch: got %s want %s", meWithRotated.User.OrgID, login.User.OrgID)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = client.RegisterAgent(&elydora.RegisterAgentRequest{
|
||||||
|
AgentID: agentID,
|
||||||
|
DisplayName: "Go SDK Compat Agent",
|
||||||
|
ResponsibleEntity: "sdk-matrix",
|
||||||
|
Keys: []elydora.RegisterAgentKeyInput{
|
||||||
|
{
|
||||||
|
KID: kid,
|
||||||
|
PublicKey: publicKey,
|
||||||
|
Algorithm: "ed25519",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("register agent failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
op, err := client.CreateOperation(&elydora.CreateOperationParams{
|
||||||
|
OperationType: "compat.go.submit",
|
||||||
|
Subject: map[string]interface{}{"entity": "sdk", "id": "go-" + suffix},
|
||||||
|
Action: map[string]interface{}{"type": "write", "resource": "matrix"},
|
||||||
|
Payload: map[string]interface{}{"sdk": "go"},
|
||||||
|
KID: kid,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("create operation failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
submit, err := client.SubmitOperation(op)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("submit operation failed: %v", err)
|
||||||
|
}
|
||||||
|
if submit.Receipt.OperationID != op.OperationID {
|
||||||
|
t.Fatalf("receipt operation mismatch: got %s want %s", submit.Receipt.OperationID, op.OperationID)
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := client.GetOperation(op.OperationID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("get operation failed: %v", err)
|
||||||
|
}
|
||||||
|
if got.Operation.OperationID != op.OperationID {
|
||||||
|
t.Fatalf("get operation mismatch: got %s want %s", got.Operation.OperationID, op.OperationID)
|
||||||
|
}
|
||||||
|
|
||||||
|
verify, err := client.VerifyOperation(op.OperationID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("verify operation failed: %v", err)
|
||||||
|
}
|
||||||
|
if !verify.Valid {
|
||||||
|
t.Fatalf("verify operation invalid: %+v", verify)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,25 @@ const (
|
|||||||
KeyStatusRevoked KeyStatus = "revoked"
|
KeyStatusRevoked KeyStatus = "revoked"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type IntegrationType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
IntegrationTypeClaudecode IntegrationType = "claudecode"
|
||||||
|
IntegrationTypeCursor IntegrationType = "cursor"
|
||||||
|
IntegrationTypeGemini IntegrationType = "gemini"
|
||||||
|
IntegrationTypeKiroCLI IntegrationType = "kirocli"
|
||||||
|
IntegrationTypeKiroIDE IntegrationType = "kiroide"
|
||||||
|
IntegrationTypeOpenCode IntegrationType = "opencode"
|
||||||
|
IntegrationTypeCopilot IntegrationType = "copilot"
|
||||||
|
IntegrationTypeLetta IntegrationType = "letta"
|
||||||
|
IntegrationTypeCodex IntegrationType = "codex"
|
||||||
|
IntegrationTypeKimi IntegrationType = "kimi"
|
||||||
|
IntegrationTypeEnterprise IntegrationType = "enterprise"
|
||||||
|
IntegrationTypeGUI IntegrationType = "gui"
|
||||||
|
IntegrationTypeSDK IntegrationType = "sdk"
|
||||||
|
IntegrationTypeOther IntegrationType = "other"
|
||||||
|
)
|
||||||
|
|
||||||
type ExportStatus string
|
type ExportStatus string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -74,6 +93,7 @@ type Agent struct {
|
|||||||
OrgID string `json:"org_id"`
|
OrgID string `json:"org_id"`
|
||||||
DisplayName string `json:"display_name"`
|
DisplayName string `json:"display_name"`
|
||||||
ResponsibleEntity string `json:"responsible_entity"`
|
ResponsibleEntity string `json:"responsible_entity"`
|
||||||
|
IntegrationType IntegrationType `json:"integration_type"`
|
||||||
Status AgentStatus `json:"status"`
|
Status AgentStatus `json:"status"`
|
||||||
CreatedAt int64 `json:"created_at"`
|
CreatedAt int64 `json:"created_at"`
|
||||||
UpdatedAt int64 `json:"updated_at"`
|
UpdatedAt int64 `json:"updated_at"`
|
||||||
@@ -130,6 +150,8 @@ type Epoch struct {
|
|||||||
type Organization struct {
|
type Organization struct {
|
||||||
OrgID string `json:"org_id"`
|
OrgID string `json:"org_id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
BAOrgID *string `json:"ba_org_id"`
|
||||||
CreatedAt int64 `json:"created_at"`
|
CreatedAt int64 `json:"created_at"`
|
||||||
UpdatedAt int64 `json:"updated_at"`
|
UpdatedAt int64 `json:"updated_at"`
|
||||||
}
|
}
|
||||||
@@ -225,6 +247,11 @@ type FreezeAgentRequest struct {
|
|||||||
Reason string `json:"reason"`
|
Reason string `json:"reason"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FreezeAgentResponse struct {
|
||||||
|
Agent Agent `json:"agent"`
|
||||||
|
PreviousStatus AgentStatus `json:"previous_status"`
|
||||||
|
}
|
||||||
|
|
||||||
type RevokeAgentRequest struct {
|
type RevokeAgentRequest struct {
|
||||||
KID string `json:"kid"`
|
KID string `json:"kid"`
|
||||||
Reason string `json:"reason"`
|
Reason string `json:"reason"`
|
||||||
@@ -234,6 +261,19 @@ type UnfreezeAgentRequest struct {
|
|||||||
Reason string `json:"reason"`
|
Reason string `json:"reason"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UnfreezeAgentResponse struct {
|
||||||
|
Agent Agent `json:"agent"`
|
||||||
|
PreviousStatus AgentStatus `json:"previous_status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateAgentRequest struct {
|
||||||
|
IntegrationType IntegrationType `json:"integration_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateAgentResponse struct {
|
||||||
|
Agent Agent `json:"agent"`
|
||||||
|
}
|
||||||
|
|
||||||
type ListAgentsResponse struct {
|
type ListAgentsResponse struct {
|
||||||
Agents []Agent `json:"agents"`
|
Agents []Agent `json:"agents"`
|
||||||
}
|
}
|
||||||
@@ -253,6 +293,13 @@ type IssueApiTokenRequest struct {
|
|||||||
type IssueApiTokenResponse struct {
|
type IssueApiTokenResponse struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
ExpiresAt *int64 `json:"expires_at"`
|
ExpiresAt *int64 `json:"expires_at"`
|
||||||
|
TokenID string `json:"token_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RotateApiTokenResponse struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
ExpiresAt *int64 `json:"expires_at"`
|
||||||
|
TokenID string `json:"token_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HealthResponse struct {
|
type HealthResponse struct {
|
||||||
@@ -307,6 +354,8 @@ type GetEpochResponse struct {
|
|||||||
|
|
||||||
type EpochAnchor struct {
|
type EpochAnchor struct {
|
||||||
TSAToken string `json:"tsa_token,omitempty"`
|
TSAToken string `json:"tsa_token,omitempty"`
|
||||||
|
TSAUrl string `json:"tsa_url,omitempty"`
|
||||||
|
AnchoredAt *int64 `json:"anchored_at,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListEpochsResponse struct {
|
type ListEpochsResponse struct {
|
||||||
@@ -370,6 +419,93 @@ type AuthLoginResponse struct {
|
|||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AdminEvent represents an administrative event log entry.
|
||||||
|
type AdminEvent struct {
|
||||||
|
EventID string `json:"event_id"`
|
||||||
|
OrgID string `json:"org_id"`
|
||||||
|
Actor string `json:"actor"`
|
||||||
|
Action string `json:"action"`
|
||||||
|
TargetType string `json:"target_type"`
|
||||||
|
TargetID string `json:"target_id"`
|
||||||
|
Details *string `json:"details"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AgentAssignment represents a many-to-many agent-to-user assignment.
|
||||||
|
type AgentAssignment struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
AgentID string `json:"agent_id"`
|
||||||
|
UserID string `json:"user_id"`
|
||||||
|
OrgID string `json:"org_id"`
|
||||||
|
AssignedBy string `json:"assigned_by"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Webhook represents a registered webhook endpoint.
|
||||||
|
type Webhook struct {
|
||||||
|
WebhookID string `json:"webhook_id"`
|
||||||
|
OrgID string `json:"org_id"`
|
||||||
|
EndpointURL string `json:"endpoint_url"`
|
||||||
|
Events []string `json:"events"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
UpdatedAt int64 `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListWebhooksResponse struct {
|
||||||
|
Webhooks []Webhook `json:"webhooks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RegisterWebhookRequest struct {
|
||||||
|
EndpointURL string `json:"endpoint_url"`
|
||||||
|
Events []string `json:"events"`
|
||||||
|
Secret string `json:"secret"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RegisterWebhookResponse struct {
|
||||||
|
Webhook Webhook `json:"webhook"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Member represents a console user returned from the members list endpoint.
|
||||||
|
type Member struct {
|
||||||
|
MemberID string `json:"member_id"`
|
||||||
|
UserID string `json:"user_id"`
|
||||||
|
Role string `json:"role"`
|
||||||
|
JoinedAt string `json:"joined_at"`
|
||||||
|
Email string `json:"email"`
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListMembersResponse struct {
|
||||||
|
Members []Member `json:"members"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListAdminEventsResponse struct {
|
||||||
|
Events []AdminEvent `json:"events"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DependencyHealth holds the health status of a single backend dependency.
|
||||||
|
type DependencyHealth struct {
|
||||||
|
Status string `json:"status"`
|
||||||
|
LatencyMs int64 `json:"latency_ms"`
|
||||||
|
Error *string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepHealthDependencies lists the health of all backend dependencies.
|
||||||
|
type DeepHealthDependencies struct {
|
||||||
|
D1 DependencyHealth `json:"d1"`
|
||||||
|
R2 DependencyHealth `json:"r2"`
|
||||||
|
KV DependencyHealth `json:"kv"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepHealthResponse is returned by GET /v1/health/deep.
|
||||||
|
type DeepHealthResponse struct {
|
||||||
|
Status string `json:"status"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
Dependencies DeepHealthDependencies `json:"dependencies"`
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// CreateOperation params (SDK-specific)
|
// CreateOperation params (SDK-specific)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
package elydora
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListWebhooks retrieves all registered webhooks for the organization.
|
||||||
|
func (c *Client) ListWebhooks() (*ListWebhooksResponse, error) {
|
||||||
|
var result ListWebhooksResponse
|
||||||
|
if err := c.doGet("/v1/webhooks", &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterWebhook registers a new webhook endpoint for the organization.
|
||||||
|
func (c *Client) RegisterWebhook(req *RegisterWebhookRequest) (*RegisterWebhookResponse, error) {
|
||||||
|
var result RegisterWebhookResponse
|
||||||
|
if err := c.doPost("/v1/webhooks", req, &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteWebhook deletes a registered webhook by ID.
|
||||||
|
func (c *Client) DeleteWebhook(webhookID string) error {
|
||||||
|
return c.doRequest(http.MethodDelete, fmt.Sprintf("/v1/webhooks/%s", webhookID), nil, nil)
|
||||||
|
}
|
||||||
Reference in new issue
Block a user