Files
de198cd4c1 feat: allow quick actions without a target (MUL-7990) (#9210)
* test: cover quick actions without an agent

* feat: allow quick actions without a target

* test(quick-actions): cover clearing an existing agent target

* fix(quick-actions): keep existing locale copy

* test: consolidate quick-action regressions in existing test file

* chore(migrations): renumber quick action optional target migration to 584

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Multica Eve <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-19 14:41:48 +08:00

297 lines
8.8 KiB
Go

// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: quick_action.sql
package db
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const countActiveQuickActions = `-- name: CountActiveQuickActions :one
SELECT COUNT(*) FROM quick_action
WHERE workspace_id = $1 AND status = 'active'
`
func (q *Queries) CountActiveQuickActions(ctx context.Context, workspaceID pgtype.UUID) (int64, error) {
row := q.db.QueryRow(ctx, countActiveQuickActions, workspaceID)
var count int64
err := row.Scan(&count)
return count, err
}
const createQuickAction = `-- name: CreateQuickAction :one
INSERT INTO quick_action (
workspace_id, name, description, assignee_type, assignee_id, prompt,
visibility, created_by_type, created_by_id
) VALUES (
$1::uuid,
$2::text,
$3::text,
$4::text,
$5::uuid,
$6::text,
$7::text,
$8::text,
$9::uuid
)
RETURNING id, workspace_id, name, description, assignee_type, assignee_id, prompt, visibility, status, last_used_at, use_count, created_by_type, created_by_id, created_at, updated_at
`
type CreateQuickActionParams struct {
WorkspaceID pgtype.UUID `json:"workspace_id"`
Name string `json:"name"`
Description string `json:"description"`
AssigneeType string `json:"assignee_type"`
AssigneeID pgtype.UUID `json:"assignee_id"`
Prompt string `json:"prompt"`
Visibility string `json:"visibility"`
CreatedByType string `json:"created_by_type"`
CreatedByID pgtype.UUID `json:"created_by_id"`
}
func (q *Queries) CreateQuickAction(ctx context.Context, arg CreateQuickActionParams) (QuickAction, error) {
row := q.db.QueryRow(ctx, createQuickAction,
arg.WorkspaceID,
arg.Name,
arg.Description,
arg.AssigneeType,
arg.AssigneeID,
arg.Prompt,
arg.Visibility,
arg.CreatedByType,
arg.CreatedByID,
)
var i QuickAction
err := row.Scan(
&i.ID,
&i.WorkspaceID,
&i.Name,
&i.Description,
&i.AssigneeType,
&i.AssigneeID,
&i.Prompt,
&i.Visibility,
&i.Status,
&i.LastUsedAt,
&i.UseCount,
&i.CreatedByType,
&i.CreatedByID,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const deletePrivateQuickActionsByCreator = `-- name: DeletePrivateQuickActionsByCreator :exec
DELETE FROM quick_action
WHERE workspace_id = $1 AND created_by_id = $2 AND visibility = 'private'
`
type DeletePrivateQuickActionsByCreatorParams struct {
WorkspaceID pgtype.UUID `json:"workspace_id"`
CreatedByID pgtype.UUID `json:"created_by_id"`
}
// Run when a member leaves or is removed. A private action is visible and
// runnable ONLY by its creator, so once they are gone nobody can see it, run
// it, or clean it up — while it still counts against the workspace's active
// limit. Public actions are workspace furniture and deliberately survive their
// author's departure.
func (q *Queries) DeletePrivateQuickActionsByCreator(ctx context.Context, arg DeletePrivateQuickActionsByCreatorParams) error {
_, err := q.db.Exec(ctx, deletePrivateQuickActionsByCreator, arg.WorkspaceID, arg.CreatedByID)
return err
}
const deleteQuickAction = `-- name: DeleteQuickAction :exec
DELETE FROM quick_action WHERE id = $1 AND workspace_id = $2
`
type DeleteQuickActionParams struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
}
// workspace_id is a SQL-layer tenant guard, matching DeleteComment.
func (q *Queries) DeleteQuickAction(ctx context.Context, arg DeleteQuickActionParams) error {
_, err := q.db.Exec(ctx, deleteQuickAction, arg.ID, arg.WorkspaceID)
return err
}
const getQuickAction = `-- name: GetQuickAction :one
SELECT id, workspace_id, name, description, assignee_type, assignee_id, prompt, visibility, status, last_used_at, use_count, created_by_type, created_by_id, created_at, updated_at FROM quick_action
WHERE id = $1 AND workspace_id = $2
`
type GetQuickActionParams struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
}
func (q *Queries) GetQuickAction(ctx context.Context, arg GetQuickActionParams) (QuickAction, error) {
row := q.db.QueryRow(ctx, getQuickAction, arg.ID, arg.WorkspaceID)
var i QuickAction
err := row.Scan(
&i.ID,
&i.WorkspaceID,
&i.Name,
&i.Description,
&i.AssigneeType,
&i.AssigneeID,
&i.Prompt,
&i.Visibility,
&i.Status,
&i.LastUsedAt,
&i.UseCount,
&i.CreatedByType,
&i.CreatedByID,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const listQuickActions = `-- name: ListQuickActions :many
SELECT id, workspace_id, name, description, assignee_type, assignee_id, prompt, visibility, status, last_used_at, use_count, created_by_type, created_by_id, created_at, updated_at FROM quick_action
WHERE workspace_id = $1::uuid
AND ($2::bool OR status = 'active')
AND (visibility = 'public' OR created_by_id = $3::uuid)
ORDER BY use_count DESC, LOWER(name) ASC
`
type ListQuickActionsParams struct {
WorkspaceID pgtype.UUID `json:"workspace_id"`
IncludeArchived bool `json:"include_archived"`
ViewerID pgtype.UUID `json:"viewer_id"`
}
// One projection for every caller. `private` rows belong to their creator, so
// they are filtered here rather than in the handler; nothing else is hidden.
// Permission to actually RUN an action is decided only at run time, so this
// query does no permission work at all.
//
// Ordering is use_count DESC everywhere — the list's job is to answer "what
// does this workspace actually use". LOWER(name) breaks ties so equal counts
// never render in random order.
func (q *Queries) ListQuickActions(ctx context.Context, arg ListQuickActionsParams) ([]QuickAction, error) {
rows, err := q.db.Query(ctx, listQuickActions, arg.WorkspaceID, arg.IncludeArchived, arg.ViewerID)
if err != nil {
return nil, err
}
defer rows.Close()
items := []QuickAction{}
for rows.Next() {
var i QuickAction
if err := rows.Scan(
&i.ID,
&i.WorkspaceID,
&i.Name,
&i.Description,
&i.AssigneeType,
&i.AssigneeID,
&i.Prompt,
&i.Visibility,
&i.Status,
&i.LastUsedAt,
&i.UseCount,
&i.CreatedByType,
&i.CreatedByID,
&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 touchQuickActionUsage = `-- name: TouchQuickActionUsage :exec
UPDATE quick_action
SET use_count = use_count + 1, last_used_at = now()
WHERE id = $1 AND workspace_id = $2
`
type TouchQuickActionUsageParams struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
}
// Best-effort usage telemetry, written after a successful run. Deliberately
// not part of the run transaction: a failed counter bump must never lose the
// run the user asked for. It also drives the list order, so it is the one
// place ordering state changes.
func (q *Queries) TouchQuickActionUsage(ctx context.Context, arg TouchQuickActionUsageParams) error {
_, err := q.db.Exec(ctx, touchQuickActionUsage, arg.ID, arg.WorkspaceID)
return err
}
const updateQuickAction = `-- name: UpdateQuickAction :one
UPDATE quick_action SET
name = COALESCE($3, name),
description = COALESCE($4, description),
assignee_type = COALESCE($5, assignee_type),
assignee_id = CASE WHEN $5::text IS NOT NULL
THEN $6::uuid ELSE assignee_id END,
prompt = COALESCE($7, prompt),
visibility = COALESCE($8, visibility),
status = COALESCE($9, status),
updated_at = now()
WHERE id = $1 AND workspace_id = $2
RETURNING id, workspace_id, name, description, assignee_type, assignee_id, prompt, visibility, status, last_used_at, use_count, created_by_type, created_by_id, created_at, updated_at
`
type UpdateQuickActionParams struct {
ID pgtype.UUID `json:"id"`
WorkspaceID pgtype.UUID `json:"workspace_id"`
Name pgtype.Text `json:"name"`
Description pgtype.Text `json:"description"`
AssigneeType pgtype.Text `json:"assignee_type"`
AssigneeID pgtype.UUID `json:"assignee_id"`
Prompt pgtype.Text `json:"prompt"`
Visibility pgtype.Text `json:"visibility"`
Status pgtype.Text `json:"status"`
}
// COALESCE-on-narg partial update: an omitted field keeps its stored value.
// The handler resolves the resulting assignee pair and writes both columns.
// A supplied type also permits clearing the UUID for a targetless action.
func (q *Queries) UpdateQuickAction(ctx context.Context, arg UpdateQuickActionParams) (QuickAction, error) {
row := q.db.QueryRow(ctx, updateQuickAction,
arg.ID,
arg.WorkspaceID,
arg.Name,
arg.Description,
arg.AssigneeType,
arg.AssigneeID,
arg.Prompt,
arg.Visibility,
arg.Status,
)
var i QuickAction
err := row.Scan(
&i.ID,
&i.WorkspaceID,
&i.Name,
&i.Description,
&i.AssigneeType,
&i.AssigneeID,
&i.Prompt,
&i.Visibility,
&i.Status,
&i.LastUsedAt,
&i.UseCount,
&i.CreatedByType,
&i.CreatedByID,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}