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
93 lines
3.2 KiB
Go
93 lines
3.2 KiB
Go
package storesqlite
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
const maxSessionTurnSummaryPageSize = 100
|
|
|
|
const sessionTurnSummarySelectSQL = `
|
|
SELECT turn_id,
|
|
phase,
|
|
COALESCE(outcome, ''),
|
|
CAST(COALESCE(json_extract(completed_command_json, '$.finalAssistantMessageId'), '') AS TEXT),
|
|
started_at_unix_ms,
|
|
COALESCE(settled_at_unix_ms, 0),
|
|
turn_origin
|
|
FROM workspace_agent_turns INDEXED BY idx_workspace_agent_turns_session_started_desc`
|
|
|
|
// ListSessionTurnSummaries returns a descending, metadata-only page. The
|
|
// query reads one extra row to compute HasMore without counting or loading the
|
|
// remaining history.
|
|
func (s *Store) ListSessionTurnSummaries(ctx context.Context, input ListSessionTurnSummariesInput) (SessionTurnSummaryPage, error) {
|
|
if s == nil || s.db == nil {
|
|
return SessionTurnSummaryPage{}, errors.New("workspace database is not initialized")
|
|
}
|
|
input.WorkspaceID = strings.TrimSpace(input.WorkspaceID)
|
|
input.AgentSessionID = strings.TrimSpace(input.AgentSessionID)
|
|
if input.WorkspaceID == "" || input.AgentSessionID == "" {
|
|
return SessionTurnSummaryPage{}, nil
|
|
}
|
|
if input.Limit < 1 || input.Limit > maxSessionTurnSummaryPageSize {
|
|
return SessionTurnSummaryPage{}, fmt.Errorf("list workspace agent session turn summaries: limit must be between 1 and %d", maxSessionTurnSummaryPageSize)
|
|
}
|
|
|
|
query := sessionTurnSummarySelectSQL + `
|
|
WHERE workspace_id = ? AND agent_session_id = ?
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM workspace_agent_turn_history history
|
|
WHERE history.workspace_id = workspace_agent_turns.workspace_id
|
|
AND history.agent_session_id = workspace_agent_turns.agent_session_id
|
|
AND history.turn_id = workspace_agent_turns.turn_id
|
|
AND history.history_state = 'retracted'
|
|
)`
|
|
args := []any{input.WorkspaceID, input.AgentSessionID}
|
|
if input.Before != nil {
|
|
turnID := strings.TrimSpace(input.Before.TurnID)
|
|
if turnID == "" {
|
|
return SessionTurnSummaryPage{}, errors.New("list workspace agent session turn summaries: before turn id is required")
|
|
}
|
|
query += `
|
|
AND (started_at_unix_ms < ? OR (started_at_unix_ms = ? AND turn_id < ?))`
|
|
args = append(args, input.Before.StartedAtUnixMS, input.Before.StartedAtUnixMS, turnID)
|
|
}
|
|
query += `
|
|
ORDER BY started_at_unix_ms DESC, turn_id DESC
|
|
LIMIT ?`
|
|
args = append(args, input.Limit+1)
|
|
|
|
rows, err := s.db.QueryContext(ctx, query, args...)
|
|
if err != nil {
|
|
return SessionTurnSummaryPage{}, fmt.Errorf("list workspace agent session turn summaries: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
turns := make([]SessionTurnSummary, 0, input.Limit+1)
|
|
for rows.Next() {
|
|
var turn SessionTurnSummary
|
|
if err := rows.Scan(
|
|
&turn.TurnID,
|
|
&turn.Phase,
|
|
&turn.Outcome,
|
|
&turn.FinalAssistantMessageID,
|
|
&turn.StartedAtUnixMS,
|
|
&turn.SettledAtUnixMS,
|
|
&turn.Origin,
|
|
); err != nil {
|
|
return SessionTurnSummaryPage{}, fmt.Errorf("scan workspace agent session turn summary: %w", err)
|
|
}
|
|
turns = append(turns, turn)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return SessionTurnSummaryPage{}, fmt.Errorf("iterate workspace agent session turn summaries: %w", err)
|
|
}
|
|
hasMore := len(turns) > input.Limit
|
|
if hasMore {
|
|
turns = turns[:input.Limit]
|
|
}
|
|
return SessionTurnSummaryPage{Turns: turns, HasMore: hasMore}, nil
|
|
}
|