Files
multica/server/pkg/db/generated/workspace.sql.go
Naiyuan Qing df37fba8a2 feat(spaces): editable identifier + workspace slug; space-context brief
Space Identifier (key) is now editable on the space detail page, and no
longer frozen after the first issue: renaming bulk-writes issue-identifier
aliases under the old key (BackfillSpaceKeyAliases) so every OLDKEY-N
reference keeps resolving, and the UI confirms the rename when the space
already holds issues. Admin-only; navigates to the new /space/<key> URL.

Workspace settings:
- drop the obsolete "Issue prefix" field — numbering is per-space now, and
  identifiers come from the space key (edited on the space detail page).
- make the workspace slug (its URL) editable: validates pattern/reserved,
  409 on collision, confirms the link-breaking change, and migrates to the
  new /<slug> URL on save.

UI: add an `underline` variant to the shared Input (was a copy-pasted
override string in three places).

Agent brief: inject the Space description into the run brief alongside the
project/workspace context (space_description through the daemon task chain);
add `multica space get` so an agent can read a space's description on demand.
Known gap: quick-create tasks don't yet carry space_description (their
QuickCreateContext snapshot lacks it) — deferred.

Also bundles in-tree WIP present on this branch (space-first sidebar,
onboarding workspace step).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 17:04:22 +08:00

248 lines
5.9 KiB
Go

// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: workspace.sql
package db
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const createWorkspace = `-- name: CreateWorkspace :one
INSERT INTO workspace (name, slug, description, context, issue_prefix)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, name, slug, description, settings, created_at, updated_at, context, repos, issue_prefix, issue_counter, avatar_url
`
type CreateWorkspaceParams struct {
Name string `json:"name"`
Slug string `json:"slug"`
Description pgtype.Text `json:"description"`
Context pgtype.Text `json:"context"`
IssuePrefix string `json:"issue_prefix"`
}
func (q *Queries) CreateWorkspace(ctx context.Context, arg CreateWorkspaceParams) (Workspace, error) {
row := q.db.QueryRow(ctx, createWorkspace,
arg.Name,
arg.Slug,
arg.Description,
arg.Context,
arg.IssuePrefix,
)
var i Workspace
err := row.Scan(
&i.ID,
&i.Name,
&i.Slug,
&i.Description,
&i.Settings,
&i.CreatedAt,
&i.UpdatedAt,
&i.Context,
&i.Repos,
&i.IssuePrefix,
&i.IssueCounter,
&i.AvatarUrl,
)
return i, err
}
const deleteWorkspace = `-- name: DeleteWorkspace :exec
WITH deleted_pending_check_suites AS (
DELETE FROM github_pending_check_suite WHERE workspace_id = $1
)
DELETE FROM workspace WHERE id = $1
`
func (q *Queries) DeleteWorkspace(ctx context.Context, id pgtype.UUID) error {
_, err := q.db.Exec(ctx, deleteWorkspace, id)
return err
}
const getWorkspace = `-- name: GetWorkspace :one
SELECT id, name, slug, description, settings, created_at, updated_at, context, repos, issue_prefix, issue_counter, avatar_url FROM workspace
WHERE id = $1
`
func (q *Queries) GetWorkspace(ctx context.Context, id pgtype.UUID) (Workspace, error) {
row := q.db.QueryRow(ctx, getWorkspace, id)
var i Workspace
err := row.Scan(
&i.ID,
&i.Name,
&i.Slug,
&i.Description,
&i.Settings,
&i.CreatedAt,
&i.UpdatedAt,
&i.Context,
&i.Repos,
&i.IssuePrefix,
&i.IssueCounter,
&i.AvatarUrl,
)
return i, err
}
const getWorkspaceBySlug = `-- name: GetWorkspaceBySlug :one
SELECT id, name, slug, description, settings, created_at, updated_at, context, repos, issue_prefix, issue_counter, avatar_url FROM workspace
WHERE slug = $1
`
func (q *Queries) GetWorkspaceBySlug(ctx context.Context, slug string) (Workspace, error) {
row := q.db.QueryRow(ctx, getWorkspaceBySlug, slug)
var i Workspace
err := row.Scan(
&i.ID,
&i.Name,
&i.Slug,
&i.Description,
&i.Settings,
&i.CreatedAt,
&i.UpdatedAt,
&i.Context,
&i.Repos,
&i.IssuePrefix,
&i.IssueCounter,
&i.AvatarUrl,
)
return i, err
}
const listWorkspaces = `-- name: ListWorkspaces :many
SELECT w.id, w.name, w.slug, w.description, w.settings,
w.created_at, w.updated_at, w.context, w.repos,
w.issue_prefix, w.issue_counter, w.avatar_url
FROM member m
JOIN workspace w ON w.id = m.workspace_id
WHERE m.user_id = $1
ORDER BY w.created_at ASC
`
func (q *Queries) ListWorkspaces(ctx context.Context, userID pgtype.UUID) ([]Workspace, error) {
rows, err := q.db.Query(ctx, listWorkspaces, userID)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Workspace{}
for rows.Next() {
var i Workspace
if err := rows.Scan(
&i.ID,
&i.Name,
&i.Slug,
&i.Description,
&i.Settings,
&i.CreatedAt,
&i.UpdatedAt,
&i.Context,
&i.Repos,
&i.IssuePrefix,
&i.IssueCounter,
&i.AvatarUrl,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listWorkspacesWithRepos = `-- name: ListWorkspacesWithRepos :many
SELECT id, repos FROM workspace
WHERE repos IS NOT NULL AND repos <> '[]'::jsonb
ORDER BY id
`
type ListWorkspacesWithReposRow struct {
ID pgtype.UUID `json:"id"`
Repos []byte `json:"repos"`
}
// Workspaces with a non-empty repo registry, to route a webhook to the repo's
// owning workspace. ORDER BY id keeps the resolver's tie-break stable on replay.
func (q *Queries) ListWorkspacesWithRepos(ctx context.Context) ([]ListWorkspacesWithReposRow, error) {
rows, err := q.db.Query(ctx, listWorkspacesWithRepos)
if err != nil {
return nil, err
}
defer rows.Close()
items := []ListWorkspacesWithReposRow{}
for rows.Next() {
var i ListWorkspacesWithReposRow
if err := rows.Scan(&i.ID, &i.Repos); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const updateWorkspace = `-- name: UpdateWorkspace :one
UPDATE workspace SET
name = COALESCE($2, name),
slug = COALESCE($3, slug),
description = COALESCE($4, description),
context = COALESCE($5, context),
settings = COALESCE($6, settings),
repos = COALESCE($7, repos),
issue_prefix = COALESCE($8, issue_prefix),
avatar_url = COALESCE($9, avatar_url),
updated_at = now()
WHERE id = $1
RETURNING id, name, slug, description, settings, created_at, updated_at, context, repos, issue_prefix, issue_counter, avatar_url
`
type UpdateWorkspaceParams struct {
ID pgtype.UUID `json:"id"`
Name pgtype.Text `json:"name"`
Slug pgtype.Text `json:"slug"`
Description pgtype.Text `json:"description"`
Context pgtype.Text `json:"context"`
Settings []byte `json:"settings"`
Repos []byte `json:"repos"`
IssuePrefix pgtype.Text `json:"issue_prefix"`
AvatarUrl pgtype.Text `json:"avatar_url"`
}
func (q *Queries) UpdateWorkspace(ctx context.Context, arg UpdateWorkspaceParams) (Workspace, error) {
row := q.db.QueryRow(ctx, updateWorkspace,
arg.ID,
arg.Name,
arg.Slug,
arg.Description,
arg.Context,
arg.Settings,
arg.Repos,
arg.IssuePrefix,
arg.AvatarUrl,
)
var i Workspace
err := row.Scan(
&i.ID,
&i.Name,
&i.Slug,
&i.Description,
&i.Settings,
&i.CreatedAt,
&i.UpdatedAt,
&i.Context,
&i.Repos,
&i.IssuePrefix,
&i.IssueCounter,
&i.AvatarUrl,
)
return i, err
}