Skip to content
Merged
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

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package transcript

type TranscriptInformation struct {
ID string `json:"id,omitempty"`
ProjectID string `json:"projectID,omitempty"`
SessionID string `json:"sessionID,omitempty"`
EnvironmentID string `json:"environmentID,omitempty"`
CreatedAt string `json:"createdAt,omitempty"`
UpdatedAt string `json:"updatedAt,omitempty"`
}

// SearchTranscriptsRequest is the request body for the search transcripts API.
type SearchTranscriptsRequest struct {
StartDate string `json:"startDate,omitempty"`
EndDate string `json:"endDate,omitempty"`
SessionID string `json:"sessionID,omitempty"`
EnvironmentID string `json:"environmentID,omitempty"`
}

// SearchTranscriptsResponse is the response from the search transcripts API.
type SearchTranscriptsResponse struct {
Transcripts []TranscriptInformation `json:"transcripts"`
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,73 +14,49 @@ type Turn struct {
StartTime time.Time `json:"startTime"`
}

type Payload struct {
Time int64 `json:"time,omitempty"`
Type string `json:"type,omitempty"`
Payload interface{} `json:"payload,omitempty"`
// GetTranscriptResponse is the wrapper for the v1 get-transcript API response.
type GetTranscriptResponse struct {
Transcript TranscriptDetail `json:"transcript"`
}

type BlockPayload struct {
BlockID string `json:"blockID"`
// TranscriptDetail contains the transcript data from the v1 API.
type TranscriptDetail struct {
ID string `json:"id"`
SessionID string `json:"sessionID"`
ProjectID string `json:"projectID"`
EnvironmentID string `json:"environmentID"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Logs []Log `json:"logs"`
}

type FlowPayload struct {
DiagramID string `json:"diagramID"`
// Log represents a single log entry in the v1 transcript response.
type Log struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}

type DebugPayload struct {
Type string `json:"type,omitempty"`
Message string `json:"message"`
}

type TextPayload struct {
Slate Slate `json:"slate"`
Message string `json:"message"`
Delay int `json:"delay"`
AI bool `json:"ai"`
// LogData is used to partially parse the Data field of a Log entry.
type LogData struct {
Type string `json:"type"`
Payload json.RawMessage `json:"payload,omitempty"`
}

type Slate struct {
ID string `json:"id"`
Content []Content `json:"content"`
MessageDelayMilliseconds int `json:"messageDelayMilliseconds"`
}

type Content struct {
Children []Children `json:"children"`
}

type Children struct {
Text string `json:"text"`
type Payload struct {
Time int64 `json:"time,omitempty"`
Type string `json:"type,omitempty"`
Payload interface{} `json:"payload,omitempty"`
}

type RequestPayload struct {
Type string `json:"type"`
Payload IntentPayload `json:"payload"`
type TextPayload struct {
Message string `json:"message"`
}

type IntentPayload struct {
Query string `json:"query"`
Intent Intent `json:"intent"`
Entities []interface{} `json:"entities"`
Confidence float64 `json:"confidence"`
}

type Intent struct {
Name string `json:"name"`
}

type AIResponseParameters struct {
System string `json:"system"`
Assistant string `json:"assistant"`
Output string `json:"output"`
Model string `json:"model"`
Temperature float64 `json:"temperature"`
MaxTokens int `json:"maxTokens"`
QueryTokens int `json:"queryTokens"`
AnswerTokens int `json:"answerTokens"`
Tokens int `json:"tokens"`
Multiplier float64 `json:"multiplier"`
Query string `json:"query"`
Confidence float64 `json:"confidence"`
}

// GetTextPayload extracts TextPayload from generic Payload
Expand All @@ -104,26 +80,7 @@ func (p Payload) GetTextPayload() (*TextPayload, error) {
return &textPayload, nil
}

func (p Payload) GetRequestPayload() (*RequestPayload, error) {
// Modified condition to accept both "request" and "intent" types
if p.Type != "request" {
return nil, fmt.Errorf("payload type is not 'request' or 'intent', got: %s", p.Type)
}

payloadBytes, err := json.Marshal(p.Payload)
if err != nil {
return nil, fmt.Errorf("failed to marshal request payload: %w", err)
}

var requestPayload RequestPayload
if err := json.Unmarshal(payloadBytes, &requestPayload); err != nil {
return nil, fmt.Errorf("failed to unmarshal request payload: %w", err)
}

return &requestPayload, nil
}

// Add GetIntentPayload method
// GetIntentPayload extracts IntentPayload from generic Payload
func (p Payload) GetIntentPayload() (*IntentPayload, error) {
if p.Type != "intent" {
return nil, fmt.Errorf("payload type is not 'intent', got: %s", p.Type)
Expand Down
19 changes: 19 additions & 0 deletions pkg/transcript/to-test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,25 @@ func TranscriptToTest(transcriptJSON []transcript.Turn, testName, testDescriptio
},
},
})
case "user-text":
userText, _ := turn.Payload.Payload.(string)
agentResponse := findNextAgentTextResponse(transcriptJSON, index)
test.Interactions = append(test.Interactions, tests.Interaction{
ID: uuid.New().String(),
User: tests.User{
Text: userText,
Type: "text",
},
Agent: tests.Agent{
Validate: []tests.Validation{
{
ID: uuid.New().String(),
Type: "equals",
Value: agentResponse,
},
},
},
})
Comment on lines +82 to +100

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Reject invalid user-text payloads instead of silently emitting empty steps.

userText, _ := turn.Payload.Payload.(string) falls back to "" on any shape mismatch, so a bad decode upstream turns into a bogus test case rather than an error.

Proposed fix
 		case "user-text":
-			userText, _ := turn.Payload.Payload.(string)
+			userText, ok := turn.Payload.Payload.(string)
+			if !ok {
+				return tests.Test{}, fmt.Errorf("unexpected user-text payload type %T", turn.Payload.Payload)
+			}
 			agentResponse := findNextAgentTextResponse(transcriptJSON, index)
 			test.Interactions = append(test.Interactions, tests.Interaction{
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case "user-text":
userText, _ := turn.Payload.Payload.(string)
agentResponse := findNextAgentTextResponse(transcriptJSON, index)
test.Interactions = append(test.Interactions, tests.Interaction{
ID: uuid.New().String(),
User: tests.User{
Text: userText,
Type: "text",
},
Agent: tests.Agent{
Validate: []tests.Validation{
{
ID: uuid.New().String(),
Type: "equals",
Value: agentResponse,
},
},
},
})
case "user-text":
userText, ok := turn.Payload.Payload.(string)
if !ok {
return tests.Test{}, fmt.Errorf("unexpected user-text payload type %T", turn.Payload.Payload)
}
agentResponse := findNextAgentTextResponse(transcriptJSON, index)
test.Interactions = append(test.Interactions, tests.Interaction{
ID: uuid.New().String(),
User: tests.User{
Text: userText,
Type: "text",
},
Agent: tests.Agent{
Validate: []tests.Validation{
{
ID: uuid.New().String(),
Type: "equals",
Value: agentResponse,
},
},
},
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/transcript/to-test.go` around lines 82 - 100, In the "user-text" case the
code does a silent type assertion userText, _ := turn.Payload.Payload.(string)
which turns invalid/malformed payloads into empty user steps; update the handler
to perform a checked assertion (userText, ok := turn.Payload.Payload.(string))
and if ok is false return or propagate an error (or log and skip) so invalid
payloads are rejected instead of producing bogus tests; ensure the flow around
findNextAgentTextResponse and the construction of tests.Interaction still uses
the validated userText when ok is true and generate a clear error path when not.

}
}
return test, nil
Expand Down
Loading
Loading