package postgres import ( "context" "database/sql" ) // ── Single-field helpers (v0.29.0) ────────────────────────────────────── // Moved from handlers/completion.go and handlers/messages.go raw SQL. func (s *ChannelStore) GetAIMode(ctx context.Context, channelID string) (string, error) { var aiMode string err := DB.QueryRowContext(ctx, ` SELECT COALESCE(ai_mode, 'auto') FROM channels WHERE id = $1 `, channelID).Scan(&aiMode) if err != nil { return "auto", err } return aiMode, nil } func (s *ChannelStore) GetTypeAndTeamID(ctx context.Context, channelID string) (string, *string, error) { var channelType string var teamID *string err := DB.QueryRowContext(ctx, ` SELECT COALESCE(type, 'direct'), team_id FROM channels WHERE id = $1 `, channelID).Scan(&channelType, &teamID) return channelType, teamID, err } func (s *ChannelStore) GetSystemPrompt(ctx context.Context, channelID string) (*string, error) { var prompt *string err := DB.QueryRowContext(ctx, ` SELECT system_prompt FROM channels WHERE id = $1 `, channelID).Scan(&prompt) if err == sql.ErrNoRows { return nil, nil } return prompt, err } func (s *ChannelStore) GetDefaultModel(ctx context.Context, channelID string) (*string, error) { var model *string err := DB.QueryRowContext(ctx, ` SELECT model FROM channels WHERE id = $1 `, channelID).Scan(&model) if err == sql.ErrNoRows { return nil, nil } return model, err } func (s *ChannelStore) TouchUpdatedAt(ctx context.Context, channelID string) error { _, err := DB.ExecContext(ctx, `UPDATE channels SET updated_at = NOW() WHERE id = $1`, channelID) return err } func (s *ChannelStore) ListUserParticipantIDs(ctx context.Context, channelID, excludeUserID string) ([]string, error) { rows, err := DB.QueryContext(ctx, ` SELECT participant_id FROM channel_participants WHERE channel_id = $1 AND participant_type = 'user' AND participant_id != $2 `, channelID, excludeUserID) if err != nil { return nil, err } defer rows.Close() var ids []string for rows.Next() { var id string if err := rows.Scan(&id); err != nil { return nil, err } ids = append(ids, id) } if ids == nil { ids = []string{} } return ids, rows.Err() } func (s *ChannelStore) ListPersonaParticipantIDs(ctx context.Context, channelID string) ([]string, error) { rows, err := DB.QueryContext(ctx, ` SELECT participant_id FROM channel_participants WHERE channel_id = $1 AND participant_type = 'persona' ORDER BY created_at `, channelID) if err != nil { return nil, err } defer rows.Close() var ids []string for rows.Next() { var id string if err := rows.Scan(&id); err != nil { return nil, err } ids = append(ids, id) } if ids == nil { ids = []string{} } return ids, rows.Err() } func (s *ChannelStore) GetLeaderPersonaID(ctx context.Context, channelID string) (string, error) { // Try group leader first var leaderID string err := DB.QueryRowContext(ctx, ` SELECT cp.participant_id FROM channel_participants cp JOIN persona_group_members pgm ON pgm.persona_id = cp.participant_id WHERE cp.channel_id = $1 AND cp.participant_type = 'persona' AND pgm.is_leader = true LIMIT 1 `, channelID).Scan(&leaderID) if err == nil && leaderID != "" { return leaderID, nil } // Fallback: first persona participant err = DB.QueryRowContext(ctx, ` SELECT participant_id FROM channel_participants WHERE channel_id = $1 AND participant_type = 'persona' ORDER BY created_at LIMIT 1 `, channelID).Scan(&leaderID) if err == sql.ErrNoRows { return "", nil } return leaderID, err } func (s *ChannelStore) GetWorkflowInfo(ctx context.Context, channelID string) (*string, int, error) { var workflowID *string var currentStage int err := DB.QueryRowContext(ctx, ` SELECT workflow_id, COALESCE(current_stage, 0) FROM channels WHERE id = $1 AND type = 'workflow' `, channelID).Scan(&workflowID, ¤tStage) if err == sql.ErrNoRows { return nil, 0, nil } return workflowID, currentStage, err }