- GraphQL Client: queries, mutations, convenience methods - Webhooks Client: create, list, test, trigger events - Email Client: send templated emails, preview templates - Full TypeScript type definitions - Zero dependencies (native fetch) - Connects to live APIs: GraphQL, Webhooks, Email
186 lines
4.8 KiB
Go
186 lines
4.8 KiB
Go
package blackroad
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// MemoryAPI provides access to memory operations.
|
|
type MemoryAPI struct {
|
|
client *Client
|
|
}
|
|
|
|
// Log creates a new memory entry.
|
|
func (m *MemoryAPI) Log(ctx context.Context, opts *LogMemoryOptions) (*MemoryEntry, error) {
|
|
resp, err := m.client.Post(ctx, "/memory", opts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var entry MemoryEntry
|
|
if err := json.Unmarshal(resp, &entry); err != nil {
|
|
return nil, NewConnectionError("failed to parse memory entry response", err)
|
|
}
|
|
return &entry, nil
|
|
}
|
|
|
|
// Query searches memory entries.
|
|
func (m *MemoryAPI) Query(ctx context.Context, opts *MemoryQueryOptions) ([]MemoryEntry, error) {
|
|
params := url.Values{}
|
|
if opts != nil {
|
|
if opts.Search != "" {
|
|
params.Set("q", opts.Search)
|
|
}
|
|
if opts.Action != "" {
|
|
params.Set("action", opts.Action)
|
|
}
|
|
if opts.Entity != "" {
|
|
params.Set("entity", opts.Entity)
|
|
}
|
|
if len(opts.Tags) > 0 {
|
|
params.Set("tags", strings.Join(opts.Tags, ","))
|
|
}
|
|
if opts.Since != nil {
|
|
params.Set("since", opts.Since.Format("2006-01-02T15:04:05Z"))
|
|
}
|
|
if opts.Until != nil {
|
|
params.Set("until", opts.Until.Format("2006-01-02T15:04:05Z"))
|
|
}
|
|
if opts.Limit > 0 {
|
|
params.Set("limit", strconv.Itoa(opts.Limit))
|
|
} else {
|
|
params.Set("limit", "100")
|
|
}
|
|
if opts.Offset > 0 {
|
|
params.Set("offset", strconv.Itoa(opts.Offset))
|
|
}
|
|
}
|
|
|
|
resp, err := m.client.Get(ctx, "/memory", params)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var result struct {
|
|
Entries []MemoryEntry `json:"entries"`
|
|
}
|
|
if err := json.Unmarshal(resp, &result); err != nil {
|
|
return nil, NewConnectionError("failed to parse memory response", err)
|
|
}
|
|
return result.Entries, nil
|
|
}
|
|
|
|
// Get returns a specific memory entry by hash.
|
|
func (m *MemoryAPI) Get(ctx context.Context, entryHash string) (*MemoryEntry, error) {
|
|
resp, err := m.client.Get(ctx, fmt.Sprintf("/memory/%s", entryHash), nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var entry MemoryEntry
|
|
if err := json.Unmarshal(resp, &entry); err != nil {
|
|
return nil, NewConnectionError("failed to parse memory entry response", err)
|
|
}
|
|
return &entry, nil
|
|
}
|
|
|
|
// Recent returns recent memory entries.
|
|
func (m *MemoryAPI) Recent(ctx context.Context, limit int) ([]MemoryEntry, error) {
|
|
if limit <= 0 {
|
|
limit = 50
|
|
}
|
|
return m.Query(ctx, &MemoryQueryOptions{Limit: limit})
|
|
}
|
|
|
|
// AgentState returns the state for an agent.
|
|
func (m *MemoryAPI) AgentState(ctx context.Context, agentID string) (map[string]interface{}, error) {
|
|
resp, err := m.client.Get(ctx, fmt.Sprintf("/memory/agents/%s/state", agentID), nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var state map[string]interface{}
|
|
if err := json.Unmarshal(resp, &state); err != nil {
|
|
return nil, NewConnectionError("failed to parse agent state response", err)
|
|
}
|
|
return state, nil
|
|
}
|
|
|
|
// SyncState syncs state for an agent.
|
|
func (m *MemoryAPI) SyncState(ctx context.Context, agentID string, state map[string]interface{}) error {
|
|
_, err := m.client.Post(ctx, fmt.Sprintf("/memory/agents/%s/state", agentID), state)
|
|
return err
|
|
}
|
|
|
|
// Broadcast sends a broadcast message.
|
|
func (m *MemoryAPI) Broadcast(ctx context.Context, msgType string, payload string) (string, error) {
|
|
resp, err := m.client.Post(ctx, "/memory/broadcast", map[string]string{
|
|
"type": msgType,
|
|
"payload": payload,
|
|
})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
var result struct {
|
|
BroadcastID string `json:"broadcast_id"`
|
|
}
|
|
if err := json.Unmarshal(resp, &result); err != nil {
|
|
return "", NewConnectionError("failed to parse broadcast response", err)
|
|
}
|
|
return result.BroadcastID, nil
|
|
}
|
|
|
|
// TIL creates a "Today I Learned" entry.
|
|
func (m *MemoryAPI) TIL(ctx context.Context, category string, learning string) (*MemoryEntry, error) {
|
|
return m.Log(ctx, &LogMemoryOptions{
|
|
Action: "til",
|
|
Entity: category,
|
|
Details: learning,
|
|
Tags: []string{"til", category},
|
|
})
|
|
}
|
|
|
|
// Stats returns memory statistics.
|
|
func (m *MemoryAPI) Stats(ctx context.Context) (*Stats, error) {
|
|
resp, err := m.client.Get(ctx, "/memory/stats", nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var stats Stats
|
|
if err := json.Unmarshal(resp, &stats); err != nil {
|
|
return nil, NewConnectionError("failed to parse stats response", err)
|
|
}
|
|
return &stats, nil
|
|
}
|
|
|
|
// VerifyChainResult contains the result of a chain verification.
|
|
type VerifyChainResult struct {
|
|
Valid bool `json:"valid"`
|
|
Checked int `json:"checked"`
|
|
}
|
|
|
|
// VerifyChain verifies the hash chain integrity.
|
|
func (m *MemoryAPI) VerifyChain(ctx context.Context, startHash string) (*VerifyChainResult, error) {
|
|
params := url.Values{}
|
|
if startHash != "" {
|
|
params.Set("start", startHash)
|
|
}
|
|
|
|
resp, err := m.client.Get(ctx, "/memory/verify", params)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var result VerifyChainResult
|
|
if err := json.Unmarshal(resp, &result); err != nil {
|
|
return nil, NewConnectionError("failed to parse verify response", err)
|
|
}
|
|
return &result, nil
|
|
}
|