mirror of
https://github.com/multica-ai/multica.git
synced 2026-08-12 19:06:06 +02:00
Replace the floating chat FAB/window with a first-class Chat tab under Inbox, laid out as an IM-style two-pane surface (thread list + conversation). Highlights: - New Chat page (packages/views/chat/chat-page.tsx) with URL-addressable session selection; web + desktop routing wired up. Removes the old chat-fab / chat-window / resize-handles / context-items paths. - IM thread list: agent avatar + last-message preview + IM timestamp, red unread *count* badge (read-cursor model), presence-gated typing vs waiting. Rename lives only in the conversation header ⋯ menu (not the list hover). - Per-session conversation header (rename / view agent / delete), agent-aware empty state (avatar + name + description + starter prompts), and a deterministic clean-title derivation from the first message. - Server: read-cursor unread model (migration 145) and per-user pinned agents (migration 146, dedicated chat_pinned_agent table + handler/queries). New-agent welcome chat auto-enqueues a real agent run (LLM intro, no static template). - Design: fade the global --border token; borderless list headers on Chat/Inbox, kept (faded) on the conversation header. Verified: pnpm typecheck (all packages), go build ./..., go vet, gofmt. Co-authored-by: multica-agent <github@multica.ai>
23 lines
836 B
SQL
23 lines
836 B
SQL
-- name: ListChatPinnedAgents :many
|
|
SELECT * FROM chat_pinned_agent
|
|
WHERE workspace_id = $1 AND user_id = $2
|
|
ORDER BY position ASC, created_at ASC;
|
|
|
|
-- name: CreateChatPinnedAgent :one
|
|
-- Idempotent: pinning an already-pinned agent is a no-op that returns the
|
|
-- existing row (DO UPDATE keeps `:one` from hitting a no-rows error).
|
|
INSERT INTO chat_pinned_agent (workspace_id, user_id, agent_id, position)
|
|
VALUES ($1, $2, $3, $4)
|
|
ON CONFLICT (workspace_id, user_id, agent_id)
|
|
DO UPDATE SET position = chat_pinned_agent.position
|
|
RETURNING *;
|
|
|
|
-- name: DeleteChatPinnedAgent :exec
|
|
DELETE FROM chat_pinned_agent
|
|
WHERE workspace_id = $1 AND user_id = $2 AND agent_id = $3;
|
|
|
|
-- name: GetMaxChatPinnedAgentPosition :one
|
|
SELECT COALESCE(MAX(position), 0)::float8 AS max_position
|
|
FROM chat_pinned_agent
|
|
WHERE workspace_id = $1 AND user_id = $2;
|