Files
agent-radar 2ed3415fb7
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
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

189 lines
6.4 KiB
Go

package storesqlite
import (
"context"
"database/sql"
"errors"
"fmt"
"strings"
)
func (s *Store) GetSession(
ctx context.Context,
workspaceID string,
agentSessionID string,
) (Session, bool, error) {
if s == nil || s.db == nil {
return Session{}, false, errors.New("workspace database is not initialized")
}
workspaceID = strings.TrimSpace(workspaceID)
agentSessionID = strings.TrimSpace(agentSessionID)
if workspaceID == "" || agentSessionID == "" {
return Session{}, false, nil
}
row := s.db.QueryRowContext(ctx, `
SELECT workspace_id, agent_session_id, session_kind, root_agent_session_id, root_turn_id,
parent_agent_session_id, parent_turn_id, parent_tool_call_id,
origin, agent_target_id, provider, provider_session_id, model,
user_id, settings_json, session_metadata_json, internal_runtime_context_json, cwd,
rail_section_key,
title, message_version, last_event_at_unix_ms,
started_at_unix_ms, ended_at_unix_ms, pinned_at_unix_ms,
created_at_unix_ms, updated_at_unix_ms, active_turn_id
FROM workspace_agent_sessions
WHERE workspace_id = ? AND agent_session_id = ? AND deleted_at_unix_ms = 0
`, workspaceID, agentSessionID)
session, err := scanAgentSession(row)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return Session{}, false, nil
}
return Session{}, false, fmt.Errorf("get workspace agent session: %w", err)
}
railSection, found, err := s.getAgentSessionRailSection(ctx, workspaceID, agentSessionID)
if err != nil {
return Session{}, false, err
}
if !found {
return Session{}, false, fmt.Errorf(
"workspace agent session %q has no rail section",
agentSessionID,
)
}
session.RailSectionKind = railSection.Kind
session.RailProjectPath = railSection.ProjectPath
session.RailSectionKey = railSection.Key
return session, true, nil
}
func (s *Store) SessionDeleted(
ctx context.Context,
workspaceID string,
agentSessionID string,
) (bool, error) {
if s == nil || s.db == nil {
return false, errors.New("workspace database is not initialized")
}
workspaceID = strings.TrimSpace(workspaceID)
agentSessionID = strings.TrimSpace(agentSessionID)
if workspaceID == "" || agentSessionID == "" {
return false, nil
}
var deletedAtUnixMS int64
err := s.db.QueryRowContext(ctx, `
SELECT deleted_at_unix_ms
FROM workspace_agent_sessions
WHERE workspace_id = ? AND agent_session_id = ?
`, workspaceID, agentSessionID).Scan(&deletedAtUnixMS)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return false, nil
}
return false, fmt.Errorf("read workspace agent session tombstone: %w", err)
}
return deletedAtUnixMS > 0, nil
}
func (s *Store) ListSessions(
ctx context.Context,
workspaceID string,
) ([]Session, bool, error) {
if s == nil || s.db == nil {
return nil, false, errors.New("workspace database is not initialized")
}
workspaceID = strings.TrimSpace(workspaceID)
if workspaceID == "" {
return nil, false, nil
}
rows, err := s.db.QueryContext(ctx, `
SELECT workspace_id, agent_session_id, session_kind, root_agent_session_id, root_turn_id,
parent_agent_session_id, parent_turn_id, parent_tool_call_id,
origin, agent_target_id, provider, provider_session_id, model,
user_id, settings_json, session_metadata_json, internal_runtime_context_json, cwd,
rail_section_key,
title, message_version, last_event_at_unix_ms,
started_at_unix_ms, ended_at_unix_ms, pinned_at_unix_ms,
created_at_unix_ms, updated_at_unix_ms, active_turn_id
FROM workspace_agent_sessions
WHERE workspace_id = ? AND session_kind = 'root' AND deleted_at_unix_ms = 0
ORDER BY updated_at_unix_ms DESC, agent_session_id ASC
`, workspaceID)
if err != nil {
return nil, false, fmt.Errorf("list workspace agent sessions: %w", err)
}
defer rows.Close()
sessions := make([]Session, 0)
for rows.Next() {
session, err := scanAgentSession(rows)
if err != nil {
return nil, false, err
}
sessions = append(sessions, session)
}
if err := rows.Err(); err != nil {
return nil, false, fmt.Errorf("iterate workspace agent sessions: %w", err)
}
return sessions, true, nil
}
func (s *Store) ListChildSessions(
ctx context.Context,
workspaceID string,
agentSessionID string,
) ([]Session, error) {
if s == nil || s.db == nil {
return nil, errors.New("workspace database is not initialized")
}
workspaceID = strings.TrimSpace(workspaceID)
agentSessionID = strings.TrimSpace(agentSessionID)
if workspaceID == "" || agentSessionID == "" {
return []Session{}, nil
}
rows, err := s.db.QueryContext(ctx, `
WITH RECURSIVE child_session_ids(agent_session_id) AS (
SELECT agent_session_id
FROM workspace_agent_sessions
WHERE workspace_id = ? AND parent_agent_session_id = ?
AND session_kind = 'child' AND deleted_at_unix_ms = 0
UNION ALL
SELECT child.agent_session_id
FROM workspace_agent_sessions child
INNER JOIN child_session_ids parent
ON child.parent_agent_session_id = parent.agent_session_id
WHERE child.workspace_id = ? AND child.session_kind = 'child'
AND child.deleted_at_unix_ms = 0
)
SELECT session.workspace_id, session.agent_session_id, session.session_kind,
session.root_agent_session_id, session.root_turn_id,
session.parent_agent_session_id, session.parent_turn_id, session.parent_tool_call_id,
session.origin, session.agent_target_id, session.provider, session.provider_session_id, session.model,
session.user_id, session.settings_json, session.session_metadata_json,
session.internal_runtime_context_json, session.cwd, session.rail_section_key,
session.title, session.message_version,
session.last_event_at_unix_ms, session.started_at_unix_ms, session.ended_at_unix_ms,
session.pinned_at_unix_ms, session.created_at_unix_ms, session.updated_at_unix_ms,
session.active_turn_id
FROM workspace_agent_sessions session
INNER JOIN child_session_ids child ON child.agent_session_id = session.agent_session_id
WHERE session.workspace_id = ?
ORDER BY session.created_at_unix_ms ASC, session.agent_session_id ASC
`, workspaceID, agentSessionID, workspaceID, workspaceID)
if err != nil {
return nil, fmt.Errorf("list child workspace agent sessions: %w", err)
}
defer rows.Close()
sessions := make([]Session, 0)
for rows.Next() {
session, err := scanAgentSession(rows)
if err != nil {
return nil, err
}
sessions = append(sessions, session)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate child workspace agent sessions: %w", err)
}
return sessions, nil
}