Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
143 lines
4.3 KiB
Go
143 lines
4.3 KiB
Go
package agentsessionstore
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
|
|
replay "github.com/tutti-os/tutti/packages/agent/session-replay"
|
|
)
|
|
|
|
func TestReportActivityAsSessionUpdatesRejectsDroppedReplayCommitContext(
|
|
t *testing.T,
|
|
) {
|
|
t.Parallel()
|
|
|
|
_, err := ReportActivityAsSessionUpdates(
|
|
context.Background(),
|
|
&captureSessionReporter{},
|
|
ReportActivityInput{
|
|
WorkspaceID: "workspace-1",
|
|
Source: EventSource{
|
|
AgentID: "session-1",
|
|
SessionOrigin: WorkspaceAgentSessionOriginRuntime,
|
|
},
|
|
StatePatches: []WorkspaceAgentStatePatch{{
|
|
AgentSessionID: "session-1",
|
|
}},
|
|
ProviderObservations: []replay.ProviderObservationBatch{{
|
|
RecordingID: "recording-1",
|
|
ConnectionID: "provider-1",
|
|
ChunkSeq: 1,
|
|
UnitIndex: 1,
|
|
}},
|
|
},
|
|
)
|
|
if err == nil ||
|
|
!strings.Contains(err.Error(), "does not support Replay commit context") {
|
|
t.Fatalf("ReportActivityAsSessionUpdates() error = %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSessionMessageDecodesDurableSequenceAsInternalID(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var message WorkspaceAgentSessionMessage
|
|
if err := json.Unmarshal([]byte(`{
|
|
"sequence": 42,
|
|
"agentSessionId": "session-1",
|
|
"messageId": "message-1",
|
|
"role": "assistant",
|
|
"kind": "text",
|
|
"occurredAtUnixMs": 100,
|
|
"version": 7
|
|
}`), &message); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if message.ID != 42 {
|
|
t.Fatalf("ID = %d, want sequence 42", message.ID)
|
|
}
|
|
}
|
|
|
|
func TestSessionMessageUpdateFromActivityUpdateUsesLifecycleTimeBeforeSeq(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
update := SessionMessageUpdateFromActivityUpdate(WorkspaceAgentMessageUpdate{
|
|
MessageID: "message-1",
|
|
Seq: 42,
|
|
TurnID: "turn-1",
|
|
Role: "assistant",
|
|
Kind: "text",
|
|
StartedAtUnixMS: 1717200001000,
|
|
})
|
|
|
|
if update.OccurredAtUnixMS != 1717200001000 {
|
|
t.Fatalf("OccurredAtUnixMS = %d, want lifecycle timestamp", update.OccurredAtUnixMS)
|
|
}
|
|
}
|
|
|
|
func TestReportActivityAsSessionUpdatesRejectsTurnlessMessageUpdate(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
reporter := &captureSessionReporter{}
|
|
_, err := ReportActivityAsSessionUpdates(context.Background(), reporter, ReportActivityInput{
|
|
WorkspaceID: "workspace-1",
|
|
Source: EventSource{
|
|
AgentID: "agent-session-1",
|
|
},
|
|
MessageUpdates: []WorkspaceAgentMessageUpdate{{
|
|
MessageID: "message-1",
|
|
Seq: 42,
|
|
Role: "assistant",
|
|
Kind: "text",
|
|
OccurredAtUnixMS: 1717200001000,
|
|
}},
|
|
})
|
|
|
|
if err == nil {
|
|
t.Fatal("ReportActivityAsSessionUpdates() error = nil, want missing turnId error")
|
|
}
|
|
if !strings.Contains(err.Error(), `message_update "message-1" is missing turnId`) {
|
|
t.Fatalf("ReportActivityAsSessionUpdates() error = %v", err)
|
|
}
|
|
if len(reporter.inputs) != 0 {
|
|
t.Fatalf("ReportSessionMessages calls = %d, want 0", len(reporter.inputs))
|
|
}
|
|
}
|
|
|
|
func TestReportActivityAsSessionUpdatesEncodesSessionAuditWithoutTurn(t *testing.T) {
|
|
t.Parallel()
|
|
reporter := &captureSessionReporter{}
|
|
reply, err := ReportActivityAsSessionUpdates(context.Background(), reporter, ReportActivityInput{
|
|
WorkspaceID: "workspace-1",
|
|
Source: EventSource{AgentID: "agent-session-1", SessionOrigin: WorkspaceAgentSessionOriginRuntime},
|
|
SessionAudits: []WorkspaceAgentSessionAuditUpdate{{
|
|
AuditID: "goal-control:op-1", Role: "user", Content: "/goal clear",
|
|
Payload: map[string]any{"goalControl": true}, OccurredAtUnixMS: 1717200001000,
|
|
}},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("ReportActivityAsSessionUpdates() error = %v", err)
|
|
}
|
|
if reply.AcceptedSessionAuditCount != 1 || len(reporter.inputs) != 1 || len(reporter.inputs[0].Updates) != 1 {
|
|
t.Fatalf("reply=%#v inputs=%#v", reply, reporter.inputs)
|
|
}
|
|
update := reporter.inputs[0].Updates[0]
|
|
if update.Kind != "session_audit" || update.TurnID != "" || update.MessageID != "goal-control:op-1" {
|
|
t.Fatalf("audit compatibility update = %#v", update)
|
|
}
|
|
}
|
|
|
|
func TestDecodeReportActivityJSONPreservesFirstClassSessionAudit(t *testing.T) {
|
|
t.Parallel()
|
|
input, err := DecodeReportActivityJSON([]byte(`{"sessionAudits":[{"auditId":"audit-1","role":"user","content":"/goal clear","occurredAtUnixMs":10}]}`))
|
|
if err != nil {
|
|
t.Fatalf("DecodeReportActivityJSON() error = %v", err)
|
|
}
|
|
if len(input.SessionAudits) != 1 || input.SessionAudits[0].AuditID != "audit-1" {
|
|
t.Fatalf("session audits = %#v", input.SessionAudits)
|
|
}
|
|
}
|