You've already forked agentic-coding-workflow
feat(chat): sqlc queries for conversations/messages/attachments/templates/endpoints/models/usage
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
-- name: InsertAttachment :one
|
||||
INSERT INTO message_attachments (id, user_id, message_id, filename, mime_type, size_bytes, sha256, storage_path)
|
||||
VALUES ($1, $2, NULL, $3, $4, $5, $6, $7)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetAttachment :one
|
||||
SELECT * FROM message_attachments WHERE id = $1;
|
||||
|
||||
-- name: ListAttachmentsForMessage :many
|
||||
SELECT * FROM message_attachments WHERE message_id = $1 ORDER BY created_at ASC;
|
||||
|
||||
-- name: ListOrphanAttachmentsForUser :many
|
||||
SELECT * FROM message_attachments
|
||||
WHERE user_id = $1 AND message_id IS NULL AND id = ANY($2::uuid[]);
|
||||
|
||||
-- name: AttachToMessage :exec
|
||||
UPDATE message_attachments SET message_id = $2 WHERE id = ANY($1::uuid[]);
|
||||
|
||||
-- name: DeleteAttachment :exec
|
||||
DELETE FROM message_attachments WHERE id = $1;
|
||||
|
||||
-- name: ListExpiredOrphans :many
|
||||
SELECT id, storage_path FROM message_attachments
|
||||
WHERE message_id IS NULL AND created_at < NOW() - ($1::interval);
|
||||
|
||||
-- name: ListAttachmentsForSoftDeletedConversations :many
|
||||
SELECT a.id, a.storage_path
|
||||
FROM message_attachments a
|
||||
JOIN messages m ON m.id = a.message_id
|
||||
JOIN conversations c ON c.id = m.conversation_id
|
||||
WHERE c.deleted_at IS NOT NULL
|
||||
AND c.deleted_at < NOW() - ($1::interval);
|
||||
@@ -0,0 +1,28 @@
|
||||
-- name: InsertConversation :one
|
||||
INSERT INTO conversations (id, user_id, project_id, workspace_id, issue_id, model_id, system_prompt, title)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetConversation :one
|
||||
SELECT * FROM conversations WHERE id = $1 AND deleted_at IS NULL;
|
||||
|
||||
-- name: ListConversationsByUser :many
|
||||
SELECT * FROM conversations
|
||||
WHERE user_id = $1 AND deleted_at IS NULL
|
||||
AND ($2::uuid IS NULL OR project_id = $2)
|
||||
AND ($3::uuid IS NULL OR workspace_id = $3)
|
||||
AND ($4::uuid IS NULL OR issue_id = $4)
|
||||
AND ($5::text = '' OR title ILIKE '%' || $5 || '%')
|
||||
ORDER BY updated_at DESC
|
||||
LIMIT $6;
|
||||
|
||||
-- name: UpdateConversationTitle :exec
|
||||
UPDATE conversations SET title = $2, title_generated_at = NOW(), updated_at = NOW()
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: SetConversationTitleManual :exec
|
||||
UPDATE conversations SET title = $2, updated_at = NOW() WHERE id = $1;
|
||||
|
||||
-- name: SoftDeleteConversation :exec
|
||||
UPDATE conversations SET deleted_at = NOW(), updated_at = NOW()
|
||||
WHERE id = $1 AND deleted_at IS NULL;
|
||||
@@ -0,0 +1,21 @@
|
||||
-- name: InsertLLMEndpoint :one
|
||||
INSERT INTO llm_endpoints (id, provider, display_name, base_url, api_key_encrypted, created_by)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetLLMEndpoint :one
|
||||
SELECT * FROM llm_endpoints WHERE id = $1;
|
||||
|
||||
-- name: ListLLMEndpoints :many
|
||||
SELECT * FROM llm_endpoints ORDER BY created_at DESC;
|
||||
|
||||
-- name: UpdateLLMEndpoint :exec
|
||||
UPDATE llm_endpoints
|
||||
SET display_name = COALESCE($2, display_name),
|
||||
base_url = COALESCE($3, base_url),
|
||||
api_key_encrypted = COALESCE($4, api_key_encrypted),
|
||||
updated_at = NOW()
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: DeleteLLMEndpoint :exec
|
||||
DELETE FROM llm_endpoints WHERE id = $1;
|
||||
@@ -0,0 +1,47 @@
|
||||
-- name: InsertMessage :one
|
||||
INSERT INTO messages (conversation_id, role, content, status)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetMessage :one
|
||||
SELECT * FROM messages WHERE id = $1;
|
||||
|
||||
-- name: ListMessagesByConversation :many
|
||||
SELECT * FROM messages
|
||||
WHERE conversation_id = $1
|
||||
AND ($2::bigint = 0 OR id < $2)
|
||||
ORDER BY id DESC
|
||||
LIMIT $3;
|
||||
|
||||
-- name: ListMessagesAscending :many
|
||||
SELECT * FROM messages WHERE conversation_id = $1 ORDER BY id ASC;
|
||||
|
||||
-- name: UpdateMessageOK :exec
|
||||
UPDATE messages
|
||||
SET content = $2, thinking = $3,
|
||||
prompt_tokens = $4, completion_tokens = $5, thinking_tokens = $6,
|
||||
status = 'ok', updated_at = NOW()
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: UpdateMessageError :exec
|
||||
UPDATE messages
|
||||
SET status = 'error', error_message = $2, updated_at = NOW()
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: UpdateMessageCancelled :exec
|
||||
UPDATE messages
|
||||
SET status = 'cancelled', updated_at = NOW()
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: DeleteMessage :exec
|
||||
DELETE FROM messages WHERE id = $1;
|
||||
|
||||
-- name: GetFirstUserMessage :one
|
||||
SELECT * FROM messages
|
||||
WHERE conversation_id = $1 AND role = 'user'
|
||||
ORDER BY id ASC LIMIT 1;
|
||||
|
||||
-- name: MarkPendingAsErrorOnStartup :exec
|
||||
UPDATE messages
|
||||
SET status = 'error', error_message = 'server restart', updated_at = NOW()
|
||||
WHERE status = 'pending';
|
||||
@@ -0,0 +1,37 @@
|
||||
-- name: InsertLLMModel :one
|
||||
INSERT INTO llm_models (
|
||||
id, endpoint_id, model_id, display_name, capabilities,
|
||||
context_window, max_output_tokens,
|
||||
prompt_price_per_million_usd, completion_price_per_million_usd, thinking_price_per_million_usd,
|
||||
is_title_generator, enabled, sort_order
|
||||
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetLLMModel :one
|
||||
SELECT * FROM llm_models WHERE id = $1;
|
||||
|
||||
-- name: GetTitleGeneratorModel :one
|
||||
SELECT * FROM llm_models WHERE is_title_generator = true AND enabled = true LIMIT 1;
|
||||
|
||||
-- name: ListLLMModels :many
|
||||
SELECT * FROM llm_models
|
||||
WHERE ($1::boolean = false) OR enabled = true
|
||||
ORDER BY sort_order, display_name;
|
||||
|
||||
-- name: UpdateLLMModel :exec
|
||||
UPDATE llm_models
|
||||
SET display_name = COALESCE($2, display_name),
|
||||
capabilities = COALESCE($3, capabilities),
|
||||
context_window = COALESCE($4, context_window),
|
||||
max_output_tokens = COALESCE($5, max_output_tokens),
|
||||
prompt_price_per_million_usd = COALESCE($6, prompt_price_per_million_usd),
|
||||
completion_price_per_million_usd = COALESCE($7, completion_price_per_million_usd),
|
||||
thinking_price_per_million_usd = COALESCE($8, thinking_price_per_million_usd),
|
||||
is_title_generator = COALESCE($9, is_title_generator),
|
||||
enabled = COALESCE($10, enabled),
|
||||
sort_order = COALESCE($11, sort_order),
|
||||
updated_at = NOW()
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: DeleteLLMModel :exec
|
||||
DELETE FROM llm_models WHERE id = $1;
|
||||
@@ -0,0 +1,19 @@
|
||||
-- name: InsertPromptTemplate :one
|
||||
INSERT INTO prompt_templates (id, name, content, scope, owner_id)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetPromptTemplate :one
|
||||
SELECT * FROM prompt_templates WHERE id = $1;
|
||||
|
||||
-- name: ListPromptTemplatesForUser :many
|
||||
SELECT * FROM prompt_templates
|
||||
WHERE scope = 'system' OR (scope = 'user' AND owner_id = $1)
|
||||
ORDER BY scope, name;
|
||||
|
||||
-- name: UpdatePromptTemplate :exec
|
||||
UPDATE prompt_templates SET name = $2, content = $3, updated_at = NOW()
|
||||
WHERE id = $1;
|
||||
|
||||
-- name: DeletePromptTemplate :exec
|
||||
DELETE FROM prompt_templates WHERE id = $1;
|
||||
@@ -0,0 +1,49 @@
|
||||
-- name: InsertUsage :exec
|
||||
INSERT INTO llm_usage (
|
||||
conversation_id, message_id, user_id, endpoint_id, model_id,
|
||||
prompt_tokens, completion_tokens, thinking_tokens, cost_usd
|
||||
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9);
|
||||
|
||||
-- name: SummarizeUsageByUser :many
|
||||
SELECT user_id,
|
||||
SUM(prompt_tokens)::int AS prompt_tokens,
|
||||
SUM(completion_tokens)::int AS completion_tokens,
|
||||
SUM(thinking_tokens)::int AS thinking_tokens,
|
||||
SUM(cost_usd)::numeric AS cost_usd
|
||||
FROM llm_usage
|
||||
WHERE created_at >= $1 AND created_at < $2
|
||||
GROUP BY user_id
|
||||
ORDER BY cost_usd DESC;
|
||||
|
||||
-- name: SummarizeUsageByModel :many
|
||||
SELECT model_id,
|
||||
SUM(prompt_tokens)::int AS prompt_tokens,
|
||||
SUM(completion_tokens)::int AS completion_tokens,
|
||||
SUM(thinking_tokens)::int AS thinking_tokens,
|
||||
SUM(cost_usd)::numeric AS cost_usd
|
||||
FROM llm_usage
|
||||
WHERE created_at >= $1 AND created_at < $2
|
||||
GROUP BY model_id
|
||||
ORDER BY cost_usd DESC;
|
||||
|
||||
-- name: SummarizeUsageByDay :many
|
||||
SELECT date_trunc('day', created_at) AS day,
|
||||
SUM(prompt_tokens)::int AS prompt_tokens,
|
||||
SUM(completion_tokens)::int AS completion_tokens,
|
||||
SUM(thinking_tokens)::int AS thinking_tokens,
|
||||
SUM(cost_usd)::numeric AS cost_usd
|
||||
FROM llm_usage
|
||||
WHERE created_at >= $1 AND created_at < $2
|
||||
GROUP BY day
|
||||
ORDER BY day;
|
||||
|
||||
-- name: SummarizeUserDaily :many
|
||||
SELECT date_trunc('day', created_at) AS day,
|
||||
SUM(prompt_tokens)::int AS prompt_tokens,
|
||||
SUM(completion_tokens)::int AS completion_tokens,
|
||||
SUM(thinking_tokens)::int AS thinking_tokens,
|
||||
SUM(cost_usd)::numeric AS cost_usd
|
||||
FROM llm_usage
|
||||
WHERE user_id = $1 AND created_at >= $2 AND created_at < $3
|
||||
GROUP BY day
|
||||
ORDER BY day;
|
||||
@@ -0,0 +1,235 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: attachments.sql
|
||||
|
||||
package chatsqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const attachToMessage = `-- name: AttachToMessage :exec
|
||||
UPDATE message_attachments SET message_id = $2 WHERE id = ANY($1::uuid[])
|
||||
`
|
||||
|
||||
type AttachToMessageParams struct {
|
||||
Column1 []pgtype.UUID `json:"column_1"`
|
||||
MessageID *int64 `json:"message_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) AttachToMessage(ctx context.Context, arg AttachToMessageParams) error {
|
||||
_, err := q.db.Exec(ctx, attachToMessage, arg.Column1, arg.MessageID)
|
||||
return err
|
||||
}
|
||||
|
||||
const deleteAttachment = `-- name: DeleteAttachment :exec
|
||||
DELETE FROM message_attachments WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteAttachment(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, deleteAttachment, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getAttachment = `-- name: GetAttachment :one
|
||||
SELECT id, user_id, message_id, filename, mime_type, size_bytes, sha256, storage_path, created_at FROM message_attachments WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetAttachment(ctx context.Context, id pgtype.UUID) (MessageAttachment, error) {
|
||||
row := q.db.QueryRow(ctx, getAttachment, id)
|
||||
var i MessageAttachment
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.MessageID,
|
||||
&i.Filename,
|
||||
&i.MimeType,
|
||||
&i.SizeBytes,
|
||||
&i.Sha256,
|
||||
&i.StoragePath,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertAttachment = `-- name: InsertAttachment :one
|
||||
INSERT INTO message_attachments (id, user_id, message_id, filename, mime_type, size_bytes, sha256, storage_path)
|
||||
VALUES ($1, $2, NULL, $3, $4, $5, $6, $7)
|
||||
RETURNING id, user_id, message_id, filename, mime_type, size_bytes, sha256, storage_path, created_at
|
||||
`
|
||||
|
||||
type InsertAttachmentParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
Filename string `json:"filename"`
|
||||
MimeType string `json:"mime_type"`
|
||||
SizeBytes int64 `json:"size_bytes"`
|
||||
Sha256 string `json:"sha256"`
|
||||
StoragePath string `json:"storage_path"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertAttachment(ctx context.Context, arg InsertAttachmentParams) (MessageAttachment, error) {
|
||||
row := q.db.QueryRow(ctx, insertAttachment,
|
||||
arg.ID,
|
||||
arg.UserID,
|
||||
arg.Filename,
|
||||
arg.MimeType,
|
||||
arg.SizeBytes,
|
||||
arg.Sha256,
|
||||
arg.StoragePath,
|
||||
)
|
||||
var i MessageAttachment
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.MessageID,
|
||||
&i.Filename,
|
||||
&i.MimeType,
|
||||
&i.SizeBytes,
|
||||
&i.Sha256,
|
||||
&i.StoragePath,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listAttachmentsForMessage = `-- name: ListAttachmentsForMessage :many
|
||||
SELECT id, user_id, message_id, filename, mime_type, size_bytes, sha256, storage_path, created_at FROM message_attachments WHERE message_id = $1 ORDER BY created_at ASC
|
||||
`
|
||||
|
||||
func (q *Queries) ListAttachmentsForMessage(ctx context.Context, messageID *int64) ([]MessageAttachment, error) {
|
||||
rows, err := q.db.Query(ctx, listAttachmentsForMessage, messageID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []MessageAttachment
|
||||
for rows.Next() {
|
||||
var i MessageAttachment
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.MessageID,
|
||||
&i.Filename,
|
||||
&i.MimeType,
|
||||
&i.SizeBytes,
|
||||
&i.Sha256,
|
||||
&i.StoragePath,
|
||||
&i.CreatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listAttachmentsForSoftDeletedConversations = `-- name: ListAttachmentsForSoftDeletedConversations :many
|
||||
SELECT a.id, a.storage_path
|
||||
FROM message_attachments a
|
||||
JOIN messages m ON m.id = a.message_id
|
||||
JOIN conversations c ON c.id = m.conversation_id
|
||||
WHERE c.deleted_at IS NOT NULL
|
||||
AND c.deleted_at < NOW() - ($1::interval)
|
||||
`
|
||||
|
||||
type ListAttachmentsForSoftDeletedConversationsRow struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
StoragePath string `json:"storage_path"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListAttachmentsForSoftDeletedConversations(ctx context.Context, dollar_1 pgtype.Interval) ([]ListAttachmentsForSoftDeletedConversationsRow, error) {
|
||||
rows, err := q.db.Query(ctx, listAttachmentsForSoftDeletedConversations, dollar_1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListAttachmentsForSoftDeletedConversationsRow
|
||||
for rows.Next() {
|
||||
var i ListAttachmentsForSoftDeletedConversationsRow
|
||||
if err := rows.Scan(&i.ID, &i.StoragePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listExpiredOrphans = `-- name: ListExpiredOrphans :many
|
||||
SELECT id, storage_path FROM message_attachments
|
||||
WHERE message_id IS NULL AND created_at < NOW() - ($1::interval)
|
||||
`
|
||||
|
||||
type ListExpiredOrphansRow struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
StoragePath string `json:"storage_path"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListExpiredOrphans(ctx context.Context, dollar_1 pgtype.Interval) ([]ListExpiredOrphansRow, error) {
|
||||
rows, err := q.db.Query(ctx, listExpiredOrphans, dollar_1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListExpiredOrphansRow
|
||||
for rows.Next() {
|
||||
var i ListExpiredOrphansRow
|
||||
if err := rows.Scan(&i.ID, &i.StoragePath); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listOrphanAttachmentsForUser = `-- name: ListOrphanAttachmentsForUser :many
|
||||
SELECT id, user_id, message_id, filename, mime_type, size_bytes, sha256, storage_path, created_at FROM message_attachments
|
||||
WHERE user_id = $1 AND message_id IS NULL AND id = ANY($2::uuid[])
|
||||
`
|
||||
|
||||
type ListOrphanAttachmentsForUserParams struct {
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
Column2 []pgtype.UUID `json:"column_2"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListOrphanAttachmentsForUser(ctx context.Context, arg ListOrphanAttachmentsForUserParams) ([]MessageAttachment, error) {
|
||||
rows, err := q.db.Query(ctx, listOrphanAttachmentsForUser, arg.UserID, arg.Column2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []MessageAttachment
|
||||
for rows.Next() {
|
||||
var i MessageAttachment
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.MessageID,
|
||||
&i.Filename,
|
||||
&i.MimeType,
|
||||
&i.SizeBytes,
|
||||
&i.Sha256,
|
||||
&i.StoragePath,
|
||||
&i.CreatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: conversations.sql
|
||||
|
||||
package chatsqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const getConversation = `-- name: GetConversation :one
|
||||
SELECT id, user_id, project_id, workspace_id, issue_id, model_id, system_prompt, title, title_generated_at, created_at, updated_at, deleted_at FROM conversations WHERE id = $1 AND deleted_at IS NULL
|
||||
`
|
||||
|
||||
func (q *Queries) GetConversation(ctx context.Context, id pgtype.UUID) (Conversation, error) {
|
||||
row := q.db.QueryRow(ctx, getConversation, id)
|
||||
var i Conversation
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.ProjectID,
|
||||
&i.WorkspaceID,
|
||||
&i.IssueID,
|
||||
&i.ModelID,
|
||||
&i.SystemPrompt,
|
||||
&i.Title,
|
||||
&i.TitleGeneratedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertConversation = `-- name: InsertConversation :one
|
||||
INSERT INTO conversations (id, user_id, project_id, workspace_id, issue_id, model_id, system_prompt, title)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING id, user_id, project_id, workspace_id, issue_id, model_id, system_prompt, title, title_generated_at, created_at, updated_at, deleted_at
|
||||
`
|
||||
|
||||
type InsertConversationParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
ProjectID pgtype.UUID `json:"project_id"`
|
||||
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
||||
IssueID pgtype.UUID `json:"issue_id"`
|
||||
ModelID pgtype.UUID `json:"model_id"`
|
||||
SystemPrompt string `json:"system_prompt"`
|
||||
Title *string `json:"title"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertConversation(ctx context.Context, arg InsertConversationParams) (Conversation, error) {
|
||||
row := q.db.QueryRow(ctx, insertConversation,
|
||||
arg.ID,
|
||||
arg.UserID,
|
||||
arg.ProjectID,
|
||||
arg.WorkspaceID,
|
||||
arg.IssueID,
|
||||
arg.ModelID,
|
||||
arg.SystemPrompt,
|
||||
arg.Title,
|
||||
)
|
||||
var i Conversation
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.ProjectID,
|
||||
&i.WorkspaceID,
|
||||
&i.IssueID,
|
||||
&i.ModelID,
|
||||
&i.SystemPrompt,
|
||||
&i.Title,
|
||||
&i.TitleGeneratedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listConversationsByUser = `-- name: ListConversationsByUser :many
|
||||
SELECT id, user_id, project_id, workspace_id, issue_id, model_id, system_prompt, title, title_generated_at, created_at, updated_at, deleted_at FROM conversations
|
||||
WHERE user_id = $1 AND deleted_at IS NULL
|
||||
AND ($2::uuid IS NULL OR project_id = $2)
|
||||
AND ($3::uuid IS NULL OR workspace_id = $3)
|
||||
AND ($4::uuid IS NULL OR issue_id = $4)
|
||||
AND ($5::text = '' OR title ILIKE '%' || $5 || '%')
|
||||
ORDER BY updated_at DESC
|
||||
LIMIT $6
|
||||
`
|
||||
|
||||
type ListConversationsByUserParams struct {
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
Column2 pgtype.UUID `json:"column_2"`
|
||||
Column3 pgtype.UUID `json:"column_3"`
|
||||
Column4 pgtype.UUID `json:"column_4"`
|
||||
Column5 string `json:"column_5"`
|
||||
Limit int32 `json:"limit"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListConversationsByUser(ctx context.Context, arg ListConversationsByUserParams) ([]Conversation, error) {
|
||||
rows, err := q.db.Query(ctx, listConversationsByUser,
|
||||
arg.UserID,
|
||||
arg.Column2,
|
||||
arg.Column3,
|
||||
arg.Column4,
|
||||
arg.Column5,
|
||||
arg.Limit,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Conversation
|
||||
for rows.Next() {
|
||||
var i Conversation
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.UserID,
|
||||
&i.ProjectID,
|
||||
&i.WorkspaceID,
|
||||
&i.IssueID,
|
||||
&i.ModelID,
|
||||
&i.SystemPrompt,
|
||||
&i.Title,
|
||||
&i.TitleGeneratedAt,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const setConversationTitleManual = `-- name: SetConversationTitleManual :exec
|
||||
UPDATE conversations SET title = $2, updated_at = NOW() WHERE id = $1
|
||||
`
|
||||
|
||||
type SetConversationTitleManualParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Title *string `json:"title"`
|
||||
}
|
||||
|
||||
func (q *Queries) SetConversationTitleManual(ctx context.Context, arg SetConversationTitleManualParams) error {
|
||||
_, err := q.db.Exec(ctx, setConversationTitleManual, arg.ID, arg.Title)
|
||||
return err
|
||||
}
|
||||
|
||||
const softDeleteConversation = `-- name: SoftDeleteConversation :exec
|
||||
UPDATE conversations SET deleted_at = NOW(), updated_at = NOW()
|
||||
WHERE id = $1 AND deleted_at IS NULL
|
||||
`
|
||||
|
||||
func (q *Queries) SoftDeleteConversation(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, softDeleteConversation, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateConversationTitle = `-- name: UpdateConversationTitle :exec
|
||||
UPDATE conversations SET title = $2, title_generated_at = NOW(), updated_at = NOW()
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateConversationTitleParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Title *string `json:"title"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateConversationTitle(ctx context.Context, arg UpdateConversationTitleParams) error {
|
||||
_, err := q.db.Exec(ctx, updateConversationTitle, arg.ID, arg.Title)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package chatsqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
|
||||
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
|
||||
QueryRow(context.Context, string, ...interface{}) pgx.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: endpoints.sql
|
||||
|
||||
package chatsqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const deleteLLMEndpoint = `-- name: DeleteLLMEndpoint :exec
|
||||
DELETE FROM llm_endpoints WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteLLMEndpoint(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, deleteLLMEndpoint, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getLLMEndpoint = `-- name: GetLLMEndpoint :one
|
||||
SELECT id, provider, display_name, base_url, api_key_encrypted, created_by, created_at, updated_at FROM llm_endpoints WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetLLMEndpoint(ctx context.Context, id pgtype.UUID) (LlmEndpoint, error) {
|
||||
row := q.db.QueryRow(ctx, getLLMEndpoint, id)
|
||||
var i LlmEndpoint
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Provider,
|
||||
&i.DisplayName,
|
||||
&i.BaseUrl,
|
||||
&i.ApiKeyEncrypted,
|
||||
&i.CreatedBy,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertLLMEndpoint = `-- name: InsertLLMEndpoint :one
|
||||
INSERT INTO llm_endpoints (id, provider, display_name, base_url, api_key_encrypted, created_by)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING id, provider, display_name, base_url, api_key_encrypted, created_by, created_at, updated_at
|
||||
`
|
||||
|
||||
type InsertLLMEndpointParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Provider string `json:"provider"`
|
||||
DisplayName string `json:"display_name"`
|
||||
BaseUrl string `json:"base_url"`
|
||||
ApiKeyEncrypted []byte `json:"api_key_encrypted"`
|
||||
CreatedBy pgtype.UUID `json:"created_by"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertLLMEndpoint(ctx context.Context, arg InsertLLMEndpointParams) (LlmEndpoint, error) {
|
||||
row := q.db.QueryRow(ctx, insertLLMEndpoint,
|
||||
arg.ID,
|
||||
arg.Provider,
|
||||
arg.DisplayName,
|
||||
arg.BaseUrl,
|
||||
arg.ApiKeyEncrypted,
|
||||
arg.CreatedBy,
|
||||
)
|
||||
var i LlmEndpoint
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Provider,
|
||||
&i.DisplayName,
|
||||
&i.BaseUrl,
|
||||
&i.ApiKeyEncrypted,
|
||||
&i.CreatedBy,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listLLMEndpoints = `-- name: ListLLMEndpoints :many
|
||||
SELECT id, provider, display_name, base_url, api_key_encrypted, created_by, created_at, updated_at FROM llm_endpoints ORDER BY created_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListLLMEndpoints(ctx context.Context) ([]LlmEndpoint, error) {
|
||||
rows, err := q.db.Query(ctx, listLLMEndpoints)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []LlmEndpoint
|
||||
for rows.Next() {
|
||||
var i LlmEndpoint
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Provider,
|
||||
&i.DisplayName,
|
||||
&i.BaseUrl,
|
||||
&i.ApiKeyEncrypted,
|
||||
&i.CreatedBy,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateLLMEndpoint = `-- name: UpdateLLMEndpoint :exec
|
||||
UPDATE llm_endpoints
|
||||
SET display_name = COALESCE($2, display_name),
|
||||
base_url = COALESCE($3, base_url),
|
||||
api_key_encrypted = COALESCE($4, api_key_encrypted),
|
||||
updated_at = NOW()
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateLLMEndpointParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
DisplayName string `json:"display_name"`
|
||||
BaseUrl string `json:"base_url"`
|
||||
ApiKeyEncrypted []byte `json:"api_key_encrypted"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateLLMEndpoint(ctx context.Context, arg UpdateLLMEndpointParams) error {
|
||||
_, err := q.db.Exec(ctx, updateLLMEndpoint,
|
||||
arg.ID,
|
||||
arg.DisplayName,
|
||||
arg.BaseUrl,
|
||||
arg.ApiKeyEncrypted,
|
||||
)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: messages.sql
|
||||
|
||||
package chatsqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const deleteMessage = `-- name: DeleteMessage :exec
|
||||
DELETE FROM messages WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteMessage(ctx context.Context, id int64) error {
|
||||
_, err := q.db.Exec(ctx, deleteMessage, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getFirstUserMessage = `-- name: GetFirstUserMessage :one
|
||||
SELECT id, conversation_id, role, content, thinking, tool_calls, status, error_message, prompt_tokens, completion_tokens, thinking_tokens, created_at, updated_at FROM messages
|
||||
WHERE conversation_id = $1 AND role = 'user'
|
||||
ORDER BY id ASC LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetFirstUserMessage(ctx context.Context, conversationID pgtype.UUID) (Message, error) {
|
||||
row := q.db.QueryRow(ctx, getFirstUserMessage, conversationID)
|
||||
var i Message
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ConversationID,
|
||||
&i.Role,
|
||||
&i.Content,
|
||||
&i.Thinking,
|
||||
&i.ToolCalls,
|
||||
&i.Status,
|
||||
&i.ErrorMessage,
|
||||
&i.PromptTokens,
|
||||
&i.CompletionTokens,
|
||||
&i.ThinkingTokens,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getMessage = `-- name: GetMessage :one
|
||||
SELECT id, conversation_id, role, content, thinking, tool_calls, status, error_message, prompt_tokens, completion_tokens, thinking_tokens, created_at, updated_at FROM messages WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetMessage(ctx context.Context, id int64) (Message, error) {
|
||||
row := q.db.QueryRow(ctx, getMessage, id)
|
||||
var i Message
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ConversationID,
|
||||
&i.Role,
|
||||
&i.Content,
|
||||
&i.Thinking,
|
||||
&i.ToolCalls,
|
||||
&i.Status,
|
||||
&i.ErrorMessage,
|
||||
&i.PromptTokens,
|
||||
&i.CompletionTokens,
|
||||
&i.ThinkingTokens,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertMessage = `-- name: InsertMessage :one
|
||||
INSERT INTO messages (conversation_id, role, content, status)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING id, conversation_id, role, content, thinking, tool_calls, status, error_message, prompt_tokens, completion_tokens, thinking_tokens, created_at, updated_at
|
||||
`
|
||||
|
||||
type InsertMessageParams struct {
|
||||
ConversationID pgtype.UUID `json:"conversation_id"`
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertMessage(ctx context.Context, arg InsertMessageParams) (Message, error) {
|
||||
row := q.db.QueryRow(ctx, insertMessage,
|
||||
arg.ConversationID,
|
||||
arg.Role,
|
||||
arg.Content,
|
||||
arg.Status,
|
||||
)
|
||||
var i Message
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.ConversationID,
|
||||
&i.Role,
|
||||
&i.Content,
|
||||
&i.Thinking,
|
||||
&i.ToolCalls,
|
||||
&i.Status,
|
||||
&i.ErrorMessage,
|
||||
&i.PromptTokens,
|
||||
&i.CompletionTokens,
|
||||
&i.ThinkingTokens,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listMessagesAscending = `-- name: ListMessagesAscending :many
|
||||
SELECT id, conversation_id, role, content, thinking, tool_calls, status, error_message, prompt_tokens, completion_tokens, thinking_tokens, created_at, updated_at FROM messages WHERE conversation_id = $1 ORDER BY id ASC
|
||||
`
|
||||
|
||||
func (q *Queries) ListMessagesAscending(ctx context.Context, conversationID pgtype.UUID) ([]Message, error) {
|
||||
rows, err := q.db.Query(ctx, listMessagesAscending, conversationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Message
|
||||
for rows.Next() {
|
||||
var i Message
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ConversationID,
|
||||
&i.Role,
|
||||
&i.Content,
|
||||
&i.Thinking,
|
||||
&i.ToolCalls,
|
||||
&i.Status,
|
||||
&i.ErrorMessage,
|
||||
&i.PromptTokens,
|
||||
&i.CompletionTokens,
|
||||
&i.ThinkingTokens,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listMessagesByConversation = `-- name: ListMessagesByConversation :many
|
||||
SELECT id, conversation_id, role, content, thinking, tool_calls, status, error_message, prompt_tokens, completion_tokens, thinking_tokens, created_at, updated_at FROM messages
|
||||
WHERE conversation_id = $1
|
||||
AND ($2::bigint = 0 OR id < $2)
|
||||
ORDER BY id DESC
|
||||
LIMIT $3
|
||||
`
|
||||
|
||||
type ListMessagesByConversationParams struct {
|
||||
ConversationID pgtype.UUID `json:"conversation_id"`
|
||||
Column2 int64 `json:"column_2"`
|
||||
Limit int32 `json:"limit"`
|
||||
}
|
||||
|
||||
func (q *Queries) ListMessagesByConversation(ctx context.Context, arg ListMessagesByConversationParams) ([]Message, error) {
|
||||
rows, err := q.db.Query(ctx, listMessagesByConversation, arg.ConversationID, arg.Column2, arg.Limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Message
|
||||
for rows.Next() {
|
||||
var i Message
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.ConversationID,
|
||||
&i.Role,
|
||||
&i.Content,
|
||||
&i.Thinking,
|
||||
&i.ToolCalls,
|
||||
&i.Status,
|
||||
&i.ErrorMessage,
|
||||
&i.PromptTokens,
|
||||
&i.CompletionTokens,
|
||||
&i.ThinkingTokens,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const markPendingAsErrorOnStartup = `-- name: MarkPendingAsErrorOnStartup :exec
|
||||
UPDATE messages
|
||||
SET status = 'error', error_message = 'server restart', updated_at = NOW()
|
||||
WHERE status = 'pending'
|
||||
`
|
||||
|
||||
func (q *Queries) MarkPendingAsErrorOnStartup(ctx context.Context) error {
|
||||
_, err := q.db.Exec(ctx, markPendingAsErrorOnStartup)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateMessageCancelled = `-- name: UpdateMessageCancelled :exec
|
||||
UPDATE messages
|
||||
SET status = 'cancelled', updated_at = NOW()
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) UpdateMessageCancelled(ctx context.Context, id int64) error {
|
||||
_, err := q.db.Exec(ctx, updateMessageCancelled, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateMessageError = `-- name: UpdateMessageError :exec
|
||||
UPDATE messages
|
||||
SET status = 'error', error_message = $2, updated_at = NOW()
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateMessageErrorParams struct {
|
||||
ID int64 `json:"id"`
|
||||
ErrorMessage *string `json:"error_message"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateMessageError(ctx context.Context, arg UpdateMessageErrorParams) error {
|
||||
_, err := q.db.Exec(ctx, updateMessageError, arg.ID, arg.ErrorMessage)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateMessageOK = `-- name: UpdateMessageOK :exec
|
||||
UPDATE messages
|
||||
SET content = $2, thinking = $3,
|
||||
prompt_tokens = $4, completion_tokens = $5, thinking_tokens = $6,
|
||||
status = 'ok', updated_at = NOW()
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateMessageOKParams struct {
|
||||
ID int64 `json:"id"`
|
||||
Content string `json:"content"`
|
||||
Thinking *string `json:"thinking"`
|
||||
PromptTokens *int32 `json:"prompt_tokens"`
|
||||
CompletionTokens *int32 `json:"completion_tokens"`
|
||||
ThinkingTokens *int32 `json:"thinking_tokens"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateMessageOK(ctx context.Context, arg UpdateMessageOKParams) error {
|
||||
_, err := q.db.Exec(ctx, updateMessageOK,
|
||||
arg.ID,
|
||||
arg.Content,
|
||||
arg.Thinking,
|
||||
arg.PromptTokens,
|
||||
arg.CompletionTokens,
|
||||
arg.ThinkingTokens,
|
||||
)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package chatsqlc
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type AuditLog struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
Action string `json:"action"`
|
||||
TargetType *string `json:"target_type"`
|
||||
TargetID *string `json:"target_id"`
|
||||
Ip *netip.Addr `json:"ip"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
}
|
||||
|
||||
type Conversation struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
ProjectID pgtype.UUID `json:"project_id"`
|
||||
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
||||
IssueID pgtype.UUID `json:"issue_id"`
|
||||
ModelID pgtype.UUID `json:"model_id"`
|
||||
SystemPrompt string `json:"system_prompt"`
|
||||
Title *string `json:"title"`
|
||||
TitleGeneratedAt pgtype.Timestamptz `json:"title_generated_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
DeletedAt pgtype.Timestamptz `json:"deleted_at"`
|
||||
}
|
||||
|
||||
type GitCredential struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
||||
Kind string `json:"kind"`
|
||||
Username *string `json:"username"`
|
||||
EncryptedSecret []byte `json:"encrypted_secret"`
|
||||
Fingerprint *string `json:"fingerprint"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Issue struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
ProjectID pgtype.UUID `json:"project_id"`
|
||||
RequirementID pgtype.UUID `json:"requirement_id"`
|
||||
Number int32 `json:"number"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Status string `json:"status"`
|
||||
AssigneeID pgtype.UUID `json:"assignee_id"`
|
||||
CreatedBy pgtype.UUID `json:"created_by"`
|
||||
ClosedAt pgtype.Timestamptz `json:"closed_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
||||
}
|
||||
|
||||
type LlmEndpoint struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Provider string `json:"provider"`
|
||||
DisplayName string `json:"display_name"`
|
||||
BaseUrl string `json:"base_url"`
|
||||
ApiKeyEncrypted []byte `json:"api_key_encrypted"`
|
||||
CreatedBy pgtype.UUID `json:"created_by"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type LlmModel struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
EndpointID pgtype.UUID `json:"endpoint_id"`
|
||||
ModelID string `json:"model_id"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Capabilities []byte `json:"capabilities"`
|
||||
ContextWindow int32 `json:"context_window"`
|
||||
MaxOutputTokens int32 `json:"max_output_tokens"`
|
||||
PromptPricePerMillionUsd pgtype.Numeric `json:"prompt_price_per_million_usd"`
|
||||
CompletionPricePerMillionUsd pgtype.Numeric `json:"completion_price_per_million_usd"`
|
||||
ThinkingPricePerMillionUsd pgtype.Numeric `json:"thinking_price_per_million_usd"`
|
||||
IsTitleGenerator bool `json:"is_title_generator"`
|
||||
Enabled bool `json:"enabled"`
|
||||
SortOrder int32 `json:"sort_order"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type LlmUsage struct {
|
||||
ID int64 `json:"id"`
|
||||
ConversationID pgtype.UUID `json:"conversation_id"`
|
||||
MessageID int64 `json:"message_id"`
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
EndpointID pgtype.UUID `json:"endpoint_id"`
|
||||
ModelID pgtype.UUID `json:"model_id"`
|
||||
PromptTokens int32 `json:"prompt_tokens"`
|
||||
CompletionTokens int32 `json:"completion_tokens"`
|
||||
ThinkingTokens int32 `json:"thinking_tokens"`
|
||||
CostUsd pgtype.Numeric `json:"cost_usd"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
ID int64 `json:"id"`
|
||||
ConversationID pgtype.UUID `json:"conversation_id"`
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content"`
|
||||
Thinking *string `json:"thinking"`
|
||||
ToolCalls []byte `json:"tool_calls"`
|
||||
Status string `json:"status"`
|
||||
ErrorMessage *string `json:"error_message"`
|
||||
PromptTokens *int32 `json:"prompt_tokens"`
|
||||
CompletionTokens *int32 `json:"completion_tokens"`
|
||||
ThinkingTokens *int32 `json:"thinking_tokens"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type MessageAttachment struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
MessageID *int64 `json:"message_id"`
|
||||
Filename string `json:"filename"`
|
||||
MimeType string `json:"mime_type"`
|
||||
SizeBytes int64 `json:"size_bytes"`
|
||||
Sha256 string `json:"sha256"`
|
||||
StoragePath string `json:"storage_path"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
}
|
||||
|
||||
type Notification struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
Topic string `json:"topic"`
|
||||
Severity string `json:"severity"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
Link *string `json:"link"`
|
||||
Metadata []byte `json:"metadata"`
|
||||
ReadAt pgtype.Timestamptz `json:"read_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
}
|
||||
|
||||
type Project struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Slug string `json:"slug"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Visibility string `json:"visibility"`
|
||||
OwnerID pgtype.UUID `json:"owner_id"`
|
||||
ArchivedAt pgtype.Timestamptz `json:"archived_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type PromptTemplate struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content"`
|
||||
Scope string `json:"scope"`
|
||||
OwnerID pgtype.UUID `json:"owner_id"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type Requirement struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
ProjectID pgtype.UUID `json:"project_id"`
|
||||
Number int32 `json:"number"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Phase string `json:"phase"`
|
||||
Status string `json:"status"`
|
||||
OwnerID pgtype.UUID `json:"owner_id"`
|
||||
ClosedAt pgtype.Timestamptz `json:"closed_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Email string `json:"email"`
|
||||
PasswordHash string `json:"password_hash"`
|
||||
DisplayName string `json:"display_name"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type UserSession struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
TokenHash []byte `json:"token_hash"`
|
||||
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
|
||||
LastSeenAt pgtype.Timestamptz `json:"last_seen_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
}
|
||||
|
||||
type Workspace struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
ProjectID pgtype.UUID `json:"project_id"`
|
||||
Slug string `json:"slug"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
GitRemoteUrl string `json:"git_remote_url"`
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
MainPath string `json:"main_path"`
|
||||
SyncStatus string `json:"sync_status"`
|
||||
LastSyncedAt pgtype.Timestamptz `json:"last_synced_at"`
|
||||
LastSyncError *string `json:"last_sync_error"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
UpdatedAt pgtype.Timestamptz `json:"updated_at"`
|
||||
}
|
||||
|
||||
type WorkspaceWorktree struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
WorkspaceID pgtype.UUID `json:"workspace_id"`
|
||||
Branch string `json:"branch"`
|
||||
Path string `json:"path"`
|
||||
Status string `json:"status"`
|
||||
ActiveHolder *string `json:"active_holder"`
|
||||
AcquiredAt pgtype.Timestamptz `json:"acquired_at"`
|
||||
LastUsedAt pgtype.Timestamptz `json:"last_used_at"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: models.sql
|
||||
|
||||
package chatsqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const deleteLLMModel = `-- name: DeleteLLMModel :exec
|
||||
DELETE FROM llm_models WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeleteLLMModel(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, deleteLLMModel, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getLLMModel = `-- name: GetLLMModel :one
|
||||
SELECT id, endpoint_id, model_id, display_name, capabilities, context_window, max_output_tokens, prompt_price_per_million_usd, completion_price_per_million_usd, thinking_price_per_million_usd, is_title_generator, enabled, sort_order, created_at, updated_at FROM llm_models WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetLLMModel(ctx context.Context, id pgtype.UUID) (LlmModel, error) {
|
||||
row := q.db.QueryRow(ctx, getLLMModel, id)
|
||||
var i LlmModel
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.EndpointID,
|
||||
&i.ModelID,
|
||||
&i.DisplayName,
|
||||
&i.Capabilities,
|
||||
&i.ContextWindow,
|
||||
&i.MaxOutputTokens,
|
||||
&i.PromptPricePerMillionUsd,
|
||||
&i.CompletionPricePerMillionUsd,
|
||||
&i.ThinkingPricePerMillionUsd,
|
||||
&i.IsTitleGenerator,
|
||||
&i.Enabled,
|
||||
&i.SortOrder,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTitleGeneratorModel = `-- name: GetTitleGeneratorModel :one
|
||||
SELECT id, endpoint_id, model_id, display_name, capabilities, context_window, max_output_tokens, prompt_price_per_million_usd, completion_price_per_million_usd, thinking_price_per_million_usd, is_title_generator, enabled, sort_order, created_at, updated_at FROM llm_models WHERE is_title_generator = true AND enabled = true LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetTitleGeneratorModel(ctx context.Context) (LlmModel, error) {
|
||||
row := q.db.QueryRow(ctx, getTitleGeneratorModel)
|
||||
var i LlmModel
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.EndpointID,
|
||||
&i.ModelID,
|
||||
&i.DisplayName,
|
||||
&i.Capabilities,
|
||||
&i.ContextWindow,
|
||||
&i.MaxOutputTokens,
|
||||
&i.PromptPricePerMillionUsd,
|
||||
&i.CompletionPricePerMillionUsd,
|
||||
&i.ThinkingPricePerMillionUsd,
|
||||
&i.IsTitleGenerator,
|
||||
&i.Enabled,
|
||||
&i.SortOrder,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertLLMModel = `-- name: InsertLLMModel :one
|
||||
INSERT INTO llm_models (
|
||||
id, endpoint_id, model_id, display_name, capabilities,
|
||||
context_window, max_output_tokens,
|
||||
prompt_price_per_million_usd, completion_price_per_million_usd, thinking_price_per_million_usd,
|
||||
is_title_generator, enabled, sort_order
|
||||
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13)
|
||||
RETURNING id, endpoint_id, model_id, display_name, capabilities, context_window, max_output_tokens, prompt_price_per_million_usd, completion_price_per_million_usd, thinking_price_per_million_usd, is_title_generator, enabled, sort_order, created_at, updated_at
|
||||
`
|
||||
|
||||
type InsertLLMModelParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
EndpointID pgtype.UUID `json:"endpoint_id"`
|
||||
ModelID string `json:"model_id"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Capabilities []byte `json:"capabilities"`
|
||||
ContextWindow int32 `json:"context_window"`
|
||||
MaxOutputTokens int32 `json:"max_output_tokens"`
|
||||
PromptPricePerMillionUsd pgtype.Numeric `json:"prompt_price_per_million_usd"`
|
||||
CompletionPricePerMillionUsd pgtype.Numeric `json:"completion_price_per_million_usd"`
|
||||
ThinkingPricePerMillionUsd pgtype.Numeric `json:"thinking_price_per_million_usd"`
|
||||
IsTitleGenerator bool `json:"is_title_generator"`
|
||||
Enabled bool `json:"enabled"`
|
||||
SortOrder int32 `json:"sort_order"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertLLMModel(ctx context.Context, arg InsertLLMModelParams) (LlmModel, error) {
|
||||
row := q.db.QueryRow(ctx, insertLLMModel,
|
||||
arg.ID,
|
||||
arg.EndpointID,
|
||||
arg.ModelID,
|
||||
arg.DisplayName,
|
||||
arg.Capabilities,
|
||||
arg.ContextWindow,
|
||||
arg.MaxOutputTokens,
|
||||
arg.PromptPricePerMillionUsd,
|
||||
arg.CompletionPricePerMillionUsd,
|
||||
arg.ThinkingPricePerMillionUsd,
|
||||
arg.IsTitleGenerator,
|
||||
arg.Enabled,
|
||||
arg.SortOrder,
|
||||
)
|
||||
var i LlmModel
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.EndpointID,
|
||||
&i.ModelID,
|
||||
&i.DisplayName,
|
||||
&i.Capabilities,
|
||||
&i.ContextWindow,
|
||||
&i.MaxOutputTokens,
|
||||
&i.PromptPricePerMillionUsd,
|
||||
&i.CompletionPricePerMillionUsd,
|
||||
&i.ThinkingPricePerMillionUsd,
|
||||
&i.IsTitleGenerator,
|
||||
&i.Enabled,
|
||||
&i.SortOrder,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listLLMModels = `-- name: ListLLMModels :many
|
||||
SELECT id, endpoint_id, model_id, display_name, capabilities, context_window, max_output_tokens, prompt_price_per_million_usd, completion_price_per_million_usd, thinking_price_per_million_usd, is_title_generator, enabled, sort_order, created_at, updated_at FROM llm_models
|
||||
WHERE ($1::boolean = false) OR enabled = true
|
||||
ORDER BY sort_order, display_name
|
||||
`
|
||||
|
||||
func (q *Queries) ListLLMModels(ctx context.Context, dollar_1 bool) ([]LlmModel, error) {
|
||||
rows, err := q.db.Query(ctx, listLLMModels, dollar_1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []LlmModel
|
||||
for rows.Next() {
|
||||
var i LlmModel
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.EndpointID,
|
||||
&i.ModelID,
|
||||
&i.DisplayName,
|
||||
&i.Capabilities,
|
||||
&i.ContextWindow,
|
||||
&i.MaxOutputTokens,
|
||||
&i.PromptPricePerMillionUsd,
|
||||
&i.CompletionPricePerMillionUsd,
|
||||
&i.ThinkingPricePerMillionUsd,
|
||||
&i.IsTitleGenerator,
|
||||
&i.Enabled,
|
||||
&i.SortOrder,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updateLLMModel = `-- name: UpdateLLMModel :exec
|
||||
UPDATE llm_models
|
||||
SET display_name = COALESCE($2, display_name),
|
||||
capabilities = COALESCE($3, capabilities),
|
||||
context_window = COALESCE($4, context_window),
|
||||
max_output_tokens = COALESCE($5, max_output_tokens),
|
||||
prompt_price_per_million_usd = COALESCE($6, prompt_price_per_million_usd),
|
||||
completion_price_per_million_usd = COALESCE($7, completion_price_per_million_usd),
|
||||
thinking_price_per_million_usd = COALESCE($8, thinking_price_per_million_usd),
|
||||
is_title_generator = COALESCE($9, is_title_generator),
|
||||
enabled = COALESCE($10, enabled),
|
||||
sort_order = COALESCE($11, sort_order),
|
||||
updated_at = NOW()
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdateLLMModelParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Capabilities []byte `json:"capabilities"`
|
||||
ContextWindow int32 `json:"context_window"`
|
||||
MaxOutputTokens int32 `json:"max_output_tokens"`
|
||||
PromptPricePerMillionUsd pgtype.Numeric `json:"prompt_price_per_million_usd"`
|
||||
CompletionPricePerMillionUsd pgtype.Numeric `json:"completion_price_per_million_usd"`
|
||||
ThinkingPricePerMillionUsd pgtype.Numeric `json:"thinking_price_per_million_usd"`
|
||||
IsTitleGenerator bool `json:"is_title_generator"`
|
||||
Enabled bool `json:"enabled"`
|
||||
SortOrder int32 `json:"sort_order"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateLLMModel(ctx context.Context, arg UpdateLLMModelParams) error {
|
||||
_, err := q.db.Exec(ctx, updateLLMModel,
|
||||
arg.ID,
|
||||
arg.DisplayName,
|
||||
arg.Capabilities,
|
||||
arg.ContextWindow,
|
||||
arg.MaxOutputTokens,
|
||||
arg.PromptPricePerMillionUsd,
|
||||
arg.CompletionPricePerMillionUsd,
|
||||
arg.ThinkingPricePerMillionUsd,
|
||||
arg.IsTitleGenerator,
|
||||
arg.Enabled,
|
||||
arg.SortOrder,
|
||||
)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: templates.sql
|
||||
|
||||
package chatsqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const deletePromptTemplate = `-- name: DeletePromptTemplate :exec
|
||||
DELETE FROM prompt_templates WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) DeletePromptTemplate(ctx context.Context, id pgtype.UUID) error {
|
||||
_, err := q.db.Exec(ctx, deletePromptTemplate, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const getPromptTemplate = `-- name: GetPromptTemplate :one
|
||||
SELECT id, name, content, scope, owner_id, created_at, updated_at FROM prompt_templates WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetPromptTemplate(ctx context.Context, id pgtype.UUID) (PromptTemplate, error) {
|
||||
row := q.db.QueryRow(ctx, getPromptTemplate, id)
|
||||
var i PromptTemplate
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Content,
|
||||
&i.Scope,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const insertPromptTemplate = `-- name: InsertPromptTemplate :one
|
||||
INSERT INTO prompt_templates (id, name, content, scope, owner_id)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING id, name, content, scope, owner_id, created_at, updated_at
|
||||
`
|
||||
|
||||
type InsertPromptTemplateParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content"`
|
||||
Scope string `json:"scope"`
|
||||
OwnerID pgtype.UUID `json:"owner_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertPromptTemplate(ctx context.Context, arg InsertPromptTemplateParams) (PromptTemplate, error) {
|
||||
row := q.db.QueryRow(ctx, insertPromptTemplate,
|
||||
arg.ID,
|
||||
arg.Name,
|
||||
arg.Content,
|
||||
arg.Scope,
|
||||
arg.OwnerID,
|
||||
)
|
||||
var i PromptTemplate
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Content,
|
||||
&i.Scope,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listPromptTemplatesForUser = `-- name: ListPromptTemplatesForUser :many
|
||||
SELECT id, name, content, scope, owner_id, created_at, updated_at FROM prompt_templates
|
||||
WHERE scope = 'system' OR (scope = 'user' AND owner_id = $1)
|
||||
ORDER BY scope, name
|
||||
`
|
||||
|
||||
func (q *Queries) ListPromptTemplatesForUser(ctx context.Context, ownerID pgtype.UUID) ([]PromptTemplate, error) {
|
||||
rows, err := q.db.Query(ctx, listPromptTemplatesForUser, ownerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []PromptTemplate
|
||||
for rows.Next() {
|
||||
var i PromptTemplate
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Name,
|
||||
&i.Content,
|
||||
&i.Scope,
|
||||
&i.OwnerID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const updatePromptTemplate = `-- name: UpdatePromptTemplate :exec
|
||||
UPDATE prompt_templates SET name = $2, content = $3, updated_at = NOW()
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
type UpdatePromptTemplateParams struct {
|
||||
ID pgtype.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdatePromptTemplate(ctx context.Context, arg UpdatePromptTemplateParams) error {
|
||||
_, err := q.db.Exec(ctx, updatePromptTemplate, arg.ID, arg.Name, arg.Content)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: usage.sql
|
||||
|
||||
package chatsqlc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const insertUsage = `-- name: InsertUsage :exec
|
||||
INSERT INTO llm_usage (
|
||||
conversation_id, message_id, user_id, endpoint_id, model_id,
|
||||
prompt_tokens, completion_tokens, thinking_tokens, cost_usd
|
||||
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)
|
||||
`
|
||||
|
||||
type InsertUsageParams struct {
|
||||
ConversationID pgtype.UUID `json:"conversation_id"`
|
||||
MessageID int64 `json:"message_id"`
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
EndpointID pgtype.UUID `json:"endpoint_id"`
|
||||
ModelID pgtype.UUID `json:"model_id"`
|
||||
PromptTokens int32 `json:"prompt_tokens"`
|
||||
CompletionTokens int32 `json:"completion_tokens"`
|
||||
ThinkingTokens int32 `json:"thinking_tokens"`
|
||||
CostUsd pgtype.Numeric `json:"cost_usd"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertUsage(ctx context.Context, arg InsertUsageParams) error {
|
||||
_, err := q.db.Exec(ctx, insertUsage,
|
||||
arg.ConversationID,
|
||||
arg.MessageID,
|
||||
arg.UserID,
|
||||
arg.EndpointID,
|
||||
arg.ModelID,
|
||||
arg.PromptTokens,
|
||||
arg.CompletionTokens,
|
||||
arg.ThinkingTokens,
|
||||
arg.CostUsd,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const summarizeUsageByDay = `-- name: SummarizeUsageByDay :many
|
||||
SELECT date_trunc('day', created_at) AS day,
|
||||
SUM(prompt_tokens)::int AS prompt_tokens,
|
||||
SUM(completion_tokens)::int AS completion_tokens,
|
||||
SUM(thinking_tokens)::int AS thinking_tokens,
|
||||
SUM(cost_usd)::numeric AS cost_usd
|
||||
FROM llm_usage
|
||||
WHERE created_at >= $1 AND created_at < $2
|
||||
GROUP BY day
|
||||
ORDER BY day
|
||||
`
|
||||
|
||||
type SummarizeUsageByDayParams struct {
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
CreatedAt_2 pgtype.Timestamptz `json:"created_at_2"`
|
||||
}
|
||||
|
||||
type SummarizeUsageByDayRow struct {
|
||||
Day pgtype.Interval `json:"day"`
|
||||
PromptTokens int32 `json:"prompt_tokens"`
|
||||
CompletionTokens int32 `json:"completion_tokens"`
|
||||
ThinkingTokens int32 `json:"thinking_tokens"`
|
||||
CostUsd pgtype.Numeric `json:"cost_usd"`
|
||||
}
|
||||
|
||||
func (q *Queries) SummarizeUsageByDay(ctx context.Context, arg SummarizeUsageByDayParams) ([]SummarizeUsageByDayRow, error) {
|
||||
rows, err := q.db.Query(ctx, summarizeUsageByDay, arg.CreatedAt, arg.CreatedAt_2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []SummarizeUsageByDayRow
|
||||
for rows.Next() {
|
||||
var i SummarizeUsageByDayRow
|
||||
if err := rows.Scan(
|
||||
&i.Day,
|
||||
&i.PromptTokens,
|
||||
&i.CompletionTokens,
|
||||
&i.ThinkingTokens,
|
||||
&i.CostUsd,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const summarizeUsageByModel = `-- name: SummarizeUsageByModel :many
|
||||
SELECT model_id,
|
||||
SUM(prompt_tokens)::int AS prompt_tokens,
|
||||
SUM(completion_tokens)::int AS completion_tokens,
|
||||
SUM(thinking_tokens)::int AS thinking_tokens,
|
||||
SUM(cost_usd)::numeric AS cost_usd
|
||||
FROM llm_usage
|
||||
WHERE created_at >= $1 AND created_at < $2
|
||||
GROUP BY model_id
|
||||
ORDER BY cost_usd DESC
|
||||
`
|
||||
|
||||
type SummarizeUsageByModelParams struct {
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
CreatedAt_2 pgtype.Timestamptz `json:"created_at_2"`
|
||||
}
|
||||
|
||||
type SummarizeUsageByModelRow struct {
|
||||
ModelID pgtype.UUID `json:"model_id"`
|
||||
PromptTokens int32 `json:"prompt_tokens"`
|
||||
CompletionTokens int32 `json:"completion_tokens"`
|
||||
ThinkingTokens int32 `json:"thinking_tokens"`
|
||||
CostUsd pgtype.Numeric `json:"cost_usd"`
|
||||
}
|
||||
|
||||
func (q *Queries) SummarizeUsageByModel(ctx context.Context, arg SummarizeUsageByModelParams) ([]SummarizeUsageByModelRow, error) {
|
||||
rows, err := q.db.Query(ctx, summarizeUsageByModel, arg.CreatedAt, arg.CreatedAt_2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []SummarizeUsageByModelRow
|
||||
for rows.Next() {
|
||||
var i SummarizeUsageByModelRow
|
||||
if err := rows.Scan(
|
||||
&i.ModelID,
|
||||
&i.PromptTokens,
|
||||
&i.CompletionTokens,
|
||||
&i.ThinkingTokens,
|
||||
&i.CostUsd,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const summarizeUsageByUser = `-- name: SummarizeUsageByUser :many
|
||||
SELECT user_id,
|
||||
SUM(prompt_tokens)::int AS prompt_tokens,
|
||||
SUM(completion_tokens)::int AS completion_tokens,
|
||||
SUM(thinking_tokens)::int AS thinking_tokens,
|
||||
SUM(cost_usd)::numeric AS cost_usd
|
||||
FROM llm_usage
|
||||
WHERE created_at >= $1 AND created_at < $2
|
||||
GROUP BY user_id
|
||||
ORDER BY cost_usd DESC
|
||||
`
|
||||
|
||||
type SummarizeUsageByUserParams struct {
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
CreatedAt_2 pgtype.Timestamptz `json:"created_at_2"`
|
||||
}
|
||||
|
||||
type SummarizeUsageByUserRow struct {
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
PromptTokens int32 `json:"prompt_tokens"`
|
||||
CompletionTokens int32 `json:"completion_tokens"`
|
||||
ThinkingTokens int32 `json:"thinking_tokens"`
|
||||
CostUsd pgtype.Numeric `json:"cost_usd"`
|
||||
}
|
||||
|
||||
func (q *Queries) SummarizeUsageByUser(ctx context.Context, arg SummarizeUsageByUserParams) ([]SummarizeUsageByUserRow, error) {
|
||||
rows, err := q.db.Query(ctx, summarizeUsageByUser, arg.CreatedAt, arg.CreatedAt_2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []SummarizeUsageByUserRow
|
||||
for rows.Next() {
|
||||
var i SummarizeUsageByUserRow
|
||||
if err := rows.Scan(
|
||||
&i.UserID,
|
||||
&i.PromptTokens,
|
||||
&i.CompletionTokens,
|
||||
&i.ThinkingTokens,
|
||||
&i.CostUsd,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const summarizeUserDaily = `-- name: SummarizeUserDaily :many
|
||||
SELECT date_trunc('day', created_at) AS day,
|
||||
SUM(prompt_tokens)::int AS prompt_tokens,
|
||||
SUM(completion_tokens)::int AS completion_tokens,
|
||||
SUM(thinking_tokens)::int AS thinking_tokens,
|
||||
SUM(cost_usd)::numeric AS cost_usd
|
||||
FROM llm_usage
|
||||
WHERE user_id = $1 AND created_at >= $2 AND created_at < $3
|
||||
GROUP BY day
|
||||
ORDER BY day
|
||||
`
|
||||
|
||||
type SummarizeUserDailyParams struct {
|
||||
UserID pgtype.UUID `json:"user_id"`
|
||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||
CreatedAt_2 pgtype.Timestamptz `json:"created_at_2"`
|
||||
}
|
||||
|
||||
type SummarizeUserDailyRow struct {
|
||||
Day pgtype.Interval `json:"day"`
|
||||
PromptTokens int32 `json:"prompt_tokens"`
|
||||
CompletionTokens int32 `json:"completion_tokens"`
|
||||
ThinkingTokens int32 `json:"thinking_tokens"`
|
||||
CostUsd pgtype.Numeric `json:"cost_usd"`
|
||||
}
|
||||
|
||||
func (q *Queries) SummarizeUserDaily(ctx context.Context, arg SummarizeUserDailyParams) ([]SummarizeUserDailyRow, error) {
|
||||
rows, err := q.db.Query(ctx, summarizeUserDaily, arg.UserID, arg.CreatedAt, arg.CreatedAt_2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []SummarizeUserDailyRow
|
||||
for rows.Next() {
|
||||
var i SummarizeUserDailyRow
|
||||
if err := rows.Scan(
|
||||
&i.Day,
|
||||
&i.PromptTokens,
|
||||
&i.CompletionTokens,
|
||||
&i.ThinkingTokens,
|
||||
&i.CostUsd,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
@@ -50,3 +50,13 @@ sql:
|
||||
sql_package: pgx/v5
|
||||
emit_pointers_for_null_types: true
|
||||
emit_json_tags: true
|
||||
- engine: postgresql
|
||||
queries: internal/chat/queries
|
||||
schema: migrations
|
||||
gen:
|
||||
go:
|
||||
package: chatsqlc
|
||||
out: internal/chat/sqlc
|
||||
sql_package: pgx/v5
|
||||
emit_pointers_for_null_types: true
|
||||
emit_json_tags: true
|
||||
|
||||
Reference in New Issue
Block a user