From fe0d93fa04d6fafc1cf3c878f06a46b3703cafab Mon Sep 17 00:00:00 2001 From: Max Date: Fri, 21 Nov 2025 09:34:57 +0800 Subject: [PATCH] Update event field names in tests and types for consistency with API specifications - Changed event field names in tests from "Type", "TraceID", and "Timestamp" to "type", "trace_id", and "timestamp" to align with the updated API format. - Updated struct field tags in types.go to reflect the new naming conventions, ensuring consistency across the codebase and improving JSON serialization. --- openapi/tests/trace/events_test.go | 18 +- openapi/trace/README.md | 293 +++++++++++++++++++++++++++++ trace/types/types.go | 84 ++++----- 3 files changed, 344 insertions(+), 51 deletions(-) create mode 100644 openapi/trace/README.md diff --git a/openapi/tests/trace/events_test.go b/openapi/tests/trace/events_test.go index 66ccd1da..2c3b68a4 100644 --- a/openapi/tests/trace/events_test.go +++ b/openapi/tests/trace/events_test.go @@ -55,7 +55,7 @@ func TestGetEvents(t *testing.T) { for _, e := range events { event, ok := e.(map[string]interface{}) if ok { - eventType, _ := event["Type"].(string) + eventType, _ := event["type"].(string) eventTypes[eventType] = true } } @@ -174,17 +174,17 @@ func TestGetEventsSSE(t *testing.T) { eventTypes := make(map[string]int) for i, event := range events { // Verify required fields - assert.NotNil(t, event["Type"], "Event %d should have Type field", i) - assert.NotNil(t, event["TraceID"], "Event %d should have TraceID field", i) - assert.NotNil(t, event["Timestamp"], "Event %d should have Timestamp field", i) + assert.NotNil(t, event["type"], "Event %d should have type field", i) + assert.NotNil(t, event["trace_id"], "Event %d should have trace_id field", i) + assert.NotNil(t, event["timestamp"], "Event %d should have timestamp field", i) // Verify TraceID matches - if traceID, ok := event["TraceID"].(string); ok { - assert.Equal(t, data.TraceID, traceID, "Event %d TraceID should match", i) + if traceID, ok := event["trace_id"].(string); ok { + assert.Equal(t, data.TraceID, traceID, "Event %d trace_id should match", i) } // Count event types - if eventType, ok := event["Type"].(string); ok { + if eventType, ok := event["type"].(string); ok { eventTypes[eventType]++ } } @@ -200,13 +200,13 @@ func TestGetEventsSSE(t *testing.T) { // Verify event order: init should be first if len(events) > 0 { - firstEventType, _ := events[0]["Type"].(string) + firstEventType, _ := events[0]["type"].(string) assert.Equal(t, "init", firstEventType, "First event should be init") } // Verify complete event is last (before [DONE]) if len(events) > 1 { - lastEventType, _ := events[len(events)-1]["Type"].(string) + lastEventType, _ := events[len(events)-1]["type"].(string) assert.Equal(t, "complete", lastEventType, "Last event should be complete") } } diff --git a/openapi/trace/README.md b/openapi/trace/README.md new file mode 100644 index 00000000..5fb664ba --- /dev/null +++ b/openapi/trace/README.md @@ -0,0 +1,293 @@ +# Trace API + +The Trace API provides endpoints to monitor, retrieve, and stream execution traces. + +**Base URL**: `/v1/trace` +**Auth**: Bearer Token (OAuth2) + +## Endpoints + +| Method | Endpoint | Description | +| :----- | :--------------------------------- | :---------------------------------------------- | +| `GET` | `/traces/:traceID/events` | Stream trace events (SSE) or get event history. | +| `GET` | `/traces/:traceID/info` | Get trace metadata (status, user, time). | +| `GET` | `/traces/:traceID/nodes` | List all execution nodes. | +| `GET` | `/traces/:traceID/nodes/:nodeID` | Get details for a specific node. | +| `GET` | `/traces/:traceID/logs` | List all logs. | +| `GET` | `/traces/:traceID/logs/:nodeID` | List logs for a specific node. | +| `GET` | `/traces/:traceID/spaces` | List memory spaces (metadata only). | +| `GET` | `/traces/:traceID/spaces/:spaceID` | Get space details (includes KV data). | + +--- + +## Events (SSE) + +**Endpoint**: `/traces/:traceID/events?stream=true` +**Format**: Server-Sent Events (SSE) +**Terminator**: `data: [DONE]` + +### Event Envelope + +Each event starts with `event: ` followed by `data: `. + +``` +event: node_start + +data: { + "type": "node_start", + "trace_id": "...", + "node_id": "...", + "space_id": "", + "timestamp": 1763633999330, + "data": { ... } +} +``` + +| Field | Type | Description | +| :---------- | :----- | :---------------------------------------------------- | +| `type` | String | Event type (e.g., `init`, `node_start`, `log_added`). | +| `trace_id` | String | Unique trace identifier. | +| `node_id` | String | (Optional) Associated node ID. | +| `space_id` | String | (Optional) Associated space ID. | +| `timestamp` | Int64 | Event time in milliseconds (Unix epoch). | +| `data` | Object | Event payload, structure varies by `type`. | + +### Event Payloads + +#### 1. `init` + +Trace initialization. + +| Field | Type | Description | +| :----------- | :----- | :-------------------------------------- | +| `trace_id` | String | Trace ID. | +| `agent_name` | String | (Optional) Name of the agent/assistant. | +| `root_node` | Object | (Optional) Preview of the root node. | + +**Example**: + +```json +{ + "type": "init", + "trace_id": "20251120633999366550", + "timestamp": 1763633999329, + "data": { + "trace_id": "20251120633999366550" + } +} +``` + +#### 2. `node_start` + +A node execution has started. + +| Field | Type | Description | +| :------ | :----- | :--------------------------------------------------------------------- | +| `node` | Object | Full node structure (see [Node Structure](#node-structure-in-events)). | +| `nodes` | Array | (Optional) List of nodes if starting in parallel. | + +**Example**: + +```json +{ + "type": "node_start", + "trace_id": "20251120633999366550", + "node_id": "701dybnkuw6a", + "timestamp": 1763633999330, + "data": { + "node": { + "id": "701dybnkuw6a", + "parent_id": "", + "label": "AI Assistant", + "icon": "assistant", + "description": "AI Assistant is processing the request", + "status": "running", + "input": [{ "role": "user", "content": "Hello there" }], + "created_at": 1763633999330, + "start_time": 1763633999330 + } + } +} +``` + +#### 3. `node_complete` + +Node execution completed successfully. + +| Field | Type | Description | +| :--------- | :----- | :---------------------------------- | +| `node_id` | String | ID of the completed node. | +| `status` | String | Always `"success"`. | +| `duration` | Int64 | Execution duration in milliseconds. | +| `end_time` | Int64 | Completion timestamp (ms). | +| `output` | Any | Node execution result. | + +**Example**: + +```json +{ + "type": "node_complete", + "node_id": "ee8e6nendxjx", + "timestamp": 1763634001537, + "data": { + "node_id": "ee8e6nendxjx", + "status": "success", + "duration": 2206, + "end_time": 1763634001537, + "output": { + "content": "Hello! How can I assist you today?", + "role": "assistant" + } + } +} +``` + +#### 4. `node_failed` + +Node execution failed with error. + +| Field | Type | Description | +| :--------- | :----- | :---------------------------------- | +| `node_id` | String | ID of the failed node. | +| `status` | String | Always `"failed"`. | +| `duration` | Int64 | Execution duration in milliseconds. | +| `end_time` | Int64 | Failure timestamp (ms). | +| `error` | String | Error message. | + +#### 5. `log_added` + +New log entry added. + +| Field | Type | Description | +| :---------- | :----- | :------------------------------------------- | +| `Level` | String | Log level: `info`, `debug`, `warn`, `error`. | +| `Message` | String | Log message text. | +| `Data` | Array | Array of structured log data objects. | +| `NodeID` | String | Associated node ID. | +| `Timestamp` | Int64 | Log timestamp (ms). | + +**Example**: + +```json +{ + "type": "log_added", + "node_id": "ee8e6nendxjx", + "timestamp": 1763633999331, + "data": { + "Level": "debug", + "Message": "OpenAI Stream: Starting stream request", + "Data": [{ "message_count": 1 }], + "NodeID": "ee8e6nendxjx", + "Timestamp": 1763633999331 + } +} +``` + +#### 6. `space_created` + +Memory space created. + +**Data**: Full `TraceSpace` object (see [Space Object](#space-object)). + +#### 7. `space_deleted` + +Memory space deleted. + +| Field | Type | Description | +| :--------- | :----- | :----------------------- | +| `space_id` | String | ID of the deleted space. | + +#### 8. `memory_add` / `memory_update` + +Key-value added or updated in a space. + +| Field | Type | Description | +| :----- | :----- | :--------------------- | +| `type` | String | Space ID. | +| `item` | Object | Memory item structure. | + +**MemoryItem Structure**: + +| Field | Type | Description | +| :----------- | :----- | :---------------------------------- | +| `id` | String | Key name. | +| `type` | String | Space ID (same as parent `type`). | +| `title` | String | (Optional) Display title. | +| `content` | Any | The value stored. | +| `timestamp` | Int64 | Operation timestamp (ms). | +| `importance` | String | (Optional) `high`, `medium`, `low`. | + +#### 9. `memory_delete` + +Key-value deleted from a space. + +| Field | Type | Description | +| :--------- | :----- | :------------------------------------- | +| `space_id` | String | Space ID. | +| `key` | String | (Optional) Deleted key name. | +| `cleared` | Bool | (Optional) `true` if all keys cleared. | + +#### 10. `complete` + +Trace execution finished. + +| Field | Type | Description | +| :--------------- | :----- | :------------------------------------------------ | +| `trace_id` | String | Trace ID. | +| `status` | String | Final status: `completed`, `failed`, `cancelled`. | +| `total_duration` | Int64 | Total execution time in milliseconds. | + +**Example**: + +```json +{ + "type": "complete", + "timestamp": 1763634001540, + "data": { + "trace_id": "20251120633999366550", + "status": "completed", + "total_duration": 2210 + } +} +``` + +--- + +## Resource Structures + +### Node Structure (in Events and API) + +When a node appears in events or API responses, it includes: + +| Field | Type | Description | +| :------------ | :----- | :------------------------------------------------------ | +| `id` | String | Unique node ID. | +| `parent_id` | String | ID of the parent node (empty for root). | +| `children` | Array | List of child node objects (usually empty in events). | +| `label` | String | Human-readable name. | +| `icon` | String | UI icon identifier. | +| `description` | String | Detailed description. | +| `status` | String | `pending`, `running`, `completed`, `failed`, `skipped`. | +| `input` | Any | Input arguments. | +| `output` | Any | Execution result (null when starting). | +| `metadata` | Map | Custom metadata (e.g., `{"node_order": 1}`). | +| `created_at` | Int64 | Timestamp (ms). | +| `start_time` | Int64 | Timestamp (ms). | +| `end_time` | Int64 | Timestamp (ms), 0 if not finished. | +| `updated_at` | Int64 | Timestamp (ms). | + +### Space Object + +Represents a memory context/container. + +| Field | Type | Description | +| :------------ | :----- | :---------------------------------------- | +| `id` | String | Unique space ID. | +| `label` | String | Human-readable name. | +| `icon` | String | UI icon identifier. | +| `description` | String | Purpose of the space. | +| `ttl` | Int64 | Time-to-live in seconds (0 = infinite). | +| `metadata` | Map | Custom metadata. | +| `data` | Map | (Detail API only) Key-value pairs stored. | +| `created_at` | Int64 | Timestamp (ms). | +| `updated_at` | Int64 | Timestamp (ms). | diff --git a/trace/types/types.go b/trace/types/types.go index 579c09e3..87fc6a1f 100644 --- a/trace/types/types.go +++ b/trace/types/types.go @@ -37,43 +37,43 @@ const ( // TraceNodeOption defines options for creating a node type TraceNodeOption struct { - Label string // Display label in UI - Icon string // Icon identifier - Description string // Node description - Metadata map[string]any // Additional metadata + Label string `json:"label"` // Display label in UI + Icon string `json:"icon"` // Icon identifier + Description string `json:"description"` // Node description + Metadata map[string]any `json:"metadata,omitempty"` // Additional metadata } // TraceSpaceOption defines options for creating a space type TraceSpaceOption struct { - Label string // Display label in UI - Icon string // Icon identifier - Description string // Space description - TTL int64 // Time to live in seconds (0 = no expiration) - for display/record only - Metadata map[string]any // Additional metadata + Label string `json:"label"` // Display label in UI + Icon string `json:"icon"` // Icon identifier + Description string `json:"description"` // Space description + TTL int64 `json:"ttl"` // Time to live in seconds (0 = no expiration) - for display/record only + Metadata map[string]any `json:"metadata,omitempty"` // Additional metadata } // TraceNode the trace node implementation type TraceNode struct { - ID string // Node ID - ParentID string // Parent node ID - Children []*TraceNode // Child nodes (for tree structure) - TraceNodeOption // Embedded option fields (Label, Icon, Description, Metadata) - Status NodeStatus // Node status (pending, running, completed, failed, skipped) - Input TraceInput // Node input data - Output TraceOutput // Node output data - CreatedAt int64 // Creation timestamp (milliseconds since epoch) - StartTime int64 // Start timestamp (milliseconds since epoch) - EndTime int64 // End timestamp (milliseconds since epoch) - UpdatedAt int64 // Last update timestamp (milliseconds since epoch) + ID string `json:"id"` // Node ID + ParentID string `json:"parent_id"` // Parent node ID + Children []*TraceNode `json:"children"` // Child nodes (for tree structure) + TraceNodeOption `json:",inline"` // Embedded option fields (Label, Icon, Description, Metadata) + Status NodeStatus `json:"status"` // Node status (pending, running, completed, failed, skipped) + Input TraceInput `json:"input,omitempty"` // Node input data + Output TraceOutput `json:"output,omitempty"` // Node output data + CreatedAt int64 `json:"created_at"` // Creation timestamp (milliseconds since epoch) + StartTime int64 `json:"start_time"` // Start timestamp (milliseconds since epoch) + EndTime int64 `json:"end_time"` // End timestamp (milliseconds since epoch) + UpdatedAt int64 `json:"updated_at"` // Last update timestamp (milliseconds since epoch) // Other fields will be added during implementation } // TraceSpace the trace memory space implementation (can add methods for serialization) type TraceSpace struct { - ID string // Space ID - TraceSpaceOption // Embedded option fields (Label, Icon, Description, TTL, Metadata) - CreatedAt int64 // Creation timestamp (milliseconds since epoch) - UpdatedAt int64 // Last update timestamp (milliseconds since epoch) + ID string `json:"id"` // Space ID + TraceSpaceOption `json:",inline"` // Embedded option fields (Label, Icon, Description, TTL, Metadata) + CreatedAt int64 `json:"created_at"` // Creation timestamp (milliseconds since epoch) + UpdatedAt int64 `json:"updated_at"` // Last update timestamp (milliseconds since epoch) // Internal data storage will be managed by implementation } @@ -120,21 +120,21 @@ const ( // TraceUpdate represents a trace update event for subscriptions type TraceUpdate struct { - Type string // Update type (see UpdateType* constants) - TraceID string // Trace ID - NodeID string // Node ID (optional, for node/log updates) - SpaceID string // Space ID (optional, for space updates) - Timestamp int64 // Update timestamp (milliseconds since epoch) - Data any // Update data (payload structures below) + Type string `json:"type"` // Update type (see UpdateType* constants) + TraceID string `json:"trace_id"` // Trace ID + NodeID string `json:"node_id"` // Node ID (optional, for node/log updates) + SpaceID string `json:"space_id"` // Space ID (optional, for space updates) + Timestamp int64 `json:"timestamp"` // Update timestamp (milliseconds since epoch) + Data any `json:"data"` // Update data (payload structures below) } // Event payload structures (matching frontend SSE format) // TraceInitData payload for "init" event type TraceInitData struct { - TraceID string `json:"traceId"` - AgentName string `json:"agentName,omitempty"` - RootNode *TraceNode `json:"rootNode,omitempty"` + TraceID string `json:"trace_id"` + AgentName string `json:"agent_name,omitempty"` + RootNode *TraceNode `json:"root_node,omitempty"` } // NodeStartData payload for "node_start" event @@ -146,18 +146,18 @@ type NodeStartData struct { // NodeCompleteData payload for "node_complete" event type NodeCompleteData struct { - NodeID string `json:"nodeId"` + NodeID string `json:"node_id"` Status CompleteStatus `json:"status"` // "success" or "failed" - EndTime int64 `json:"endTime"` // milliseconds since epoch + EndTime int64 `json:"end_time"` // milliseconds since epoch Duration int64 `json:"duration"` // duration in milliseconds Output TraceOutput `json:"output,omitempty"` } // NodeFailedData payload for "node_failed" event (same as NodeCompleteData but with error) type NodeFailedData struct { - NodeID string `json:"nodeId"` + NodeID string `json:"node_id"` Status CompleteStatus `json:"status"` // "failed" - EndTime int64 `json:"endTime"` // milliseconds since epoch + EndTime int64 `json:"end_time"` // milliseconds since epoch Duration int64 `json:"duration"` // duration in milliseconds Error string `json:"error"` } @@ -180,19 +180,19 @@ type MemoryItem struct { // TraceCompleteData payload for "complete" event type TraceCompleteData struct { - TraceID string `json:"traceId"` - Status TraceStatus `json:"status"` // "completed" - TotalDuration int64 `json:"totalDuration"` // duration in milliseconds + TraceID string `json:"trace_id"` + Status TraceStatus `json:"status"` // "completed" + TotalDuration int64 `json:"total_duration"` // duration in milliseconds } // SpaceDeletedData payload for "space_deleted" event type SpaceDeletedData struct { - SpaceID string `json:"spaceId"` + SpaceID string `json:"space_id"` } // MemoryDeleteData payload for "memory_delete" event type MemoryDeleteData struct { - SpaceID string `json:"spaceId"` + SpaceID string `json:"space_id"` Key string `json:"key,omitempty"` // Empty when clearing all Cleared bool `json:"cleared,omitempty"` // True when clearing all keys }