From 4d52642c79b7396fe52bbb72f581ae299c6ece09 Mon Sep 17 00:00:00 2001 From: Shakker Date: Sun, 10 May 2026 19:42:15 +0100 Subject: [PATCH] fix: harden chat storage scaling and privacy --- apps/api/cmd/clickclack/main.go | 59 ++ apps/api/internal/httpapi/features.go | 2 +- apps/api/internal/store/sqlite/chat_test.go | 6 +- apps/api/internal/store/sqlite/dms.go | 95 +++- apps/api/internal/store/sqlite/events.go | 47 ++ apps/api/internal/store/sqlite/export.go | 2 +- apps/api/internal/store/sqlite/helpers.go | 17 +- .../sqlite/message_privacy_scaling_test.go | 522 ++++++++++++++++++ .../0010_message_privacy_scaling.sql | 296 ++++++++++ apps/api/internal/store/sqlite/misc_test.go | 2 +- apps/api/internal/store/sqlite/mutations.go | 30 +- .../internal/store/sqlite/mutations_test.go | 23 +- apps/api/internal/store/sqlite/reads.go | 10 +- apps/api/internal/store/sqlite/search.go | 17 +- apps/api/internal/store/sqlite/sqlite.go | 70 ++- apps/api/internal/store/sqlite/sqlite_test.go | 2 +- apps/api/internal/store/sqlite/uploads.go | 58 +- apps/api/internal/store/types.go | 2 +- .../{index-DI8HZC7D.js => index-CySuZTQ7.js} | 18 +- apps/api/internal/webassets/dist/index.html | 2 +- apps/web/src/ChatApp.svelte | 10 +- docs/cli.md | 17 +- docs/data-model.md | 13 +- docs/deployment.md | 13 + docs/features/dms.md | 20 +- docs/features/realtime.md | 9 +- docs/features/search.md | 10 +- .../sqlite/0005_upload_dimensions.sql | 3 + .../sqlite/0006_message_client_nonce.sql | 5 + infra/migrations/sqlite/0007_unread.sql | 15 + .../sqlite/0008_message_paging_indexes.sql | 7 + .../0008_user_notification_settings.sql | 5 + infra/migrations/sqlite/0009_bots.sql | 19 + .../sqlite/0010_message_privacy_scaling.sql | 296 ++++++++++ packages/protocol/openapi.yaml | 5 + packages/sdk-ts/src/generated/openapi.d.ts | 1 + packages/sdk-ts/src/index.ts | 8 +- 37 files changed, 1632 insertions(+), 104 deletions(-) create mode 100644 apps/api/internal/store/sqlite/events.go create mode 100644 apps/api/internal/store/sqlite/message_privacy_scaling_test.go create mode 100644 apps/api/internal/store/sqlite/migrations/0010_message_privacy_scaling.sql rename apps/api/internal/webassets/dist/assets/{index-DI8HZC7D.js => index-CySuZTQ7.js} (92%) create mode 100644 infra/migrations/sqlite/0005_upload_dimensions.sql create mode 100644 infra/migrations/sqlite/0006_message_client_nonce.sql create mode 100644 infra/migrations/sqlite/0007_unread.sql create mode 100644 infra/migrations/sqlite/0008_message_paging_indexes.sql create mode 100644 infra/migrations/sqlite/0008_user_notification_settings.sql create mode 100644 infra/migrations/sqlite/0009_bots.sql create mode 100644 infra/migrations/sqlite/0010_message_privacy_scaling.sql diff --git a/apps/api/cmd/clickclack/main.go b/apps/api/cmd/clickclack/main.go index 88efb77..3af039f 100644 --- a/apps/api/cmd/clickclack/main.go +++ b/apps/api/cmd/clickclack/main.go @@ -10,6 +10,7 @@ import ( "os/signal" "path/filepath" "strings" + "time" "github.com/openclaw/clickclack/apps/api/internal/config" "github.com/openclaw/clickclack/apps/api/internal/httpapi" @@ -270,6 +271,64 @@ func admin(args []string) error { return nil } return json.NewEncoder(os.Stdout).Encode(map[string]any{"bot": bot, "bot_token": token, "token": token.Token}) + case "events": + if len(args) < 2 || args[1] != "prune" { + return fmt.Errorf("usage: clickclack admin events prune --workspace WORKSPACE_ID [--older-than-days DAYS | --before RFC3339] [--keep-latest N]") + } + flags := flag.NewFlagSet("admin events prune", flag.ExitOnError) + data := flags.String("data", "./data", "data directory") + dbURL := flags.String("db", "", "database URL") + workspaceID := flags.String("workspace", "", "workspace id") + olderThanDays := flags.Int("older-than-days", 0, "delete events older than this many days") + before := flags.String("before", "", "delete events created before this RFC3339 timestamp") + keepLatest := flags.Int("keep-latest", 0, "always keep the latest N events in the workspace") + if err := flags.Parse(args[2:]); err != nil { + return err + } + if *workspaceID == "" { + return fmt.Errorf("--workspace is required") + } + if *olderThanDays < 0 { + return fmt.Errorf("--older-than-days must be non-negative") + } + if *keepLatest < 0 { + return fmt.Errorf("--keep-latest must be non-negative") + } + if *olderThanDays > 0 && strings.TrimSpace(*before) != "" { + return fmt.Errorf("--older-than-days and --before are mutually exclusive") + } + cutoff := strings.TrimSpace(*before) + if cutoff != "" { + parsed, err := time.Parse(time.RFC3339Nano, cutoff) + if err != nil { + return fmt.Errorf("--before must be RFC3339: %w", err) + } + cutoff = parsed.UTC().Format(time.RFC3339Nano) + } + if *olderThanDays > 0 { + cutoff = time.Now().UTC().Add(-time.Duration(*olderThanDays) * 24 * time.Hour).Format(time.RFC3339Nano) + } + if cutoff == "" && *keepLatest == 0 { + return fmt.Errorf("provide --older-than-days, --before, or --keep-latest") + } + if err := ensureDirs(*data); err != nil { + return err + } + st, err := sqlitestore.Open(resolveDB(*data, *dbURL)) + if err != nil { + return err + } + defer st.Close() + ctx := context.Background() + if err := st.Migrate(ctx); err != nil { + return err + } + pruned, err := st.PruneEvents(ctx, *workspaceID, *keepLatest, cutoff) + if err != nil { + return err + } + fmt.Printf("pruned %d events\n", pruned) + return nil case "magic-link": if len(args) < 2 || args[1] != "create" { return fmt.Errorf("usage: clickclack admin magic-link create --email EMAIL [--name NAME]") diff --git a/apps/api/internal/httpapi/features.go b/apps/api/internal/httpapi/features.go index 40338b2..a804e04 100644 --- a/apps/api/internal/httpapi/features.go +++ b/apps/api/internal/httpapi/features.go @@ -84,7 +84,7 @@ func (s *Server) search(w http.ResponseWriter, r *http.Request) { writeError(w, http.StatusForbidden, err) return } - results, err := s.store.SearchMessages(r.Context(), workspaceID, act.user.ID, r.URL.Query().Get("q"), queryInt(r, "limit", 50)) + results, err := s.store.SearchMessages(r.Context(), workspaceID, r.URL.Query().Get("channel_id"), act.user.ID, r.URL.Query().Get("q"), queryInt(r, "limit", 50)) writeResult(w, map[string]any{"results": results}, err) } diff --git a/apps/api/internal/store/sqlite/chat_test.go b/apps/api/internal/store/sqlite/chat_test.go index 724a903..16ceb9a 100644 --- a/apps/api/internal/store/sqlite/chat_test.go +++ b/apps/api/internal/store/sqlite/chat_test.go @@ -126,7 +126,7 @@ func TestStoreChatThreadsSearchUploadsAndEvents(t *testing.T) { t.Fatalf("unexpected thread: %#v %#v %#v", threadRoot, replies, threadState) } - results, err := st.SearchMessages(ctx, workspace.ID, owner.ID, "searchable", 10) + results, err := st.SearchMessages(ctx, workspace.ID, "", owner.ID, "searchable", 10) if err != nil { t.Fatal(err) } @@ -656,7 +656,7 @@ func TestStoreBranchCases(t *testing.T) { if _, err := st.ListMessages(ctx, "chn_missing", owner.ID, store.MessagePageRequest{Limit: 10}); err == nil { t.Fatal("expected missing channel list error") } - if results, err := st.SearchMessages(ctx, workspace.ID, owner.ID, "missingterm", 999); err != nil || len(results) != 0 { + if results, err := st.SearchMessages(ctx, workspace.ID, "", owner.ID, "missingterm", 999); err != nil || len(results) != 0 { t.Fatalf("expected no search results, got %#v err=%v", results, err) } if _, err := st.ListEventsAfter(ctx, workspace.ID, owner.ID, "", 999); err != nil { @@ -669,7 +669,7 @@ func TestStoreBranchCases(t *testing.T) { if _, err := st.CreateInvite(ctx, workspace.ID, outsider.ID); err == nil { t.Fatal("expected invite membership error") } - if _, err := st.SearchMessages(ctx, workspace.ID, outsider.ID, "root", 10); err == nil { + if _, err := st.SearchMessages(ctx, workspace.ID, "", outsider.ID, "root", 10); err == nil { t.Fatal("expected search membership error") } diff --git a/apps/api/internal/store/sqlite/dms.go b/apps/api/internal/store/sqlite/dms.go index ba06845..95a9cd7 100644 --- a/apps/api/internal/store/sqlite/dms.go +++ b/apps/api/internal/store/sqlite/dms.go @@ -10,13 +10,15 @@ import ( "github.com/openclaw/clickclack/apps/api/internal/store" ) +const directConversationMemberHydrationBatchSize = 500 + func (s *Store) ListDirectConversations(ctx context.Context, workspaceID, userID string) ([]store.DirectConversation, error) { if err := s.requireMembership(ctx, workspaceID, userID); err != nil { return nil, err } rows, err := s.db.QueryContext(ctx, ` SELECT dc.id, dc.workspace_id, dc.created_at, - COALESCE((SELECT MAX(channel_seq) FROM messages WHERE direct_conversation_id = dc.id), 0) AS last_seq, + COALESCE((SELECT MAX(channel_seq) FROM messages WHERE direct_conversation_id = dc.id AND parent_message_id IS NULL), 0) AS last_seq, COALESCE((SELECT last_read_seq FROM direct_reads WHERE conversation_id = dc.id AND user_id = ?), 0) AS last_read_seq FROM direct_conversations dc JOIN direct_conversation_members dcm ON dcm.conversation_id = dc.id @@ -43,12 +45,16 @@ func (s *Store) ListDirectConversations(ctx context.Context, workspaceID, userID if err := rows.Close(); err != nil { return nil, err } + ids := make([]string, 0, len(out)) + for _, dm := range out { + ids = append(ids, dm.ID) + } + membersByConversation, err := s.directConversationMembersByConversationIDs(ctx, ids) + if err != nil { + return nil, err + } for i := range out { - members, err := s.directConversationMembers(ctx, out[i].ID) - if err != nil { - return nil, err - } - out[i].Members = members + out[i].Members = membersByConversation[out[i].ID] } return out, nil } @@ -57,7 +63,7 @@ func (s *Store) GetDirectConversation(ctx context.Context, conversationID, userI var dm store.DirectConversation if err := s.db.QueryRowContext(ctx, ` SELECT dc.id, dc.workspace_id, dc.created_at, - COALESCE((SELECT MAX(channel_seq) FROM messages WHERE direct_conversation_id = dc.id), 0) AS last_seq, + COALESCE((SELECT MAX(channel_seq) FROM messages WHERE direct_conversation_id = dc.id AND parent_message_id IS NULL), 0) AS last_seq, COALESCE((SELECT last_read_seq FROM direct_reads WHERE conversation_id = dc.id AND user_id = ?), 0) AS last_read_seq FROM direct_conversations dc JOIN direct_conversation_members dcm ON dcm.conversation_id = dc.id @@ -120,7 +126,7 @@ func (s *Store) ListDirectMessages(ctx context.Context, conversationID, userID s return store.MessagePage{}, err } return s.listMessagePage(ctx, messagePageScope{ - where: "m.direct_conversation_id = ?", + where: "m.direct_conversation_id = ? AND m.parent_message_id IS NULL", args: []any{conversationID}, }, page) } @@ -184,7 +190,11 @@ func (s *Store) CreateDirectMessage(ctx context.Context, input store.CreateDirec if _, err := tx.ExecContext(ctx, `INSERT INTO thread_state (root_message_id) VALUES (?)`, id); err != nil { return store.Message{}, store.Event{}, err } - event, err := insertEvent(ctx, tx, workspaceID, "", "message.created", &seq, eventPayload(map[string]string{"message_id": id, "direct_conversation_id": input.ConversationID, "author_id": input.AuthorID}, nonce)) + recipients, err := directConversationMemberIDsTx(ctx, tx, input.ConversationID) + if err != nil { + return store.Message{}, store.Event{}, err + } + event, err := insertEventWithRecipients(ctx, tx, workspaceID, "", "message.created", &seq, eventPayload(map[string]string{"message_id": id, "direct_conversation_id": input.ConversationID, "author_id": input.AuthorID}, nonce), recipients) if err != nil { return store.Message{}, store.Event{}, err } @@ -205,6 +215,27 @@ func requireDirectMembershipTx(ctx context.Context, tx *sql.Tx, conversationID, return tx.QueryRowContext(ctx, `SELECT 1 FROM direct_conversation_members WHERE conversation_id = ? AND user_id = ?`, conversationID, userID).Scan(&one) } +func directConversationMemberIDsTx(ctx context.Context, tx *sql.Tx, conversationID string) ([]string, error) { + rows, err := tx.QueryContext(ctx, ` + SELECT user_id + FROM direct_conversation_members + WHERE conversation_id = ? + ORDER BY user_id`, conversationID) + if err != nil { + return nil, err + } + defer rows.Close() + ids := []string{} + for rows.Next() { + var id string + if err := rows.Scan(&id); err != nil { + return nil, err + } + ids = append(ids, id) + } + return ids, rows.Err() +} + func (s *Store) directConversationMembers(ctx context.Context, conversationID string) ([]store.User, error) { rows, err := s.db.QueryContext(ctx, ` SELECT u.id, u.kind, u.owner_user_id, u.display_name, u.handle, u.avatar_url, u.created_at @@ -227,6 +258,52 @@ func (s *Store) directConversationMembers(ctx context.Context, conversationID st return members, rows.Err() } +func (s *Store) directConversationMembersByConversationIDs(ctx context.Context, conversationIDs []string) (map[string][]store.User, error) { + out := map[string][]store.User{} + if len(conversationIDs) == 0 { + return out, nil + } + for start := 0; start < len(conversationIDs); start += directConversationMemberHydrationBatchSize { + end := min(start+directConversationMemberHydrationBatchSize, len(conversationIDs)) + batch := conversationIDs[start:end] + placeholders := strings.TrimRight(strings.Repeat("?,", len(batch)), ",") + args := make([]any, 0, len(batch)) + for _, id := range batch { + args = append(args, id) + } + rows, err := s.db.QueryContext(ctx, ` + SELECT dcm.conversation_id, u.id, u.kind, u.owner_user_id, u.display_name, u.handle, u.avatar_url, u.created_at + FROM direct_conversation_members dcm + JOIN users u ON u.id = dcm.user_id + WHERE dcm.conversation_id IN (`+placeholders+`) + ORDER BY dcm.conversation_id, u.display_name`, args...) + if err != nil { + return nil, err + } + for rows.Next() { + var conversationID string + var owner sql.NullString + var member store.User + if err := rows.Scan(&conversationID, &member.ID, &member.Kind, &owner, &member.DisplayName, &member.Handle, &member.AvatarURL, &member.CreatedAt); err != nil { + _ = rows.Close() + return nil, err + } + if owner.Valid { + member.OwnerUserID = owner.String + } + out[conversationID] = append(out[conversationID], member) + } + if err := rows.Err(); err != nil { + _ = rows.Close() + return nil, err + } + if err := rows.Close(); err != nil { + return nil, err + } + } + return out, nil +} + func compactStrings(values []string) []string { var out []string for _, value := range values { diff --git a/apps/api/internal/store/sqlite/events.go b/apps/api/internal/store/sqlite/events.go new file mode 100644 index 0000000..2448aeb --- /dev/null +++ b/apps/api/internal/store/sqlite/events.go @@ -0,0 +1,47 @@ +package sqlite + +import ( + "context" + "errors" + "strings" + "time" +) + +// PruneEvents deletes old durable events for a workspace while preserving the +// newest keepLatest events. At least one retention bound is required so callers +// cannot accidentally wipe the whole event log with default zero values. +func (s *Store) PruneEvents(ctx context.Context, workspaceID string, keepLatest int, before string) (int64, error) { + workspaceID = strings.TrimSpace(workspaceID) + before = strings.TrimSpace(before) + if workspaceID == "" { + return 0, errors.New("workspace is required") + } + if keepLatest < 0 { + return 0, errors.New("keep_latest must be non-negative") + } + if keepLatest == 0 && before == "" { + return 0, errors.New("keep_latest or before is required") + } + if before != "" { + parsed, err := time.Parse(time.RFC3339Nano, before) + if err != nil { + return 0, errors.New("before must be RFC3339") + } + before = parsed.UTC().Format(time.RFC3339Nano) + } + result, err := s.db.ExecContext(ctx, ` + DELETE FROM events + WHERE workspace_id = ? + AND (? = '' OR julianday(created_at) < julianday(?)) + AND id NOT IN ( + SELECT id + FROM events + WHERE workspace_id = ? + ORDER BY cursor DESC + LIMIT ? + )`, workspaceID, before, before, workspaceID, keepLatest) + if err != nil { + return 0, err + } + return result.RowsAffected() +} diff --git a/apps/api/internal/store/sqlite/export.go b/apps/api/internal/store/sqlite/export.go index b9a1aed..b6021d4 100644 --- a/apps/api/internal/store/sqlite/export.go +++ b/apps/api/internal/store/sqlite/export.go @@ -16,7 +16,7 @@ func (s *Store) ExportJSON(ctx context.Context, writer io.Writer) error { out := map[string]any{} tables := []string{ "users", "user_notification_settings", "identities", "workspaces", "workspace_members", "channels", - "messages", "thread_state", "reactions", "events", "uploads", + "messages", "thread_state", "reactions", "events", "event_recipients", "uploads", "message_attachments", "direct_conversations", "direct_conversation_members", "invites", "auth_magic_links", "sessions", "bot_tokens", } diff --git a/apps/api/internal/store/sqlite/helpers.go b/apps/api/internal/store/sqlite/helpers.go index 5468673..d44cd82 100644 --- a/apps/api/internal/store/sqlite/helpers.go +++ b/apps/api/internal/store/sqlite/helpers.go @@ -233,10 +233,15 @@ func updateThreadState(ctx context.Context, tx *sql.Tx, rootID, authorID, create } func insertEvent(ctx context.Context, tx *sql.Tx, workspaceID, channelID, eventType string, seq *int64, payload any) (store.Event, error) { + return insertEventWithRecipients(ctx, tx, workspaceID, channelID, eventType, seq, payload, nil) +} + +func insertEventWithRecipients(ctx context.Context, tx *sql.Tx, workspaceID, channelID, eventType string, seq *int64, payload any, recipientUserIDs []string) (store.Event, error) { payloadJSON, err := json.Marshal(payload) if err != nil { return store.Event{}, err } + recipients := compactStrings(recipientUserIDs) event := store.Event{ ID: newID("evt"), Cursor: newID("cur"), @@ -248,9 +253,19 @@ func insertEvent(ctx context.Context, tx *sql.Tx, workspaceID, channelID, eventT PayloadJSON: string(payloadJSON), Payload: payload, } - if _, err := tx.ExecContext(ctx, `INSERT INTO events (id, cursor, workspace_id, channel_id, type, seq, payload_json, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, event.ID, event.Cursor, event.WorkspaceID, nullableString(event.ChannelID), event.Type, event.Seq, event.PayloadJSON, event.CreatedAt); err != nil { + isPrivate := 0 + if len(recipients) > 0 { + isPrivate = 1 + } + if _, err := tx.ExecContext(ctx, `INSERT INTO events (id, cursor, workspace_id, channel_id, type, seq, payload_json, created_at, is_private) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, event.ID, event.Cursor, event.WorkspaceID, nullableString(event.ChannelID), event.Type, event.Seq, event.PayloadJSON, event.CreatedAt, isPrivate); err != nil { return store.Event{}, err } + for _, userID := range recipients { + if _, err := tx.ExecContext(ctx, `INSERT INTO event_recipients (event_id, user_id) VALUES (?, ?)`, event.ID, userID); err != nil { + return store.Event{}, err + } + event.RecipientUserIDs = append(event.RecipientUserIDs, userID) + } return event, nil } diff --git a/apps/api/internal/store/sqlite/message_privacy_scaling_test.go b/apps/api/internal/store/sqlite/message_privacy_scaling_test.go new file mode 100644 index 0000000..8a13215 --- /dev/null +++ b/apps/api/internal/store/sqlite/message_privacy_scaling_test.go @@ -0,0 +1,522 @@ +package sqlite + +import ( + "context" + "path/filepath" + "strings" + "testing" + + "github.com/openclaw/clickclack/apps/api/internal/store" +) + +func TestMessagePrivacyScalingPrivacyAndDMThreads(t *testing.T) { + t.Parallel() + ctx, st, owner, workspace, channel := seededStore(t) + + member, err := st.CreateUser(ctx, store.CreateUserInput{DisplayName: "DM Member", Email: "dm-member@example.com"}) + if err != nil { + t.Fatal(err) + } + workspaceOnly, err := st.CreateUser(ctx, store.CreateUserInput{DisplayName: "Workspace Only", Email: "workspace-only-hardening@example.com"}) + if err != nil { + t.Fatal(err) + } + if err := st.AddWorkspaceMember(ctx, workspace.ID, member.ID, "member"); err != nil { + t.Fatal(err) + } + if err := st.AddWorkspaceMember(ctx, workspace.ID, workspaceOnly.ID, "member"); err != nil { + t.Fatal(err) + } + + publicMessage, _, err := st.CreateMessage(ctx, store.CreateMessageInput{ + ChannelID: channel.ID, + AuthorID: owner.ID, + Body: "public searchable channel text", + }) + if err != nil { + t.Fatal(err) + } + otherChannel, _, err := st.CreateChannel(ctx, store.CreateChannelInput{WorkspaceID: workspace.ID, UserID: owner.ID, Name: "other-hardening"}) + if err != nil { + t.Fatal(err) + } + otherChannelMessage, _, err := st.CreateMessage(ctx, store.CreateMessageInput{ + ChannelID: otherChannel.ID, + AuthorID: owner.ID, + Body: "public searchable other channel text", + }) + if err != nil { + t.Fatal(err) + } + dm, err := st.CreateDirectConversation(ctx, store.CreateDirectConversationInput{WorkspaceID: workspace.ID, UserID: owner.ID, MemberIDs: []string{member.ID}}) + if err != nil { + t.Fatal(err) + } + dmMessage, _, err := st.CreateDirectMessage(ctx, store.CreateDirectMessageInput{ + ConversationID: dm.ID, + AuthorID: owner.ID, + Body: "private searchable dm secret", + }) + if err != nil { + t.Fatal(err) + } + + results, err := st.SearchMessages(ctx, workspace.ID, "", owner.ID, "searchable", 10) + if err != nil { + t.Fatal(err) + } + if len(results) != 2 { + t.Fatalf("expected workspace search to exclude DMs, got %#v", results) + } + scopedResults, err := st.SearchMessages(ctx, workspace.ID, channel.ID, owner.ID, "searchable", 10) + if err != nil { + t.Fatal(err) + } + if len(scopedResults) != 1 || scopedResults[0].Message.ID != publicMessage.ID { + t.Fatalf("expected channel search to stay in channel, got %#v; other=%s", scopedResults, otherChannelMessage.ID) + } + dmOnlyResults, err := st.SearchMessages(ctx, workspace.ID, "", owner.ID, "secret", 10) + if err != nil { + t.Fatal(err) + } + if len(dmOnlyResults) != 0 { + t.Fatalf("expected DM-only search term to be hidden from workspace search, got %#v", dmOnlyResults) + } + + if _, _, err := st.UpdateMessage(ctx, store.UpdateMessageInput{MessageID: dmMessage.ID, UserID: workspaceOnly.ID, Body: "blocked"}); err == nil { + t.Fatal("expected non-DM member to be blocked from updating a DM message") + } + if _, _, err := st.DeleteMessage(ctx, store.DeleteMessageInput{MessageID: dmMessage.ID, UserID: workspaceOnly.ID}); err == nil { + t.Fatal("expected non-DM member to be blocked from deleting a DM message") + } + if _, err := st.AddReaction(ctx, store.CreateReactionInput{MessageID: dmMessage.ID, UserID: workspaceOnly.ID, Emoji: "nope"}); err == nil { + t.Fatal("expected non-DM member to be blocked from reacting to a DM message") + } + upload, err := st.CreateUpload(ctx, store.CreateUploadInput{WorkspaceID: workspace.ID, OwnerID: owner.ID, Filename: "dm.txt", ContentType: "text/plain", ByteSize: 1, StoragePath: "/tmp/dm.txt"}) + if err != nil { + t.Fatal(err) + } + if err := st.AttachUpload(ctx, store.AttachUploadInput{MessageID: dmMessage.ID, UploadID: upload.ID, UserID: workspaceOnly.ID}); err == nil { + t.Fatal("expected non-DM member to be blocked from attaching to a DM message") + } + + reply, state, events, err := st.CreateThreadReply(ctx, store.CreateThreadReplyInput{ + RootMessageID: dmMessage.ID, + AuthorID: member.ID, + Body: "dm thread reply secret", + }) + if err != nil { + t.Fatal(err) + } + if reply.DirectConversationID != dm.ID || reply.ChannelID != "" || state.ReplyCount != 1 || len(events) != 2 { + t.Fatalf("unexpected DM thread reply result: %#v %#v %#v", reply, state, events) + } + page, err := st.ListDirectMessages(ctx, dm.ID, owner.ID, store.MessagePageRequest{Limit: 10}) + if err != nil { + t.Fatal(err) + } + if len(page.Messages) != 1 || page.Messages[0].ID != dmMessage.ID || page.NewestSeq != *dmMessage.ChannelSeq { + t.Fatalf("expected DM root timeline to exclude thread replies, got %#v", page) + } + receipt, readEvent, err := st.MarkDirectRead(ctx, dm.ID, owner.ID, 999) + if err != nil { + t.Fatal(err) + } + if receipt.LastReadSeq != *dmMessage.ChannelSeq || len(readEvent.RecipientUserIDs) != 1 || readEvent.RecipientUserIDs[0] != owner.ID { + t.Fatalf("expected DM read to cap to root sequence and target the reader, got %#v %#v", receipt, readEvent) + } + _, replies, _, err := st.GetThread(ctx, dmMessage.ID, owner.ID, 10) + if err != nil { + t.Fatal(err) + } + if len(replies) != 1 || replies[0].ID != reply.ID || replies[0].DirectConversationID != dm.ID { + t.Fatalf("unexpected DM thread replies: %#v", replies) + } + if _, _, _, err := st.GetThread(ctx, dmMessage.ID, workspaceOnly.ID, 10); err == nil { + t.Fatal("expected non-DM member to be blocked from DM thread") + } + + ownerEvents, err := st.ListEventsAfter(ctx, workspace.ID, owner.ID, "", 50) + if err != nil { + t.Fatal(err) + } + memberEvents, err := st.ListEventsAfter(ctx, workspace.ID, member.ID, "", 50) + if err != nil { + t.Fatal(err) + } + workspaceOnlyEvents, err := st.ListEventsAfter(ctx, workspace.ID, workspaceOnly.ID, "", 50) + if err != nil { + t.Fatal(err) + } + for _, events := range [][]store.Event{ownerEvents, memberEvents} { + if !hasEventForMessage(events, "message.created", dmMessage.ID) { + t.Fatalf("expected DM member event replay to include DM message event: %#v", events) + } + if !hasEventForMessage(events, "thread.reply_created", reply.ID) { + t.Fatalf("expected DM member event replay to include DM thread event: %#v", events) + } + } + if hasEventForMessage(workspaceOnlyEvents, "message.created", dmMessage.ID) || hasEventForMessage(workspaceOnlyEvents, "thread.reply_created", reply.ID) { + t.Fatalf("expected workspace-only member replay to hide DM events, got %#v", workspaceOnlyEvents) + } + for _, event := range workspaceOnlyEvents { + if event.Type == "dm.read" || event.Type == "channel.read" { + t.Fatalf("expected private read receipts to be filtered at replay query, got %#v", workspaceOnlyEvents) + } + } + if _, err := st.db.ExecContext(ctx, `DELETE FROM event_recipients WHERE event_id IN (SELECT id FROM events WHERE type = 'message.created' AND json_extract(payload_json, '$.direct_conversation_id') = ?)`, dm.ID); err != nil { + t.Fatal(err) + } + workspaceOnlyEvents, err = st.ListEventsAfter(ctx, workspace.ID, workspaceOnly.ID, "", 50) + if err != nil { + t.Fatal(err) + } + if hasEventForMessage(workspaceOnlyEvents, "message.created", dmMessage.ID) { + t.Fatalf("expected private event flag to hide DM event even after recipient rows are removed, got %#v", workspaceOnlyEvents) + } +} + +func TestMessagePrivacyScalingMessageShapeAndSequenceGuards(t *testing.T) { + t.Parallel() + ctx, st, owner, workspace, channel := seededStore(t) + root, _, err := st.CreateMessage(ctx, store.CreateMessageInput{ChannelID: channel.ID, AuthorID: owner.ID, Body: "root"}) + if err != nil { + t.Fatal(err) + } + if _, err := st.db.ExecContext(ctx, ` + INSERT INTO messages (id, workspace_id, channel_id, direct_conversation_id, author_id, parent_message_id, thread_root_id, channel_seq, thread_seq, body, body_format, created_at) + VALUES ('msg_invalid_shape', ?, ?, 'dm_fake', ?, NULL, 'msg_invalid_shape', 999, NULL, 'bad', 'markdown', ?)`, + workspace.ID, channel.ID, owner.ID, now()); err == nil { + t.Fatal("expected invalid message shape to be rejected") + } + if _, err := st.db.ExecContext(ctx, ` + INSERT INTO messages (id, workspace_id, channel_id, direct_conversation_id, author_id, parent_message_id, thread_root_id, channel_seq, thread_seq, body, body_format, created_at) + VALUES ('msg_duplicate_seq', ?, ?, NULL, ?, NULL, 'msg_duplicate_seq', ?, NULL, 'dupe', 'markdown', ?)`, + workspace.ID, channel.ID, owner.ID, *root.ChannelSeq, now()); err == nil { + t.Fatal("expected duplicate channel sequence to be rejected") + } + otherRoot, _, err := st.CreateMessage(ctx, store.CreateMessageInput{ChannelID: channel.ID, AuthorID: owner.ID, Body: "other root"}) + if err != nil { + t.Fatal(err) + } + if _, err := st.db.ExecContext(ctx, ` + INSERT INTO messages (id, workspace_id, channel_id, direct_conversation_id, author_id, parent_message_id, thread_root_id, channel_seq, thread_seq, body, body_format, created_at) + VALUES ('msg_mismatched_thread', ?, ?, NULL, ?, ?, ?, NULL, 1, 'bad reply', 'markdown', ?)`, + workspace.ID, channel.ID, owner.ID, root.ID, otherRoot.ID, now()); err == nil { + t.Fatal("expected mismatched parent and thread root to be rejected") + } + otherChannel, _, err := st.CreateChannel(ctx, store.CreateChannelInput{WorkspaceID: workspace.ID, UserID: owner.ID, Name: "wrong-thread-surface"}) + if err != nil { + t.Fatal(err) + } + if _, err := st.db.ExecContext(ctx, ` + INSERT INTO messages (id, workspace_id, channel_id, direct_conversation_id, author_id, parent_message_id, thread_root_id, channel_seq, thread_seq, body, body_format, created_at) + VALUES ('msg_wrong_channel_thread', ?, ?, NULL, ?, ?, ?, NULL, 1, 'bad reply', 'markdown', ?)`, + workspace.ID, otherChannel.ID, owner.ID, root.ID, root.ID, now()); err == nil { + t.Fatal("expected reply on the wrong channel surface to be rejected") + } + if _, err := st.db.ExecContext(ctx, ` + INSERT INTO messages (id, workspace_id, channel_id, direct_conversation_id, author_id, parent_message_id, thread_root_id, channel_seq, thread_seq, body, body_format, created_at) + VALUES ('msg_valid_shape_reply', ?, ?, NULL, ?, ?, ?, NULL, 1, 'valid reply', 'markdown', ?)`, + workspace.ID, channel.ID, owner.ID, root.ID, root.ID, now()); err != nil { + t.Fatalf("expected valid root reply shape to be accepted: %v", err) + } +} + +func TestMessagePrivacyScalingDirectMemberHydrationBatchesLargeInputs(t *testing.T) { + t.Parallel() + ctx, st, _, _, _ := seededStore(t) + ids := make([]string, directConversationMemberHydrationBatchSize+25) + for i := range ids { + ids[i] = "dm_missing_" + strings.Repeat("x", i%8) + } + members, err := st.directConversationMembersByConversationIDs(ctx, ids) + if err != nil { + t.Fatal(err) + } + if len(members) != 0 { + t.Fatalf("expected no members for missing conversations, got %#v", members) + } +} + +func TestMessagePrivacyScalingMigrationBackfillsCurrentMainDMThreadPrivacy(t *testing.T) { + ctx := context.Background() + st, err := Open("sqlite://" + filepath.Join(t.TempDir(), "clickclack.db")) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = st.Close() }) + applySQLiteMigrations(t, ctx, st, "0001_initial.sql", "0002_auth.sql", "0003_user_profiles.sql", "0004_message_quotes.sql", "0005_upload_dimensions.sql", "0006_message_client_nonce.sql", "0007_unread.sql", "0008_message_paging_indexes.sql", "0008_user_notification_settings.sql", "0009_bots.sql") + + const ( + workspaceID = "wsp_migration" + ownerID = "usr_owner" + memberID = "usr_member" + workspaceOnlyID = "usr_workspace_only" + dmID = "dm_private" + rootID = "msg_dm_root" + replyID = "msg_dm_reply" + ) + if _, err := st.db.ExecContext(ctx, `PRAGMA foreign_keys = OFF`); err != nil { + t.Fatal(err) + } + mustExecSQL(t, ctx, st, `INSERT INTO users (id, display_name, avatar_url, created_at) VALUES (?, 'Owner', '', '2026-01-01T00:00:00Z')`, ownerID) + mustExecSQL(t, ctx, st, `INSERT INTO users (id, display_name, avatar_url, created_at) VALUES (?, 'Member', '', '2026-01-01T00:00:00Z')`, memberID) + mustExecSQL(t, ctx, st, `INSERT INTO users (id, display_name, avatar_url, created_at) VALUES (?, 'Workspace Only', '', '2026-01-01T00:00:00Z')`, workspaceOnlyID) + mustExecSQL(t, ctx, st, `INSERT INTO workspaces (id, name, slug, created_at) VALUES (?, 'Workspace', 'workspace', '2026-01-01T00:00:00Z')`, workspaceID) + mustExecSQL(t, ctx, st, `INSERT INTO workspace_members (workspace_id, user_id, role, created_at) VALUES (?, ?, 'owner', '2026-01-01T00:00:00Z')`, workspaceID, ownerID) + mustExecSQL(t, ctx, st, `INSERT INTO workspace_members (workspace_id, user_id, role, created_at) VALUES (?, ?, 'member', '2026-01-01T00:00:00Z')`, workspaceID, memberID) + mustExecSQL(t, ctx, st, `INSERT INTO workspace_members (workspace_id, user_id, role, created_at) VALUES (?, ?, 'member', '2026-01-01T00:00:00Z')`, workspaceID, workspaceOnlyID) + mustExecSQL(t, ctx, st, `INSERT INTO direct_conversations (id, workspace_id, created_at) VALUES (?, ?, '2026-01-01T00:00:00Z')`, dmID, workspaceID) + mustExecSQL(t, ctx, st, `INSERT INTO direct_conversation_members (conversation_id, user_id, created_at) VALUES (?, ?, '2026-01-01T00:00:00Z')`, dmID, ownerID) + mustExecSQL(t, ctx, st, `INSERT INTO direct_conversation_members (conversation_id, user_id, created_at) VALUES (?, ?, '2026-01-01T00:00:00Z')`, dmID, memberID) + mustExecSQL(t, ctx, st, `INSERT INTO messages (id, workspace_id, channel_id, direct_conversation_id, author_id, parent_message_id, thread_root_id, channel_seq, thread_seq, body, body_format, created_at) VALUES (?, ?, NULL, ?, ?, NULL, ?, 1, NULL, 'private root', 'markdown', '2026-01-01T00:00:01Z')`, rootID, workspaceID, dmID, ownerID, rootID) + mustExecSQL(t, ctx, st, `INSERT INTO thread_state (root_message_id, reply_count, last_reply_at, last_reply_author_ids_json) VALUES (?, 1, '2026-01-01T00:00:02Z', '["usr_member"]')`, rootID) + mustExecSQL(t, ctx, st, `INSERT INTO messages (id, workspace_id, channel_id, direct_conversation_id, author_id, parent_message_id, thread_root_id, channel_seq, thread_seq, body, body_format, created_at) VALUES (?, ?, '', NULL, ?, ?, ?, NULL, 1, 'private reply', 'markdown', '2026-01-01T00:00:02Z')`, replyID, workspaceID, memberID, rootID, rootID) + mustExecSQL(t, ctx, st, `INSERT INTO events (id, cursor, workspace_id, channel_id, type, seq, payload_json, created_at) VALUES ('evt_dm_message', 'cur_001', ?, NULL, 'message.created', 1, '{"message_id":"msg_dm_root","direct_conversation_id":"dm_private","author_id":"usr_owner"}', '2026-01-01T00:00:01Z')`, workspaceID) + mustExecSQL(t, ctx, st, `INSERT INTO events (id, cursor, workspace_id, channel_id, type, seq, payload_json, created_at) VALUES ('evt_thread_reply', 'cur_002', ?, NULL, 'thread.reply_created', NULL, '{"message_id":"msg_dm_reply","root_message_id":"msg_dm_root"}', '2026-01-01T00:00:02Z')`, workspaceID) + mustExecSQL(t, ctx, st, `INSERT INTO events (id, cursor, workspace_id, channel_id, type, seq, payload_json, created_at) VALUES ('evt_thread_state', 'cur_003', ?, NULL, 'thread.state_updated', NULL, '{"root_message_id":"msg_dm_root"}', '2026-01-01T00:00:02Z')`, workspaceID) + mustExecSQL(t, ctx, st, `INSERT INTO events (id, cursor, workspace_id, channel_id, type, seq, payload_json, created_at) VALUES ('evt_reply_reaction', 'cur_004', ?, NULL, 'reaction.added', NULL, '{"message_id":"msg_dm_reply","emoji":":ok:"}', '2026-01-01T00:00:03Z')`, workspaceID) + if _, err := st.db.ExecContext(ctx, `PRAGMA foreign_keys = ON`); err != nil { + t.Fatal(err) + } + + applySQLiteMigrations(t, ctx, st, "0010_message_privacy_scaling.sql") + + var replyDM string + var replyChannel any + if err := st.db.QueryRowContext(ctx, `SELECT direct_conversation_id, channel_id FROM messages WHERE id = ?`, replyID).Scan(&replyDM, &replyChannel); err != nil { + t.Fatal(err) + } + if replyDM != dmID || replyChannel != nil { + t.Fatalf("expected migration to attach old DM reply to DM surface, got dm=%q channel=%#v", replyDM, replyChannel) + } + if got := scalarCount(t, ctx, st, `SELECT COUNT(*) FROM events WHERE id IN ('evt_dm_message', 'evt_thread_reply', 'evt_thread_state', 'evt_reply_reaction') AND is_private = 1`); got != 4 { + t.Fatalf("expected all historical DM events to be private, got %d", got) + } + if got := scalarCount(t, ctx, st, `SELECT COUNT(*) FROM event_recipients WHERE event_id IN ('evt_thread_reply', 'evt_thread_state', 'evt_reply_reaction')`); got != 6 { + t.Fatalf("expected historical DM thread/reaction events to be recipient-scoped, got %d", got) + } + workspaceOnlyEvents, err := st.ListEventsAfter(ctx, workspaceID, workspaceOnlyID, "", 20) + if err != nil { + t.Fatal(err) + } + if len(workspaceOnlyEvents) != 0 { + t.Fatalf("expected workspace-only member to see no private historical DM events, got %#v", workspaceOnlyEvents) + } +} + +func TestMessagePrivacyScalingHotPathQueryPlans(t *testing.T) { + t.Parallel() + ctx, st, _, _, _ := seededStore(t) + for _, tc := range []struct { + name string + query string + args []any + wantIndex string + }{ + { + name: "channel page", + query: `EXPLAIN QUERY PLAN SELECT m.id FROM messages m WHERE m.channel_id = ? AND m.parent_message_id IS NULL ORDER BY m.channel_seq DESC LIMIT ?`, + args: []any{"chn_x", 100}, + wantIndex: "idx_messages_channel_root_page", + }, + { + name: "dm page", + query: `EXPLAIN QUERY PLAN SELECT m.id FROM messages m WHERE m.direct_conversation_id = ? AND m.parent_message_id IS NULL ORDER BY m.channel_seq DESC LIMIT ?`, + args: []any{"dm_x", 100}, + wantIndex: "idx_messages_direct_page", + }, + { + name: "dm sidebar membership", + query: `EXPLAIN QUERY PLAN SELECT dc.id FROM direct_conversation_members dcm JOIN direct_conversations dc ON dc.id = dcm.conversation_id WHERE dcm.user_id = ? ORDER BY dc.created_at`, + args: []any{"usr_x"}, + wantIndex: "idx_direct_conversation_members_user", + }, + { + name: "attachment hydration", + query: `EXPLAIN QUERY PLAN SELECT u.id FROM message_attachments ma JOIN uploads u ON u.id = ma.upload_id WHERE ma.message_id = ? ORDER BY ma.created_at`, + args: []any{"msg_x"}, + wantIndex: "idx_message_attachments_message_created", + }, + { + name: "event replay", + query: `EXPLAIN QUERY PLAN + SELECT e.id + FROM events e + WHERE e.workspace_id = ? AND e.cursor > ? + AND ( + e.is_private = 0 + OR EXISTS (SELECT 1 FROM event_recipients er WHERE er.event_id = e.id AND er.user_id = ?) + ) + ORDER BY e.cursor + LIMIT ?`, + args: []any{"wsp_x", "cur_x", "usr_x", 200}, + wantIndex: "idx_events_workspace_cursor", + }, + } { + t.Run(tc.name, func(t *testing.T) { + plan := explainQueryPlan(t, ctx, st, tc.query, tc.args...) + if !strings.Contains(plan, tc.wantIndex) { + t.Fatalf("expected query plan to use %s, got:\n%s", tc.wantIndex, plan) + } + }) + } +} + +func TestMessagePrivacyScalingEventPruning(t *testing.T) { + t.Parallel() + ctx, st, owner, workspace, channel := seededStore(t) + message, _, err := st.CreateMessage(ctx, store.CreateMessageInput{ChannelID: channel.ID, AuthorID: owner.ID, Body: "event prune message"}) + if err != nil { + t.Fatal(err) + } + if _, _, err := st.MarkChannelRead(ctx, channel.ID, owner.ID, *message.ChannelSeq); err != nil { + t.Fatal(err) + } + if got := scalarCount(t, ctx, st, `SELECT COUNT(*) FROM event_recipients`); got == 0 { + t.Fatal("expected private read event recipients before pruning") + } + if _, err := st.PruneEvents(ctx, workspace.ID, 0, ""); err == nil { + t.Fatal("expected prune without retention bounds to be rejected") + } + if _, err := st.PruneEvents(ctx, "", 1, ""); err == nil { + t.Fatal("expected prune without workspace to be rejected") + } + if _, err := st.PruneEvents(ctx, workspace.ID, -1, ""); err == nil { + t.Fatal("expected prune with negative keep_latest to be rejected") + } + if _, err := st.PruneEvents(ctx, workspace.ID, 0, "not-a-time"); err == nil { + t.Fatal("expected prune with invalid cutoff to be rejected") + } + pruned, err := st.PruneEvents(ctx, workspace.ID, 0, "9999-01-01T00:00:00Z") + if err != nil { + t.Fatal(err) + } + if pruned == 0 { + t.Fatal("expected pruning to delete events") + } + if got := scalarCount(t, ctx, st, `SELECT COUNT(*) FROM events WHERE workspace_id = ?`, workspace.ID); got != 0 { + t.Fatalf("expected all workspace events to be pruned, got %d", got) + } + if got := scalarCount(t, ctx, st, `SELECT COUNT(*) FROM event_recipients`); got != 0 { + t.Fatalf("expected event recipient rows to cascade on prune, got %d", got) + } + + for i := 0; i < 3; i++ { + if _, _, err := st.CreateMessage(ctx, store.CreateMessageInput{ChannelID: channel.ID, AuthorID: owner.ID, Body: "event keep latest"}); err != nil { + t.Fatal(err) + } + } + pruned, err = st.PruneEvents(ctx, workspace.ID, 1, "") + if err != nil { + t.Fatal(err) + } + if pruned != 2 { + t.Fatalf("expected keep_latest prune to delete 2 events, got %d", pruned) + } + if got := scalarCount(t, ctx, st, `SELECT COUNT(*) FROM events WHERE workspace_id = ?`, workspace.ID); got != 1 { + t.Fatalf("expected latest event to be retained, got %d", got) + } +} + +func TestMessagePrivacyScalingEventPruningUsesTimestampCutoff(t *testing.T) { + t.Parallel() + ctx, st, _, workspace, _ := seededStore(t) + mustExecSQL(t, ctx, st, `DELETE FROM event_recipients`) + mustExecSQL(t, ctx, st, `DELETE FROM events WHERE workspace_id = ?`, workspace.ID) + mustExecSQL(t, ctx, st, ` + INSERT INTO events (id, cursor, workspace_id, channel_id, type, seq, payload_json, created_at, is_private) + VALUES + ('evt_before_cutoff', 'cur_prune_001', ?, NULL, 'test.before', NULL, '{}', '2025-12-31T23:59:59.999999999Z', 0), + ('evt_at_cutoff', 'cur_prune_002', ?, NULL, 'test.equal', NULL, '{}', '2026-01-01T00:00:00Z', 0), + ('evt_after_fractional_cutoff', 'cur_prune_003', ?, NULL, 'test.after', NULL, '{}', '2026-01-01T00:00:00.5Z', 0) + `, workspace.ID, workspace.ID, workspace.ID) + + pruned, err := st.PruneEvents(ctx, workspace.ID, 0, "2026-01-01T00:00:00Z") + if err != nil { + t.Fatal(err) + } + if pruned != 1 { + t.Fatalf("expected only event before cutoff to be pruned, got %d", pruned) + } + if got := scalarCount(t, ctx, st, `SELECT COUNT(*) FROM events WHERE id = 'evt_before_cutoff'`); got != 0 { + t.Fatalf("expected event before cutoff to be deleted, got %d", got) + } + if got := scalarCount(t, ctx, st, `SELECT COUNT(*) FROM events WHERE id = 'evt_at_cutoff'`); got != 1 { + t.Fatalf("expected event exactly at cutoff to be retained, got %d", got) + } + if got := scalarCount(t, ctx, st, `SELECT COUNT(*) FROM events WHERE id = 'evt_after_fractional_cutoff'`); got != 1 { + t.Fatalf("expected fractional event after cutoff to be retained, got %d", got) + } +} + +func hasEventForMessage(events []store.Event, eventType, messageID string) bool { + for _, event := range events { + if event.Type != eventType { + continue + } + switch payload := event.Payload.(type) { + case map[string]string: + if payload["message_id"] == messageID { + return true + } + case map[string]any: + if got, _ := payload["message_id"].(string); got == messageID { + return true + } + } + } + return false +} + +func scalarCount(t *testing.T, ctx context.Context, st *Store, query string, args ...any) int64 { + t.Helper() + var count int64 + if err := st.db.QueryRowContext(ctx, query, args...).Scan(&count); err != nil { + t.Fatal(err) + } + return count +} + +func explainQueryPlan(t *testing.T, ctx context.Context, st *Store, query string, args ...any) string { + t.Helper() + rows, err := st.db.QueryContext(ctx, query, args...) + if err != nil { + t.Fatal(err) + } + defer rows.Close() + var details []string + for rows.Next() { + var id, parent, notUsed int + var detail string + if err := rows.Scan(&id, &parent, ¬Used, &detail); err != nil { + t.Fatal(err) + } + details = append(details, detail) + } + if err := rows.Err(); err != nil { + t.Fatal(err) + } + return strings.Join(details, "\n") +} + +func applySQLiteMigrations(t *testing.T, ctx context.Context, st *Store, names ...string) { + t.Helper() + for _, name := range names { + body, err := migrationsFS.ReadFile("migrations/" + name) + if err != nil { + t.Fatal(err) + } + if _, err := st.db.ExecContext(ctx, string(body)); err != nil { + t.Fatalf("%s: %v", name, err) + } + } +} + +func mustExecSQL(t *testing.T, ctx context.Context, st *Store, query string, args ...any) { + t.Helper() + if _, err := st.db.ExecContext(ctx, query, args...); err != nil { + t.Fatal(err) + } +} diff --git a/apps/api/internal/store/sqlite/migrations/0010_message_privacy_scaling.sql b/apps/api/internal/store/sqlite/migrations/0010_message_privacy_scaling.sql new file mode 100644 index 0000000..3ad9d1c --- /dev/null +++ b/apps/api/internal/store/sqlite/migrations/0010_message_privacy_scaling.sql @@ -0,0 +1,296 @@ +CREATE INDEX IF NOT EXISTS idx_direct_conversation_members_user + ON direct_conversation_members(user_id, conversation_id); + +CREATE INDEX IF NOT EXISTS idx_message_attachments_message_created + ON message_attachments(message_id, created_at, upload_id); + +DROP INDEX IF EXISTS idx_messages_direct_page; + +CREATE INDEX IF NOT EXISTS idx_messages_direct_page + ON messages(direct_conversation_id, parent_message_id, channel_seq) + WHERE direct_conversation_id IS NOT NULL + AND parent_message_id IS NULL; + +CREATE UNIQUE INDEX IF NOT EXISTS idx_messages_channel_root_unique_seq + ON messages(channel_id, channel_seq) + WHERE channel_id IS NOT NULL + AND parent_message_id IS NULL + AND channel_seq IS NOT NULL; + +CREATE UNIQUE INDEX IF NOT EXISTS idx_messages_direct_unique_seq + ON messages(direct_conversation_id, channel_seq) + WHERE direct_conversation_id IS NOT NULL + AND parent_message_id IS NULL + AND channel_seq IS NOT NULL; + +CREATE UNIQUE INDEX IF NOT EXISTS idx_messages_thread_unique_seq + ON messages(thread_root_id, thread_seq) + WHERE parent_message_id IS NOT NULL + AND thread_seq IS NOT NULL; + +ALTER TABLE events ADD COLUMN is_private INTEGER NOT NULL DEFAULT 0 CHECK (is_private IN (0, 1)); + +CREATE TABLE IF NOT EXISTS event_recipients ( + event_id TEXT NOT NULL REFERENCES events(id) ON DELETE CASCADE, + user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE, + PRIMARY KEY (event_id, user_id) +); + +CREATE INDEX IF NOT EXISTS idx_event_recipients_user_event + ON event_recipients(user_id, event_id); + +UPDATE messages +SET channel_id = NULL, + direct_conversation_id = ( + SELECT root.direct_conversation_id + FROM messages root + WHERE root.id = messages.thread_root_id + ) +WHERE parent_message_id IS NOT NULL + AND (direct_conversation_id IS NULL OR direct_conversation_id = '') + AND EXISTS ( + SELECT 1 + FROM messages root + WHERE root.id = messages.thread_root_id + AND root.parent_message_id IS NULL + AND root.direct_conversation_id IS NOT NULL + AND root.direct_conversation_id <> '' + ); + +INSERT OR IGNORE INTO event_recipients (event_id, user_id) +SELECT e.id, dcm.user_id +FROM events e +JOIN direct_conversation_members dcm + ON dcm.conversation_id = json_extract(e.payload_json, '$.direct_conversation_id') +WHERE json_extract(e.payload_json, '$.direct_conversation_id') IS NOT NULL + AND json_extract(e.payload_json, '$.direct_conversation_id') <> ''; + +INSERT OR IGNORE INTO event_recipients (event_id, user_id) +SELECT e.id, dcm.user_id +FROM events e +JOIN messages m + ON m.id = json_extract(e.payload_json, '$.message_id') +JOIN direct_conversation_members dcm + ON dcm.conversation_id = m.direct_conversation_id +WHERE json_extract(e.payload_json, '$.message_id') IS NOT NULL + AND json_extract(e.payload_json, '$.message_id') <> '' + AND m.direct_conversation_id IS NOT NULL + AND m.direct_conversation_id <> ''; + +INSERT OR IGNORE INTO event_recipients (event_id, user_id) +SELECT e.id, dcm.user_id +FROM events e +JOIN messages root + ON root.id = json_extract(e.payload_json, '$.root_message_id') +JOIN direct_conversation_members dcm + ON dcm.conversation_id = root.direct_conversation_id +WHERE json_extract(e.payload_json, '$.root_message_id') IS NOT NULL + AND json_extract(e.payload_json, '$.root_message_id') <> '' + AND root.parent_message_id IS NULL + AND root.direct_conversation_id IS NOT NULL + AND root.direct_conversation_id <> ''; + +INSERT OR IGNORE INTO event_recipients (event_id, user_id) +SELECT e.id, u.id +FROM events e +JOIN users u + ON u.id = json_extract(e.payload_json, '$.user_id') +WHERE e.type IN ('channel.read', 'dm.read') + AND json_extract(e.payload_json, '$.user_id') IS NOT NULL + AND json_extract(e.payload_json, '$.user_id') <> ''; + +UPDATE events +SET is_private = 1 +WHERE json_extract(payload_json, '$.direct_conversation_id') IS NOT NULL + AND json_extract(payload_json, '$.direct_conversation_id') <> ''; + +UPDATE events +SET is_private = 1 +WHERE type IN ('channel.read', 'dm.read') + AND json_extract(payload_json, '$.user_id') IS NOT NULL + AND json_extract(payload_json, '$.user_id') <> ''; + +UPDATE events +SET is_private = 1 +WHERE EXISTS ( + SELECT 1 + FROM event_recipients er + WHERE er.event_id = events.id +); + +UPDATE events +SET is_private = 1 +WHERE EXISTS ( + SELECT 1 + FROM messages m + WHERE m.id = json_extract(events.payload_json, '$.message_id') + AND m.direct_conversation_id IS NOT NULL + AND m.direct_conversation_id <> '' +); + +UPDATE events +SET is_private = 1 +WHERE EXISTS ( + SELECT 1 + FROM messages root + WHERE root.id = json_extract(events.payload_json, '$.root_message_id') + AND root.parent_message_id IS NULL + AND root.direct_conversation_id IS NOT NULL + AND root.direct_conversation_id <> '' +); + +CREATE TRIGGER IF NOT EXISTS event_recipients_mark_private +AFTER INSERT ON event_recipients +BEGIN + UPDATE events SET is_private = 1 WHERE id = NEW.event_id; +END; + +CREATE TRIGGER IF NOT EXISTS messages_shape_insert +BEFORE INSERT ON messages +WHEN NOT ( + ( + NEW.parent_message_id IS NULL + AND NEW.channel_id IS NOT NULL + AND NEW.direct_conversation_id IS NULL + AND NEW.thread_root_id = NEW.id + AND NEW.channel_seq IS NOT NULL + AND NEW.thread_seq IS NULL + AND EXISTS ( + SELECT 1 + FROM channels c + WHERE c.id = NEW.channel_id + AND c.workspace_id = NEW.workspace_id + ) + ) + OR + ( + NEW.parent_message_id IS NULL + AND NEW.channel_id IS NULL + AND NEW.direct_conversation_id IS NOT NULL + AND NEW.thread_root_id = NEW.id + AND NEW.channel_seq IS NOT NULL + AND NEW.thread_seq IS NULL + AND EXISTS ( + SELECT 1 + FROM direct_conversations dc + WHERE dc.id = NEW.direct_conversation_id + AND dc.workspace_id = NEW.workspace_id + ) + ) + OR + ( + NEW.parent_message_id IS NOT NULL + AND NEW.parent_message_id = NEW.thread_root_id + AND NEW.channel_seq IS NULL + AND NEW.thread_seq IS NOT NULL + AND ( + ( + NEW.channel_id IS NOT NULL + AND NEW.direct_conversation_id IS NULL + AND EXISTS ( + SELECT 1 + FROM messages root + WHERE root.id = NEW.thread_root_id + AND root.parent_message_id IS NULL + AND root.thread_root_id = root.id + AND root.workspace_id = NEW.workspace_id + AND root.channel_id = NEW.channel_id + AND root.direct_conversation_id IS NULL + ) + ) + OR + ( + NEW.channel_id IS NULL + AND NEW.direct_conversation_id IS NOT NULL + AND EXISTS ( + SELECT 1 + FROM messages root + WHERE root.id = NEW.thread_root_id + AND root.parent_message_id IS NULL + AND root.thread_root_id = root.id + AND root.workspace_id = NEW.workspace_id + AND root.channel_id IS NULL + AND root.direct_conversation_id = NEW.direct_conversation_id + ) + ) + ) + ) +) +BEGIN + SELECT RAISE(ABORT, 'invalid message shape'); +END; + +CREATE TRIGGER IF NOT EXISTS messages_shape_update +BEFORE UPDATE OF channel_id, direct_conversation_id, parent_message_id, thread_root_id, channel_seq, thread_seq ON messages +WHEN NOT ( + ( + NEW.parent_message_id IS NULL + AND NEW.channel_id IS NOT NULL + AND NEW.direct_conversation_id IS NULL + AND NEW.thread_root_id = NEW.id + AND NEW.channel_seq IS NOT NULL + AND NEW.thread_seq IS NULL + AND EXISTS ( + SELECT 1 + FROM channels c + WHERE c.id = NEW.channel_id + AND c.workspace_id = NEW.workspace_id + ) + ) + OR + ( + NEW.parent_message_id IS NULL + AND NEW.channel_id IS NULL + AND NEW.direct_conversation_id IS NOT NULL + AND NEW.thread_root_id = NEW.id + AND NEW.channel_seq IS NOT NULL + AND NEW.thread_seq IS NULL + AND EXISTS ( + SELECT 1 + FROM direct_conversations dc + WHERE dc.id = NEW.direct_conversation_id + AND dc.workspace_id = NEW.workspace_id + ) + ) + OR + ( + NEW.parent_message_id IS NOT NULL + AND NEW.parent_message_id = NEW.thread_root_id + AND NEW.channel_seq IS NULL + AND NEW.thread_seq IS NOT NULL + AND ( + ( + NEW.channel_id IS NOT NULL + AND NEW.direct_conversation_id IS NULL + AND EXISTS ( + SELECT 1 + FROM messages root + WHERE root.id = NEW.thread_root_id + AND root.parent_message_id IS NULL + AND root.thread_root_id = root.id + AND root.workspace_id = NEW.workspace_id + AND root.channel_id = NEW.channel_id + AND root.direct_conversation_id IS NULL + ) + ) + OR + ( + NEW.channel_id IS NULL + AND NEW.direct_conversation_id IS NOT NULL + AND EXISTS ( + SELECT 1 + FROM messages root + WHERE root.id = NEW.thread_root_id + AND root.parent_message_id IS NULL + AND root.thread_root_id = root.id + AND root.workspace_id = NEW.workspace_id + AND root.channel_id IS NULL + AND root.direct_conversation_id = NEW.direct_conversation_id + ) + ) + ) + ) +) +BEGIN + SELECT RAISE(ABORT, 'invalid message shape'); +END; diff --git a/apps/api/internal/store/sqlite/misc_test.go b/apps/api/internal/store/sqlite/misc_test.go index 55d7c6a..d1c2b1e 100644 --- a/apps/api/internal/store/sqlite/misc_test.go +++ b/apps/api/internal/store/sqlite/misc_test.go @@ -235,7 +235,7 @@ func TestStoreMiscBranches(t *testing.T) { if replies[len(replies)-1].EditedAt == nil || replies[len(replies)-1].DeletedAt == nil { t.Fatalf("expected edited/deleted reply fields, got %#v", replies[len(replies)-1]) } - results, err := st.SearchMessages(ctx, workspaces[0].ID, owner.ID, "reply", 10) + results, err := st.SearchMessages(ctx, workspaces[0].ID, "", owner.ID, "reply", 10) if err != nil { t.Fatal(err) } diff --git a/apps/api/internal/store/sqlite/mutations.go b/apps/api/internal/store/sqlite/mutations.go index fa9526e..9f4b4c6 100644 --- a/apps/api/internal/store/sqlite/mutations.go +++ b/apps/api/internal/store/sqlite/mutations.go @@ -2,6 +2,7 @@ package sqlite import ( "context" + "database/sql" "errors" "strings" @@ -64,9 +65,12 @@ func (s *Store) UpdateMessage(ctx context.Context, input store.UpdateMessageInpu if err != nil { return store.Message{}, store.Event{}, err } - if err := requireMembershipTx(ctx, tx, msg.WorkspaceID, input.UserID); err != nil { + if err := requireMessageAccessTx(ctx, tx, msg, input.UserID); err != nil { return store.Message{}, store.Event{}, err } + if msg.AuthorID != input.UserID { + return store.Message{}, store.Event{}, errors.New("only the author can edit a message") + } body := strings.TrimSpace(input.Body) if body == "" { return store.Message{}, store.Event{}, errors.New("message body is required") @@ -76,7 +80,11 @@ func (s *Store) UpdateMessage(ctx context.Context, input store.UpdateMessageInpu return store.Message{}, store.Event{}, err } payload := messagePayload(msg) - event, err := insertEvent(ctx, tx, msg.WorkspaceID, msg.ChannelID, "message.updated", msg.ChannelSeq, payload) + recipients, err := eventRecipientsForMessageTx(ctx, tx, msg) + if err != nil { + return store.Message{}, store.Event{}, err + } + event, err := insertEventWithRecipients(ctx, tx, msg.WorkspaceID, msg.ChannelID, "message.updated", msg.ChannelSeq, payload, recipients) if err != nil { return store.Message{}, store.Event{}, err } @@ -95,14 +103,21 @@ func (s *Store) DeleteMessage(ctx context.Context, input store.DeleteMessageInpu if err != nil { return store.Message{}, store.Event{}, err } - if err := requireMembershipTx(ctx, tx, msg.WorkspaceID, input.UserID); err != nil { + if err := requireMessageAccessTx(ctx, tx, msg, input.UserID); err != nil { return store.Message{}, store.Event{}, err } + if msg.AuthorID != input.UserID { + return store.Message{}, store.Event{}, errors.New("only the author can delete a message") + } deletedAt := now() if _, err := tx.ExecContext(ctx, `UPDATE messages SET body = '', deleted_at = ? WHERE id = ?`, deletedAt, msg.ID); err != nil { return store.Message{}, store.Event{}, err } - event, err := insertEvent(ctx, tx, msg.WorkspaceID, msg.ChannelID, "message.deleted", msg.ChannelSeq, messagePayload(msg)) + recipients, err := eventRecipientsForMessageTx(ctx, tx, msg) + if err != nil { + return store.Message{}, store.Event{}, err + } + event, err := insertEventWithRecipients(ctx, tx, msg.WorkspaceID, msg.ChannelID, "message.deleted", msg.ChannelSeq, messagePayload(msg), recipients) if err != nil { return store.Message{}, store.Event{}, err } @@ -118,3 +133,10 @@ func messagePayload(msg store.Message) map[string]string { } return payload } + +func eventRecipientsForMessageTx(ctx context.Context, tx *sql.Tx, msg store.Message) ([]string, error) { + if msg.DirectConversationID == "" { + return nil, nil + } + return directConversationMemberIDsTx(ctx, tx, msg.DirectConversationID) +} diff --git a/apps/api/internal/store/sqlite/mutations_test.go b/apps/api/internal/store/sqlite/mutations_test.go index fe6f4bb..47cf298 100644 --- a/apps/api/internal/store/sqlite/mutations_test.go +++ b/apps/api/internal/store/sqlite/mutations_test.go @@ -75,14 +75,20 @@ func TestMutationsCreateDurableEvents(t *testing.T) { if err != nil { t.Fatal(err) } - updatedDM, dmEvent, err := st.UpdateMessage(ctx, store.UpdateMessageInput{MessageID: dmMessage.ID, UserID: second.ID, Body: "dm after"}) + if _, _, err := st.UpdateMessage(ctx, store.UpdateMessageInput{MessageID: dmMessage.ID, UserID: second.ID, Body: "dm after"}); err == nil { + t.Fatal("expected non-author DM member update to be rejected") + } + updatedDM, dmEvent, err := st.UpdateMessage(ctx, store.UpdateMessageInput{MessageID: dmMessage.ID, UserID: owner.ID, Body: "dm after"}) if err != nil { t.Fatal(err) } if updatedDM.DirectConversationID != dm.ID || dmEvent.ChannelID != "" { t.Fatalf("unexpected dm update: %#v %#v", updatedDM, dmEvent) } - if _, _, err := st.DeleteMessage(ctx, store.DeleteMessageInput{MessageID: dmMessage.ID, UserID: second.ID}); err != nil { + if _, _, err := st.DeleteMessage(ctx, store.DeleteMessageInput{MessageID: dmMessage.ID, UserID: second.ID}); err == nil { + t.Fatal("expected non-author DM member delete to be rejected") + } + if _, _, err := st.DeleteMessage(ctx, store.DeleteMessageInput{MessageID: dmMessage.ID, UserID: owner.ID}); err != nil { t.Fatal(err) } events, err := st.ListEventsAfter(ctx, workspaces[0].ID, owner.ID, "", 20) @@ -145,6 +151,19 @@ func TestMutationsRejectInvalidInput(t *testing.T) { if _, _, err := st.DeleteMessage(ctx, store.DeleteMessageInput{MessageID: message.ID, UserID: outsider.ID}); err == nil { t.Fatal("expected outsider message delete error") } + member, err := st.CreateUser(ctx, store.CreateUserInput{DisplayName: "Member", Email: "member-mutations@example.com"}) + if err != nil { + t.Fatal(err) + } + if err := st.AddWorkspaceMember(ctx, workspaces[0].ID, member.ID, "member"); err != nil { + t.Fatal(err) + } + if _, _, err := st.UpdateMessage(ctx, store.UpdateMessageInput{MessageID: message.ID, UserID: member.ID, Body: "nope"}); err == nil { + t.Fatal("expected non-author member message update error") + } + if _, _, err := st.DeleteMessage(ctx, store.DeleteMessageInput{MessageID: message.ID, UserID: member.ID}); err == nil { + t.Fatal("expected non-author member message delete error") + } } func TestMutationsReturnOutboxErrors(t *testing.T) { diff --git a/apps/api/internal/store/sqlite/reads.go b/apps/api/internal/store/sqlite/reads.go index 4b357fa..3552e40 100644 --- a/apps/api/internal/store/sqlite/reads.go +++ b/apps/api/internal/store/sqlite/reads.go @@ -50,10 +50,10 @@ func (s *Store) MarkChannelRead(ctx context.Context, channelID, userID string, s channelID, userID, seq, at); err != nil { return store.ReadReceipt{}, store.Event{}, err } - event, err := insertEvent(ctx, tx, workspaceID, channelID, "channel.read", &seq, map[string]string{ + event, err := insertEventWithRecipients(ctx, tx, workspaceID, channelID, "channel.read", &seq, map[string]string{ "channel_id": channelID, "user_id": userID, - }) + }, []string{userID}) if err != nil { return store.ReadReceipt{}, store.Event{}, err } @@ -78,7 +78,7 @@ func (s *Store) MarkDirectRead(ctx context.Context, conversationID, userID strin return store.ReadReceipt{}, store.Event{}, err } var lastSeq int64 - if err := tx.QueryRowContext(ctx, `SELECT COALESCE(MAX(channel_seq), 0) FROM messages WHERE direct_conversation_id = ?`, conversationID).Scan(&lastSeq); err != nil { + if err := tx.QueryRowContext(ctx, `SELECT COALESCE(MAX(channel_seq), 0) FROM messages WHERE direct_conversation_id = ? AND parent_message_id IS NULL`, conversationID).Scan(&lastSeq); err != nil { return store.ReadReceipt{}, store.Event{}, err } if seq > lastSeq { @@ -98,10 +98,10 @@ func (s *Store) MarkDirectRead(ctx context.Context, conversationID, userID strin conversationID, userID, seq, at); err != nil { return store.ReadReceipt{}, store.Event{}, err } - event, err := insertEvent(ctx, tx, workspaceID, "", "dm.read", &seq, map[string]string{ + event, err := insertEventWithRecipients(ctx, tx, workspaceID, "", "dm.read", &seq, map[string]string{ "direct_conversation_id": conversationID, "user_id": userID, - }) + }, []string{userID}) if err != nil { return store.ReadReceipt{}, store.Event{}, err } diff --git a/apps/api/internal/store/sqlite/search.go b/apps/api/internal/store/sqlite/search.go index d6ed0a5..a61b140 100644 --- a/apps/api/internal/store/sqlite/search.go +++ b/apps/api/internal/store/sqlite/search.go @@ -8,7 +8,7 @@ import ( "github.com/openclaw/clickclack/apps/api/internal/store" ) -func (s *Store) SearchMessages(ctx context.Context, workspaceID, userID, query string, limit int) ([]store.SearchResult, error) { +func (s *Store) SearchMessages(ctx context.Context, workspaceID, channelID, userID, query string, limit int) ([]store.SearchResult, error) { if limit <= 0 || limit > 100 { limit = 50 } @@ -19,6 +19,13 @@ func (s *Store) SearchMessages(ctx context.Context, workspaceID, userID, query s if query == "" { return []store.SearchResult{}, nil } + channelWhere := "" + args := []any{workspaceID, query} + if channelID != "" { + channelWhere = " AND m.channel_id = ?" + args = append(args, channelID) + } + args = append(args, limit) rows, err := s.db.QueryContext(ctx, ` SELECT m.id, m.workspace_id, COALESCE(m.channel_id, ''), COALESCE(m.direct_conversation_id, ''), m.author_id, m.parent_message_id, m.thread_root_id, m.channel_seq, m.thread_seq, m.body, m.body_format, m.created_at, m.edited_at, m.deleted_at, @@ -30,9 +37,13 @@ func (s *Store) SearchMessages(ctx context.Context, workspaceID, userID, query s JOIN messages m ON m.id = messages_fts.message_id JOIN users u ON u.id = m.author_id LEFT JOIN users qu ON qu.id = m.quoted_author_id - WHERE messages_fts.workspace_id = ? AND messages_fts MATCH ? + WHERE messages_fts.workspace_id = ? + AND messages_fts MATCH ? + AND m.direct_conversation_id IS NULL + AND m.channel_id IS NOT NULL + `+channelWhere+` ORDER BY rank - LIMIT ?`, workspaceID, query, limit) + LIMIT ?`, args...) if err != nil { return nil, err } diff --git a/apps/api/internal/store/sqlite/sqlite.go b/apps/api/internal/store/sqlite/sqlite.go index 7511aa0..3715096 100644 --- a/apps/api/internal/store/sqlite/sqlite.go +++ b/apps/api/internal/store/sqlite/sqlite.go @@ -331,18 +331,16 @@ func (s *Store) requireMessageAccess(ctx context.Context, message store.Message, if message.DirectConversationID != "" { return s.requireDirectMembership(ctx, message.DirectConversationID, userID) } - if message.ParentMessageID != nil && message.ThreadRootID != "" && message.ChannelID == "" { - root, err := getMessage(ctx, s.db, message.ThreadRootID) - if err != nil { - return err - } - if root.DirectConversationID != "" { - return s.requireDirectMembership(ctx, root.DirectConversationID, userID) - } - } return s.requireMembership(ctx, message.WorkspaceID, userID) } +func requireMessageAccessTx(ctx context.Context, tx *sql.Tx, message store.Message, userID string) error { + if message.DirectConversationID != "" { + return requireDirectMembershipTx(ctx, tx, message.DirectConversationID, userID) + } + return requireMembershipTx(ctx, tx, message.WorkspaceID, userID) +} + func (s *Store) CreateMessage(ctx context.Context, input store.CreateMessageInput) (store.Message, store.Event, error) { tx, err := s.db.BeginTx(ctx, nil) if err != nil { @@ -424,7 +422,7 @@ func (s *Store) GetThread(ctx context.Context, rootMessageID, userID string, lim if root.ParentMessageID != nil { return store.Message{}, nil, store.ThreadState{}, errors.New("thread root must be a root message") } - if err := s.requireMembership(ctx, root.WorkspaceID, userID); err != nil { + if err := s.requireMessageAccess(ctx, root, userID); err != nil { return store.Message{}, nil, store.ThreadState{}, err } roots, err := s.hydrateAttachments(ctx, []store.Message{root}) @@ -465,7 +463,7 @@ func (s *Store) CreateThreadReply(ctx context.Context, input store.CreateThreadR if root.ParentMessageID != nil { return store.Message{}, store.ThreadState{}, nil, errors.New("nested thread replies are not supported") } - if err := requireMembershipTx(ctx, tx, root.WorkspaceID, input.AuthorID); err != nil { + if err := requireMessageAccessTx(ctx, tx, root, input.AuthorID); err != nil { return store.Message{}, store.ThreadState{}, nil, err } var seq int64 @@ -488,20 +486,38 @@ func (s *Store) CreateThreadReply(ctx context.Context, input store.CreateThreadR quotedSnapshot = snap quotedAuthorID = authorID } + var channelID any + var directConversationID any + if root.DirectConversationID != "" { + directConversationID = root.DirectConversationID + } else { + channelID = root.ChannelID + } if _, err := tx.ExecContext(ctx, ` INSERT INTO messages (id, workspace_id, channel_id, direct_conversation_id, author_id, parent_message_id, thread_root_id, channel_seq, thread_seq, body, body_format, created_at, quoted_message_id, quoted_body_snapshot, quoted_author_id) - VALUES (?, ?, ?, NULL, ?, ?, ?, NULL, ?, ?, 'markdown', ?, ?, ?, ?)`, id, root.WorkspaceID, root.ChannelID, input.AuthorID, root.ID, root.ID, seq, body, createdAt, nullableQuotedID(quotedID), quotedSnapshot, nullableQuotedID(quotedAuthorID)); err != nil { + VALUES (?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, 'markdown', ?, ?, ?, ?)`, id, root.WorkspaceID, channelID, directConversationID, input.AuthorID, root.ID, root.ID, seq, body, createdAt, nullableQuotedID(quotedID), quotedSnapshot, nullableQuotedID(quotedAuthorID)); err != nil { return store.Message{}, store.ThreadState{}, nil, err } state, err := updateThreadState(ctx, tx, root.ID, input.AuthorID, createdAt) if err != nil { return store.Message{}, store.ThreadState{}, nil, err } - replyEvent, err := insertEvent(ctx, tx, root.WorkspaceID, root.ChannelID, "thread.reply_created", nil, map[string]string{"message_id": id, "root_message_id": root.ID}) + replyPayload := map[string]string{"message_id": id, "root_message_id": root.ID} + statePayload := map[string]string{"root_message_id": root.ID} + var recipients []string + if root.DirectConversationID != "" { + replyPayload["direct_conversation_id"] = root.DirectConversationID + statePayload["direct_conversation_id"] = root.DirectConversationID + recipients, err = directConversationMemberIDsTx(ctx, tx, root.DirectConversationID) + if err != nil { + return store.Message{}, store.ThreadState{}, nil, err + } + } + replyEvent, err := insertEventWithRecipients(ctx, tx, root.WorkspaceID, root.ChannelID, "thread.reply_created", nil, replyPayload, recipients) if err != nil { return store.Message{}, store.ThreadState{}, nil, err } - stateEvent, err := insertEvent(ctx, tx, root.WorkspaceID, root.ChannelID, "thread.state_updated", nil, map[string]string{"root_message_id": root.ID}) + stateEvent, err := insertEventWithRecipients(ctx, tx, root.WorkspaceID, root.ChannelID, "thread.state_updated", nil, statePayload, recipients) if err != nil { return store.Message{}, store.ThreadState{}, nil, err } @@ -528,11 +544,15 @@ func (s *Store) ListEventsAfter(ctx context.Context, workspaceID, userID, cursor return nil, err } rows, err := s.db.QueryContext(ctx, ` - SELECT id, cursor, workspace_id, COALESCE(channel_id, ''), type, seq, payload_json, created_at - FROM events - WHERE workspace_id = ? AND cursor > ? - ORDER BY cursor - LIMIT ?`, workspaceID, cursor, limit) + SELECT e.id, e.cursor, e.workspace_id, COALESCE(e.channel_id, ''), e.type, e.seq, e.payload_json, e.created_at + FROM events e + WHERE e.workspace_id = ? AND e.cursor > ? + AND ( + e.is_private = 0 + OR EXISTS (SELECT 1 FROM event_recipients er WHERE er.event_id = e.id AND er.user_id = ?) + ) + ORDER BY e.cursor + LIMIT ?`, workspaceID, cursor, userID, limit) if err != nil { return nil, err } @@ -550,7 +570,7 @@ func (s *Store) reaction(ctx context.Context, input store.CreateReactionInput, a if err != nil { return store.Event{}, err } - if err := requireMembershipTx(ctx, tx, msg.WorkspaceID, input.UserID); err != nil { + if err := requireMessageAccessTx(ctx, tx, msg, input.UserID); err != nil { return store.Event{}, err } if add { @@ -565,7 +585,15 @@ func (s *Store) reaction(ctx context.Context, input store.CreateReactionInput, a if !add { eventType = "reaction.removed" } - event, err := insertEvent(ctx, tx, msg.WorkspaceID, msg.ChannelID, eventType, msg.ChannelSeq, map[string]string{"message_id": input.MessageID, "emoji": input.Emoji}) + payload := map[string]string{"message_id": input.MessageID, "emoji": input.Emoji} + if msg.DirectConversationID != "" { + payload["direct_conversation_id"] = msg.DirectConversationID + } + recipients, err := eventRecipientsForMessageTx(ctx, tx, msg) + if err != nil { + return store.Event{}, err + } + event, err := insertEventWithRecipients(ctx, tx, msg.WorkspaceID, msg.ChannelID, eventType, msg.ChannelSeq, payload, recipients) if err != nil { return store.Event{}, err } diff --git a/apps/api/internal/store/sqlite/sqlite_test.go b/apps/api/internal/store/sqlite/sqlite_test.go index b4b4e9d..8253bbd 100644 --- a/apps/api/internal/store/sqlite/sqlite_test.go +++ b/apps/api/internal/store/sqlite/sqlite_test.go @@ -43,7 +43,7 @@ func TestStoreValidationAndAdminHelpers(t *testing.T) { if _, _, _, err := st.CreateThreadReply(ctx, store.CreateThreadReplyInput{RootMessageID: channel.ID, AuthorID: owner.ID, Body: "nope"}); err == nil { t.Fatal("expected missing root message error") } - if results, err := st.SearchMessages(ctx, workspace.ID, owner.ID, "", 10); err != nil || len(results) != 0 { + if results, err := st.SearchMessages(ctx, workspace.ID, "", owner.ID, "", 10); err != nil || len(results) != 0 { t.Fatalf("expected empty search results, got %#v err=%v", results, err) } if _, err := st.CreateInvite(ctx, workspace.ID, owner.ID); err != nil { diff --git a/apps/api/internal/store/sqlite/uploads.go b/apps/api/internal/store/sqlite/uploads.go index 84840e9..085901c 100644 --- a/apps/api/internal/store/sqlite/uploads.go +++ b/apps/api/internal/store/sqlite/uploads.go @@ -3,6 +3,7 @@ package sqlite import ( "context" "errors" + "strings" "github.com/openclaw/clickclack/apps/api/internal/store" ) @@ -55,7 +56,7 @@ func (s *Store) AttachUpload(ctx context.Context, input store.AttachUploadInput) if err != nil { return err } - if err := requireMembershipTx(ctx, tx, msg.WorkspaceID, input.UserID); err != nil { + if err := requireMessageAccessTx(ctx, tx, msg, input.UserID); err != nil { return err } var uploadWorkspace string @@ -79,31 +80,42 @@ func scanUpload(row scanner) (store.Upload, error) { } func (s *Store) hydrateAttachments(ctx context.Context, messages []store.Message) ([]store.Message, error) { - for i := range messages { - rows, err := s.db.QueryContext(ctx, ` - SELECT u.id, u.workspace_id, u.owner_id, u.filename, u.content_type, u.byte_size, u.width, u.height, u.duration_ms, u.storage_path, u.created_at - FROM uploads u - JOIN message_attachments ma ON ma.upload_id = u.id - WHERE ma.message_id = ? - ORDER BY ma.created_at`, messages[i].ID) - if err != nil { - return nil, err - } - uploads := []store.Upload{} - for rows.Next() { - upload, err := scanUpload(rows) - if err != nil { - _ = rows.Close() - return nil, err - } - uploads = append(uploads, upload) - } - if err := rows.Close(); err != nil { + if len(messages) == 0 { + return messages, nil + } + ids := make([]string, 0, len(messages)) + indexByID := make(map[string]int, len(messages)) + for i, message := range messages { + ids = append(ids, message.ID) + indexByID[message.ID] = i + } + placeholders := strings.TrimRight(strings.Repeat("?,", len(ids)), ",") + args := make([]any, 0, len(ids)) + for _, id := range ids { + args = append(args, id) + } + rows, err := s.db.QueryContext(ctx, ` + SELECT ma.message_id, u.id, u.workspace_id, u.owner_id, u.filename, u.content_type, u.byte_size, u.width, u.height, u.duration_ms, u.storage_path, u.created_at + FROM message_attachments ma + JOIN uploads u ON u.id = ma.upload_id + WHERE ma.message_id IN (`+placeholders+`) + ORDER BY ma.message_id, ma.created_at`, args...) + if err != nil { + return nil, err + } + defer rows.Close() + for rows.Next() { + var messageID string + var upload store.Upload + if err := rows.Scan(&messageID, &upload.ID, &upload.WorkspaceID, &upload.OwnerID, &upload.Filename, &upload.ContentType, &upload.ByteSize, &upload.Width, &upload.Height, &upload.DurationMS, &upload.StoragePath, &upload.CreatedAt); err != nil { return nil, err } - if len(uploads) > 0 { - messages[i].Attachments = uploads + if index, ok := indexByID[messageID]; ok { + messages[index].Attachments = append(messages[index].Attachments, upload) } } + if err := rows.Err(); err != nil { + return nil, err + } return messages, nil } diff --git a/apps/api/internal/store/types.go b/apps/api/internal/store/types.go index cead921..a47c323 100644 --- a/apps/api/internal/store/types.go +++ b/apps/api/internal/store/types.go @@ -360,7 +360,7 @@ type Store interface { CreateUpload(ctx context.Context, input CreateUploadInput) (Upload, error) GetUpload(ctx context.Context, uploadID, userID string) (Upload, error) AttachUpload(ctx context.Context, input AttachUploadInput) error - SearchMessages(ctx context.Context, workspaceID, userID, query string, limit int) ([]SearchResult, error) + SearchMessages(ctx context.Context, workspaceID, channelID, userID, query string, limit int) ([]SearchResult, error) ListDirectConversations(ctx context.Context, workspaceID, userID string) ([]DirectConversation, error) GetDirectConversation(ctx context.Context, conversationID, userID string) (DirectConversation, error) CreateDirectConversation(ctx context.Context, input CreateDirectConversationInput) (DirectConversation, error) diff --git a/apps/api/internal/webassets/dist/assets/index-DI8HZC7D.js b/apps/api/internal/webassets/dist/assets/index-CySuZTQ7.js similarity index 92% rename from apps/api/internal/webassets/dist/assets/index-DI8HZC7D.js rename to apps/api/internal/webassets/dist/assets/index-CySuZTQ7.js index 99ed43d..ee05238 100644 --- a/apps/api/internal/webassets/dist/assets/index-DI8HZC7D.js +++ b/apps/api/internal/webassets/dist/assets/index-CySuZTQ7.js @@ -1,6 +1,6 @@ -(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))r(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(i){if(i.ep)return;i.ep=!0;const s=n(i);fetch(i.href,s)}})();const Gc=!1;var Wi=Array.isArray,jc=Array.prototype.indexOf,Lr=Array.prototype.includes,ja=Array.from,Vc=Object.defineProperty,Or=Object.getOwnPropertyDescriptor,Ao=Object.getOwnPropertyDescriptors,Kc=Object.prototype,Yc=Array.prototype,Gi=Object.getPrototypeOf,Ws=Object.isExtensible;const _i=()=>{};function Zc(t){return t()}function bi(t){for(var e=0;e{t=r,e=i});return{promise:n,resolve:t,reject:e}}const Lt=2,Pr=4,pa=8,ji=1<<24,Ln=16,yn=32,er=64,wi=128,on=512,ut=1024,It=2048,kn=4096,Ht=8192,nn=16384,kr=32768,yi=1<<25,tr=65536,ki=1<<17,Ro=1<<18,Sr=1<<19,Co=1<<20,Mn=1<<25,vr=65536,qa=1<<21,ca=1<<22,$n=1<<23,Gn=Symbol("$state"),Xc=Symbol("legacy props"),Qc=Symbol(""),Wn=new class extends Error{name="StaleReactionError";message="The reaction that called `getAbortSignal()` was re-run or destroyed"},Vi=!!globalThis.document?.contentType&&globalThis.document.contentType.includes("xml");function Do(t){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Jc(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function $c(t,e,n){throw new Error("https://svelte.dev/e/each_key_duplicate")}function eu(t){throw new Error("https://svelte.dev/e/effect_in_teardown")}function tu(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function nu(t){throw new Error("https://svelte.dev/e/effect_orphan")}function ru(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function au(t){throw new Error("https://svelte.dev/e/props_invalid_value")}function iu(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function su(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function ou(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function lu(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}const cu=1,uu=2,Mo=4,du=8,fu=16,hu=1,pu=2,gu=4,vu=8,mu=16,_u=1,bu=2,mt=Symbol(),Oo="http://www.w3.org/1999/xhtml",Lo="http://www.w3.org/2000/svg",wu="http://www.w3.org/1998/Math/MathML",yu="@attach";function ku(){console.warn("https://svelte.dev/e/derived_inert")}function Su(){console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function Tu(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}function Po(t){return t===this.v}function No(t,e){return t!=t?e==e:t!==e||t!==null&&typeof t=="object"||typeof t=="function"}function qo(t){return!No(t,this.v)}let Ur=!1,xu=!1;function Eu(){Ur=!0}let je=null;function Nr(t){je=t}function Fe(t,e=!1,n){je={p:je,i:!1,c:null,e:null,s:t,x:null,r:ye,l:Ur&&!e?{s:null,u:null,$:[]}:null}}function He(t){var e=je,n=e.e;if(n!==null){e.e=null;for(var r of n)rl(r)}return t!==void 0&&(e.x=t),e.i=!0,je=e.p,t??{}}function ga(){return!Ur||je!==null&&je.l===null}let or=[];function Uo(){var t=or;or=[],bi(t)}function jn(t){if(or.length===0&&!sa){var e=or;queueMicrotask(()=>{e===or&&Uo()})}or.push(t)}function Au(){for(;or.length>0;)Uo()}function zo(t){var e=ye;if(e===null)return Oe.f|=$n,t;if((e.f&kr)===0&&(e.f&Pr)===0)throw t;Qn(t,e)}function Qn(t,e){for(;e!==null;){if((e.f&wi)!==0){if((e.f&kr)===0)throw t;try{e.b.error(t);return}catch(n){t=n}}e=e.parent}throw t}const Iu=-7169;function ot(t,e){t.f=t.f&Iu|e}function Ki(t){(t.f&on)!==0||t.deps===null?ot(t,ut):ot(t,kn)}function Bo(t){if(t!==null)for(const e of t)(e.f&Lt)===0||(e.f&vr)===0||(e.f^=vr,Bo(e.deps))}function Fo(t,e,n){(t.f&It)!==0?e.add(t):(t.f&kn)!==0&&n.add(t),Bo(t.deps),ot(t,ut)}let Aa=!1;function Ru(t){var e=Aa;try{return Aa=!1,[t(),Aa]}finally{Aa=e}}const ir=new Set;let Me=null,_n=null,Si=null,sa=!1,oi=!1,Mr=null,La=null;var Gs=0;let Cu=1;class nr{id=Cu++;current=new Map;previous=new Map;#n=new Set;#l=new Set;#e=new Set;#a=new Map;#r=new Map;#i=null;#t=[];#s=[];#c=new Set;#u=new Set;#o=new Map;#f=new Set;is_fork=!1;#p=!1;#h=new Set;#d(){return this.is_fork||this.#r.size>0}#m(){for(const r of this.#h)for(const i of r.#r.keys()){for(var e=!1,n=i;n.parent!==null;){if(this.#o.has(n)){e=!0;break}n=n.parent}if(!e)return!0}return!1}skip_effect(e){this.#o.has(e)||this.#o.set(e,{d:[],m:[]}),this.#f.delete(e)}unskip_effect(e,n=r=>this.schedule(r)){var r=this.#o.get(e);if(r){this.#o.delete(e);for(var i of r.d)ot(i,It),n(i);for(i of r.m)ot(i,kn),n(i)}this.#f.add(e)}#g(){if(Gs++>1e3&&(ir.delete(this),Mu()),!this.#d()){for(const u of this.#c)this.#u.delete(u),ot(u,It),this.schedule(u);for(const u of this.#u)ot(u,kn),this.schedule(u)}const e=this.#t;this.#t=[],this.apply();var n=Mr=[],r=[],i=La=[];for(const u of e)try{this.#_(u,n,r)}catch(l){throw Go(u),l}if(Me=null,i.length>0){var s=nr.ensure();for(const u of i)s.schedule(u)}if(Mr=null,La=null,this.#d()||this.#m()){this.#v(r),this.#v(n);for(const[u,l]of this.#o)Wo(u,l)}else{this.#a.size===0&&ir.delete(this),this.#c.clear(),this.#u.clear();for(const u of this.#n)u(this);this.#n.clear(),js(r),js(n),this.#i?.resolve()}var o=Me;if(this.#t.length>0){const u=o??=this;u.#t.push(...this.#t.filter(l=>!u.#t.includes(l)))}o!==null&&(ir.add(o),o.#g())}#_(e,n,r){e.f^=ut;for(var i=e.first;i!==null;){var s=i.f,o=(s&(yn|er))!==0,u=o&&(s&ut)!==0,l=u||(s&Ht)!==0||this.#o.has(i);if(!l&&i.fn!==null){o?i.f^=ut:(s&Pr)!==0?n.push(i):Br(i)&&((s&Ln)!==0&&this.#u.add(i),_r(i));var f=i.first;if(f!==null){i=f;continue}}for(;i!==null;){var d=i.next;if(d!==null){i=d;break}i=i.parent}}}#v(e){for(var n=0;n!this.current.has(p));if(i.length===0)e&&d.discard();else if(n.length>0){if(e)for(const p of this.#f)d.unskip_effect(p,m=>{(m.f&(Ln|ca))!==0?d.schedule(m):d.#v([m])});d.activate();var s=new Set,o=new Map;for(var u of n)Ho(u,i,s,o);o=new Map;var l=[...d.current.keys()].filter(p=>this.current.has(p)?this.current.get(p)[0]!==p:!0);for(const p of this.#s)(p.f&(nn|Ht|ki))===0&&Yi(p,l,o)&&((p.f&(ca|Ln))!==0?(ot(p,It),d.schedule(p)):d.#c.add(p));if(d.#t.length>0){d.apply();for(var f of d.#t)d.#_(f,[],[]);d.#t=[]}d.deactivate()}}for(const d of ir)d.#h.has(this)&&(d.#h.delete(this),d.#h.size===0&&!d.#d()&&(d.activate(),d.#g()))}increment(e,n){let r=this.#a.get(n)??0;if(this.#a.set(n,r+1),e){let i=this.#r.get(n)??0;this.#r.set(n,i+1)}}decrement(e,n,r){let i=this.#a.get(n)??0;if(i===1?this.#a.delete(n):this.#a.set(n,i-1),e){let s=this.#r.get(n)??0;s===1?this.#r.delete(n):this.#r.set(n,s-1)}this.#p||r||(this.#p=!0,jn(()=>{this.#p=!1,this.flush()}))}transfer_effects(e,n){for(const r of e)this.#c.add(r);for(const r of n)this.#u.add(r);e.clear(),n.clear()}oncommit(e){this.#n.add(e)}ondiscard(e){this.#l.add(e)}on_fork_commit(e){this.#e.add(e)}run_fork_commit_callbacks(){for(const e of this.#e)e(this);this.#e.clear()}settled(){return(this.#i??=Io()).promise}static ensure(){if(Me===null){const e=Me=new nr;oi||(ir.add(Me),sa||jn(()=>{Me===e&&e.flush()}))}return Me}apply(){{_n=null;return}}schedule(e){if(Si=e,e.b?.is_pending&&(e.f&(Pr|pa|ji))!==0&&(e.f&kr)===0){e.b.defer_effect(e);return}for(var n=e;n.parent!==null;){n=n.parent;var r=n.f;if(Mr!==null&&n===ye&&(Oe===null||(Oe.f&Lt)===0))return;if((r&(er|yn))!==0){if((r&ut)===0)return;n.f^=ut}}this.#t.push(n)}}function Du(t){var e=sa;sa=!0;try{for(var n;;){if(Au(),Me===null)return n;Me.flush()}}finally{sa=e}}function Mu(){try{ru()}catch(t){Qn(t,Si)}}let Hn=null;function js(t){var e=t.length;if(e!==0){for(var n=0;n0)){fr.clear();for(const i of Hn){if((i.f&(nn|Ht))!==0)continue;const s=[i];let o=i.parent;for(;o!==null;)Hn.has(o)&&(Hn.delete(o),s.push(o)),o=o.parent;for(let u=s.length-1;u>=0;u--){const l=s[u];(l.f&(nn|Ht))===0&&_r(l)}}Hn.clear()}}Hn=null}}function Ho(t,e,n,r){if(!n.has(t)&&(n.add(t),t.reactions!==null))for(const i of t.reactions){const s=i.f;(s&Lt)!==0?Ho(i,e,n,r):(s&(ca|Ln))!==0&&(s&It)===0&&Yi(i,e,r)&&(ot(i,It),Zi(i))}}function Yi(t,e,n){const r=n.get(t);if(r!==void 0)return r;if(t.deps!==null)for(const i of t.deps){if(Lr.call(e,i))return!0;if((i.f&Lt)!==0&&Yi(i,e,n))return n.set(i,!0),!0}return n.set(t,!1),!1}function Zi(t){Me.schedule(t)}function Wo(t,e){if(!((t.f&yn)!==0&&(t.f&ut)!==0)){(t.f&It)!==0?e.d.push(t):(t.f&kn)!==0&&e.m.push(t),ot(t,ut);for(var n=t.first;n!==null;)Wo(n,e),n=n.next}}function Go(t){ot(t,ut);for(var e=t.first;e!==null;)Go(e),e=e.next}function Ou(t){let e=0,n=mr(0),r;return()=>{$i()&&(a(n),ba(()=>(e===0&&(r=_t(()=>t(()=>oa(n)))),e+=1,()=>{jn(()=>{e-=1,e===0&&(r?.(),r=void 0,oa(n))})})))}}var Lu=tr|Sr;function Pu(t,e,n,r){new Nu(t,e,n,r)}class Nu{parent;is_pending=!1;transform_error;#n;#l=null;#e;#a;#r;#i=null;#t=null;#s=null;#c=null;#u=0;#o=0;#f=!1;#p=new Set;#h=new Set;#d=null;#m=Ou(()=>(this.#d=mr(this.#u),()=>{this.#d=null}));constructor(e,n,r,i){this.#n=e,this.#e=n,this.#a=s=>{var o=ye;o.b=this,o.f|=wi,r(s)},this.parent=ye.b,this.transform_error=i??this.parent?.transform_error??(s=>s),this.#r=zr(()=>{this.#b()},Lu)}#g(){try{this.#i=$t(()=>this.#a(this.#n))}catch(e){this.error(e)}}#_(e){const n=this.#e.failed;n&&(this.#s=$t(()=>{n(this.#n,()=>e,()=>()=>{})}))}#v(){const e=this.#e.pending;e&&(this.is_pending=!0,this.#t=$t(()=>e(this.#n)),jn(()=>{var n=this.#c=document.createDocumentFragment(),r=wn();n.append(r),this.#i=this.#y(()=>$t(()=>this.#a(r))),this.#o===0&&(this.#n.before(n),this.#c=null,hr(this.#t,()=>{this.#t=null}),this.#w(Me))}))}#b(){try{if(this.is_pending=this.has_pending_snippet(),this.#o=0,this.#u=0,this.#i=$t(()=>{this.#a(this.#n)}),this.#o>0){var e=this.#c=document.createDocumentFragment();ns(this.#i,e);const n=this.#e.pending;this.#t=$t(()=>n(this.#n))}else this.#w(Me)}catch(n){this.error(n)}}#w(e){this.is_pending=!1,e.transfer_effects(this.#p,this.#h)}defer_effect(e){Fo(e,this.#p,this.#h)}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!this.#e.pending}#y(e){var n=ye,r=Oe,i=je;un(this.#r),cn(this.#r),Nr(this.#r.ctx);try{return nr.ensure(),e()}catch(s){return zo(s),null}finally{un(n),cn(r),Nr(i)}}#k(e,n){if(!this.has_pending_snippet()){this.parent&&this.parent.#k(e,n);return}this.#o+=e,this.#o===0&&(this.#w(n),this.#t&&hr(this.#t,()=>{this.#t=null}),this.#c&&(this.#n.before(this.#c),this.#c=null))}update_pending_count(e,n){this.#k(e,n),this.#u+=e,!(!this.#d||this.#f)&&(this.#f=!0,jn(()=>{this.#f=!1,this.#d&&qr(this.#d,this.#u)}))}get_effect_pending(){return this.#m(),a(this.#d)}error(e){if(!this.#e.onerror&&!this.#e.failed)throw e;Me?.is_fork?(this.#i&&Me.skip_effect(this.#i),this.#t&&Me.skip_effect(this.#t),this.#s&&Me.skip_effect(this.#s),Me.on_fork_commit(()=>{this.#S(e)})):this.#S(e)}#S(e){this.#i&&(Rt(this.#i),this.#i=null),this.#t&&(Rt(this.#t),this.#t=null),this.#s&&(Rt(this.#s),this.#s=null);var n=this.#e.onerror;let r=this.#e.failed;var i=!1,s=!1;const o=()=>{if(i){Tu();return}i=!0,s&&lu(),this.#s!==null&&hr(this.#s,()=>{this.#s=null}),this.#y(()=>{this.#b()})},u=l=>{try{s=!0,n?.(l,o),s=!1}catch(f){Qn(f,this.#r&&this.#r.parent)}r&&(this.#s=this.#y(()=>{try{return $t(()=>{var f=ye;f.b=this,f.f|=wi,r(this.#n,()=>l,()=>o)})}catch(f){return Qn(f,this.#r.parent),null}}))};jn(()=>{var l;try{l=this.transform_error(e)}catch(f){Qn(f,this.#r&&this.#r.parent);return}l!==null&&typeof l=="object"&&typeof l.then=="function"?l.then(u,f=>Qn(f,this.#r&&this.#r.parent)):u(l)})}}function jo(t,e,n,r){const i=ga()?va:Ot;var s=t.filter(m=>!m.settled);if(n.length===0&&s.length===0){r(e.map(i));return}var o=ye,u=qu(),l=s.length===1?s[0].promise:s.length>1?Promise.all(s.map(m=>m.promise)):null;function f(m){u();try{r(m)}catch(w){(o.f&nn)===0&&Qn(w,o)}Ua()}if(n.length===0){l.then(()=>f(e.map(i)));return}var d=Vo();function p(){Promise.all(n.map(m=>Uu(m))).then(m=>f([...e.map(i),...m])).catch(m=>Qn(m,o)).finally(()=>d())}l?l.then(()=>{u(),p(),Ua()}):p()}function qu(){var t=ye,e=Oe,n=je,r=Me;return function(s=!0){un(t),cn(e),Nr(n),s&&(t.f&nn)===0&&(r?.activate(),r?.apply())}}function Ua(t=!0){un(null),cn(null),Nr(null),t&&Me?.deactivate()}function Vo(){var t=ye,e=t.b,n=Me,r=e.is_rendered();return e.update_pending_count(1,n),n.increment(r,t),(i=!1)=>{e.update_pending_count(-1,n),n.decrement(r,t,i)}}function va(t){var e=Lt|It;return ye!==null&&(ye.f|=Sr),{ctx:je,deps:null,effects:null,equals:Po,f:e,fn:t,reactions:null,rv:0,v:mt,wv:0,parent:ye,ac:null}}function Uu(t,e,n){let r=ye;r===null&&Jc();var i=void 0,s=mr(mt),o=!Oe,u=new Map;return Zu(()=>{var l=ye,f=Io();i=f.promise;try{Promise.resolve(t()).then(f.resolve,f.reject).finally(Ua)}catch(w){f.reject(w),Ua()}var d=Me;if(o){if((l.f&kr)!==0)var p=Vo();if(r.b.is_rendered())u.get(d)?.reject(Wn),u.delete(d);else{for(const w of u.values())w.reject(Wn);u.clear()}u.set(d,f)}const m=(w,y=void 0)=>{if(p){var x=y===Wn;p(x)}if(!(y===Wn||(l.f&nn)!==0)){if(d.activate(),y)s.f|=$n,qr(s,y);else{(s.f&$n)!==0&&(s.f^=$n),qr(s,w);for(const[k,g]of u){if(u.delete(k),k===d)break;g.reject(Wn)}}d.deactivate()}};f.promise.then(m,w=>m(null,w||"unknown"))}),Va(()=>{for(const l of u.values())l.reject(Wn)}),new Promise(l=>{function f(d){function p(){d===i?l(s):f(i)}d.then(p,p)}f(i)})}function le(t){const e=va(t);return ul(e),e}function Ot(t){const e=va(t);return e.equals=qo,e}function zu(t){var e=t.effects;if(e!==null){t.effects=null;for(var n=0;n0&&!Zo&&Fu()}return e}function Fu(){Zo=!1;for(const t of Ti)(t.f&ut)!==0&&ot(t,kn),Br(t)&&_r(t);Ti.clear()}function oa(t){v(t,t.v+1)}function Xo(t,e,n){var r=t.reactions;if(r!==null)for(var i=ga(),s=r.length,o=0;o{if(pr===s)return u();var l=Oe,f=pr;cn(null),Ys(s);var d=u();return cn(l),Ys(f),d};return r&&n.set("length",Be(t.length)),new Proxy(t,{defineProperty(u,l,f){(!("value"in f)||f.configurable===!1||f.enumerable===!1||f.writable===!1)&&iu();var d=n.get(l);return d===void 0?o(()=>{var p=Be(f.value);return n.set(l,p),p}):v(d,f.value,!0),!0},deleteProperty(u,l){var f=n.get(l);if(f===void 0){if(l in u){const d=o(()=>Be(mt));n.set(l,d),oa(i)}}else v(f,mt),oa(i);return!0},get(u,l,f){if(l===Gn)return t;var d=n.get(l),p=l in u;if(d===void 0&&(!p||Or(u,l)?.writable)&&(d=o(()=>{var w=lr(p?u[l]:mt),y=Be(w);return y}),n.set(l,d)),d!==void 0){var m=a(d);return m===mt?void 0:m}return Reflect.get(u,l,f)},getOwnPropertyDescriptor(u,l){var f=Reflect.getOwnPropertyDescriptor(u,l);if(f&&"value"in f){var d=n.get(l);d&&(f.value=a(d))}else if(f===void 0){var p=n.get(l),m=p?.v;if(p!==void 0&&m!==mt)return{enumerable:!0,configurable:!0,value:m,writable:!0}}return f},has(u,l){if(l===Gn)return!0;var f=n.get(l),d=f!==void 0&&f.v!==mt||Reflect.has(u,l);if(f!==void 0||ye!==null&&(!d||Or(u,l)?.writable)){f===void 0&&(f=o(()=>{var m=d?lr(u[l]):mt,w=Be(m);return w}),n.set(l,f));var p=a(f);if(p===mt)return!1}return d},set(u,l,f,d){var p=n.get(l),m=l in u;if(r&&l==="length")for(var w=f;wBe(mt)),n.set(w+"",y))}if(p===void 0)(!m||Or(u,l)?.writable)&&(p=o(()=>Be(void 0)),v(p,lr(f)),n.set(l,p));else{m=p.v!==mt;var x=o(()=>lr(f));v(p,x)}var k=Reflect.getOwnPropertyDescriptor(u,l);if(k?.set&&k.set.call(d,f),!m){if(r&&typeof l=="string"){var g=n.get("length"),A=Number(l);Number.isInteger(A)&&A>=g.v&&v(g,A+1)}oa(i)}return!0},ownKeys(u){a(i);var l=Reflect.ownKeys(u).filter(p=>{var m=n.get(p);return m===void 0||m.v!==mt});for(var[f,d]of n)d.v!==mt&&!(f in u)&&l.push(f);return l},setPrototypeOf(){su()}})}function Vs(t){try{if(t!==null&&typeof t=="object"&&Gn in t)return t[Gn]}catch{}return t}function Hu(t,e){return Object.is(Vs(t),Vs(e))}var xi,Qo,Jo,$o,el;function Wu(){if(xi===void 0){xi=window,Qo=document,Jo=/Firefox/.test(navigator.userAgent);var t=Element.prototype,e=Node.prototype,n=Text.prototype;$o=Or(e,"firstChild").get,el=Or(e,"nextSibling").get,Ws(t)&&(t.__click=void 0,t.__className=void 0,t.__attributes=null,t.__style=void 0,t.__e=void 0),Ws(n)&&(n.__t=void 0)}}function wn(t=""){return document.createTextNode(t)}function Jn(t){return $o.call(t)}function ma(t){return el.call(t)}function b(t,e){return Jn(t)}function Gt(t,e=!1){{var n=Jn(t);return n instanceof Comment&&n.data===""?ma(n):n}}function S(t,e=1,n=!1){let r=t;for(;e--;)r=ma(r);return r}function Gu(t){t.textContent=""}function tl(){return!1}function Qi(t,e,n){return document.createElementNS(e??Oo,t,void 0)}function ju(t,e){if(e){const n=document.body;t.autofocus=!0,jn(()=>{document.activeElement===n&&t.focus()})}}function Ji(t){var e=Oe,n=ye;cn(null),un(null);try{return t()}finally{cn(e),un(n)}}function nl(t){ye===null&&(Oe===null&&nu(),tu()),Vn&&eu()}function Vu(t,e){var n=e.last;n===null?e.last=e.first=t:(n.next=t,t.prev=n,e.last=t)}function Tn(t,e){var n=ye;n!==null&&(n.f&Ht)!==0&&(t|=Ht);var r={ctx:je,deps:null,nodes:null,f:t|It|on,first:null,fn:e,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null};Me?.register_created_effect(r);var i=r;if((t&Pr)!==0)Mr!==null?Mr.push(r):nr.ensure().schedule(r);else if(e!==null){try{_r(r)}catch(o){throw Rt(r),o}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&(i.f&Sr)===0&&(i=i.first,(t&Ln)!==0&&(t&tr)!==0&&i!==null&&(i.f|=tr))}if(i!==null&&(i.parent=n,n!==null&&Vu(i,n),Oe!==null&&(Oe.f&Lt)!==0&&(t&er)===0)){var s=Oe;(s.effects??=[]).push(i)}return r}function $i(){return Oe!==null&&!bn}function Va(t){const e=Tn(pa,null);return ot(e,ut),e.teardown=t,e}function Qt(t){nl();var e=ye.f,n=!Oe&&(e&yn)!==0&&(e&kr)===0;if(n){var r=je;(r.e??=[]).push(t)}else return rl(t)}function rl(t){return Tn(Pr|Co,t)}function za(t){return nl(),Tn(pa|Co,t)}function Ku(t){nr.ensure();const e=Tn(er|Sr,t);return(n={})=>new Promise(r=>{n.outro?hr(e,()=>{Rt(e),r(void 0)}):(Rt(e),r(void 0))})}function _a(t){return Tn(Pr,t)}function zt(t,e){var n=je,r={effect:null,ran:!1,deps:t};n.l.$.push(r),r.effect=ba(()=>{if(t(),!r.ran){r.ran=!0;var i=ye;try{un(i.parent),_t(e)}finally{un(i)}}})}function Yu(){var t=je;ba(()=>{for(var e of t.l.$){e.deps();var n=e.effect;(n.f&ut)!==0&&n.deps!==null&&ot(n,kn),Br(n)&&_r(n),e.ran=!1}})}function Zu(t){return Tn(ca|Sr,t)}function ba(t,e=0){return Tn(pa|e,t)}function te(t,e=[],n=[],r=[]){jo(r,e,n,i=>{Tn(pa,()=>t(...i.map(a)))})}function zr(t,e=0){var n=Tn(Ln|e,t);return n}function al(t,e=0){var n=Tn(ji|e,t);return n}function $t(t){return Tn(yn|Sr,t)}function il(t){var e=t.teardown;if(e!==null){const n=Vn,r=Oe;Ks(!0),cn(null);try{e.call(null)}finally{Ks(n),cn(r)}}}function es(t,e=!1){var n=t.first;for(t.first=t.last=null;n!==null;){const i=n.ac;i!==null&&Ji(()=>{i.abort(Wn)});var r=n.next;(n.f&er)!==0?n.parent=null:Rt(n,e),n=r}}function Xu(t){for(var e=t.first;e!==null;){var n=e.next;(e.f&yn)===0&&Rt(e),e=n}}function Rt(t,e=!0){var n=!1;(e||(t.f&Ro)!==0)&&t.nodes!==null&&t.nodes.end!==null&&(sl(t.nodes.start,t.nodes.end),n=!0),ot(t,yi),es(t,e&&!n),ua(t,0);var r=t.nodes&&t.nodes.t;if(r!==null)for(const s of r)s.stop();il(t),t.f^=yi,t.f|=nn;var i=t.parent;i!==null&&i.first!==null&&ol(t),t.next=t.prev=t.teardown=t.ctx=t.deps=t.fn=t.nodes=t.ac=t.b=null}function sl(t,e){for(;t!==null;){var n=t===e?null:ma(t);t.remove(),t=n}}function ol(t){var e=t.parent,n=t.prev,r=t.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),e!==null&&(e.first===t&&(e.first=r),e.last===t&&(e.last=n))}function hr(t,e,n=!0){var r=[];ll(t,r,!0);var i=()=>{n&&Rt(t),e&&e()},s=r.length;if(s>0){var o=()=>--s||i();for(var u of r)u.out(o)}else i()}function ll(t,e,n){if((t.f&Ht)===0){t.f^=Ht;var r=t.nodes&&t.nodes.t;if(r!==null)for(const u of r)(u.is_global||n)&&e.push(u);for(var i=t.first;i!==null;){var s=i.next;if((i.f&er)===0){var o=(i.f&tr)!==0||(i.f&yn)!==0&&(t.f&Ln)!==0;ll(i,e,o?n:!1)}i=s}}}function ts(t){cl(t,!0)}function cl(t,e){if((t.f&Ht)!==0){t.f^=Ht,(t.f&ut)===0&&(ot(t,It),nr.ensure().schedule(t));for(var n=t.first;n!==null;){var r=n.next,i=(n.f&tr)!==0||(n.f&yn)!==0;cl(n,i?e:!1),n=r}var s=t.nodes&&t.nodes.t;if(s!==null)for(const o of s)(o.is_global||e)&&o.in()}}function ns(t,e){if(t.nodes)for(var n=t.nodes.start,r=t.nodes.end;n!==null;){var i=n===r?null:ma(n);e.append(n),n=i}}let Pa=!1,Vn=!1;function Ks(t){Vn=t}let Oe=null,bn=!1;function cn(t){Oe=t}let ye=null;function un(t){ye=t}let ln=null;function ul(t){Oe!==null&&(ln===null?ln=[t]:ln.push(t))}let Jt=null,tn=0,sn=null;function Qu(t){sn=t}let dl=1,cr=0,pr=cr;function Ys(t){pr=t}function fl(){return++dl}function Br(t){var e=t.f;if((e&It)!==0)return!0;if(e&Lt&&(t.f&=~vr),(e&kn)!==0){for(var n=t.deps,r=n.length,i=0;it.wv)return!0}(e&on)!==0&&_n===null&&ot(t,ut)}return!1}function hl(t,e,n=!0){var r=t.reactions;if(r!==null&&!(ln!==null&&Lr.call(ln,t)))for(var i=0;i{t.ac.abort(Wn)}),t.ac=null);try{t.f|=qa;var d=t.fn,p=d();t.f|=kr;var m=t.deps,w=Me?.is_fork;if(Jt!==null){var y;if(w||ua(t,tn),m!==null&&tn>0)for(m.length=tn+Jt.length,y=0;yn?.call(this,s))}return t.startsWith("pointer")||t.startsWith("touch")||t==="wheel"?jn(()=>{e.addEventListener(t,i,r)}):e.addEventListener(t,i,r),i}function dn(t,e,n,r,i){var s={capture:r,passive:i},o=_l(t,e,n,s);(e===document.body||e===window||e===document||e instanceof HTMLMediaElement)&&Va(()=>{e.removeEventListener(t,o,s)})}function V(t,e,n){(e[na]??={})[t]=n}function Qe(t){for(var e=0;e{throw k});throw m}}finally{t[na]=e,delete t.currentTarget,cn(d),un(p)}}}const sd=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:t=>t});function od(t){return sd?.createHTML(t)??t}function ld(t){var e=Qi("template");return e.innerHTML=od(t.replaceAll("","")),e.content}function br(t,e){var n=ye;n.nodes===null&&(n.nodes={start:t,end:e,a:null,t:null})}function z(t,e){var n=(e&_u)!==0,r=(e&bu)!==0,i,s=!t.startsWith("");return()=>{i===void 0&&(i=ld(s?t:""+t),n||(i=Jn(i)));var o=r||Jo?document.importNode(i,!0):i.cloneNode(!0);if(n){var u=Jn(o),l=o.lastChild;br(u,l)}else br(o,o);return o}}function Xn(t=""){{var e=wn(t+"");return br(e,e),e}}function Sn(){var t=document.createDocumentFragment(),e=document.createComment(""),n=wn();return t.append(e,n),br(e,n),t}function L(t,e){t!==null&&t.before(e)}function ee(t,e){var n=e==null?"":typeof e=="object"?`${e}`:e;n!==(t.__t??=t.nodeValue)&&(t.__t=n,t.nodeValue=`${n}`)}function cd(t,e){return ud(t,e)}const Ia=new Map;function ud(t,{target:e,anchor:n,props:r={},events:i,context:s,intro:o=!0,transformError:u}){Wu();var l=void 0,f=Ku(()=>{var d=n??e.appendChild(wn());Pu(d,{pending:()=>{}},w=>{Fe({});var y=je;s&&(y.c=s),i&&(r.$$events=i),l=t(w,r)||{},He()},u);var p=new Set,m=w=>{for(var y=0;y{for(var w of p)for(const k of[e,document]){var y=Ia.get(k),x=y.get(w);--x==0?(k.removeEventListener(w,Ii),y.delete(w),y.size===0&&Ia.delete(k)):y.set(w,x)}Ai.delete(m),d!==n&&d.parentNode?.removeChild(d)}});return dd.set(l,f),l}let dd=new WeakMap;class as{anchor;#n=new Map;#l=new Map;#e=new Map;#a=new Set;#r=!0;constructor(e,n=!0){this.anchor=e,this.#r=n}#i=e=>{if(this.#n.has(e)){var n=this.#n.get(e),r=this.#l.get(n);if(r)ts(r),this.#a.delete(n);else{var i=this.#e.get(n);i&&(this.#l.set(n,i.effect),this.#e.delete(n),i.fragment.lastChild.remove(),this.anchor.before(i.fragment),r=i.effect)}for(const[s,o]of this.#n){if(this.#n.delete(s),s===e)break;const u=this.#e.get(o);u&&(Rt(u.effect),this.#e.delete(o))}for(const[s,o]of this.#l){if(s===n||this.#a.has(s))continue;const u=()=>{if(Array.from(this.#n.values()).includes(s)){var f=document.createDocumentFragment();ns(o,f),f.append(wn()),this.#e.set(s,{effect:o,fragment:f})}else Rt(o);this.#a.delete(s),this.#l.delete(s)};this.#r||!r?(this.#a.add(s),hr(o,u,!1)):u()}}};#t=e=>{this.#n.delete(e);const n=Array.from(this.#n.values());for(const[r,i]of this.#e)n.includes(r)||(Rt(i.effect),this.#e.delete(r))};ensure(e,n){var r=Me,i=tl();if(n&&!this.#l.has(e)&&!this.#e.has(e))if(i){var s=document.createDocumentFragment(),o=wn();s.append(o),this.#e.set(e,{effect:$t(()=>n(o)),fragment:s})}else this.#l.set(e,$t(()=>n(this.anchor)));if(this.#n.set(r,e),i){for(const[u,l]of this.#l)u===e?r.unskip_effect(l):r.skip_effect(l);for(const[u,l]of this.#e)u===e?r.unskip_effect(l.effect):r.skip_effect(l.effect);r.oncommit(this.#i),r.ondiscard(this.#t)}else this.#i(r)}}function oe(t,e,n=!1){var r=new as(t),i=n?tr:0;function s(o,u){r.ensure(o,u)}zr(()=>{var o=!1;e((u,l=0)=>{o=!0,s(l,u)}),o||s(-1,null)},i)}function bl(t,e){return e}function fd(t,e,n){for(var r=[],i=e.length,s,o=e.length,u=0;u{if(s){if(s.pending.delete(p),s.done.add(p),s.pending.size===0){var m=t.outrogroups;Ri(t,ja(s.done)),m.delete(s),m.size===0&&(t.outrogroups=null)}}else o-=1},!1)}if(o===0){var l=r.length===0&&n!==null;if(l){var f=n,d=f.parentNode;Gu(d),d.append(f),t.items.clear()}Ri(t,e,!l)}else s={pending:new Set(e),done:new Set},(t.outrogroups??=new Set).add(s)}function Ri(t,e,n=!0){var r;if(t.pending.size>0){r=new Set;for(const o of t.pending.values())for(const u of o)r.add(t.items.get(u).e)}for(var i=0;i{var E=n();return Wi(E)?E:E==null?[]:ja(E)}),m,w=new Map,y=!0;function x(E){(A.effect.f&nn)===0&&(A.pending.delete(E),A.fallback=d,hd(A,m,o,e,r),d!==null&&(m.length===0?(d.f&Mn)===0?ts(d):(d.f^=Mn,ra(d,null,o)):hr(d,()=>{d=null})))}function k(E){A.pending.delete(E)}var g=zr(()=>{m=a(p);for(var E=m.length,I=new Set,D=Me,C=tl(),U=0;Us(o)):(d=$t(()=>s(Xs??=wn())),d.f|=Mn)),E>I.size&&$c(),!y)if(w.set(D,I),C){for(const[Z,Y]of u)I.has(Z)||D.skip_effect(Y.e);D.oncommit(x),D.ondiscard(k)}else x(D);a(p)}),A={effect:g,items:u,pending:w,outrogroups:null,fallback:d};y=!1}function Vr(t){for(;t!==null&&(t.f&yn)===0;)t=t.next;return t}function hd(t,e,n,r,i){var s=(r&du)!==0,o=e.length,u=t.items,l=Vr(t.effect.first),f,d=null,p,m=[],w=[],y,x,k,g;if(s)for(g=0;g0){var G=(r&Mo)!==0&&o===0?n:null;if(s){for(g=0;g{if(p!==void 0)for(k of p)k.nodes?.a?.apply()})}function pd(t,e,n,r,i,s,o,u){var l=(o&cu)!==0?(o&fu)===0?Q(n,!1,!1):mr(n):null,f=(o&uu)!==0?mr(i):null;return{v:l,i:f,e:$t(()=>(s(e,l??n,f??i,u),()=>{t.delete(r)}))}}function ra(t,e,n){if(t.nodes)for(var r=t.nodes.start,i=t.nodes.end,s=e&&(e.f&Mn)===0?e.nodes.start:n;r!==null;){var o=ma(r);if(s.before(r),r===i)return;r=o}}function Zn(t,e,n){e===null?t.effect.first=n:e.next=n,n===null?t.effect.last=e:n.prev=e}function Ci(t,e,n=!1,r=!1,i=!1,s=!1){var o=t,u="";if(n)var l=t;te(()=>{var f=ye;if(u!==(u=e()??"")){if(n){f.nodes=null,l.innerHTML=u,u!==""&&br(Jn(l),l.lastChild);return}if(f.nodes!==null&&(sl(f.nodes.start,f.nodes.end),f.nodes=null),u!==""){var d=r?Lo:i?wu:void 0,p=Qi(r?"svg":i?"math":"template",d);p.innerHTML=u;var m=r||i?p:p.content;if(br(Jn(m),m.lastChild),r||i)for(;Jn(m);)o.before(Jn(m));else o.before(m)}}})}function gd(t,e,...n){var r=new as(t);zr(()=>{const i=e()??null;r.ensure(i,i&&(s=>i(s,...n)))},tr)}function wl(t,e,n,r,i,s){var o=null,u=t,l=new as(u,!1);zr(()=>{const f=e()||null;var d=f==="svg"?Lo:void 0;if(f===null){l.ensure(null,null);return}return l.ensure(f,p=>{if(f){if(o=Qi(f,d),br(o,o),r){var m=o.appendChild(wn());r(o,m)}ye.nodes.end=o,p.before(o)}}),()=>{}},tr),Va(()=>{})}function yl(t,e){var n;n=document.head.appendChild(wn()),zr(()=>e(n),Ro|Sr)}function vd(t,e,n){_a(()=>{var r=_t(()=>e(t,n?.())||{});if(n&&r?.update){var i=!1,s={};ba(()=>{var o=n();rs(o),i&&No(s,o)&&(s=o,r.update(o))}),i=!0}if(r?.destroy)return()=>r.destroy()})}function md(t,e){var n=void 0,r;al(()=>{n!==(n=e())&&(r&&(Rt(r),r=null),n&&(r=$t(()=>{_a(()=>n(t))})))})}function kl(t){var e,n,r="";if(typeof t=="string"||typeof t=="number")r+=t;else if(typeof t=="object")if(Array.isArray(t)){var i=t.length;for(e=0;e=0;){var u=o+s;(o===0||Qs.includes(r[o-1]))&&(u===r.length||Qs.includes(r[u]))?r=(o===0?"":r.substring(0,o))+r.substring(u+1):o=u}}return r===""?null:r}function Js(t,e=!1){var n=e?" !important;":";",r="";for(var i of Object.keys(t)){var s=t[i];s!=null&&s!==""&&(r+=" "+i+": "+s+n)}return r}function li(t){return t[0]!=="-"||t[1]!=="-"?t.toLowerCase():t}function wd(t,e){if(e){var n="",r,i;if(Array.isArray(e)?(r=e[0],i=e[1]):r=e,t){t=String(t).replaceAll(/\s*\/\*.*?\*\/\s*/g,"").trim();var s=!1,o=0,u=!1,l=[];r&&l.push(...Object.keys(r).map(li)),i&&l.push(...Object.keys(i).map(li));var f=0,d=-1;const x=t.length;for(var p=0;p{Di(t,t.__value)});e.observe(t,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),Va(()=>{e.disconnect()})}function $s(t){return"__value"in t?t.__value:t.value}const Kr=Symbol("class"),Yr=Symbol("style"),Sl=Symbol("is custom element"),Tl=Symbol("is html"),kd=Vi?"option":"OPTION",Sd=Vi?"select":"SELECT",Td=Vi?"progress":"PROGRESS";function On(t,e){var n=Ka(t);n.value===(n.value=e??void 0)||t.value===e&&(e!==0||t.nodeName!==Td)||(t.value=e??"")}function xd(t,e){var n=Ka(t);n.checked!==(n.checked=e??void 0)&&(t.checked=e)}function Ed(t,e){e?t.hasAttribute("selected")||t.setAttribute("selected",""):t.removeAttribute("selected")}function X(t,e,n,r){var i=Ka(t);i[e]!==(i[e]=n)&&(e==="loading"&&(t[Qc]=n),n==null?t.removeAttribute(e):typeof n!="string"&&El(t).includes(e)?t[e]=n:t.setAttribute(e,n))}function Ad(t,e,n,r,i=!1,s=!1){var o=Ka(t),u=o[Sl],l=!o[Tl],f=e||{},d=t.nodeName===kd;for(var p in e)p in n||(n[p]=null);n.class?n.class=Ba(n.class):n[Kr]&&(n.class=null),n[Yr]&&(n.style??=null);var m=El(t);for(const I in n){let D=n[I];if(d&&I==="value"&&D==null){t.value=t.__value="",f[I]=D;continue}if(I==="class"){var w=t.namespaceURI==="http://www.w3.org/1999/xhtml";lt(t,w,D,r,e?.[Kr],n[Kr]),f[I]=D,f[Kr]=n[Kr];continue}if(I==="style"){wr(t,D,e?.[Yr],n[Yr]),f[I]=D,f[Yr]=n[Yr];continue}var y=f[I];if(!(D===y&&!(D===void 0&&t.hasAttribute(I)))){f[I]=D;var x=I[0]+I[1];if(x!=="$$")if(x==="on"){const C={},U="$$"+I;let P=I.slice(2);var k=td(P);if($u(P)&&(P=P.slice(0,-7),C.capture=!0),!k&&y){if(D!=null)continue;t.removeEventListener(P,f[U],C),f[U]=null}if(k)V(P,t,D),Qe([P]);else if(D!=null){let G=function(K){f[I].call(this,K)};var E=G;f[U]=_l(P,t,G,C)}}else if(I==="style")X(t,I,D);else if(I==="autofocus")ju(t,!!D);else if(!u&&(I==="__value"||I==="value"&&D!=null))t.value=t.__value=D;else if(I==="selected"&&d)Ed(t,D);else{var g=I;l||(g=rd(g));var A=g==="defaultValue"||g==="defaultChecked";if(D==null&&!u&&!A)if(o[I]=null,g==="value"||g==="checked"){let C=t;const U=e===void 0;if(g==="value"){let P=C.defaultValue;C.removeAttribute(g),C.defaultValue=P,C.value=C.__value=U?P:null}else{let P=C.defaultChecked;C.removeAttribute(g),C.defaultChecked=P,C.checked=U?P:!1}}else t.removeAttribute(I);else A||m.includes(g)&&(u||typeof D!="string")?(t[g]=D,g in o&&(o[g]=mt)):typeof D!="function"&&X(t,g,D)}}}return f}function xl(t,e,n=[],r=[],i=[],s,o=!1,u=!1){jo(i,n,r,l=>{var f=void 0,d={},p=t.nodeName===Sd,m=!1;if(al(()=>{var y=e(...l.map(a)),x=Ad(t,f,y,s,o,u);m&&p&&"value"in y&&Di(t,y.value);for(let g of Object.getOwnPropertySymbols(d))y[g]||Rt(d[g]);for(let g of Object.getOwnPropertySymbols(y)){var k=y[g];g.description===yu&&(!f||k!==f[g])&&(d[g]&&Rt(d[g]),d[g]=$t(()=>md(t,()=>k))),x[g]=k}f=x}),p){var w=t;_a(()=>{Di(w,f.value,!0),yd(w)})}m=!0})}function Ka(t){return t.__attributes??={[Sl]:t.nodeName.includes("-"),[Tl]:t.namespaceURI===Oo}}var eo=new Map;function El(t){var e=t.getAttribute("is")||t.nodeName,n=eo.get(e);if(n)return n;eo.set(e,n=[]);for(var r,i=t,s=Element.prototype;s!==i;){r=Ao(i);for(var o in r)r[o].set&&n.push(o);i=Gi(i)}return n}function to(t,e){return t===e||t?.[Gn]===e}function gr(t={},e,n,r){var i=je.r,s=ye;return _a(()=>{var o,u;return ba(()=>{o=u,u=[],_t(()=>{t!==n(...u)&&(e(t,...u),o&&to(n(...o),t)&&e(null,...o))})}),()=>{let l=s;for(;l!==i&&l.parent!==null&&l.parent.f&yi;)l=l.parent;const f=()=>{u&&to(n(...u),t)&&e(null,...u)},d=l.teardown;l.teardown=()=>{f(),d?.()}}}),t}function Al(t=!1){const e=je,n=e.l.u;if(!n)return;let r=()=>rs(e.s);if(t){let i=0,s={};const o=va(()=>{let u=!1;const l=e.s;for(const f in l)l[f]!==s[f]&&(s[f]=l[f],u=!0);return u&&i++,i});r=()=>a(o)}n.b.length&&za(()=>{no(e,r),bi(n.b)}),Qt(()=>{const i=_t(()=>n.m.map(Zc));return()=>{for(const s of i)typeof s=="function"&&s()}}),n.a.length&&Qt(()=>{no(e,r),bi(n.a)})}function no(t,e){if(t.l.s)for(const n of t.l.s)a(n);e()}function Ee(t,e,n,r){var i=!Ur||(n&pu)!==0,s=(n&vu)!==0,o=(n&mu)!==0,u=r,l=!0,f=()=>(l&&(l=!1,u=o?_t(r):r),u);let d;if(s){var p=Gn in t||Xc in t;d=Or(t,e)?.set??(p&&e in t?E=>t[e]=E:void 0)}var m,w=!1;s?[m,w]=Ru(()=>t[e]):m=t[e],m===void 0&&r!==void 0&&(m=f(),d&&(i&&au(),d(m)));var y;if(i?y=()=>{var E=t[e];return E===void 0?f():(l=!0,E)}:y=()=>{var E=t[e];return E!==void 0&&(u=void 0),E===void 0?u:E},i&&(n&gu)===0)return y;if(d){var x=t.$$legacy;return(function(E,I){return arguments.length>0?((!i||!I||x||w)&&d(I?y():E),E):y()})}var k=!1,g=((n&hu)!==0?va:Ot)(()=>(k=!1,y()));s&&a(g);var A=ye;return(function(E,I){if(arguments.length>0){const D=I?a(g):i&&s?lr(E):E;return v(g,D),k=!0,u!==void 0&&(u=D),E}return Vn&&k||(A.f&nn)!==0?g.v:a(g)})}function is(t){je===null&&Do(),Ur&&je.l!==null?Id(je).m.push(t):Qt(()=>{const e=_t(t);if(typeof e=="function")return e})}function Ya(t){je===null&&Do(),is(()=>()=>_t(t))}function Id(t){var e=t.l;return e.u??={a:[],b:[],m:[]}}const Rd="5";typeof window<"u"&&((window.__svelte??={}).v??=new Set).add(Rd);Eu();class Il extends Error{constructor(e,n){super(n),this.status=e}status}async function tt(t,e={}){const n=new Headers(e.headers);n.set("Accept","application/json"),e.body&&!(e.body instanceof FormData)&&n.set("Content-Type","application/json");const r=await fetch(t,{...e,headers:n});if(!r.ok)throw new Il(r.status,await r.text());return r.json()}async function Cd(t){return t.type.startsWith("image/")?Dd(t):t.type.startsWith("video/")?Md(t):{width:0,height:0,durationMS:0}}function Dd(t){return new Promise(e=>{const n=URL.createObjectURL(t),r=new Image;r.onload=()=>{const i={width:r.naturalWidth,height:r.naturalHeight,durationMS:0};URL.revokeObjectURL(n),e(i)},r.onerror=()=>{URL.revokeObjectURL(n),e({width:0,height:0,durationMS:0})},r.src=n})}function Md(t){return new Promise(e=>{const n=URL.createObjectURL(t),r=document.createElement("video");r.preload="metadata",r.muted=!0;const i=()=>{URL.revokeObjectURL(n),r.src=""};r.onloadedmetadata=()=>{const s=Number.isFinite(r.duration)&&r.duration>0?Math.round(r.duration*1e3):0,o={width:r.videoWidth,height:r.videoHeight,durationMS:s};i(),e(o)},r.onerror=()=>{i(),e({width:0,height:0,durationMS:0})},r.src=n})}const Od=[{title:"Ship it",url:"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExYjJ1bm1meHE4N2x3bnN0djJkMWtjNGc5bXYzZDFiOHBsbG16M3F0ZSZlcD12MV9naWZzX3NlYXJjaCZjdD1n/l0HlHFRbmaZtBRhXG/giphy.gif",tags:["ship","launch","done"]},{title:"Approved",url:"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExazBpbzJ6ODZ3bXQ3OHBvNGJidWZoajc0cHV6YnVub3MzZ3c1a2Z2dSZlcD12MV9naWZzX3NlYXJjaCZjdD1n/111ebonMs90YLu/giphy.gif",tags:["yes","approved","nice"]},{title:"Deploy dance",url:"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExY3NkaTVmZW9ydWNnZnl0ZWQ5aHQyeGNrd2k3NG4wZWNqYzNmd3k1ZCZlcD12MV9naWZzX3NlYXJjaCZjdD1n/GeimqsH0TLDt4tScGw/giphy.gif",tags:["deploy","dance","celebrate"]},{title:"Looking",url:"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExYWZ3emE0dm5mN2h0bGVsY2w0OXBodGd2cGJlNDRiZXo1YWNtdWRmZyZlcD12MV9naWZzX3NlYXJjaCZjdD1n/26n6WywJyh39n1pBu/giphy.gif",tags:["search","looking","debug"]},{title:"Typing faster",url:"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExOWFlbnJnbnIzbHYxcDIzdXZ3NGF3N2FocHNvMmR5enU3bHpycHBlZSZlcD12MV9naWZzX3NlYXJjaCZjdD1n/13HgwGsXF0aiGY/giphy.gif",tags:["typing","code","work"]},{title:"Tiny victory",url:"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExdjJ2b2tqNmF4dG16NjE0eXhuc3h5bTlvamgwNTR0Zmd6ZjhtM2JuaSZlcD12MV9naWZzX3NlYXJjaCZjdD1n/3o7abKhOpu0NwenH3O/giphy.gif",tags:["win","victory","celebrate"]}],Ra=100,Mi=50,Rl=900,Ar=700,ui=Rl+Mi*2,Ld=8,Pd=16;function Nd(t,e,n){if(t.length<=Rl)return t;const r=qd(t,n);if(e==="prepend")return di(t,0,Ar,r,"start");if(e==="append")return di(t,Math.max(0,t.length-Ar),t.length,r,"end");if(e==="around"){const i=r?.first??-1,s=i>=0?i:Math.floor(t.length/2);let o=Math.max(0,s-Math.floor(Ar/2)),u=Math.min(t.length,o+Ar);return o=Math.max(0,u-Ar),t.slice(o,u)}return di(t,Math.max(0,t.length-Ar),t.length,r,"end")}function qd(t,e){if(e.size===0)return null;let n=-1,r=-1;for(let i=0;iui&&(i==="start"?(s=e,o=Math.min(t.length,s+ui)):(o=n,s=Math.max(0,o-ui))),t.slice(s,o)}function Ud(t){const e=t.trim();if(!e)return"?";const n=e.split(/\s+/);return n.length>=2?(n[0][0]+n[1][0]).toUpperCase():e.slice(0,2).toUpperCase()}function zd(t){if(!t)return"?";const e=t.trim();return e?e[0].toUpperCase():"?"}function Kn(t){return t?`@${t}`:""}function Cl(t){let e=0;for(let n=0;n>>0;return e%360}function Bd(t,e){return t.members.find(n=>n.id!==e)||t.members[0]}function da(t,e){const n=t.members.filter(i=>i.id!==e);return(n.length>0?n:t.members).map(i=>i.display_name).join(", ")}function Fd(t,e,n){const r=new Map;for(const i of e)for(const s of i.members)s.id&&s.id!==n&&r.set(s.id,s);for(const i of[...t].reverse()){const s=i.author;s?.id&&s.id!==n&&r.set(s.id,s)}return[...r.values()].slice(0,12)}function Hd(t,e){return t.find(n=>n.members.some(r=>r.id===e))}const Wd=new Set(["button","checkbox","combobox","link","listbox","menu","menubar","menuitem","menuitemcheckbox","menuitemradio","option","radio","radiogroup","slider","spinbutton","switch","tab","tablist","textbox","tree","treeitem"]),Gd=new Set(["INPUT","TEXTAREA","SELECT","BUTTON","A","DETAILS","SUMMARY","VIDEO","AUDIO"]);function jd(t){if(!t)return!1;if(t.isContentEditable)return!0;if(t instanceof HTMLInputElement){const e=(t.type||"text").toLowerCase();return e!=="checkbox"&&e!=="radio"&&e!=="button"&&e!=="submit"&&e!=="reset"&&e!=="file"}return t instanceof HTMLTextAreaElement}function Vd(t){if(!t||Kd(t))return!1;if(Gd.has(t.tagName))return!0;const e=t.getAttribute("role");if(e&&Wd.has(e))return!0;const n=t.getAttribute("tabindex");return!!(n!==null&&n!=="-1"&&t.hasAttribute("aria-keyshortcuts"))}function Kd(t){if(!t.closest(".messages, .thread"))return!1;if(t instanceof HTMLButtonElement||t instanceof HTMLAnchorElement)return!0;const e=t.getAttribute("role");return e==="button"||e==="link"}function Yd(){const t=typeof window<"u"?window.getSelection():null;if(!t||t.isCollapsed||t.rangeCount===0)return!1;const e=t.getRangeAt(0).commonAncestorContainer;return e?!!(e.nodeType===Node.ELEMENT_NODE?e:e.parentElement)?.closest(".messages, .thread, .markdown"):!1}function Zd(t,e){if(e.authRequired||e.isModalOpen()||t.defaultPrevented||t.isComposing||t.keyCode===229||t.ctrlKey||t.metaKey||t.altKey||t.key.length!==1||Yd())return!1;const n=document.activeElement;return!(n===e.messageInput||n===e.replyInput||jd(n)||Vd(n))}function Xd(t,e){if(!Zd(t,e))return;const n=e.target();if(!n||n.disabled||n.readOnly)return;t.key===" "&&t.preventDefault(),n.focus({preventScroll:!0});const r=n.value.length;if(n.setSelectionRange(r,r),t.key===" "){const i=n.selectionStart??r,s=n.selectionEnd??r;n.setRangeText(" ",i,s,"end"),n.dispatchEvent(new Event("input",{bubbles:!0}))}}const ro=t=>`clickclack:${t}:cursor`;function Qd(t){const{workspaceID:e,onEvent:n,onStatusChange:r}=t,i=t.reconnectDelayMs??1200;let s=null,o,u=!1,l=!1;function f(p){l!==p&&(l=p,r?.(p))}function d(){if(u)return;const p=new URL("/api/realtime/ws",window.location.href);p.protocol=window.location.protocol==="https:"?"wss:":"ws:",p.searchParams.set("workspace_id",e);const m=localStorage.getItem(ro(e))||"";m&&p.searchParams.set("after_cursor",m);const w=new WebSocket(p);s=w,w.addEventListener("open",()=>{s===w&&f(!0)}),w.addEventListener("message",y=>{const x=JSON.parse(String(y.data));x.cursor&&localStorage.setItem(ro(e),x.cursor),n(x)}),w.addEventListener("close",()=>{s!==w||u||(s=null,f(!1),o=window.setTimeout(d,i))})}return d(),{get connected(){return l},close(){u=!0,f(!1),o&&window.clearTimeout(o),s?.close(),s=null}}}const Jd=5e3,$d=4e3;let vt=null;function ef(t,e){return t.workspaceID===e.workspaceID&&(t.channelID??"")===(e.channelID??"")&&(t.directConversationID??"")===(e.directConversationID??"")}function tf(t){const e={};return t.channelID&&(e.channel_id=t.channelID),t.directConversationID&&(e.direct_conversation_id=t.directConversationID),e}async function Dl(t,e){try{await tt("/api/realtime/ephemeral",{method:"POST",body:JSON.stringify({workspace_id:t.workspaceID,channel_id:t.channelID||"",direct_conversation_id:t.directConversationID||"",type:e,payload:tf(t)})})}catch{}}function nf(t){if(!t.workspaceID||!t.channelID&&!t.directConversationID)return;const e=Date.now();vt&&!ef(vt.scope,t)&&(Oi(vt),vt=null),vt||(vt={scope:t,active:!1,lastPingAt:0}),(!vt.active||e-vt.lastPingAt>=$d)&&(vt.active=!0,vt.lastPingAt=e,Dl(t,"typing.started")),vt.idleTimer&&window.clearTimeout(vt.idleTimer),vt.idleTimer=window.setTimeout(()=>{vt&&(Oi(vt),vt=null)},Jd)}async function Oi(t){t.idleTimer&&window.clearTimeout(t.idleTimer),t.active&&await Dl(t.scope,"typing.stopped")}function Ca(){vt&&(Oi(vt),vt=null)}function rf(t,e){const n=()=>{const s=t.style.height;t.style.height="auto";const o=`${t.scrollHeight}px`;s!==o?t.style.height=o:t.style.height=s},r=()=>n(),i=()=>n();return requestAnimationFrame(n),t.addEventListener("input",r),window.addEventListener("resize",i),{update(){requestAnimationFrame(n)},destroy(){t.removeEventListener("input",r),window.removeEventListener("resize",i)}}}function Fa(t){return`/api/uploads/${encodeURIComponent(t.id)}`}function af(t){return t.content_type.startsWith("image/")}function sf(t){return t<1024?`${t} B`:t<1024*1024?`${Math.round(t/1024)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}var of=z('
');function lf(t,e){Fe(e,!0);var n=of(),r=b(n),i=S(r,2),s=S(i,2),o=b(s);o.textContent="<>";var u=S(s,2),l=b(u);l.textContent="{}";var f=S(u,2),d=S(f,2);let p;te(()=>p=lt(d,1,"",null,p,{active:e.showGifPicker})),V("click",r,()=>e.onWrap("**")),V("click",i,()=>e.onWrap("_")),V("click",s,()=>e.onWrap("`")),V("click",u,()=>e.onWrap("```","\n```")),V("click",f,()=>e.onAppend("[label](https://)")),V("click",d,function(...m){e.onToggleGif?.apply(this,m)}),L(t,n),He()}Qe(["click"]);var cf=z(''),uf=z('
GIFs
');function df(t,e){Fe(e,!0);var n=uf(),r=b(n),i=S(b(r),2),s=S(r,2);Wt(s,21,()=>e.gifs,o=>o.url,(o,u)=>{var l=cf(),f=b(l),d=S(f,2),p=b(d);te(()=>{X(f,"src",a(u).url),X(f,"alt",a(u).title),ee(p,a(u).title)}),V("click",l,()=>e.onPick(a(u).url,a(u).title)),L(o,l)}),te(()=>On(i,e.query)),V("input",i,o=>e.onQuery(o.currentTarget.value)),L(t,n),He()}Qe(["input","click"]);function Li(t,e=120){if(!t)return"";const n=t.replace(/\s+/g," ").trim();return n.length>e?n.slice(0,e-1)+"...":n}function ao(t){return t.quoted_author?.display_name||"Unknown"}function ff(t,e){return e===t.id?"Open":"Thread"}function hf(t){const e=new Date(t),n=new Date,r=new Date;r.setDate(n.getDate()-1);const i=(s,o)=>s.getFullYear()===o.getFullYear()&&s.getMonth()===o.getMonth()&&s.getDate()===o.getDate();return i(e,n)?"Today":i(e,r)?"Yesterday":new Intl.DateTimeFormat(void 0,{weekday:"long",month:"long",day:"numeric"}).format(e)}function pf(t){const e=[];let n="",r="",i=0;for(const s of t){const o=new Date(s.created_at),u=o.toDateString(),l=s.author?.id||s.author_id||"local",f=u!==n,d=l!==r,p=o.getTime()-i>300*1e3;f||d||p||e.length===0?e.push({key:s.id,dayLabel:f?hf(s.created_at):null,messages:[s],authorName:s.author?.display_name||"Local User",authorHandle:s.author?.handle||"",authorAvatarURL:s.author?.avatar_url||"",authorID:l,timestamp:s.created_at}):e[e.length-1].messages.push(s),n=u,r=l,i=o.getTime()}return e}var gf=z('
Replying to
');function vf(t,e){Fe(e,!0);var n=gf(),r=S(b(n),2),i=b(r),s=S(b(i)),o=b(s),u=S(i,2),l=b(u),f=S(r,2);te(d=>{ee(o,e.target.author?.display_name||"Local User"),ee(l,d)},[()=>Li(e.target.body)]),V("click",f,function(...d){e.onClear?.apply(this,d)}),L(t,n),He()}Qe(["click"]);var mf=z(''),_f=z('
'),bf=z(''),wf=z('
');function Ml(t,e){Fe(e,!0);let n=Ee(e,"formClass",3,"composer"),r=Ee(e,"pendingUpload",3,null),i=Ee(e,"replyTarget",3,null),s=Ee(e,"showUpload",3,!1),o=Ee(e,"showToolbar",3,!1),u=Ee(e,"showGifPicker",3,!1),l=Ee(e,"gifQuery",3,""),f=Ee(e,"filteredGifs",19,()=>[]),d=Ee(e,"onUploadFile",3,()=>{}),p=Ee(e,"onRemoveUpload",3,()=>{}),m=Ee(e,"onClearReply",3,()=>{}),w=Ee(e,"onApplyMarkdownWrap",3,()=>{}),y=Ee(e,"onAppendToComposer",3,()=>{}),x=Ee(e,"onToggleGif",3,()=>{}),k=Ee(e,"onGifQuery",3,()=>{}),g=Ee(e,"onPickGif",3,()=>{}),A=Be(null);Qt(()=>(e.onInputRef(a(A)),()=>e.onInputRef(null)));var E=wf(),I=b(E);{var D=B=>{df(B,{get gifs(){return f()},get query(){return l()},get onQuery(){return k()},get onPick(){return g()}})};oe(I,B=>{u()&&B(D)})}var C=S(I,2),U=b(C);{var P=B=>{var ae=_f(),ce=S(b(ae),2);{var $=Ue=>{var Je=mf();te(se=>{X(Je,"src",se),X(Je,"alt",r().filename)},[()=>Fa(r())]),L(Ue,Je)},Ae=le(()=>af(r()));oe(ce,Ue=>{a(Ae)&&Ue($)})}var ge=S(ce,2),De=b(ge),_e=S(ge,2);te(Ue=>ee(De,`${r().filename??""} · ${Ue??""}`),[()=>sf(r().byte_size)]),V("click",_e,function(...Ue){p()?.apply(this,Ue)}),L(B,ae)};oe(U,B=>{r()&&B(P)})}var G=S(U,2);{var K=B=>{vf(B,{get target(){return i()},get onClear(){return m()}})};oe(G,B=>{i()&&B(K)})}var Z=S(G,2),Y=b(Z);{var O=B=>{var ae=bf(),ce=b(ae);V("change",ce,function(...$){d()?.apply(this,$)}),L(B,ae)};oe(Y,B=>{s()&&B(O)})}var W=S(Y,2);gr(W,B=>v(A,B),()=>a(A)),vd(W,(B,ae)=>rf?.(B),()=>e.value);var J=S(W,2),fe=S(Z,2);{var ie=B=>{lf(B,{get showGifPicker(){return u()},get onWrap(){return w()},get onAppend(){return y()},get onToggleGif(){return x()}})};oe(fe,B=>{o()&&B(ie)})}te(B=>{lt(E,1,Ba(n())),On(W,e.value),X(W,"placeholder",e.placeholder),X(W,"aria-label",e.ariaLabel),X(J,"aria-label",e.submitLabel),J.disabled=B},[()=>!e.value.trim()]),dn("submit",E,B=>{B.preventDefault(),e.onSubmit()}),V("input",W,B=>e.onValue(B.currentTarget.value)),dn("focus",W,function(...B){e.onFocus?.apply(this,B)}),V("keydown",W,function(...B){e.onKeydown?.apply(this,B)}),L(t,E),He()}Qe(["click","change","input","keydown"]);var yf=z('');function kf(t,e){var n=yf(),r=b(n),i=S(r,2),s=b(i),o=b(s),u=b(o),l=S(o,2),f=b(l),d=S(f,2),p=S(s,2),m=b(p);te(()=>{ee(u,e.title),X(f,"href",e.url),X(m,"src",e.url),X(m,"alt",e.title)}),V("click",r,function(...w){e.onClose?.apply(this,w)}),V("click",d,function(...w){e.onClose?.apply(this,w)}),L(t,n)}Qe(["click"]);const Ol=t=>Object.keys(t).reduce((e,n)=>{const r=t[n];return r==null?e:e+`${n}:${r};`},""),Sf=(t,e)=>"_"+e,fa=null,{min:dr,max:gn,abs:io,floor:Tf}=Math,Ll=(t,e,n)=>dr(n,gn(e,t)),Pl=t=>[...t].sort((e,n)=>e-n),xf=typeof queueMicrotask=="function"?queueMicrotask:t=>{Promise.resolve().then(t)},Pi=()=>{let t;return[new Promise(e=>{t=e}),t]},Nl=t=>{let e;return()=>(t&&(e=t(),t=void 0),e)},la=(t,e,n)=>{const r=n?"unshift":"push";for(let i=0;i{const n=t.t[e];return n===-1?t.o:n},Ef=(t,e,n)=>{const r=t.t[e]===-1;return t.t[e]=n,t.i=dr(e,t.i),r},Na=(t,e)=>{if(!t.l)return 0;if(t.i>=e)return t.u[e];t.i<0&&(t.u[0]=0,t.i=0);let n=t.i,r=t.u[n];for(;n{let i=n;for(;n<=r;){const s=Tf((n+r)/2);Na(t,s)<=e?(i=s,n=s+1):r=s-1}return Ll(i,0,t.l-1)},so=(t,e,n)=>{const r=e-t.l;return t.i=n?-1:dr(e-1,t.i),t.l=e,r>0?(la(t.u,r),la(t.t,r,n),t.o*r):(t.u.splice(r),(n?t.t.splice(0,-r):t.t.splice(r)).reduce((i,s)=>i-(s===-1?t.o:s),0))},Af=t=>t.documentElement,If=t=>t.ownerDocument,Rf=t=>t.defaultView,Ul=Nl(()=>!!/iP(hone|od|ad)/.test(navigator.userAgent)||navigator.platform==="MacIntel"&&navigator.maxTouchPoints>0),Cf=Nl(()=>"scrollBehavior"in Af(document).style),Df=5,Mf=6,Of=1,Lf=4,Pf=8,Nf=t=>gn(t.$getTotalSize(),t.$getViewportSize()),qf=(t,e=40,n=0,r,i=!1)=>{let s=!!n,o=1,u=0,l=0,f=0,d=0,p=0,m=0,w=0,y=0,x=fa,k=[0,s?gn(n-1,0):-1],g=0,A=!1;const E=((O,W,J)=>({o:W,t:J?la(J.slice(0,dr(O,J.length)),gn(0,O-J.length)):la([],O),l:O,i:-1,u:la([],O+1)}))(t,r?r[1]:e,r&&r[0]),I=new Set,D=()=>f-l,C=()=>D()+p+d,U=(O,W)=>((J,fe,ie,B)=>{if(B=dr(B,J.l-1),Na(J,B)<=fe){const ae=Ir(J,ie,B);return[Ir(J,fe,B,ae),ae]}{const ae=Ir(J,fe,void 0,B);return[ae,Ir(J,ie,ae)]}})(E,O,W,k[0]),P=()=>Na(E,E.l),G=(O,W)=>{const J=Na(E,O)-p;return W?P()-J-K(O):J},K=O=>ql(E,O),Z=(O,W=-1)=>E.t[O]===W,Y=O=>{O&&(Ul()&&w!==0||x&&y===1?p+=O:d+=O)};return{$dispose:()=>{I.clear()},$getStateVersion:()=>o,$getCacheSnapshot:()=>(O=>[O.t.slice(),O.o])(E),$getRange:(O=200)=>{if(!A||s)return k;let W,J;if(m)[W,J]=k;else{let fe=gn(0,C()),ie=fe+u;i||(O=gn(0,O),w!==1&&(fe-=O),w!==2&&(ie+=O)),[W,J]=k=U(gn(0,fe),gn(0,ie)),x&&(W=dr(W,x[0]),J=gn(J,x[1]))}return[gn(W,0),dr(J,E.l-1)]},$findItemIndex:O=>Ir(E,O-l),$isUnmeasuredItem:Z,$getItemOffset:G,$getItemSize:K,$getItemsLength:()=>E.l,$getScrollOffset:()=>f,$isScrolling:()=>w!==0,$getViewportSize:()=>u,$getStartSpacerSize:()=>l,$getTotalSize:P,$:()=>(m=d,d=0,[m,y===2]),$subscribe:(O,W)=>{const J=[O,W];return I.add(J),()=>{I.delete(J)}},$update:(O,W)=>{let J,fe,ie=0;switch(O){case 1:{if(W===f&&y===0)break;const B=m;m=0;const ae=W-f,ce=io(ae);B&&ce=-u&&$<=P()&&(ie+=1,fe=ce>u);break}case 2:ie=8,w!==0&&(J=!0,ie+=1),w=0,y=0,x=fa;break;case 3:{const B=W.filter(([ae,ce])=>!Z(ae,ce));if(!B.length)break;Y(B.reduce((ae,[ce,$])=>{let Ae;if(y===2)Ae=!0;else if(x&&y===1)Ae=ceu&&(Y(((ae,ce)=>{let $=0;const Ae=[];ae.t.forEach((se,be)=>{se!==-1&&(Ae.push(se),be{ie&B&&ae(fe)}))}}},ss=setTimeout,fi=(t,e)=>e?-t:t,Uf=(t,e,n,r,i,s)=>{const o=Date.now;let u=0,l=!1,f=!1,d=!1,p=!1;const m=(()=>{let g;const A=()=>{g!=fa&&clearTimeout(g)},E=()=>{A(),g=ss(()=>{g=fa,(()=>{if(l||f)return l=!1,void m();d=!1,t.$update(2)})()},150)};return E.p=A,E})(),w=()=>{u=o(),d&&(p=!0),t.$update(1,r()),m()},y=g=>{if(l||!t.$isScrolling()||g.ctrlKey)return;const A=o()-u;150>A&&50{f=!0,d=p=!1},k=()=>{f=!1,Ul()&&(d=!0)};return e.addEventListener("scroll",w),e.addEventListener("wheel",y,{passive:!0}),e.addEventListener("touchstart",x,{passive:!0}),e.addEventListener("touchend",k,{passive:!0}),{h:()=>{e.removeEventListener("scroll",w),e.removeEventListener("wheel",y),e.removeEventListener("touchstart",x),e.removeEventListener("touchend",k),m.p()},m:()=>{const[g,A]=t.$();g&&(i(g,A,p),p=!1,A&&t.$getViewportSize()>t.$getTotalSize()&&t.$update(1,r()))}}},zf=(t,e,n)=>{let r;return[async(i,s)=>{if(!await e())return;r&&r();const o=()=>{const[u,l]=Pi();return r=()=>{l(!1)},t.$getViewportSize()&&ss(r,150),[u,t.$subscribe(2,()=>{l(!0)})]};if(s&&Cf())t.$update(8,i()),xf(async()=>{for(;;){let u=!0;for(let[d,p]=t.$getRange();d<=p;d++)if(t.$isUnmeasuredItem(d)){u=!1;break}if(u)break;const[l,f]=o();try{if(!await l)return}finally{f()}}t.$update(7),n(i(),s)});else for(;;){const[u,l]=o();try{if(t.$update(7),n(i()),!await u)return}finally{l()}}},()=>{r&&r()}]},Bf=(t,e)=>{let n,r,i=Pi(),s=!1;const o=e?"scrollLeft":"scrollTop",u=e?"overflowX":"overflowY",[l,f]=zf(t,()=>i[0],(d,p)=>{d=fi(d,s),p?n.scrollTo({[e?"left":"top"]:d,behavior:"smooth"}):n[o]=d});return{$observe(d,p){n=p,e&&(s=getComputedStyle(p).direction==="rtl"),r=Uf(t,p,e,()=>fi(p[o],s),(m,w,y)=>{if(y){const x=p.style,k=x[u];x[u]="hidden",ss(()=>{x[u]=k})}p[o]=fi(t.$getScrollOffset()+m,s),w&&f()}),i[1](!0)},$dispose(){r&&r.h(),i[1](!1),i=Pi()},$isNegative:()=>s,$scrollTo(d){l(()=>d)},$scrollBy(d){d+=t.$getScrollOffset(),l(()=>d)},$scrollToIndex(d,{align:p,smooth:m,offset:w=0}={}){if(d=Ll(d,0,t.$getItemsLength()-1),p==="nearest"){const y=t.$getItemOffset(d),x=t.$getScrollOffset();if(yx+t.$getViewportSize()))return;p="end"}}l(()=>w+t.$getStartSpacerSize()+t.$getItemOffset(d)+(p==="end"?t.$getItemSize(d)-t.$getViewportSize():p==="center"?(t.$getItemSize(d)-t.$getViewportSize())/2:0),m)},$fixScrollJump:()=>{r&&r.m()}}},Ff=t=>{let e;return{v(n){(e||(e=new(Rf(If(n))).ResizeObserver(t))).observe(n)},S(n){e.unobserve(n)},h(){e&&e.disconnect()}}},Hf=(t,e)=>{let n;const r=e?"width":"height",i=new WeakMap,s=Ff(o=>{const u=[];for(const{target:l,contentRect:f}of o)if(l.offsetParent)if(l===n)t.$update(4,f[r]);else{const d=i.get(l);d!=fa&&u.push([d,f[r]])}u.length&&t.$update(3,u)});return{$observeRoot(o){s.v(n=o)},$observeItem:(o,u)=>(i.set(o,u),s.v(o),()=>{i.delete(o),s.S(o)}),$dispose:s.h}};function Wf(t,e){Fe(e,!0);let n=Ee(e,"as",3,"div"),r,i,s;Qt(()=>{s!==e.index&&(i&&i(),i=e.resizer(r,s=e.index))}),Ya(()=>{i&&i()});let o=le(()=>{const f={contain:"layout style",position:"absolute",[e.horizontal?"height":"width"]:"100%",[e.horizontal?"top":"left"]:"0px",[e.horizontal?"left":"top"]:e.offset+"px",visibility:e.hide?"hidden":void 0};return e.horizontal&&(f.display="inline-flex"),Ol(f)});var u=Sn(),l=Gt(u);wl(l,n,!1,(f,d)=>{gr(f,w=>r=w,()=>r),xl(f,()=>({style:a(o)}));var p=Sn(),m=Gt(p);gd(m,()=>e.children,()=>e.item,()=>e.index),L(d,p)}),L(t,u),He()}function Gf(t,e){Fe(e,!0);let n=Ee(e,"getKey",3,Sf),r=Ee(e,"as",3,"div"),i=Ee(e,"shift",3,!1),s=Ee(e,"horizontal",3,!1),o=Ee(e,"startMargin",3,0);const u=qf(e.data.length,e.itemSize,e.ssrCount,e.cache,!e.itemSize),l=Hf(u,s()),f=Bf(u,s());u.$subscribe(Of,()=>{v(p,u.$getStateVersion(),!0)}),u.$subscribe(Lf,()=>{e.onscroll&&e.onscroll(u.$getScrollOffset())}),u.$subscribe(Pf,()=>{e.onscrollend&&e.onscrollend()});let d=Be(void 0),p=Be(lr(u.$getStateVersion())),m=le(()=>a(p)&&u.$getRange(e.bufferSize)),w=le(()=>a(p)&&u.$isScrolling()),y=le(()=>a(p)&&u.$getTotalSize()),x=le(()=>a(p)&&f.$isNegative()),k=le(()=>{const fe=e.data.length,[ie,B]=a(m),ae=[];if(e.keepMounted){const ce=new Set(e.keepMounted);for(let $=ie;$<=B;$++)ce.add($);for(const $ of Pl([...ce]))${const fe=a(d),ie=B=>{l.$observeRoot(B),f.$observe(fe,B)};ur().then(()=>{e.scrollRef?ie(e.scrollRef):ie(fe.parentElement)})}),Ya(()=>{u.$dispose(),l.$dispose(),f.$dispose()}),za(()=>{e.data.length!==u.$getItemsLength()&&u.$update(Df,[e.data.length,i()])}),za(()=>{o()!==u.$getStartSpacerSize()&&u.$update(Mf,o())});let g;Qt(()=>{g!==a(p)&&(g=a(p),f.$fixScrollJump())});const A=u.$getCacheSnapshot,E=u.$getScrollOffset,I=()=>Nf(u),D=u.$getViewportSize,C=u.$findItemIndex,U=u.$getItemOffset,P=u.$getItemSize,G=f.$scrollToIndex,K=f.$scrollTo,Z=f.$scrollBy;let Y=le(()=>Ol({contain:"size style","overflow-anchor":"none",flex:"none",position:"relative",width:s()?a(y)+"px":"100%",height:s()?"100%":a(y)+"px","pointer-events":a(w)?"none":void 0}));var O={getCache:A,getScrollOffset:E,getScrollSize:I,getViewportSize:D,findItemIndex:C,getItemOffset:U,getItemSize:P,scrollToIndex:G,scrollTo:K,scrollBy:Z},W=Sn(),J=Gt(W);return wl(J,r,!1,(fe,ie)=>{gr(fe,ce=>v(d,ce,!0),()=>a(d)),xl(fe,()=>({style:a(Y)}));var B=Sn(),ae=Gt(B);Wt(ae,17,()=>a(k),ce=>n()(e.data[ce],ce),(ce,$)=>{const Ae=le(()=>e.data[a($)]);{let ge=le(()=>a(p)&&u.$getItemOffset(a($),a(x))),De=le(()=>a(p)&&u.$isUnmeasuredItem(a($)));Wf(ce,{get children(){return e.children},get item(){return a(Ae)},get index(){return a($)},get as(){return e.item},get offset(){return a(ge)},get hide(){return a(De)},get horizontal(){return s()},get resizer(){return l.$observeItem}})}}),L(ie,B)}),L(t,W),He(O)}var jf=z('
'),Vf=z('
');function oo(t,e){let n=Ee(e,"rows",3,3);var r=Vf();Wt(r,21,()=>Array.from({length:n()}),bl,(i,s,o)=>{var u=jf();wr(u,`--history-row: ${o}`),L(i,u)}),te(()=>{lt(r,1,`history-loader history-loader--${e.direction}`),X(r,"aria-label",e.direction==="older"?"Loading older messages":"Loading newer messages")}),L(t,r)}const Kf=512,Zr=new Map;function Yf(t){const e=t?.trim()||"";if(!e)return"";const n=Zr.get(e);if(n)return n;if(Zr.size>=Kf){const r=Zr.keys().next().value;r&&Zr.delete(r)}return Zr.set(e,e),e}var Zf=z(''),Xf=z(''),Qf=z(''),Jf=z("");function Pn(t,e){Fe(e,!0);let n=Ee(e,"class",3,"avatar"),r=Ee(e,"size",3,40),i=Ee(e,"loading",3,"lazy"),s=Ee(e,"fetchPriority",3,"low"),o=Be("");const u=le(()=>Yf(e.src)),l=le(()=>a(u)!==""&&a(o)!==a(u)),f=le(()=>Cl(e.id||e.name||a(u)||"avatar")),d=le(()=>zd(e.name));function p(){v(o,a(u),!0)}var m=Sn(),w=Gt(m);{var y=k=>{var g=Xf(),A=b(g);{var E=D=>{var C=Zf();te(()=>{X(C,"src",a(u)),X(C,"width",r()),X(C,"height",r()),X(C,"loading",i()),X(C,"fetchpriority",s())}),dn("error",C,p),L(D,C)},I=D=>{var C=Xn();te(()=>ee(C,a(d))),L(D,C)};oe(A,D=>{a(l)?D(E):D(I,-1)})}te(()=>{lt(g,1,Ba(n())),wr(g,`--hue: ${a(f)??""}deg`),X(g,"aria-label",e.buttonLabel)}),V("click",g,function(...D){e.onclick?.apply(this,D)}),L(k,g)},x=k=>{var g=Jf(),A=b(g);{var E=D=>{var C=Qf();te(()=>{X(C,"src",a(u)),X(C,"width",r()),X(C,"height",r()),X(C,"loading",i()),X(C,"fetchpriority",s())}),dn("error",C,p),L(D,C)},I=D=>{var C=Xn();te(()=>ee(C,a(d))),L(D,C)};oe(A,D=>{a(l)?D(E):D(I,-1)})}te(()=>{lt(g,1,Ba(n())),wr(g,`--hue: ${a(f)??""}deg`)}),L(k,g)};oe(w,k=>{e.buttonLabel?k(y):k(x,-1)})}L(t,m),He()}Qe(["click"]);const{entries:zl,setPrototypeOf:lo,isFrozen:$f,getPrototypeOf:eh,getOwnPropertyDescriptor:th}=Object;let{freeze:jt,seal:fn,create:Cr}=Object,{apply:Ni,construct:qi}=typeof Reflect<"u"&&Reflect;jt||(jt=function(e){return e});fn||(fn=function(e){return e});Ni||(Ni=function(e,n){for(var r=arguments.length,i=new Array(r>2?r-2:0),s=2;s1?n-1:0),i=1;i"u"?null:dt(BigInt.prototype.toString),po=typeof Symbol>"u"?null:dt(Symbol.prototype.toString),st=dt(Object.prototype.hasOwnProperty),Jr=dt(Object.prototype.toString),At=dt(RegExp.prototype.test),Da=oh(TypeError);function dt(t){return function(e){e instanceof RegExp&&(e.lastIndex=0);for(var n=arguments.length,r=new Array(n>1?n-1:0),i=1;i2&&arguments[2]!==void 0?arguments[2]:aa;if(lo&&lo(t,null),!Bt(e))return t;let r=e.length;for(;r--;){let i=e[r];if(typeof i=="string"){const s=n(i);s!==i&&($f(e)||(e[r]=s),i=s)}t[i]=!0}return t}function lh(t){for(let e=0;e/gm),gh=fn(/\$\{[\w\W]*/gm),vh=fn(/^data-[\-\w.\u00B7-\uFFFF]+$/),mh=fn(/^aria-[\-\w]+$/),Bl=fn(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),_h=fn(/^(?:\w+script|data):/i),bh=fn(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),Fl=fn(/^html$/i),wh=fn(/^[a-z][.\w]*(-[.\w]+)+$/i);var bo=Object.freeze({__proto__:null,ARIA_ATTR:mh,ATTR_WHITESPACE:bh,CUSTOM_ELEMENT:wh,DATA_ATTR:vh,DOCTYPE_NAME:Fl,ERB_EXPR:ph,IS_ALLOWED_URI:Bl,IS_SCRIPT_OR_DATA:_h,MUSTACHE_EXPR:hh,TMPLIT_EXPR:gh});const $r={element:1,text:3,progressingInstruction:7,comment:8,document:9},yh=function(){return typeof window>"u"?null:window},kh=function(e,n){if(typeof e!="object"||typeof e.createPolicy!="function")return null;let r=null;const i="data-tt-policy-suffix";n&&n.hasAttribute(i)&&(r=n.getAttribute(i));const s="dompurify"+(r?"#"+r:"");try{return e.createPolicy(s,{createHTML(o){return o},createScriptURL(o){return o}})}catch{return console.warn("TrustedTypes policy "+s+" could not be created."),null}},wo=function(){return{afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}};function Hl(){let t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:yh();const e=de=>Hl(de);if(e.version="3.4.2",e.removed=[],!t||!t.document||t.document.nodeType!==$r.document||!t.Element)return e.isSupported=!1,e;let{document:n}=t;const r=n,i=r.currentScript,{DocumentFragment:s,HTMLTemplateElement:o,Node:u,Element:l,NodeFilter:f,NamedNodeMap:d=t.NamedNodeMap||t.MozNamedAttrMap,HTMLFormElement:p,DOMParser:m,trustedTypes:w}=t,y=l.prototype,x=Dr(y,"cloneNode"),k=Dr(y,"remove"),g=Dr(y,"nextSibling"),A=Dr(y,"childNodes"),E=Dr(y,"parentNode");if(typeof o=="function"){const de=n.createElement("template");de.content&&de.content.ownerDocument&&(n=de.content.ownerDocument)}let I,D="";const{implementation:C,createNodeIterator:U,createDocumentFragment:P,getElementsByTagName:G}=n,{importNode:K}=r;let Z=wo();e.isSupported=typeof zl=="function"&&typeof E=="function"&&C&&C.createHTMLDocument!==void 0;const{MUSTACHE_EXPR:Y,ERB_EXPR:O,TMPLIT_EXPR:W,DATA_ATTR:J,ARIA_ATTR:fe,IS_SCRIPT_OR_DATA:ie,ATTR_WHITESPACE:B,CUSTOM_ELEMENT:ae}=bo;let{IS_ALLOWED_URI:ce}=bo,$=null;const Ae=we({},[...go,...pi,...gi,...vi,...vo]);let ge=null;const De=we({},[...mo,...mi,..._o,...Ma]);let _e=Object.seal(Cr(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Ue=null,Je=null;const se=Object.seal(Cr(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}}));let be=!0,Se=!0,nt=!1,bt=!0,wt=!1,rt=!0,at=!1,Pe=!1,en=!1,ft=!1,Ct=!1,Vt=!1,Kt=!0,xn=!1;const En="user-content-";let Nn=!0,rn=!1,Ge={},ht=null;const Yt=we({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let rr=null;const Pt=we({},["audio","video","img","source","image","track"]);let Nt=null;const qn=we({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),an="http://www.w3.org/1998/Math/MathML",Ve="http://www.w3.org/2000/svg",ke="http://www.w3.org/1999/xhtml";let Ke=ke,An=!1,In=null;const yt=we({},[an,Ve,ke],hi);let pt=we({},["mi","mo","mn","ms","mtext"]),Zt=we({},["annotation-xml"]);const xr=we({},["title","style","font","a","script"]);let Rn=null;const Hr=["application/xhtml+xml","text/html"],Wr="text/html";let $e=null,M=null;const H=n.createElement("form"),j=function(_){return _ instanceof RegExp||_ instanceof Function},F=function(){let _=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};if(M&&M===_)return;(!_||typeof _!="object")&&(_={}),_=Xt(_),Rn=Hr.indexOf(_.PARSER_MEDIA_TYPE)===-1?Wr:_.PARSER_MEDIA_TYPE,$e=Rn==="application/xhtml+xml"?hi:aa,$=st(_,"ALLOWED_TAGS")&&Bt(_.ALLOWED_TAGS)?we({},_.ALLOWED_TAGS,$e):Ae,ge=st(_,"ALLOWED_ATTR")&&Bt(_.ALLOWED_ATTR)?we({},_.ALLOWED_ATTR,$e):De,In=st(_,"ALLOWED_NAMESPACES")&&Bt(_.ALLOWED_NAMESPACES)?we({},_.ALLOWED_NAMESPACES,hi):yt,Nt=st(_,"ADD_URI_SAFE_ATTR")&&Bt(_.ADD_URI_SAFE_ATTR)?we(Xt(qn),_.ADD_URI_SAFE_ATTR,$e):qn,rr=st(_,"ADD_DATA_URI_TAGS")&&Bt(_.ADD_DATA_URI_TAGS)?we(Xt(Pt),_.ADD_DATA_URI_TAGS,$e):Pt,ht=st(_,"FORBID_CONTENTS")&&Bt(_.FORBID_CONTENTS)?we({},_.FORBID_CONTENTS,$e):Yt,Ue=st(_,"FORBID_TAGS")&&Bt(_.FORBID_TAGS)?we({},_.FORBID_TAGS,$e):Xt({}),Je=st(_,"FORBID_ATTR")&&Bt(_.FORBID_ATTR)?we({},_.FORBID_ATTR,$e):Xt({}),Ge=st(_,"USE_PROFILES")?_.USE_PROFILES&&typeof _.USE_PROFILES=="object"?Xt(_.USE_PROFILES):_.USE_PROFILES:!1,be=_.ALLOW_ARIA_ATTR!==!1,Se=_.ALLOW_DATA_ATTR!==!1,nt=_.ALLOW_UNKNOWN_PROTOCOLS||!1,bt=_.ALLOW_SELF_CLOSE_IN_ATTR!==!1,wt=_.SAFE_FOR_TEMPLATES||!1,rt=_.SAFE_FOR_XML!==!1,at=_.WHOLE_DOCUMENT||!1,ft=_.RETURN_DOM||!1,Ct=_.RETURN_DOM_FRAGMENT||!1,Vt=_.RETURN_TRUSTED_TYPE||!1,en=_.FORCE_BODY||!1,Kt=_.SANITIZE_DOM!==!1,xn=_.SANITIZE_NAMED_PROPS||!1,Nn=_.KEEP_CONTENT!==!1,rn=_.IN_PLACE||!1,ce=uh(_.ALLOWED_URI_REGEXP)?_.ALLOWED_URI_REGEXP:Bl,Ke=typeof _.NAMESPACE=="string"?_.NAMESPACE:ke,pt=st(_,"MATHML_TEXT_INTEGRATION_POINTS")&&_.MATHML_TEXT_INTEGRATION_POINTS&&typeof _.MATHML_TEXT_INTEGRATION_POINTS=="object"?Xt(_.MATHML_TEXT_INTEGRATION_POINTS):we({},["mi","mo","mn","ms","mtext"]),Zt=st(_,"HTML_INTEGRATION_POINTS")&&_.HTML_INTEGRATION_POINTS&&typeof _.HTML_INTEGRATION_POINTS=="object"?Xt(_.HTML_INTEGRATION_POINTS):we({},["annotation-xml"]);const N=st(_,"CUSTOM_ELEMENT_HANDLING")&&_.CUSTOM_ELEMENT_HANDLING&&typeof _.CUSTOM_ELEMENT_HANDLING=="object"?Xt(_.CUSTOM_ELEMENT_HANDLING):Cr(null);if(_e=Cr(null),st(N,"tagNameCheck")&&j(N.tagNameCheck)&&(_e.tagNameCheck=N.tagNameCheck),st(N,"attributeNameCheck")&&j(N.attributeNameCheck)&&(_e.attributeNameCheck=N.attributeNameCheck),st(N,"allowCustomizedBuiltInElements")&&typeof N.allowCustomizedBuiltInElements=="boolean"&&(_e.allowCustomizedBuiltInElements=N.allowCustomizedBuiltInElements),wt&&(Se=!1),Ct&&(ft=!0),Ge&&($=we({},vo),ge=Cr(null),Ge.html===!0&&(we($,go),we(ge,mo)),Ge.svg===!0&&(we($,pi),we(ge,mi),we(ge,Ma)),Ge.svgFilters===!0&&(we($,gi),we(ge,mi),we(ge,Ma)),Ge.mathMl===!0&&(we($,vi),we(ge,_o),we(ge,Ma))),se.tagCheck=null,se.attributeCheck=null,st(_,"ADD_TAGS")&&(typeof _.ADD_TAGS=="function"?se.tagCheck=_.ADD_TAGS:Bt(_.ADD_TAGS)&&($===Ae&&($=Xt($)),we($,_.ADD_TAGS,$e))),st(_,"ADD_ATTR")&&(typeof _.ADD_ATTR=="function"?se.attributeCheck=_.ADD_ATTR:Bt(_.ADD_ATTR)&&(ge===De&&(ge=Xt(ge)),we(ge,_.ADD_ATTR,$e))),st(_,"ADD_URI_SAFE_ATTR")&&Bt(_.ADD_URI_SAFE_ATTR)&&we(Nt,_.ADD_URI_SAFE_ATTR,$e),st(_,"FORBID_CONTENTS")&&Bt(_.FORBID_CONTENTS)&&(ht===Yt&&(ht=Xt(ht)),we(ht,_.FORBID_CONTENTS,$e)),st(_,"ADD_FORBID_CONTENTS")&&Bt(_.ADD_FORBID_CONTENTS)&&(ht===Yt&&(ht=Xt(ht)),we(ht,_.ADD_FORBID_CONTENTS,$e)),Nn&&($["#text"]=!0),at&&we($,["html","head","body"]),$.table&&(we($,["tbody"]),delete Ue.tbody),_.TRUSTED_TYPES_POLICY){if(typeof _.TRUSTED_TYPES_POLICY.createHTML!="function")throw Da('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if(typeof _.TRUSTED_TYPES_POLICY.createScriptURL!="function")throw Da('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');I=_.TRUSTED_TYPES_POLICY,D=I.createHTML("")}else I===void 0&&(I=kh(w,i)),I!==null&&typeof D=="string"&&(D=I.createHTML(""));jt&&jt(_),M=_},ue=we({},[...pi,...gi,...dh]),me=we({},[...vi,...fh]),Ie=function(_){let N=E(_);(!N||!N.tagName)&&(N={namespaceURI:Ke,tagName:"template"});const ne=aa(_.tagName),Ne=aa(N.tagName);return In[_.namespaceURI]?_.namespaceURI===Ve?N.namespaceURI===ke?ne==="svg":N.namespaceURI===an?ne==="svg"&&(Ne==="annotation-xml"||pt[Ne]):!!ue[ne]:_.namespaceURI===an?N.namespaceURI===ke?ne==="math":N.namespaceURI===Ve?ne==="math"&&Zt[Ne]:!!me[ne]:_.namespaceURI===ke?N.namespaceURI===Ve&&!Zt[Ne]||N.namespaceURI===an&&!pt[Ne]?!1:!me[ne]&&(xr[ne]||!ue[ne]):!!(Rn==="application/xhtml+xml"&&In[_.namespaceURI]):!1},Le=function(_){Qr(e.removed,{element:_});try{E(_).removeChild(_)}catch{k(_)}},Ye=function(_,N){try{Qr(e.removed,{attribute:N.getAttributeNode(_),from:N})}catch{Qr(e.removed,{attribute:null,from:N})}if(N.removeAttribute(_),_==="is")if(ft||Ct)try{Le(N)}catch{}else try{N.setAttribute(_,"")}catch{}},Dt=function(_){let N=null,ne=null;if(en)_=""+_;else{const ve=uo(_,/^[\r\n\t ]+/);ne=ve&&ve[0]}Rn==="application/xhtml+xml"&&Ke===ke&&(_=''+_+"");const Ne=I?I.createHTML(_):_;if(Ke===ke)try{N=new m().parseFromString(Ne,Rn)}catch{}if(!N||!N.documentElement){N=C.createDocument(Ke,"template",null);try{N.documentElement.innerHTML=An?D:Ne}catch{}}const kt=N.body||N.documentElement;return _&&ne&&kt.insertBefore(n.createTextNode(ne),kt.childNodes[0]||null),Ke===ke?G.call(N,at?"html":"body")[0]:at?N.documentElement:kt},St=function(_){return U.call(_.ownerDocument||_,_,f.SHOW_ELEMENT|f.SHOW_COMMENT|f.SHOW_TEXT|f.SHOW_PROCESSING_INSTRUCTION|f.SHOW_CDATA_SECTION,null)},We=function(_){return _ instanceof p&&(typeof _.nodeName!="string"||typeof _.textContent!="string"||typeof _.removeChild!="function"||!(_.attributes instanceof d)||typeof _.removeAttribute!="function"||typeof _.setAttribute!="function"||typeof _.namespaceURI!="string"||typeof _.insertBefore!="function"||typeof _.hasChildNodes!="function")},gt=function(_){return typeof u=="function"&&_ instanceof u};function qt(de,_,N){Xr(de,ne=>{ne.call(e,_,N,M)})}const Yn=function(_){let N=null;if(qt(Z.beforeSanitizeElements,_,null),We(_))return Le(_),!0;const ne=$e(_.nodeName);if(qt(Z.uponSanitizeElement,_,{tagName:ne,allowedTags:$}),rt&&_.hasChildNodes()&&!gt(_.firstElementChild)&&At(/<[/\w!]/g,_.innerHTML)&&At(/<[/\w!]/g,_.textContent)||rt&&_.namespaceURI===ke&&ne==="style"&>(_.firstElementChild)||_.nodeType===$r.progressingInstruction||rt&&_.nodeType===$r.comment&&At(/<[/\w]/g,_.data))return Le(_),!0;if(Ue[ne]||!(se.tagCheck instanceof Function&&se.tagCheck(ne))&&!$[ne]){if(!Ue[ne]&&hn(ne)&&(_e.tagNameCheck instanceof RegExp&&At(_e.tagNameCheck,ne)||_e.tagNameCheck instanceof Function&&_e.tagNameCheck(ne)))return!1;if(Nn&&!ht[ne]){const Ne=E(_)||_.parentNode,kt=A(_)||_.childNodes;if(kt&&Ne){const ve=kt.length;for(let Et=ve-1;Et>=0;--Et){const Ut=x(kt[Et],!0);Ne.insertBefore(Ut,g(_))}}}return Le(_),!0}return _ instanceof l&&!Ie(_)||(ne==="noscript"||ne==="noembed"||ne==="noframes")&&At(/<\/no(script|embed|frames)/i,_.innerHTML)?(Le(_),!0):(wt&&_.nodeType===$r.text&&(N=_.textContent,Xr([Y,O,W],Ne=>{N=Rr(N,Ne," ")}),_.textContent!==N&&(Qr(e.removed,{element:_.cloneNode()}),_.textContent=N)),qt(Z.afterSanitizeElements,_,null),!1)},Tt=function(_,N,ne){if(Je[N]||Kt&&(N==="id"||N==="name")&&(ne in n||ne in H))return!1;const Ne=ge[N]||se.attributeCheck instanceof Function&&se.attributeCheck(N,_);if(!(Se&&!Je[N]&&At(J,N))){if(!(be&&At(fe,N))){if(!Ne||Je[N]){if(!(hn(_)&&(_e.tagNameCheck instanceof RegExp&&At(_e.tagNameCheck,_)||_e.tagNameCheck instanceof Function&&_e.tagNameCheck(_))&&(_e.attributeNameCheck instanceof RegExp&&At(_e.attributeNameCheck,N)||_e.attributeNameCheck instanceof Function&&_e.attributeNameCheck(N,_))||N==="is"&&_e.allowCustomizedBuiltInElements&&(_e.tagNameCheck instanceof RegExp&&At(_e.tagNameCheck,ne)||_e.tagNameCheck instanceof Function&&_e.tagNameCheck(ne))))return!1}else if(!Nt[N]){if(!At(ce,Rr(ne,B,""))){if(!((N==="src"||N==="xlink:href"||N==="href")&&_!=="script"&&fo(ne,"data:")===0&&rr[_])){if(!(nt&&!At(ie,Rr(ne,B,"")))){if(ne)return!1}}}}}}return!0},xt=we({},["annotation-xml","color-profile","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","missing-glyph"]),hn=function(_){return!xt[aa(_)]&&At(ae,_)},ar=function(_){qt(Z.beforeSanitizeAttributes,_,null);const{attributes:N}=_;if(!N||We(_))return;const ne={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:ge,forceKeepAttr:void 0};let Ne=N.length;for(;Ne--;){const kt=N[Ne],{name:ve,namespaceURI:Et,value:Ut}=kt,Mt=$e(ve),Gr=Ut;let ct=ve==="value"?Gr:ah(Gr);if(ne.attrName=Mt,ne.attrValue=ct,ne.keepAttr=!0,ne.forceKeepAttr=void 0,qt(Z.uponSanitizeAttribute,_,ne),ct=ne.attrValue,xn&&(Mt==="id"||Mt==="name")&&fo(ct,En)!==0&&(Ye(ve,_),ct=En+ct),rt&&At(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i,ct)){Ye(ve,_);continue}if(Mt==="attributename"&&uo(ct,"href")){Ye(ve,_);continue}if(ne.forceKeepAttr)continue;if(!ne.keepAttr){Ye(ve,_);continue}if(!bt&&At(/\/>/i,ct)){Ye(ve,_);continue}wt&&Xr([Y,O,W],Sa=>{ct=Rr(ct,Sa," ")});const ka=$e(_.nodeName);if(!Tt(ka,Mt,ct)){Ye(ve,_);continue}if(I&&typeof w=="object"&&typeof w.getAttributeType=="function"&&!Et)switch(w.getAttributeType(ka,Mt)){case"TrustedHTML":{ct=I.createHTML(ct);break}case"TrustedScriptURL":{ct=I.createScriptURL(ct);break}}if(ct!==Gr)try{Et?_.setAttributeNS(Et,ve,ct):_.setAttribute(ve,ct),We(_)?Le(_):co(e.removed)}catch{Ye(ve,_)}}qt(Z.afterSanitizeAttributes,_,null)},ya=function(_){let N=null;const ne=St(_);for(qt(Z.beforeSanitizeShadowDOM,_,null);N=ne.nextNode();)qt(Z.uponSanitizeShadowNode,N,null),Yn(N),ar(N),N.content instanceof s&&ya(N.content);qt(Z.afterSanitizeShadowDOM,_,null)};return e.sanitize=function(de){let _=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},N=null,ne=null,Ne=null,kt=null;if(An=!de,An&&(de=""),typeof de!="string"&&!gt(de)&&(de=ch(de),typeof de!="string"))throw Da("dirty is not a string, aborting");if(!e.isSupported)return de;if(Pe||F(_),e.removed=[],typeof de=="string"&&(rn=!1),rn){const Ut=de.nodeName;if(typeof Ut=="string"){const Mt=$e(Ut);if(!$[Mt]||Ue[Mt])throw Da("root node is forbidden and cannot be sanitized in-place")}}else if(de instanceof u)N=Dt(""),ne=N.ownerDocument.importNode(de,!0),ne.nodeType===$r.element&&ne.nodeName==="BODY"||ne.nodeName==="HTML"?N=ne:N.appendChild(ne);else{if(!ft&&!wt&&!at&&de.indexOf("<")===-1)return I&&Vt?I.createHTML(de):de;if(N=Dt(de),!N)return ft?null:Vt?D:""}N&&en&&Le(N.firstChild);const ve=St(rn?de:N);for(;Ne=ve.nextNode();)Yn(Ne),ar(Ne),Ne.content instanceof s&&ya(Ne.content);if(rn)return de;if(ft){if(wt){N.normalize();let Ut=N.innerHTML;Xr([Y,O,W],Mt=>{Ut=Rr(Ut,Mt," ")}),N.innerHTML=Ut}if(Ct)for(kt=P.call(N.ownerDocument);N.firstChild;)kt.appendChild(N.firstChild);else kt=N;return(ge.shadowroot||ge.shadowrootmode)&&(kt=K.call(r,kt,!0)),kt}let Et=at?N.outerHTML:N.innerHTML;return at&&$["!doctype"]&&N.ownerDocument&&N.ownerDocument.doctype&&N.ownerDocument.doctype.name&&At(Fl,N.ownerDocument.doctype.name)&&(Et=" -`+Et),wt&&Xr([Y,O,W],Ut=>{Et=Rr(Et,Ut," ")}),I&&Vt?I.createHTML(Et):Et},e.setConfig=function(){let de=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};F(de),Pe=!0},e.clearConfig=function(){M=null,Pe=!1},e.isValidAttribute=function(de,_,N){M||F({});const ne=$e(de),Ne=$e(_);return Tt(ne,Ne,N)},e.addHook=function(de,_){typeof _=="function"&&Qr(Z[de],_)},e.removeHook=function(de,_){if(_!==void 0){const N=nh(Z[de],_);return N===-1?void 0:rh(Z[de],N,1)[0]}return co(Z[de])},e.removeHooks=function(de){Z[de]=[]},e.removeAllHooks=function(){Z=wo()},e}var Sh=Hl();function os(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var Tr=os();function Wl(t){Tr=t}var sr={exec:()=>null};function Ce(t,e=""){let n=typeof t=="string"?t:t.source,r={replace:(i,s)=>{let o=typeof s=="string"?s:s.source;return o=o.replace(Ft.caret,"$1"),n=n.replace(i,o),r},getRegex:()=>new RegExp(n,e)};return r}var Th=(()=>{try{return!!new RegExp("(?<=1)(?/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:t=>new RegExp(`^( {0,3}${t})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),hrRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}#`),htmlBeginRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}<(?:[a-z].*>|!--)`,"i"),blockquoteBeginRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}>`)},xh=/^(?:[ \t]*(?:\n|$))+/,Eh=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,Ah=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,wa=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,Ih=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,ls=/ {0,3}(?:[*+-]|\d{1,9}[.)])/,Gl=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,jl=Ce(Gl).replace(/bull/g,ls).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),Rh=Ce(Gl).replace(/bull/g,ls).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),cs=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,Ch=/^[^\n]+/,us=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,Dh=Ce(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",us).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),Mh=Ce(/^(bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,ls).getRegex(),Za="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",ds=/|$))/,Oh=Ce("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",ds).replace("tag",Za).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),Vl=Ce(cs).replace("hr",wa).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",Za).getRegex(),Lh=Ce(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",Vl).getRegex(),fs={blockquote:Lh,code:Eh,def:Dh,fences:Ah,heading:Ih,hr:wa,html:Oh,lheading:jl,list:Mh,newline:xh,paragraph:Vl,table:sr,text:Ch},yo=Ce("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",wa).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",Za).getRegex(),Ph={...fs,lheading:Rh,table:yo,paragraph:Ce(cs).replace("hr",wa).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",yo).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",Za).getRegex()},Nh={...fs,html:Ce(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",ds).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:sr,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:Ce(cs).replace("hr",wa).replace("heading",` *#{1,6} *[^ +(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))r(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(i){if(i.ep)return;i.ep=!0;const s=n(i);fetch(i.href,s)}})();const Gc=!1;var Wi=Array.isArray,jc=Array.prototype.indexOf,Lr=Array.prototype.includes,ja=Array.from,Vc=Object.defineProperty,Or=Object.getOwnPropertyDescriptor,Ao=Object.getOwnPropertyDescriptors,Kc=Object.prototype,Yc=Array.prototype,Gi=Object.getPrototypeOf,Ws=Object.isExtensible;const _i=()=>{};function Zc(t){return t()}function bi(t){for(var e=0;e{t=r,e=i});return{promise:n,resolve:t,reject:e}}const Lt=2,Pr=4,pa=8,ji=1<<24,Ln=16,yn=32,er=64,wi=128,on=512,ut=1024,It=2048,kn=4096,Ht=8192,nn=16384,kr=32768,yi=1<<25,tr=65536,ki=1<<17,Ro=1<<18,Sr=1<<19,Co=1<<20,Mn=1<<25,vr=65536,qa=1<<21,ca=1<<22,$n=1<<23,Gn=Symbol("$state"),Xc=Symbol("legacy props"),Qc=Symbol(""),Wn=new class extends Error{name="StaleReactionError";message="The reaction that called `getAbortSignal()` was re-run or destroyed"},Vi=!!globalThis.document?.contentType&&globalThis.document.contentType.includes("xml");function Do(t){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Jc(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function $c(t,e,n){throw new Error("https://svelte.dev/e/each_key_duplicate")}function eu(t){throw new Error("https://svelte.dev/e/effect_in_teardown")}function tu(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function nu(t){throw new Error("https://svelte.dev/e/effect_orphan")}function ru(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function au(t){throw new Error("https://svelte.dev/e/props_invalid_value")}function iu(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function su(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function ou(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function lu(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}const cu=1,uu=2,Mo=4,du=8,fu=16,hu=1,pu=2,gu=4,vu=8,mu=16,_u=1,bu=2,mt=Symbol(),Oo="http://www.w3.org/1999/xhtml",Lo="http://www.w3.org/2000/svg",wu="http://www.w3.org/1998/Math/MathML",yu="@attach";function ku(){console.warn("https://svelte.dev/e/derived_inert")}function Su(){console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function Tu(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}function Po(t){return t===this.v}function No(t,e){return t!=t?e==e:t!==e||t!==null&&typeof t=="object"||typeof t=="function"}function qo(t){return!No(t,this.v)}let Ur=!1,xu=!1;function Eu(){Ur=!0}let je=null;function Nr(t){je=t}function Fe(t,e=!1,n){je={p:je,i:!1,c:null,e:null,s:t,x:null,r:ye,l:Ur&&!e?{s:null,u:null,$:[]}:null}}function He(t){var e=je,n=e.e;if(n!==null){e.e=null;for(var r of n)rl(r)}return t!==void 0&&(e.x=t),e.i=!0,je=e.p,t??{}}function ga(){return!Ur||je!==null&&je.l===null}let or=[];function Uo(){var t=or;or=[],bi(t)}function jn(t){if(or.length===0&&!sa){var e=or;queueMicrotask(()=>{e===or&&Uo()})}or.push(t)}function Au(){for(;or.length>0;)Uo()}function zo(t){var e=ye;if(e===null)return Oe.f|=$n,t;if((e.f&kr)===0&&(e.f&Pr)===0)throw t;Qn(t,e)}function Qn(t,e){for(;e!==null;){if((e.f&wi)!==0){if((e.f&kr)===0)throw t;try{e.b.error(t);return}catch(n){t=n}}e=e.parent}throw t}const Iu=-7169;function ot(t,e){t.f=t.f&Iu|e}function Ki(t){(t.f&on)!==0||t.deps===null?ot(t,ut):ot(t,kn)}function Bo(t){if(t!==null)for(const e of t)(e.f&Lt)===0||(e.f&vr)===0||(e.f^=vr,Bo(e.deps))}function Fo(t,e,n){(t.f&It)!==0?e.add(t):(t.f&kn)!==0&&n.add(t),Bo(t.deps),ot(t,ut)}let Aa=!1;function Ru(t){var e=Aa;try{return Aa=!1,[t(),Aa]}finally{Aa=e}}const ir=new Set;let Me=null,_n=null,Si=null,sa=!1,oi=!1,Mr=null,La=null;var Gs=0;let Cu=1;class nr{id=Cu++;current=new Map;previous=new Map;#n=new Set;#l=new Set;#e=new Set;#a=new Map;#r=new Map;#i=null;#t=[];#s=[];#c=new Set;#u=new Set;#o=new Map;#f=new Set;is_fork=!1;#p=!1;#h=new Set;#d(){return this.is_fork||this.#r.size>0}#m(){for(const r of this.#h)for(const i of r.#r.keys()){for(var e=!1,n=i;n.parent!==null;){if(this.#o.has(n)){e=!0;break}n=n.parent}if(!e)return!0}return!1}skip_effect(e){this.#o.has(e)||this.#o.set(e,{d:[],m:[]}),this.#f.delete(e)}unskip_effect(e,n=r=>this.schedule(r)){var r=this.#o.get(e);if(r){this.#o.delete(e);for(var i of r.d)ot(i,It),n(i);for(i of r.m)ot(i,kn),n(i)}this.#f.add(e)}#g(){if(Gs++>1e3&&(ir.delete(this),Mu()),!this.#d()){for(const u of this.#c)this.#u.delete(u),ot(u,It),this.schedule(u);for(const u of this.#u)ot(u,kn),this.schedule(u)}const e=this.#t;this.#t=[],this.apply();var n=Mr=[],r=[],i=La=[];for(const u of e)try{this.#_(u,n,r)}catch(l){throw Go(u),l}if(Me=null,i.length>0){var s=nr.ensure();for(const u of i)s.schedule(u)}if(Mr=null,La=null,this.#d()||this.#m()){this.#v(r),this.#v(n);for(const[u,l]of this.#o)Wo(u,l)}else{this.#a.size===0&&ir.delete(this),this.#c.clear(),this.#u.clear();for(const u of this.#n)u(this);this.#n.clear(),js(r),js(n),this.#i?.resolve()}var o=Me;if(this.#t.length>0){const u=o??=this;u.#t.push(...this.#t.filter(l=>!u.#t.includes(l)))}o!==null&&(ir.add(o),o.#g())}#_(e,n,r){e.f^=ut;for(var i=e.first;i!==null;){var s=i.f,o=(s&(yn|er))!==0,u=o&&(s&ut)!==0,l=u||(s&Ht)!==0||this.#o.has(i);if(!l&&i.fn!==null){o?i.f^=ut:(s&Pr)!==0?n.push(i):Br(i)&&((s&Ln)!==0&&this.#u.add(i),_r(i));var f=i.first;if(f!==null){i=f;continue}}for(;i!==null;){var d=i.next;if(d!==null){i=d;break}i=i.parent}}}#v(e){for(var n=0;n!this.current.has(p));if(i.length===0)e&&d.discard();else if(n.length>0){if(e)for(const p of this.#f)d.unskip_effect(p,m=>{(m.f&(Ln|ca))!==0?d.schedule(m):d.#v([m])});d.activate();var s=new Set,o=new Map;for(var u of n)Ho(u,i,s,o);o=new Map;var l=[...d.current.keys()].filter(p=>this.current.has(p)?this.current.get(p)[0]!==p:!0);for(const p of this.#s)(p.f&(nn|Ht|ki))===0&&Yi(p,l,o)&&((p.f&(ca|Ln))!==0?(ot(p,It),d.schedule(p)):d.#c.add(p));if(d.#t.length>0){d.apply();for(var f of d.#t)d.#_(f,[],[]);d.#t=[]}d.deactivate()}}for(const d of ir)d.#h.has(this)&&(d.#h.delete(this),d.#h.size===0&&!d.#d()&&(d.activate(),d.#g()))}increment(e,n){let r=this.#a.get(n)??0;if(this.#a.set(n,r+1),e){let i=this.#r.get(n)??0;this.#r.set(n,i+1)}}decrement(e,n,r){let i=this.#a.get(n)??0;if(i===1?this.#a.delete(n):this.#a.set(n,i-1),e){let s=this.#r.get(n)??0;s===1?this.#r.delete(n):this.#r.set(n,s-1)}this.#p||r||(this.#p=!0,jn(()=>{this.#p=!1,this.flush()}))}transfer_effects(e,n){for(const r of e)this.#c.add(r);for(const r of n)this.#u.add(r);e.clear(),n.clear()}oncommit(e){this.#n.add(e)}ondiscard(e){this.#l.add(e)}on_fork_commit(e){this.#e.add(e)}run_fork_commit_callbacks(){for(const e of this.#e)e(this);this.#e.clear()}settled(){return(this.#i??=Io()).promise}static ensure(){if(Me===null){const e=Me=new nr;oi||(ir.add(Me),sa||jn(()=>{Me===e&&e.flush()}))}return Me}apply(){{_n=null;return}}schedule(e){if(Si=e,e.b?.is_pending&&(e.f&(Pr|pa|ji))!==0&&(e.f&kr)===0){e.b.defer_effect(e);return}for(var n=e;n.parent!==null;){n=n.parent;var r=n.f;if(Mr!==null&&n===ye&&(Oe===null||(Oe.f&Lt)===0))return;if((r&(er|yn))!==0){if((r&ut)===0)return;n.f^=ut}}this.#t.push(n)}}function Du(t){var e=sa;sa=!0;try{for(var n;;){if(Au(),Me===null)return n;Me.flush()}}finally{sa=e}}function Mu(){try{ru()}catch(t){Qn(t,Si)}}let Hn=null;function js(t){var e=t.length;if(e!==0){for(var n=0;n0)){fr.clear();for(const i of Hn){if((i.f&(nn|Ht))!==0)continue;const s=[i];let o=i.parent;for(;o!==null;)Hn.has(o)&&(Hn.delete(o),s.push(o)),o=o.parent;for(let u=s.length-1;u>=0;u--){const l=s[u];(l.f&(nn|Ht))===0&&_r(l)}}Hn.clear()}}Hn=null}}function Ho(t,e,n,r){if(!n.has(t)&&(n.add(t),t.reactions!==null))for(const i of t.reactions){const s=i.f;(s&Lt)!==0?Ho(i,e,n,r):(s&(ca|Ln))!==0&&(s&It)===0&&Yi(i,e,r)&&(ot(i,It),Zi(i))}}function Yi(t,e,n){const r=n.get(t);if(r!==void 0)return r;if(t.deps!==null)for(const i of t.deps){if(Lr.call(e,i))return!0;if((i.f&Lt)!==0&&Yi(i,e,n))return n.set(i,!0),!0}return n.set(t,!1),!1}function Zi(t){Me.schedule(t)}function Wo(t,e){if(!((t.f&yn)!==0&&(t.f&ut)!==0)){(t.f&It)!==0?e.d.push(t):(t.f&kn)!==0&&e.m.push(t),ot(t,ut);for(var n=t.first;n!==null;)Wo(n,e),n=n.next}}function Go(t){ot(t,ut);for(var e=t.first;e!==null;)Go(e),e=e.next}function Ou(t){let e=0,n=mr(0),r;return()=>{$i()&&(a(n),ba(()=>(e===0&&(r=_t(()=>t(()=>oa(n)))),e+=1,()=>{jn(()=>{e-=1,e===0&&(r?.(),r=void 0,oa(n))})})))}}var Lu=tr|Sr;function Pu(t,e,n,r){new Nu(t,e,n,r)}class Nu{parent;is_pending=!1;transform_error;#n;#l=null;#e;#a;#r;#i=null;#t=null;#s=null;#c=null;#u=0;#o=0;#f=!1;#p=new Set;#h=new Set;#d=null;#m=Ou(()=>(this.#d=mr(this.#u),()=>{this.#d=null}));constructor(e,n,r,i){this.#n=e,this.#e=n,this.#a=s=>{var o=ye;o.b=this,o.f|=wi,r(s)},this.parent=ye.b,this.transform_error=i??this.parent?.transform_error??(s=>s),this.#r=zr(()=>{this.#b()},Lu)}#g(){try{this.#i=$t(()=>this.#a(this.#n))}catch(e){this.error(e)}}#_(e){const n=this.#e.failed;n&&(this.#s=$t(()=>{n(this.#n,()=>e,()=>()=>{})}))}#v(){const e=this.#e.pending;e&&(this.is_pending=!0,this.#t=$t(()=>e(this.#n)),jn(()=>{var n=this.#c=document.createDocumentFragment(),r=wn();n.append(r),this.#i=this.#y(()=>$t(()=>this.#a(r))),this.#o===0&&(this.#n.before(n),this.#c=null,hr(this.#t,()=>{this.#t=null}),this.#w(Me))}))}#b(){try{if(this.is_pending=this.has_pending_snippet(),this.#o=0,this.#u=0,this.#i=$t(()=>{this.#a(this.#n)}),this.#o>0){var e=this.#c=document.createDocumentFragment();ns(this.#i,e);const n=this.#e.pending;this.#t=$t(()=>n(this.#n))}else this.#w(Me)}catch(n){this.error(n)}}#w(e){this.is_pending=!1,e.transfer_effects(this.#p,this.#h)}defer_effect(e){Fo(e,this.#p,this.#h)}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!this.#e.pending}#y(e){var n=ye,r=Oe,i=je;un(this.#r),cn(this.#r),Nr(this.#r.ctx);try{return nr.ensure(),e()}catch(s){return zo(s),null}finally{un(n),cn(r),Nr(i)}}#k(e,n){if(!this.has_pending_snippet()){this.parent&&this.parent.#k(e,n);return}this.#o+=e,this.#o===0&&(this.#w(n),this.#t&&hr(this.#t,()=>{this.#t=null}),this.#c&&(this.#n.before(this.#c),this.#c=null))}update_pending_count(e,n){this.#k(e,n),this.#u+=e,!(!this.#d||this.#f)&&(this.#f=!0,jn(()=>{this.#f=!1,this.#d&&qr(this.#d,this.#u)}))}get_effect_pending(){return this.#m(),a(this.#d)}error(e){if(!this.#e.onerror&&!this.#e.failed)throw e;Me?.is_fork?(this.#i&&Me.skip_effect(this.#i),this.#t&&Me.skip_effect(this.#t),this.#s&&Me.skip_effect(this.#s),Me.on_fork_commit(()=>{this.#S(e)})):this.#S(e)}#S(e){this.#i&&(Rt(this.#i),this.#i=null),this.#t&&(Rt(this.#t),this.#t=null),this.#s&&(Rt(this.#s),this.#s=null);var n=this.#e.onerror;let r=this.#e.failed;var i=!1,s=!1;const o=()=>{if(i){Tu();return}i=!0,s&&lu(),this.#s!==null&&hr(this.#s,()=>{this.#s=null}),this.#y(()=>{this.#b()})},u=l=>{try{s=!0,n?.(l,o),s=!1}catch(f){Qn(f,this.#r&&this.#r.parent)}r&&(this.#s=this.#y(()=>{try{return $t(()=>{var f=ye;f.b=this,f.f|=wi,r(this.#n,()=>l,()=>o)})}catch(f){return Qn(f,this.#r.parent),null}}))};jn(()=>{var l;try{l=this.transform_error(e)}catch(f){Qn(f,this.#r&&this.#r.parent);return}l!==null&&typeof l=="object"&&typeof l.then=="function"?l.then(u,f=>Qn(f,this.#r&&this.#r.parent)):u(l)})}}function jo(t,e,n,r){const i=ga()?va:Ot;var s=t.filter(m=>!m.settled);if(n.length===0&&s.length===0){r(e.map(i));return}var o=ye,u=qu(),l=s.length===1?s[0].promise:s.length>1?Promise.all(s.map(m=>m.promise)):null;function f(m){u();try{r(m)}catch(w){(o.f&nn)===0&&Qn(w,o)}Ua()}if(n.length===0){l.then(()=>f(e.map(i)));return}var d=Vo();function p(){Promise.all(n.map(m=>Uu(m))).then(m=>f([...e.map(i),...m])).catch(m=>Qn(m,o)).finally(()=>d())}l?l.then(()=>{u(),p(),Ua()}):p()}function qu(){var t=ye,e=Oe,n=je,r=Me;return function(s=!0){un(t),cn(e),Nr(n),s&&(t.f&nn)===0&&(r?.activate(),r?.apply())}}function Ua(t=!0){un(null),cn(null),Nr(null),t&&Me?.deactivate()}function Vo(){var t=ye,e=t.b,n=Me,r=e.is_rendered();return e.update_pending_count(1,n),n.increment(r,t),(i=!1)=>{e.update_pending_count(-1,n),n.decrement(r,t,i)}}function va(t){var e=Lt|It;return ye!==null&&(ye.f|=Sr),{ctx:je,deps:null,effects:null,equals:Po,f:e,fn:t,reactions:null,rv:0,v:mt,wv:0,parent:ye,ac:null}}function Uu(t,e,n){let r=ye;r===null&&Jc();var i=void 0,s=mr(mt),o=!Oe,u=new Map;return Zu(()=>{var l=ye,f=Io();i=f.promise;try{Promise.resolve(t()).then(f.resolve,f.reject).finally(Ua)}catch(w){f.reject(w),Ua()}var d=Me;if(o){if((l.f&kr)!==0)var p=Vo();if(r.b.is_rendered())u.get(d)?.reject(Wn),u.delete(d);else{for(const w of u.values())w.reject(Wn);u.clear()}u.set(d,f)}const m=(w,y=void 0)=>{if(p){var x=y===Wn;p(x)}if(!(y===Wn||(l.f&nn)!==0)){if(d.activate(),y)s.f|=$n,qr(s,y);else{(s.f&$n)!==0&&(s.f^=$n),qr(s,w);for(const[k,g]of u){if(u.delete(k),k===d)break;g.reject(Wn)}}d.deactivate()}};f.promise.then(m,w=>m(null,w||"unknown"))}),Va(()=>{for(const l of u.values())l.reject(Wn)}),new Promise(l=>{function f(d){function p(){d===i?l(s):f(i)}d.then(p,p)}f(i)})}function le(t){const e=va(t);return ul(e),e}function Ot(t){const e=va(t);return e.equals=qo,e}function zu(t){var e=t.effects;if(e!==null){t.effects=null;for(var n=0;n0&&!Zo&&Fu()}return e}function Fu(){Zo=!1;for(const t of Ti)(t.f&ut)!==0&&ot(t,kn),Br(t)&&_r(t);Ti.clear()}function oa(t){v(t,t.v+1)}function Xo(t,e,n){var r=t.reactions;if(r!==null)for(var i=ga(),s=r.length,o=0;o{if(pr===s)return u();var l=Oe,f=pr;cn(null),Ys(s);var d=u();return cn(l),Ys(f),d};return r&&n.set("length",Be(t.length)),new Proxy(t,{defineProperty(u,l,f){(!("value"in f)||f.configurable===!1||f.enumerable===!1||f.writable===!1)&&iu();var d=n.get(l);return d===void 0?o(()=>{var p=Be(f.value);return n.set(l,p),p}):v(d,f.value,!0),!0},deleteProperty(u,l){var f=n.get(l);if(f===void 0){if(l in u){const d=o(()=>Be(mt));n.set(l,d),oa(i)}}else v(f,mt),oa(i);return!0},get(u,l,f){if(l===Gn)return t;var d=n.get(l),p=l in u;if(d===void 0&&(!p||Or(u,l)?.writable)&&(d=o(()=>{var w=lr(p?u[l]:mt),y=Be(w);return y}),n.set(l,d)),d!==void 0){var m=a(d);return m===mt?void 0:m}return Reflect.get(u,l,f)},getOwnPropertyDescriptor(u,l){var f=Reflect.getOwnPropertyDescriptor(u,l);if(f&&"value"in f){var d=n.get(l);d&&(f.value=a(d))}else if(f===void 0){var p=n.get(l),m=p?.v;if(p!==void 0&&m!==mt)return{enumerable:!0,configurable:!0,value:m,writable:!0}}return f},has(u,l){if(l===Gn)return!0;var f=n.get(l),d=f!==void 0&&f.v!==mt||Reflect.has(u,l);if(f!==void 0||ye!==null&&(!d||Or(u,l)?.writable)){f===void 0&&(f=o(()=>{var m=d?lr(u[l]):mt,w=Be(m);return w}),n.set(l,f));var p=a(f);if(p===mt)return!1}return d},set(u,l,f,d){var p=n.get(l),m=l in u;if(r&&l==="length")for(var w=f;wBe(mt)),n.set(w+"",y))}if(p===void 0)(!m||Or(u,l)?.writable)&&(p=o(()=>Be(void 0)),v(p,lr(f)),n.set(l,p));else{m=p.v!==mt;var x=o(()=>lr(f));v(p,x)}var k=Reflect.getOwnPropertyDescriptor(u,l);if(k?.set&&k.set.call(d,f),!m){if(r&&typeof l=="string"){var g=n.get("length"),I=Number(l);Number.isInteger(I)&&I>=g.v&&v(g,I+1)}oa(i)}return!0},ownKeys(u){a(i);var l=Reflect.ownKeys(u).filter(p=>{var m=n.get(p);return m===void 0||m.v!==mt});for(var[f,d]of n)d.v!==mt&&!(f in u)&&l.push(f);return l},setPrototypeOf(){su()}})}function Vs(t){try{if(t!==null&&typeof t=="object"&&Gn in t)return t[Gn]}catch{}return t}function Hu(t,e){return Object.is(Vs(t),Vs(e))}var xi,Qo,Jo,$o,el;function Wu(){if(xi===void 0){xi=window,Qo=document,Jo=/Firefox/.test(navigator.userAgent);var t=Element.prototype,e=Node.prototype,n=Text.prototype;$o=Or(e,"firstChild").get,el=Or(e,"nextSibling").get,Ws(t)&&(t.__click=void 0,t.__className=void 0,t.__attributes=null,t.__style=void 0,t.__e=void 0),Ws(n)&&(n.__t=void 0)}}function wn(t=""){return document.createTextNode(t)}function Jn(t){return $o.call(t)}function ma(t){return el.call(t)}function b(t,e){return Jn(t)}function Gt(t,e=!1){{var n=Jn(t);return n instanceof Comment&&n.data===""?ma(n):n}}function S(t,e=1,n=!1){let r=t;for(;e--;)r=ma(r);return r}function Gu(t){t.textContent=""}function tl(){return!1}function Qi(t,e,n){return document.createElementNS(e??Oo,t,void 0)}function ju(t,e){if(e){const n=document.body;t.autofocus=!0,jn(()=>{document.activeElement===n&&t.focus()})}}function Ji(t){var e=Oe,n=ye;cn(null),un(null);try{return t()}finally{cn(e),un(n)}}function nl(t){ye===null&&(Oe===null&&nu(),tu()),Vn&&eu()}function Vu(t,e){var n=e.last;n===null?e.last=e.first=t:(n.next=t,t.prev=n,e.last=t)}function Tn(t,e){var n=ye;n!==null&&(n.f&Ht)!==0&&(t|=Ht);var r={ctx:je,deps:null,nodes:null,f:t|It|on,first:null,fn:e,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null};Me?.register_created_effect(r);var i=r;if((t&Pr)!==0)Mr!==null?Mr.push(r):nr.ensure().schedule(r);else if(e!==null){try{_r(r)}catch(o){throw Rt(r),o}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&(i.f&Sr)===0&&(i=i.first,(t&Ln)!==0&&(t&tr)!==0&&i!==null&&(i.f|=tr))}if(i!==null&&(i.parent=n,n!==null&&Vu(i,n),Oe!==null&&(Oe.f&Lt)!==0&&(t&er)===0)){var s=Oe;(s.effects??=[]).push(i)}return r}function $i(){return Oe!==null&&!bn}function Va(t){const e=Tn(pa,null);return ot(e,ut),e.teardown=t,e}function Qt(t){nl();var e=ye.f,n=!Oe&&(e&yn)!==0&&(e&kr)===0;if(n){var r=je;(r.e??=[]).push(t)}else return rl(t)}function rl(t){return Tn(Pr|Co,t)}function za(t){return nl(),Tn(pa|Co,t)}function Ku(t){nr.ensure();const e=Tn(er|Sr,t);return(n={})=>new Promise(r=>{n.outro?hr(e,()=>{Rt(e),r(void 0)}):(Rt(e),r(void 0))})}function _a(t){return Tn(Pr,t)}function zt(t,e){var n=je,r={effect:null,ran:!1,deps:t};n.l.$.push(r),r.effect=ba(()=>{if(t(),!r.ran){r.ran=!0;var i=ye;try{un(i.parent),_t(e)}finally{un(i)}}})}function Yu(){var t=je;ba(()=>{for(var e of t.l.$){e.deps();var n=e.effect;(n.f&ut)!==0&&n.deps!==null&&ot(n,kn),Br(n)&&_r(n),e.ran=!1}})}function Zu(t){return Tn(ca|Sr,t)}function ba(t,e=0){return Tn(pa|e,t)}function te(t,e=[],n=[],r=[]){jo(r,e,n,i=>{Tn(pa,()=>t(...i.map(a)))})}function zr(t,e=0){var n=Tn(Ln|e,t);return n}function al(t,e=0){var n=Tn(ji|e,t);return n}function $t(t){return Tn(yn|Sr,t)}function il(t){var e=t.teardown;if(e!==null){const n=Vn,r=Oe;Ks(!0),cn(null);try{e.call(null)}finally{Ks(n),cn(r)}}}function es(t,e=!1){var n=t.first;for(t.first=t.last=null;n!==null;){const i=n.ac;i!==null&&Ji(()=>{i.abort(Wn)});var r=n.next;(n.f&er)!==0?n.parent=null:Rt(n,e),n=r}}function Xu(t){for(var e=t.first;e!==null;){var n=e.next;(e.f&yn)===0&&Rt(e),e=n}}function Rt(t,e=!0){var n=!1;(e||(t.f&Ro)!==0)&&t.nodes!==null&&t.nodes.end!==null&&(sl(t.nodes.start,t.nodes.end),n=!0),ot(t,yi),es(t,e&&!n),ua(t,0);var r=t.nodes&&t.nodes.t;if(r!==null)for(const s of r)s.stop();il(t),t.f^=yi,t.f|=nn;var i=t.parent;i!==null&&i.first!==null&&ol(t),t.next=t.prev=t.teardown=t.ctx=t.deps=t.fn=t.nodes=t.ac=t.b=null}function sl(t,e){for(;t!==null;){var n=t===e?null:ma(t);t.remove(),t=n}}function ol(t){var e=t.parent,n=t.prev,r=t.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),e!==null&&(e.first===t&&(e.first=r),e.last===t&&(e.last=n))}function hr(t,e,n=!0){var r=[];ll(t,r,!0);var i=()=>{n&&Rt(t),e&&e()},s=r.length;if(s>0){var o=()=>--s||i();for(var u of r)u.out(o)}else i()}function ll(t,e,n){if((t.f&Ht)===0){t.f^=Ht;var r=t.nodes&&t.nodes.t;if(r!==null)for(const u of r)(u.is_global||n)&&e.push(u);for(var i=t.first;i!==null;){var s=i.next;if((i.f&er)===0){var o=(i.f&tr)!==0||(i.f&yn)!==0&&(t.f&Ln)!==0;ll(i,e,o?n:!1)}i=s}}}function ts(t){cl(t,!0)}function cl(t,e){if((t.f&Ht)!==0){t.f^=Ht,(t.f&ut)===0&&(ot(t,It),nr.ensure().schedule(t));for(var n=t.first;n!==null;){var r=n.next,i=(n.f&tr)!==0||(n.f&yn)!==0;cl(n,i?e:!1),n=r}var s=t.nodes&&t.nodes.t;if(s!==null)for(const o of s)(o.is_global||e)&&o.in()}}function ns(t,e){if(t.nodes)for(var n=t.nodes.start,r=t.nodes.end;n!==null;){var i=n===r?null:ma(n);e.append(n),n=i}}let Pa=!1,Vn=!1;function Ks(t){Vn=t}let Oe=null,bn=!1;function cn(t){Oe=t}let ye=null;function un(t){ye=t}let ln=null;function ul(t){Oe!==null&&(ln===null?ln=[t]:ln.push(t))}let Jt=null,tn=0,sn=null;function Qu(t){sn=t}let dl=1,cr=0,pr=cr;function Ys(t){pr=t}function fl(){return++dl}function Br(t){var e=t.f;if((e&It)!==0)return!0;if(e&Lt&&(t.f&=~vr),(e&kn)!==0){for(var n=t.deps,r=n.length,i=0;it.wv)return!0}(e&on)!==0&&_n===null&&ot(t,ut)}return!1}function hl(t,e,n=!0){var r=t.reactions;if(r!==null&&!(ln!==null&&Lr.call(ln,t)))for(var i=0;i{t.ac.abort(Wn)}),t.ac=null);try{t.f|=qa;var d=t.fn,p=d();t.f|=kr;var m=t.deps,w=Me?.is_fork;if(Jt!==null){var y;if(w||ua(t,tn),m!==null&&tn>0)for(m.length=tn+Jt.length,y=0;yn?.call(this,s))}return t.startsWith("pointer")||t.startsWith("touch")||t==="wheel"?jn(()=>{e.addEventListener(t,i,r)}):e.addEventListener(t,i,r),i}function dn(t,e,n,r,i){var s={capture:r,passive:i},o=_l(t,e,n,s);(e===document.body||e===window||e===document||e instanceof HTMLMediaElement)&&Va(()=>{e.removeEventListener(t,o,s)})}function V(t,e,n){(e[na]??={})[t]=n}function Qe(t){for(var e=0;e{throw k});throw m}}finally{t[na]=e,delete t.currentTarget,cn(d),un(p)}}}const sd=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:t=>t});function od(t){return sd?.createHTML(t)??t}function ld(t){var e=Qi("template");return e.innerHTML=od(t.replaceAll("","")),e.content}function br(t,e){var n=ye;n.nodes===null&&(n.nodes={start:t,end:e,a:null,t:null})}function z(t,e){var n=(e&_u)!==0,r=(e&bu)!==0,i,s=!t.startsWith("");return()=>{i===void 0&&(i=ld(s?t:""+t),n||(i=Jn(i)));var o=r||Jo?document.importNode(i,!0):i.cloneNode(!0);if(n){var u=Jn(o),l=o.lastChild;br(u,l)}else br(o,o);return o}}function Xn(t=""){{var e=wn(t+"");return br(e,e),e}}function Sn(){var t=document.createDocumentFragment(),e=document.createComment(""),n=wn();return t.append(e,n),br(e,n),t}function L(t,e){t!==null&&t.before(e)}function ee(t,e){var n=e==null?"":typeof e=="object"?`${e}`:e;n!==(t.__t??=t.nodeValue)&&(t.__t=n,t.nodeValue=`${n}`)}function cd(t,e){return ud(t,e)}const Ia=new Map;function ud(t,{target:e,anchor:n,props:r={},events:i,context:s,intro:o=!0,transformError:u}){Wu();var l=void 0,f=Ku(()=>{var d=n??e.appendChild(wn());Pu(d,{pending:()=>{}},w=>{Fe({});var y=je;s&&(y.c=s),i&&(r.$$events=i),l=t(w,r)||{},He()},u);var p=new Set,m=w=>{for(var y=0;y{for(var w of p)for(const k of[e,document]){var y=Ia.get(k),x=y.get(w);--x==0?(k.removeEventListener(w,Ii),y.delete(w),y.size===0&&Ia.delete(k)):y.set(w,x)}Ai.delete(m),d!==n&&d.parentNode?.removeChild(d)}});return dd.set(l,f),l}let dd=new WeakMap;class as{anchor;#n=new Map;#l=new Map;#e=new Map;#a=new Set;#r=!0;constructor(e,n=!0){this.anchor=e,this.#r=n}#i=e=>{if(this.#n.has(e)){var n=this.#n.get(e),r=this.#l.get(n);if(r)ts(r),this.#a.delete(n);else{var i=this.#e.get(n);i&&(this.#l.set(n,i.effect),this.#e.delete(n),i.fragment.lastChild.remove(),this.anchor.before(i.fragment),r=i.effect)}for(const[s,o]of this.#n){if(this.#n.delete(s),s===e)break;const u=this.#e.get(o);u&&(Rt(u.effect),this.#e.delete(o))}for(const[s,o]of this.#l){if(s===n||this.#a.has(s))continue;const u=()=>{if(Array.from(this.#n.values()).includes(s)){var f=document.createDocumentFragment();ns(o,f),f.append(wn()),this.#e.set(s,{effect:o,fragment:f})}else Rt(o);this.#a.delete(s),this.#l.delete(s)};this.#r||!r?(this.#a.add(s),hr(o,u,!1)):u()}}};#t=e=>{this.#n.delete(e);const n=Array.from(this.#n.values());for(const[r,i]of this.#e)n.includes(r)||(Rt(i.effect),this.#e.delete(r))};ensure(e,n){var r=Me,i=tl();if(n&&!this.#l.has(e)&&!this.#e.has(e))if(i){var s=document.createDocumentFragment(),o=wn();s.append(o),this.#e.set(e,{effect:$t(()=>n(o)),fragment:s})}else this.#l.set(e,$t(()=>n(this.anchor)));if(this.#n.set(r,e),i){for(const[u,l]of this.#l)u===e?r.unskip_effect(l):r.skip_effect(l);for(const[u,l]of this.#e)u===e?r.unskip_effect(l.effect):r.skip_effect(l.effect);r.oncommit(this.#i),r.ondiscard(this.#t)}else this.#i(r)}}function oe(t,e,n=!1){var r=new as(t),i=n?tr:0;function s(o,u){r.ensure(o,u)}zr(()=>{var o=!1;e((u,l=0)=>{o=!0,s(l,u)}),o||s(-1,null)},i)}function bl(t,e){return e}function fd(t,e,n){for(var r=[],i=e.length,s,o=e.length,u=0;u{if(s){if(s.pending.delete(p),s.done.add(p),s.pending.size===0){var m=t.outrogroups;Ri(t,ja(s.done)),m.delete(s),m.size===0&&(t.outrogroups=null)}}else o-=1},!1)}if(o===0){var l=r.length===0&&n!==null;if(l){var f=n,d=f.parentNode;Gu(d),d.append(f),t.items.clear()}Ri(t,e,!l)}else s={pending:new Set(e),done:new Set},(t.outrogroups??=new Set).add(s)}function Ri(t,e,n=!0){var r;if(t.pending.size>0){r=new Set;for(const o of t.pending.values())for(const u of o)r.add(t.items.get(u).e)}for(var i=0;i{var E=n();return Wi(E)?E:E==null?[]:ja(E)}),m,w=new Map,y=!0;function x(E){(I.effect.f&nn)===0&&(I.pending.delete(E),I.fallback=d,hd(I,m,o,e,r),d!==null&&(m.length===0?(d.f&Mn)===0?ts(d):(d.f^=Mn,ra(d,null,o)):hr(d,()=>{d=null})))}function k(E){I.pending.delete(E)}var g=zr(()=>{m=a(p);for(var E=m.length,A=new Set,D=Me,C=tl(),U=0;Us(o)):(d=$t(()=>s(Xs??=wn())),d.f|=Mn)),E>A.size&&$c(),!y)if(w.set(D,A),C){for(const[Z,Y]of u)A.has(Z)||D.skip_effect(Y.e);D.oncommit(x),D.ondiscard(k)}else x(D);a(p)}),I={effect:g,items:u,pending:w,outrogroups:null,fallback:d};y=!1}function Vr(t){for(;t!==null&&(t.f&yn)===0;)t=t.next;return t}function hd(t,e,n,r,i){var s=(r&du)!==0,o=e.length,u=t.items,l=Vr(t.effect.first),f,d=null,p,m=[],w=[],y,x,k,g;if(s)for(g=0;g0){var G=(r&Mo)!==0&&o===0?n:null;if(s){for(g=0;g{if(p!==void 0)for(k of p)k.nodes?.a?.apply()})}function pd(t,e,n,r,i,s,o,u){var l=(o&cu)!==0?(o&fu)===0?Q(n,!1,!1):mr(n):null,f=(o&uu)!==0?mr(i):null;return{v:l,i:f,e:$t(()=>(s(e,l??n,f??i,u),()=>{t.delete(r)}))}}function ra(t,e,n){if(t.nodes)for(var r=t.nodes.start,i=t.nodes.end,s=e&&(e.f&Mn)===0?e.nodes.start:n;r!==null;){var o=ma(r);if(s.before(r),r===i)return;r=o}}function Zn(t,e,n){e===null?t.effect.first=n:e.next=n,n===null?t.effect.last=e:n.prev=e}function Ci(t,e,n=!1,r=!1,i=!1,s=!1){var o=t,u="";if(n)var l=t;te(()=>{var f=ye;if(u!==(u=e()??"")){if(n){f.nodes=null,l.innerHTML=u,u!==""&&br(Jn(l),l.lastChild);return}if(f.nodes!==null&&(sl(f.nodes.start,f.nodes.end),f.nodes=null),u!==""){var d=r?Lo:i?wu:void 0,p=Qi(r?"svg":i?"math":"template",d);p.innerHTML=u;var m=r||i?p:p.content;if(br(Jn(m),m.lastChild),r||i)for(;Jn(m);)o.before(Jn(m));else o.before(m)}}})}function gd(t,e,...n){var r=new as(t);zr(()=>{const i=e()??null;r.ensure(i,i&&(s=>i(s,...n)))},tr)}function wl(t,e,n,r,i,s){var o=null,u=t,l=new as(u,!1);zr(()=>{const f=e()||null;var d=f==="svg"?Lo:void 0;if(f===null){l.ensure(null,null);return}return l.ensure(f,p=>{if(f){if(o=Qi(f,d),br(o,o),r){var m=o.appendChild(wn());r(o,m)}ye.nodes.end=o,p.before(o)}}),()=>{}},tr),Va(()=>{})}function yl(t,e){var n;n=document.head.appendChild(wn()),zr(()=>e(n),Ro|Sr)}function vd(t,e,n){_a(()=>{var r=_t(()=>e(t,n?.())||{});if(n&&r?.update){var i=!1,s={};ba(()=>{var o=n();rs(o),i&&No(s,o)&&(s=o,r.update(o))}),i=!0}if(r?.destroy)return()=>r.destroy()})}function md(t,e){var n=void 0,r;al(()=>{n!==(n=e())&&(r&&(Rt(r),r=null),n&&(r=$t(()=>{_a(()=>n(t))})))})}function kl(t){var e,n,r="";if(typeof t=="string"||typeof t=="number")r+=t;else if(typeof t=="object")if(Array.isArray(t)){var i=t.length;for(e=0;e=0;){var u=o+s;(o===0||Qs.includes(r[o-1]))&&(u===r.length||Qs.includes(r[u]))?r=(o===0?"":r.substring(0,o))+r.substring(u+1):o=u}}return r===""?null:r}function Js(t,e=!1){var n=e?" !important;":";",r="";for(var i of Object.keys(t)){var s=t[i];s!=null&&s!==""&&(r+=" "+i+": "+s+n)}return r}function li(t){return t[0]!=="-"||t[1]!=="-"?t.toLowerCase():t}function wd(t,e){if(e){var n="",r,i;if(Array.isArray(e)?(r=e[0],i=e[1]):r=e,t){t=String(t).replaceAll(/\s*\/\*.*?\*\/\s*/g,"").trim();var s=!1,o=0,u=!1,l=[];r&&l.push(...Object.keys(r).map(li)),i&&l.push(...Object.keys(i).map(li));var f=0,d=-1;const x=t.length;for(var p=0;p{Di(t,t.__value)});e.observe(t,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),Va(()=>{e.disconnect()})}function $s(t){return"__value"in t?t.__value:t.value}const Kr=Symbol("class"),Yr=Symbol("style"),Sl=Symbol("is custom element"),Tl=Symbol("is html"),kd=Vi?"option":"OPTION",Sd=Vi?"select":"SELECT",Td=Vi?"progress":"PROGRESS";function On(t,e){var n=Ka(t);n.value===(n.value=e??void 0)||t.value===e&&(e!==0||t.nodeName!==Td)||(t.value=e??"")}function xd(t,e){var n=Ka(t);n.checked!==(n.checked=e??void 0)&&(t.checked=e)}function Ed(t,e){e?t.hasAttribute("selected")||t.setAttribute("selected",""):t.removeAttribute("selected")}function X(t,e,n,r){var i=Ka(t);i[e]!==(i[e]=n)&&(e==="loading"&&(t[Qc]=n),n==null?t.removeAttribute(e):typeof n!="string"&&El(t).includes(e)?t[e]=n:t.setAttribute(e,n))}function Ad(t,e,n,r,i=!1,s=!1){var o=Ka(t),u=o[Sl],l=!o[Tl],f=e||{},d=t.nodeName===kd;for(var p in e)p in n||(n[p]=null);n.class?n.class=Ba(n.class):n[Kr]&&(n.class=null),n[Yr]&&(n.style??=null);var m=El(t);for(const A in n){let D=n[A];if(d&&A==="value"&&D==null){t.value=t.__value="",f[A]=D;continue}if(A==="class"){var w=t.namespaceURI==="http://www.w3.org/1999/xhtml";lt(t,w,D,r,e?.[Kr],n[Kr]),f[A]=D,f[Kr]=n[Kr];continue}if(A==="style"){wr(t,D,e?.[Yr],n[Yr]),f[A]=D,f[Yr]=n[Yr];continue}var y=f[A];if(!(D===y&&!(D===void 0&&t.hasAttribute(A)))){f[A]=D;var x=A[0]+A[1];if(x!=="$$")if(x==="on"){const C={},U="$$"+A;let P=A.slice(2);var k=td(P);if($u(P)&&(P=P.slice(0,-7),C.capture=!0),!k&&y){if(D!=null)continue;t.removeEventListener(P,f[U],C),f[U]=null}if(k)V(P,t,D),Qe([P]);else if(D!=null){let G=function(K){f[A].call(this,K)};var E=G;f[U]=_l(P,t,G,C)}}else if(A==="style")X(t,A,D);else if(A==="autofocus")ju(t,!!D);else if(!u&&(A==="__value"||A==="value"&&D!=null))t.value=t.__value=D;else if(A==="selected"&&d)Ed(t,D);else{var g=A;l||(g=rd(g));var I=g==="defaultValue"||g==="defaultChecked";if(D==null&&!u&&!I)if(o[A]=null,g==="value"||g==="checked"){let C=t;const U=e===void 0;if(g==="value"){let P=C.defaultValue;C.removeAttribute(g),C.defaultValue=P,C.value=C.__value=U?P:null}else{let P=C.defaultChecked;C.removeAttribute(g),C.defaultChecked=P,C.checked=U?P:!1}}else t.removeAttribute(A);else I||m.includes(g)&&(u||typeof D!="string")?(t[g]=D,g in o&&(o[g]=mt)):typeof D!="function"&&X(t,g,D)}}}return f}function xl(t,e,n=[],r=[],i=[],s,o=!1,u=!1){jo(i,n,r,l=>{var f=void 0,d={},p=t.nodeName===Sd,m=!1;if(al(()=>{var y=e(...l.map(a)),x=Ad(t,f,y,s,o,u);m&&p&&"value"in y&&Di(t,y.value);for(let g of Object.getOwnPropertySymbols(d))y[g]||Rt(d[g]);for(let g of Object.getOwnPropertySymbols(y)){var k=y[g];g.description===yu&&(!f||k!==f[g])&&(d[g]&&Rt(d[g]),d[g]=$t(()=>md(t,()=>k))),x[g]=k}f=x}),p){var w=t;_a(()=>{Di(w,f.value,!0),yd(w)})}m=!0})}function Ka(t){return t.__attributes??={[Sl]:t.nodeName.includes("-"),[Tl]:t.namespaceURI===Oo}}var eo=new Map;function El(t){var e=t.getAttribute("is")||t.nodeName,n=eo.get(e);if(n)return n;eo.set(e,n=[]);for(var r,i=t,s=Element.prototype;s!==i;){r=Ao(i);for(var o in r)r[o].set&&n.push(o);i=Gi(i)}return n}function to(t,e){return t===e||t?.[Gn]===e}function gr(t={},e,n,r){var i=je.r,s=ye;return _a(()=>{var o,u;return ba(()=>{o=u,u=[],_t(()=>{t!==n(...u)&&(e(t,...u),o&&to(n(...o),t)&&e(null,...o))})}),()=>{let l=s;for(;l!==i&&l.parent!==null&&l.parent.f&yi;)l=l.parent;const f=()=>{u&&to(n(...u),t)&&e(null,...u)},d=l.teardown;l.teardown=()=>{f(),d?.()}}}),t}function Al(t=!1){const e=je,n=e.l.u;if(!n)return;let r=()=>rs(e.s);if(t){let i=0,s={};const o=va(()=>{let u=!1;const l=e.s;for(const f in l)l[f]!==s[f]&&(s[f]=l[f],u=!0);return u&&i++,i});r=()=>a(o)}n.b.length&&za(()=>{no(e,r),bi(n.b)}),Qt(()=>{const i=_t(()=>n.m.map(Zc));return()=>{for(const s of i)typeof s=="function"&&s()}}),n.a.length&&Qt(()=>{no(e,r),bi(n.a)})}function no(t,e){if(t.l.s)for(const n of t.l.s)a(n);e()}function Ee(t,e,n,r){var i=!Ur||(n&pu)!==0,s=(n&vu)!==0,o=(n&mu)!==0,u=r,l=!0,f=()=>(l&&(l=!1,u=o?_t(r):r),u);let d;if(s){var p=Gn in t||Xc in t;d=Or(t,e)?.set??(p&&e in t?E=>t[e]=E:void 0)}var m,w=!1;s?[m,w]=Ru(()=>t[e]):m=t[e],m===void 0&&r!==void 0&&(m=f(),d&&(i&&au(),d(m)));var y;if(i?y=()=>{var E=t[e];return E===void 0?f():(l=!0,E)}:y=()=>{var E=t[e];return E!==void 0&&(u=void 0),E===void 0?u:E},i&&(n&gu)===0)return y;if(d){var x=t.$$legacy;return(function(E,A){return arguments.length>0?((!i||!A||x||w)&&d(A?y():E),E):y()})}var k=!1,g=((n&hu)!==0?va:Ot)(()=>(k=!1,y()));s&&a(g);var I=ye;return(function(E,A){if(arguments.length>0){const D=A?a(g):i&&s?lr(E):E;return v(g,D),k=!0,u!==void 0&&(u=D),E}return Vn&&k||(I.f&nn)!==0?g.v:a(g)})}function is(t){je===null&&Do(),Ur&&je.l!==null?Id(je).m.push(t):Qt(()=>{const e=_t(t);if(typeof e=="function")return e})}function Ya(t){je===null&&Do(),is(()=>()=>_t(t))}function Id(t){var e=t.l;return e.u??={a:[],b:[],m:[]}}const Rd="5";typeof window<"u"&&((window.__svelte??={}).v??=new Set).add(Rd);Eu();class Il extends Error{constructor(e,n){super(n),this.status=e}status}async function tt(t,e={}){const n=new Headers(e.headers);n.set("Accept","application/json"),e.body&&!(e.body instanceof FormData)&&n.set("Content-Type","application/json");const r=await fetch(t,{...e,headers:n});if(!r.ok)throw new Il(r.status,await r.text());return r.json()}async function Cd(t){return t.type.startsWith("image/")?Dd(t):t.type.startsWith("video/")?Md(t):{width:0,height:0,durationMS:0}}function Dd(t){return new Promise(e=>{const n=URL.createObjectURL(t),r=new Image;r.onload=()=>{const i={width:r.naturalWidth,height:r.naturalHeight,durationMS:0};URL.revokeObjectURL(n),e(i)},r.onerror=()=>{URL.revokeObjectURL(n),e({width:0,height:0,durationMS:0})},r.src=n})}function Md(t){return new Promise(e=>{const n=URL.createObjectURL(t),r=document.createElement("video");r.preload="metadata",r.muted=!0;const i=()=>{URL.revokeObjectURL(n),r.src=""};r.onloadedmetadata=()=>{const s=Number.isFinite(r.duration)&&r.duration>0?Math.round(r.duration*1e3):0,o={width:r.videoWidth,height:r.videoHeight,durationMS:s};i(),e(o)},r.onerror=()=>{i(),e({width:0,height:0,durationMS:0})},r.src=n})}const Od=[{title:"Ship it",url:"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExYjJ1bm1meHE4N2x3bnN0djJkMWtjNGc5bXYzZDFiOHBsbG16M3F0ZSZlcD12MV9naWZzX3NlYXJjaCZjdD1n/l0HlHFRbmaZtBRhXG/giphy.gif",tags:["ship","launch","done"]},{title:"Approved",url:"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExazBpbzJ6ODZ3bXQ3OHBvNGJidWZoajc0cHV6YnVub3MzZ3c1a2Z2dSZlcD12MV9naWZzX3NlYXJjaCZjdD1n/111ebonMs90YLu/giphy.gif",tags:["yes","approved","nice"]},{title:"Deploy dance",url:"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExY3NkaTVmZW9ydWNnZnl0ZWQ5aHQyeGNrd2k3NG4wZWNqYzNmd3k1ZCZlcD12MV9naWZzX3NlYXJjaCZjdD1n/GeimqsH0TLDt4tScGw/giphy.gif",tags:["deploy","dance","celebrate"]},{title:"Looking",url:"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExYWZ3emE0dm5mN2h0bGVsY2w0OXBodGd2cGJlNDRiZXo1YWNtdWRmZyZlcD12MV9naWZzX3NlYXJjaCZjdD1n/26n6WywJyh39n1pBu/giphy.gif",tags:["search","looking","debug"]},{title:"Typing faster",url:"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExOWFlbnJnbnIzbHYxcDIzdXZ3NGF3N2FocHNvMmR5enU3bHpycHBlZSZlcD12MV9naWZzX3NlYXJjaCZjdD1n/13HgwGsXF0aiGY/giphy.gif",tags:["typing","code","work"]},{title:"Tiny victory",url:"https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExdjJ2b2tqNmF4dG16NjE0eXhuc3h5bTlvamgwNTR0Zmd6ZjhtM2JuaSZlcD12MV9naWZzX3NlYXJjaCZjdD1n/3o7abKhOpu0NwenH3O/giphy.gif",tags:["win","victory","celebrate"]}],Ra=100,Mi=50,Rl=900,Ar=700,ui=Rl+Mi*2,Ld=8,Pd=16;function Nd(t,e,n){if(t.length<=Rl)return t;const r=qd(t,n);if(e==="prepend")return di(t,0,Ar,r,"start");if(e==="append")return di(t,Math.max(0,t.length-Ar),t.length,r,"end");if(e==="around"){const i=r?.first??-1,s=i>=0?i:Math.floor(t.length/2);let o=Math.max(0,s-Math.floor(Ar/2)),u=Math.min(t.length,o+Ar);return o=Math.max(0,u-Ar),t.slice(o,u)}return di(t,Math.max(0,t.length-Ar),t.length,r,"end")}function qd(t,e){if(e.size===0)return null;let n=-1,r=-1;for(let i=0;iui&&(i==="start"?(s=e,o=Math.min(t.length,s+ui)):(o=n,s=Math.max(0,o-ui))),t.slice(s,o)}function Ud(t){const e=t.trim();if(!e)return"?";const n=e.split(/\s+/);return n.length>=2?(n[0][0]+n[1][0]).toUpperCase():e.slice(0,2).toUpperCase()}function zd(t){if(!t)return"?";const e=t.trim();return e?e[0].toUpperCase():"?"}function Kn(t){return t?`@${t}`:""}function Cl(t){let e=0;for(let n=0;n>>0;return e%360}function Bd(t,e){return t.members.find(n=>n.id!==e)||t.members[0]}function da(t,e){const n=t.members.filter(i=>i.id!==e);return(n.length>0?n:t.members).map(i=>i.display_name).join(", ")}function Fd(t,e,n){const r=new Map;for(const i of e)for(const s of i.members)s.id&&s.id!==n&&r.set(s.id,s);for(const i of[...t].reverse()){const s=i.author;s?.id&&s.id!==n&&r.set(s.id,s)}return[...r.values()].slice(0,12)}function Hd(t,e){return t.find(n=>n.members.some(r=>r.id===e))}const Wd=new Set(["button","checkbox","combobox","link","listbox","menu","menubar","menuitem","menuitemcheckbox","menuitemradio","option","radio","radiogroup","slider","spinbutton","switch","tab","tablist","textbox","tree","treeitem"]),Gd=new Set(["INPUT","TEXTAREA","SELECT","BUTTON","A","DETAILS","SUMMARY","VIDEO","AUDIO"]);function jd(t){if(!t)return!1;if(t.isContentEditable)return!0;if(t instanceof HTMLInputElement){const e=(t.type||"text").toLowerCase();return e!=="checkbox"&&e!=="radio"&&e!=="button"&&e!=="submit"&&e!=="reset"&&e!=="file"}return t instanceof HTMLTextAreaElement}function Vd(t){if(!t||Kd(t))return!1;if(Gd.has(t.tagName))return!0;const e=t.getAttribute("role");if(e&&Wd.has(e))return!0;const n=t.getAttribute("tabindex");return!!(n!==null&&n!=="-1"&&t.hasAttribute("aria-keyshortcuts"))}function Kd(t){if(!t.closest(".messages, .thread"))return!1;if(t instanceof HTMLButtonElement||t instanceof HTMLAnchorElement)return!0;const e=t.getAttribute("role");return e==="button"||e==="link"}function Yd(){const t=typeof window<"u"?window.getSelection():null;if(!t||t.isCollapsed||t.rangeCount===0)return!1;const e=t.getRangeAt(0).commonAncestorContainer;return e?!!(e.nodeType===Node.ELEMENT_NODE?e:e.parentElement)?.closest(".messages, .thread, .markdown"):!1}function Zd(t,e){if(e.authRequired||e.isModalOpen()||t.defaultPrevented||t.isComposing||t.keyCode===229||t.ctrlKey||t.metaKey||t.altKey||t.key.length!==1||Yd())return!1;const n=document.activeElement;return!(n===e.messageInput||n===e.replyInput||jd(n)||Vd(n))}function Xd(t,e){if(!Zd(t,e))return;const n=e.target();if(!n||n.disabled||n.readOnly)return;t.key===" "&&t.preventDefault(),n.focus({preventScroll:!0});const r=n.value.length;if(n.setSelectionRange(r,r),t.key===" "){const i=n.selectionStart??r,s=n.selectionEnd??r;n.setRangeText(" ",i,s,"end"),n.dispatchEvent(new Event("input",{bubbles:!0}))}}const ro=t=>`clickclack:${t}:cursor`;function Qd(t){const{workspaceID:e,onEvent:n,onStatusChange:r}=t,i=t.reconnectDelayMs??1200;let s=null,o,u=!1,l=!1;function f(p){l!==p&&(l=p,r?.(p))}function d(){if(u)return;const p=new URL("/api/realtime/ws",window.location.href);p.protocol=window.location.protocol==="https:"?"wss:":"ws:",p.searchParams.set("workspace_id",e);const m=localStorage.getItem(ro(e))||"";m&&p.searchParams.set("after_cursor",m);const w=new WebSocket(p);s=w,w.addEventListener("open",()=>{s===w&&f(!0)}),w.addEventListener("message",y=>{const x=JSON.parse(String(y.data));x.cursor&&localStorage.setItem(ro(e),x.cursor),n(x)}),w.addEventListener("close",()=>{s!==w||u||(s=null,f(!1),o=window.setTimeout(d,i))})}return d(),{get connected(){return l},close(){u=!0,f(!1),o&&window.clearTimeout(o),s?.close(),s=null}}}const Jd=5e3,$d=4e3;let vt=null;function ef(t,e){return t.workspaceID===e.workspaceID&&(t.channelID??"")===(e.channelID??"")&&(t.directConversationID??"")===(e.directConversationID??"")}function tf(t){const e={};return t.channelID&&(e.channel_id=t.channelID),t.directConversationID&&(e.direct_conversation_id=t.directConversationID),e}async function Dl(t,e){try{await tt("/api/realtime/ephemeral",{method:"POST",body:JSON.stringify({workspace_id:t.workspaceID,channel_id:t.channelID||"",direct_conversation_id:t.directConversationID||"",type:e,payload:tf(t)})})}catch{}}function nf(t){if(!t.workspaceID||!t.channelID&&!t.directConversationID)return;const e=Date.now();vt&&!ef(vt.scope,t)&&(Oi(vt),vt=null),vt||(vt={scope:t,active:!1,lastPingAt:0}),(!vt.active||e-vt.lastPingAt>=$d)&&(vt.active=!0,vt.lastPingAt=e,Dl(t,"typing.started")),vt.idleTimer&&window.clearTimeout(vt.idleTimer),vt.idleTimer=window.setTimeout(()=>{vt&&(Oi(vt),vt=null)},Jd)}async function Oi(t){t.idleTimer&&window.clearTimeout(t.idleTimer),t.active&&await Dl(t.scope,"typing.stopped")}function Ca(){vt&&(Oi(vt),vt=null)}function rf(t,e){const n=()=>{const s=t.style.height;t.style.height="auto";const o=`${t.scrollHeight}px`;s!==o?t.style.height=o:t.style.height=s},r=()=>n(),i=()=>n();return requestAnimationFrame(n),t.addEventListener("input",r),window.addEventListener("resize",i),{update(){requestAnimationFrame(n)},destroy(){t.removeEventListener("input",r),window.removeEventListener("resize",i)}}}function Fa(t){return`/api/uploads/${encodeURIComponent(t.id)}`}function af(t){return t.content_type.startsWith("image/")}function sf(t){return t<1024?`${t} B`:t<1024*1024?`${Math.round(t/1024)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}var of=z('
');function lf(t,e){Fe(e,!0);var n=of(),r=b(n),i=S(r,2),s=S(i,2),o=b(s);o.textContent="<>";var u=S(s,2),l=b(u);l.textContent="{}";var f=S(u,2),d=S(f,2);let p;te(()=>p=lt(d,1,"",null,p,{active:e.showGifPicker})),V("click",r,()=>e.onWrap("**")),V("click",i,()=>e.onWrap("_")),V("click",s,()=>e.onWrap("`")),V("click",u,()=>e.onWrap("```","\n```")),V("click",f,()=>e.onAppend("[label](https://)")),V("click",d,function(...m){e.onToggleGif?.apply(this,m)}),L(t,n),He()}Qe(["click"]);var cf=z(''),uf=z('
GIFs
');function df(t,e){Fe(e,!0);var n=uf(),r=b(n),i=S(b(r),2),s=S(r,2);Wt(s,21,()=>e.gifs,o=>o.url,(o,u)=>{var l=cf(),f=b(l),d=S(f,2),p=b(d);te(()=>{X(f,"src",a(u).url),X(f,"alt",a(u).title),ee(p,a(u).title)}),V("click",l,()=>e.onPick(a(u).url,a(u).title)),L(o,l)}),te(()=>On(i,e.query)),V("input",i,o=>e.onQuery(o.currentTarget.value)),L(t,n),He()}Qe(["input","click"]);function Li(t,e=120){if(!t)return"";const n=t.replace(/\s+/g," ").trim();return n.length>e?n.slice(0,e-1)+"...":n}function ao(t){return t.quoted_author?.display_name||"Unknown"}function ff(t,e){return e===t.id?"Open":"Thread"}function hf(t){const e=new Date(t),n=new Date,r=new Date;r.setDate(n.getDate()-1);const i=(s,o)=>s.getFullYear()===o.getFullYear()&&s.getMonth()===o.getMonth()&&s.getDate()===o.getDate();return i(e,n)?"Today":i(e,r)?"Yesterday":new Intl.DateTimeFormat(void 0,{weekday:"long",month:"long",day:"numeric"}).format(e)}function pf(t){const e=[];let n="",r="",i=0;for(const s of t){const o=new Date(s.created_at),u=o.toDateString(),l=s.author?.id||s.author_id||"local",f=u!==n,d=l!==r,p=o.getTime()-i>300*1e3;f||d||p||e.length===0?e.push({key:s.id,dayLabel:f?hf(s.created_at):null,messages:[s],authorName:s.author?.display_name||"Local User",authorHandle:s.author?.handle||"",authorAvatarURL:s.author?.avatar_url||"",authorID:l,timestamp:s.created_at}):e[e.length-1].messages.push(s),n=u,r=l,i=o.getTime()}return e}var gf=z('
Replying to
');function vf(t,e){Fe(e,!0);var n=gf(),r=S(b(n),2),i=b(r),s=S(b(i)),o=b(s),u=S(i,2),l=b(u),f=S(r,2);te(d=>{ee(o,e.target.author?.display_name||"Local User"),ee(l,d)},[()=>Li(e.target.body)]),V("click",f,function(...d){e.onClear?.apply(this,d)}),L(t,n),He()}Qe(["click"]);var mf=z(''),_f=z('
'),bf=z(''),wf=z('
');function Ml(t,e){Fe(e,!0);let n=Ee(e,"formClass",3,"composer"),r=Ee(e,"pendingUpload",3,null),i=Ee(e,"replyTarget",3,null),s=Ee(e,"showUpload",3,!1),o=Ee(e,"showToolbar",3,!1),u=Ee(e,"showGifPicker",3,!1),l=Ee(e,"gifQuery",3,""),f=Ee(e,"filteredGifs",19,()=>[]),d=Ee(e,"onUploadFile",3,()=>{}),p=Ee(e,"onRemoveUpload",3,()=>{}),m=Ee(e,"onClearReply",3,()=>{}),w=Ee(e,"onApplyMarkdownWrap",3,()=>{}),y=Ee(e,"onAppendToComposer",3,()=>{}),x=Ee(e,"onToggleGif",3,()=>{}),k=Ee(e,"onGifQuery",3,()=>{}),g=Ee(e,"onPickGif",3,()=>{}),I=Be(null);Qt(()=>(e.onInputRef(a(I)),()=>e.onInputRef(null)));var E=wf(),A=b(E);{var D=B=>{df(B,{get gifs(){return f()},get query(){return l()},get onQuery(){return k()},get onPick(){return g()}})};oe(A,B=>{u()&&B(D)})}var C=S(A,2),U=b(C);{var P=B=>{var ae=_f(),ce=S(b(ae),2);{var $=Ue=>{var Je=mf();te(se=>{X(Je,"src",se),X(Je,"alt",r().filename)},[()=>Fa(r())]),L(Ue,Je)},Ae=le(()=>af(r()));oe(ce,Ue=>{a(Ae)&&Ue($)})}var ge=S(ce,2),De=b(ge),_e=S(ge,2);te(Ue=>ee(De,`${r().filename??""} · ${Ue??""}`),[()=>sf(r().byte_size)]),V("click",_e,function(...Ue){p()?.apply(this,Ue)}),L(B,ae)};oe(U,B=>{r()&&B(P)})}var G=S(U,2);{var K=B=>{vf(B,{get target(){return i()},get onClear(){return m()}})};oe(G,B=>{i()&&B(K)})}var Z=S(G,2),Y=b(Z);{var O=B=>{var ae=bf(),ce=b(ae);V("change",ce,function(...$){d()?.apply(this,$)}),L(B,ae)};oe(Y,B=>{s()&&B(O)})}var W=S(Y,2);gr(W,B=>v(I,B),()=>a(I)),vd(W,(B,ae)=>rf?.(B),()=>e.value);var J=S(W,2),fe=S(Z,2);{var ie=B=>{lf(B,{get showGifPicker(){return u()},get onWrap(){return w()},get onAppend(){return y()},get onToggleGif(){return x()}})};oe(fe,B=>{o()&&B(ie)})}te(B=>{lt(E,1,Ba(n())),On(W,e.value),X(W,"placeholder",e.placeholder),X(W,"aria-label",e.ariaLabel),X(J,"aria-label",e.submitLabel),J.disabled=B},[()=>!e.value.trim()]),dn("submit",E,B=>{B.preventDefault(),e.onSubmit()}),V("input",W,B=>e.onValue(B.currentTarget.value)),dn("focus",W,function(...B){e.onFocus?.apply(this,B)}),V("keydown",W,function(...B){e.onKeydown?.apply(this,B)}),L(t,E),He()}Qe(["click","change","input","keydown"]);var yf=z('
');function kf(t,e){var n=yf(),r=b(n),i=S(r,2),s=b(i),o=b(s),u=b(o),l=S(o,2),f=b(l),d=S(f,2),p=S(s,2),m=b(p);te(()=>{ee(u,e.title),X(f,"href",e.url),X(m,"src",e.url),X(m,"alt",e.title)}),V("click",r,function(...w){e.onClose?.apply(this,w)}),V("click",d,function(...w){e.onClose?.apply(this,w)}),L(t,n)}Qe(["click"]);const Ol=t=>Object.keys(t).reduce((e,n)=>{const r=t[n];return r==null?e:e+`${n}:${r};`},""),Sf=(t,e)=>"_"+e,fa=null,{min:dr,max:gn,abs:io,floor:Tf}=Math,Ll=(t,e,n)=>dr(n,gn(e,t)),Pl=t=>[...t].sort((e,n)=>e-n),xf=typeof queueMicrotask=="function"?queueMicrotask:t=>{Promise.resolve().then(t)},Pi=()=>{let t;return[new Promise(e=>{t=e}),t]},Nl=t=>{let e;return()=>(t&&(e=t(),t=void 0),e)},la=(t,e,n)=>{const r=n?"unshift":"push";for(let i=0;i{const n=t.t[e];return n===-1?t.o:n},Ef=(t,e,n)=>{const r=t.t[e]===-1;return t.t[e]=n,t.i=dr(e,t.i),r},Na=(t,e)=>{if(!t.l)return 0;if(t.i>=e)return t.u[e];t.i<0&&(t.u[0]=0,t.i=0);let n=t.i,r=t.u[n];for(;n{let i=n;for(;n<=r;){const s=Tf((n+r)/2);Na(t,s)<=e?(i=s,n=s+1):r=s-1}return Ll(i,0,t.l-1)},so=(t,e,n)=>{const r=e-t.l;return t.i=n?-1:dr(e-1,t.i),t.l=e,r>0?(la(t.u,r),la(t.t,r,n),t.o*r):(t.u.splice(r),(n?t.t.splice(0,-r):t.t.splice(r)).reduce((i,s)=>i-(s===-1?t.o:s),0))},Af=t=>t.documentElement,If=t=>t.ownerDocument,Rf=t=>t.defaultView,Ul=Nl(()=>!!/iP(hone|od|ad)/.test(navigator.userAgent)||navigator.platform==="MacIntel"&&navigator.maxTouchPoints>0),Cf=Nl(()=>"scrollBehavior"in Af(document).style),Df=5,Mf=6,Of=1,Lf=4,Pf=8,Nf=t=>gn(t.$getTotalSize(),t.$getViewportSize()),qf=(t,e=40,n=0,r,i=!1)=>{let s=!!n,o=1,u=0,l=0,f=0,d=0,p=0,m=0,w=0,y=0,x=fa,k=[0,s?gn(n-1,0):-1],g=0,I=!1;const E=((O,W,J)=>({o:W,t:J?la(J.slice(0,dr(O,J.length)),gn(0,O-J.length)):la([],O),l:O,i:-1,u:la([],O+1)}))(t,r?r[1]:e,r&&r[0]),A=new Set,D=()=>f-l,C=()=>D()+p+d,U=(O,W)=>((J,fe,ie,B)=>{if(B=dr(B,J.l-1),Na(J,B)<=fe){const ae=Ir(J,ie,B);return[Ir(J,fe,B,ae),ae]}{const ae=Ir(J,fe,void 0,B);return[ae,Ir(J,ie,ae)]}})(E,O,W,k[0]),P=()=>Na(E,E.l),G=(O,W)=>{const J=Na(E,O)-p;return W?P()-J-K(O):J},K=O=>ql(E,O),Z=(O,W=-1)=>E.t[O]===W,Y=O=>{O&&(Ul()&&w!==0||x&&y===1?p+=O:d+=O)};return{$dispose:()=>{A.clear()},$getStateVersion:()=>o,$getCacheSnapshot:()=>(O=>[O.t.slice(),O.o])(E),$getRange:(O=200)=>{if(!I||s)return k;let W,J;if(m)[W,J]=k;else{let fe=gn(0,C()),ie=fe+u;i||(O=gn(0,O),w!==1&&(fe-=O),w!==2&&(ie+=O)),[W,J]=k=U(gn(0,fe),gn(0,ie)),x&&(W=dr(W,x[0]),J=gn(J,x[1]))}return[gn(W,0),dr(J,E.l-1)]},$findItemIndex:O=>Ir(E,O-l),$isUnmeasuredItem:Z,$getItemOffset:G,$getItemSize:K,$getItemsLength:()=>E.l,$getScrollOffset:()=>f,$isScrolling:()=>w!==0,$getViewportSize:()=>u,$getStartSpacerSize:()=>l,$getTotalSize:P,$:()=>(m=d,d=0,[m,y===2]),$subscribe:(O,W)=>{const J=[O,W];return A.add(J),()=>{A.delete(J)}},$update:(O,W)=>{let J,fe,ie=0;switch(O){case 1:{if(W===f&&y===0)break;const B=m;m=0;const ae=W-f,ce=io(ae);B&&ce=-u&&$<=P()&&(ie+=1,fe=ce>u);break}case 2:ie=8,w!==0&&(J=!0,ie+=1),w=0,y=0,x=fa;break;case 3:{const B=W.filter(([ae,ce])=>!Z(ae,ce));if(!B.length)break;Y(B.reduce((ae,[ce,$])=>{let Ae;if(y===2)Ae=!0;else if(x&&y===1)Ae=ceu&&(Y(((ae,ce)=>{let $=0;const Ae=[];ae.t.forEach((se,be)=>{se!==-1&&(Ae.push(se),be{ie&B&&ae(fe)}))}}},ss=setTimeout,fi=(t,e)=>e?-t:t,Uf=(t,e,n,r,i,s)=>{const o=Date.now;let u=0,l=!1,f=!1,d=!1,p=!1;const m=(()=>{let g;const I=()=>{g!=fa&&clearTimeout(g)},E=()=>{I(),g=ss(()=>{g=fa,(()=>{if(l||f)return l=!1,void m();d=!1,t.$update(2)})()},150)};return E.p=I,E})(),w=()=>{u=o(),d&&(p=!0),t.$update(1,r()),m()},y=g=>{if(l||!t.$isScrolling()||g.ctrlKey)return;const I=o()-u;150>I&&50{f=!0,d=p=!1},k=()=>{f=!1,Ul()&&(d=!0)};return e.addEventListener("scroll",w),e.addEventListener("wheel",y,{passive:!0}),e.addEventListener("touchstart",x,{passive:!0}),e.addEventListener("touchend",k,{passive:!0}),{h:()=>{e.removeEventListener("scroll",w),e.removeEventListener("wheel",y),e.removeEventListener("touchstart",x),e.removeEventListener("touchend",k),m.p()},m:()=>{const[g,I]=t.$();g&&(i(g,I,p),p=!1,I&&t.$getViewportSize()>t.$getTotalSize()&&t.$update(1,r()))}}},zf=(t,e,n)=>{let r;return[async(i,s)=>{if(!await e())return;r&&r();const o=()=>{const[u,l]=Pi();return r=()=>{l(!1)},t.$getViewportSize()&&ss(r,150),[u,t.$subscribe(2,()=>{l(!0)})]};if(s&&Cf())t.$update(8,i()),xf(async()=>{for(;;){let u=!0;for(let[d,p]=t.$getRange();d<=p;d++)if(t.$isUnmeasuredItem(d)){u=!1;break}if(u)break;const[l,f]=o();try{if(!await l)return}finally{f()}}t.$update(7),n(i(),s)});else for(;;){const[u,l]=o();try{if(t.$update(7),n(i()),!await u)return}finally{l()}}},()=>{r&&r()}]},Bf=(t,e)=>{let n,r,i=Pi(),s=!1;const o=e?"scrollLeft":"scrollTop",u=e?"overflowX":"overflowY",[l,f]=zf(t,()=>i[0],(d,p)=>{d=fi(d,s),p?n.scrollTo({[e?"left":"top"]:d,behavior:"smooth"}):n[o]=d});return{$observe(d,p){n=p,e&&(s=getComputedStyle(p).direction==="rtl"),r=Uf(t,p,e,()=>fi(p[o],s),(m,w,y)=>{if(y){const x=p.style,k=x[u];x[u]="hidden",ss(()=>{x[u]=k})}p[o]=fi(t.$getScrollOffset()+m,s),w&&f()}),i[1](!0)},$dispose(){r&&r.h(),i[1](!1),i=Pi()},$isNegative:()=>s,$scrollTo(d){l(()=>d)},$scrollBy(d){d+=t.$getScrollOffset(),l(()=>d)},$scrollToIndex(d,{align:p,smooth:m,offset:w=0}={}){if(d=Ll(d,0,t.$getItemsLength()-1),p==="nearest"){const y=t.$getItemOffset(d),x=t.$getScrollOffset();if(yx+t.$getViewportSize()))return;p="end"}}l(()=>w+t.$getStartSpacerSize()+t.$getItemOffset(d)+(p==="end"?t.$getItemSize(d)-t.$getViewportSize():p==="center"?(t.$getItemSize(d)-t.$getViewportSize())/2:0),m)},$fixScrollJump:()=>{r&&r.m()}}},Ff=t=>{let e;return{v(n){(e||(e=new(Rf(If(n))).ResizeObserver(t))).observe(n)},S(n){e.unobserve(n)},h(){e&&e.disconnect()}}},Hf=(t,e)=>{let n;const r=e?"width":"height",i=new WeakMap,s=Ff(o=>{const u=[];for(const{target:l,contentRect:f}of o)if(l.offsetParent)if(l===n)t.$update(4,f[r]);else{const d=i.get(l);d!=fa&&u.push([d,f[r]])}u.length&&t.$update(3,u)});return{$observeRoot(o){s.v(n=o)},$observeItem:(o,u)=>(i.set(o,u),s.v(o),()=>{i.delete(o),s.S(o)}),$dispose:s.h}};function Wf(t,e){Fe(e,!0);let n=Ee(e,"as",3,"div"),r,i,s;Qt(()=>{s!==e.index&&(i&&i(),i=e.resizer(r,s=e.index))}),Ya(()=>{i&&i()});let o=le(()=>{const f={contain:"layout style",position:"absolute",[e.horizontal?"height":"width"]:"100%",[e.horizontal?"top":"left"]:"0px",[e.horizontal?"left":"top"]:e.offset+"px",visibility:e.hide?"hidden":void 0};return e.horizontal&&(f.display="inline-flex"),Ol(f)});var u=Sn(),l=Gt(u);wl(l,n,!1,(f,d)=>{gr(f,w=>r=w,()=>r),xl(f,()=>({style:a(o)}));var p=Sn(),m=Gt(p);gd(m,()=>e.children,()=>e.item,()=>e.index),L(d,p)}),L(t,u),He()}function Gf(t,e){Fe(e,!0);let n=Ee(e,"getKey",3,Sf),r=Ee(e,"as",3,"div"),i=Ee(e,"shift",3,!1),s=Ee(e,"horizontal",3,!1),o=Ee(e,"startMargin",3,0);const u=qf(e.data.length,e.itemSize,e.ssrCount,e.cache,!e.itemSize),l=Hf(u,s()),f=Bf(u,s());u.$subscribe(Of,()=>{v(p,u.$getStateVersion(),!0)}),u.$subscribe(Lf,()=>{e.onscroll&&e.onscroll(u.$getScrollOffset())}),u.$subscribe(Pf,()=>{e.onscrollend&&e.onscrollend()});let d=Be(void 0),p=Be(lr(u.$getStateVersion())),m=le(()=>a(p)&&u.$getRange(e.bufferSize)),w=le(()=>a(p)&&u.$isScrolling()),y=le(()=>a(p)&&u.$getTotalSize()),x=le(()=>a(p)&&f.$isNegative()),k=le(()=>{const fe=e.data.length,[ie,B]=a(m),ae=[];if(e.keepMounted){const ce=new Set(e.keepMounted);for(let $=ie;$<=B;$++)ce.add($);for(const $ of Pl([...ce]))${const fe=a(d),ie=B=>{l.$observeRoot(B),f.$observe(fe,B)};ur().then(()=>{e.scrollRef?ie(e.scrollRef):ie(fe.parentElement)})}),Ya(()=>{u.$dispose(),l.$dispose(),f.$dispose()}),za(()=>{e.data.length!==u.$getItemsLength()&&u.$update(Df,[e.data.length,i()])}),za(()=>{o()!==u.$getStartSpacerSize()&&u.$update(Mf,o())});let g;Qt(()=>{g!==a(p)&&(g=a(p),f.$fixScrollJump())});const I=u.$getCacheSnapshot,E=u.$getScrollOffset,A=()=>Nf(u),D=u.$getViewportSize,C=u.$findItemIndex,U=u.$getItemOffset,P=u.$getItemSize,G=f.$scrollToIndex,K=f.$scrollTo,Z=f.$scrollBy;let Y=le(()=>Ol({contain:"size style","overflow-anchor":"none",flex:"none",position:"relative",width:s()?a(y)+"px":"100%",height:s()?"100%":a(y)+"px","pointer-events":a(w)?"none":void 0}));var O={getCache:I,getScrollOffset:E,getScrollSize:A,getViewportSize:D,findItemIndex:C,getItemOffset:U,getItemSize:P,scrollToIndex:G,scrollTo:K,scrollBy:Z},W=Sn(),J=Gt(W);return wl(J,r,!1,(fe,ie)=>{gr(fe,ce=>v(d,ce,!0),()=>a(d)),xl(fe,()=>({style:a(Y)}));var B=Sn(),ae=Gt(B);Wt(ae,17,()=>a(k),ce=>n()(e.data[ce],ce),(ce,$)=>{const Ae=le(()=>e.data[a($)]);{let ge=le(()=>a(p)&&u.$getItemOffset(a($),a(x))),De=le(()=>a(p)&&u.$isUnmeasuredItem(a($)));Wf(ce,{get children(){return e.children},get item(){return a(Ae)},get index(){return a($)},get as(){return e.item},get offset(){return a(ge)},get hide(){return a(De)},get horizontal(){return s()},get resizer(){return l.$observeItem}})}}),L(ie,B)}),L(t,W),He(O)}var jf=z('
'),Vf=z('
');function oo(t,e){let n=Ee(e,"rows",3,3);var r=Vf();Wt(r,21,()=>Array.from({length:n()}),bl,(i,s,o)=>{var u=jf();wr(u,`--history-row: ${o}`),L(i,u)}),te(()=>{lt(r,1,`history-loader history-loader--${e.direction}`),X(r,"aria-label",e.direction==="older"?"Loading older messages":"Loading newer messages")}),L(t,r)}const Kf=512,Zr=new Map;function Yf(t){const e=t?.trim()||"";if(!e)return"";const n=Zr.get(e);if(n)return n;if(Zr.size>=Kf){const r=Zr.keys().next().value;r&&Zr.delete(r)}return Zr.set(e,e),e}var Zf=z(''),Xf=z(''),Qf=z(''),Jf=z("");function Pn(t,e){Fe(e,!0);let n=Ee(e,"class",3,"avatar"),r=Ee(e,"size",3,40),i=Ee(e,"loading",3,"lazy"),s=Ee(e,"fetchPriority",3,"low"),o=Be("");const u=le(()=>Yf(e.src)),l=le(()=>a(u)!==""&&a(o)!==a(u)),f=le(()=>Cl(e.id||e.name||a(u)||"avatar")),d=le(()=>zd(e.name));function p(){v(o,a(u),!0)}var m=Sn(),w=Gt(m);{var y=k=>{var g=Xf(),I=b(g);{var E=D=>{var C=Zf();te(()=>{X(C,"src",a(u)),X(C,"width",r()),X(C,"height",r()),X(C,"loading",i()),X(C,"fetchpriority",s())}),dn("error",C,p),L(D,C)},A=D=>{var C=Xn();te(()=>ee(C,a(d))),L(D,C)};oe(I,D=>{a(l)?D(E):D(A,-1)})}te(()=>{lt(g,1,Ba(n())),wr(g,`--hue: ${a(f)??""}deg`),X(g,"aria-label",e.buttonLabel)}),V("click",g,function(...D){e.onclick?.apply(this,D)}),L(k,g)},x=k=>{var g=Jf(),I=b(g);{var E=D=>{var C=Qf();te(()=>{X(C,"src",a(u)),X(C,"width",r()),X(C,"height",r()),X(C,"loading",i()),X(C,"fetchpriority",s())}),dn("error",C,p),L(D,C)},A=D=>{var C=Xn();te(()=>ee(C,a(d))),L(D,C)};oe(I,D=>{a(l)?D(E):D(A,-1)})}te(()=>{lt(g,1,Ba(n())),wr(g,`--hue: ${a(f)??""}deg`)}),L(k,g)};oe(w,k=>{e.buttonLabel?k(y):k(x,-1)})}L(t,m),He()}Qe(["click"]);const{entries:zl,setPrototypeOf:lo,isFrozen:$f,getPrototypeOf:eh,getOwnPropertyDescriptor:th}=Object;let{freeze:jt,seal:fn,create:Cr}=Object,{apply:Ni,construct:qi}=typeof Reflect<"u"&&Reflect;jt||(jt=function(e){return e});fn||(fn=function(e){return e});Ni||(Ni=function(e,n){for(var r=arguments.length,i=new Array(r>2?r-2:0),s=2;s1?n-1:0),i=1;i"u"?null:dt(BigInt.prototype.toString),po=typeof Symbol>"u"?null:dt(Symbol.prototype.toString),st=dt(Object.prototype.hasOwnProperty),Jr=dt(Object.prototype.toString),At=dt(RegExp.prototype.test),Da=oh(TypeError);function dt(t){return function(e){e instanceof RegExp&&(e.lastIndex=0);for(var n=arguments.length,r=new Array(n>1?n-1:0),i=1;i2&&arguments[2]!==void 0?arguments[2]:aa;if(lo&&lo(t,null),!Bt(e))return t;let r=e.length;for(;r--;){let i=e[r];if(typeof i=="string"){const s=n(i);s!==i&&($f(e)||(e[r]=s),i=s)}t[i]=!0}return t}function lh(t){for(let e=0;e/gm),gh=fn(/\$\{[\w\W]*/gm),vh=fn(/^data-[\-\w.\u00B7-\uFFFF]+$/),mh=fn(/^aria-[\-\w]+$/),Bl=fn(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),_h=fn(/^(?:\w+script|data):/i),bh=fn(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),Fl=fn(/^html$/i),wh=fn(/^[a-z][.\w]*(-[.\w]+)+$/i);var bo=Object.freeze({__proto__:null,ARIA_ATTR:mh,ATTR_WHITESPACE:bh,CUSTOM_ELEMENT:wh,DATA_ATTR:vh,DOCTYPE_NAME:Fl,ERB_EXPR:ph,IS_ALLOWED_URI:Bl,IS_SCRIPT_OR_DATA:_h,MUSTACHE_EXPR:hh,TMPLIT_EXPR:gh});const $r={element:1,text:3,progressingInstruction:7,comment:8,document:9},yh=function(){return typeof window>"u"?null:window},kh=function(e,n){if(typeof e!="object"||typeof e.createPolicy!="function")return null;let r=null;const i="data-tt-policy-suffix";n&&n.hasAttribute(i)&&(r=n.getAttribute(i));const s="dompurify"+(r?"#"+r:"");try{return e.createPolicy(s,{createHTML(o){return o},createScriptURL(o){return o}})}catch{return console.warn("TrustedTypes policy "+s+" could not be created."),null}},wo=function(){return{afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}};function Hl(){let t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:yh();const e=de=>Hl(de);if(e.version="3.4.2",e.removed=[],!t||!t.document||t.document.nodeType!==$r.document||!t.Element)return e.isSupported=!1,e;let{document:n}=t;const r=n,i=r.currentScript,{DocumentFragment:s,HTMLTemplateElement:o,Node:u,Element:l,NodeFilter:f,NamedNodeMap:d=t.NamedNodeMap||t.MozNamedAttrMap,HTMLFormElement:p,DOMParser:m,trustedTypes:w}=t,y=l.prototype,x=Dr(y,"cloneNode"),k=Dr(y,"remove"),g=Dr(y,"nextSibling"),I=Dr(y,"childNodes"),E=Dr(y,"parentNode");if(typeof o=="function"){const de=n.createElement("template");de.content&&de.content.ownerDocument&&(n=de.content.ownerDocument)}let A,D="";const{implementation:C,createNodeIterator:U,createDocumentFragment:P,getElementsByTagName:G}=n,{importNode:K}=r;let Z=wo();e.isSupported=typeof zl=="function"&&typeof E=="function"&&C&&C.createHTMLDocument!==void 0;const{MUSTACHE_EXPR:Y,ERB_EXPR:O,TMPLIT_EXPR:W,DATA_ATTR:J,ARIA_ATTR:fe,IS_SCRIPT_OR_DATA:ie,ATTR_WHITESPACE:B,CUSTOM_ELEMENT:ae}=bo;let{IS_ALLOWED_URI:ce}=bo,$=null;const Ae=we({},[...go,...pi,...gi,...vi,...vo]);let ge=null;const De=we({},[...mo,...mi,..._o,...Ma]);let _e=Object.seal(Cr(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Ue=null,Je=null;const se=Object.seal(Cr(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}}));let be=!0,Se=!0,nt=!1,bt=!0,wt=!1,rt=!0,at=!1,Pe=!1,en=!1,ft=!1,Ct=!1,Vt=!1,Kt=!0,xn=!1;const En="user-content-";let Nn=!0,rn=!1,Ge={},ht=null;const Yt=we({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let rr=null;const Pt=we({},["audio","video","img","source","image","track"]);let Nt=null;const qn=we({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),an="http://www.w3.org/1998/Math/MathML",Ve="http://www.w3.org/2000/svg",ke="http://www.w3.org/1999/xhtml";let Ke=ke,An=!1,In=null;const yt=we({},[an,Ve,ke],hi);let pt=we({},["mi","mo","mn","ms","mtext"]),Zt=we({},["annotation-xml"]);const xr=we({},["title","style","font","a","script"]);let Rn=null;const Hr=["application/xhtml+xml","text/html"],Wr="text/html";let $e=null,M=null;const H=n.createElement("form"),j=function(_){return _ instanceof RegExp||_ instanceof Function},F=function(){let _=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};if(M&&M===_)return;(!_||typeof _!="object")&&(_={}),_=Xt(_),Rn=Hr.indexOf(_.PARSER_MEDIA_TYPE)===-1?Wr:_.PARSER_MEDIA_TYPE,$e=Rn==="application/xhtml+xml"?hi:aa,$=st(_,"ALLOWED_TAGS")&&Bt(_.ALLOWED_TAGS)?we({},_.ALLOWED_TAGS,$e):Ae,ge=st(_,"ALLOWED_ATTR")&&Bt(_.ALLOWED_ATTR)?we({},_.ALLOWED_ATTR,$e):De,In=st(_,"ALLOWED_NAMESPACES")&&Bt(_.ALLOWED_NAMESPACES)?we({},_.ALLOWED_NAMESPACES,hi):yt,Nt=st(_,"ADD_URI_SAFE_ATTR")&&Bt(_.ADD_URI_SAFE_ATTR)?we(Xt(qn),_.ADD_URI_SAFE_ATTR,$e):qn,rr=st(_,"ADD_DATA_URI_TAGS")&&Bt(_.ADD_DATA_URI_TAGS)?we(Xt(Pt),_.ADD_DATA_URI_TAGS,$e):Pt,ht=st(_,"FORBID_CONTENTS")&&Bt(_.FORBID_CONTENTS)?we({},_.FORBID_CONTENTS,$e):Yt,Ue=st(_,"FORBID_TAGS")&&Bt(_.FORBID_TAGS)?we({},_.FORBID_TAGS,$e):Xt({}),Je=st(_,"FORBID_ATTR")&&Bt(_.FORBID_ATTR)?we({},_.FORBID_ATTR,$e):Xt({}),Ge=st(_,"USE_PROFILES")?_.USE_PROFILES&&typeof _.USE_PROFILES=="object"?Xt(_.USE_PROFILES):_.USE_PROFILES:!1,be=_.ALLOW_ARIA_ATTR!==!1,Se=_.ALLOW_DATA_ATTR!==!1,nt=_.ALLOW_UNKNOWN_PROTOCOLS||!1,bt=_.ALLOW_SELF_CLOSE_IN_ATTR!==!1,wt=_.SAFE_FOR_TEMPLATES||!1,rt=_.SAFE_FOR_XML!==!1,at=_.WHOLE_DOCUMENT||!1,ft=_.RETURN_DOM||!1,Ct=_.RETURN_DOM_FRAGMENT||!1,Vt=_.RETURN_TRUSTED_TYPE||!1,en=_.FORCE_BODY||!1,Kt=_.SANITIZE_DOM!==!1,xn=_.SANITIZE_NAMED_PROPS||!1,Nn=_.KEEP_CONTENT!==!1,rn=_.IN_PLACE||!1,ce=uh(_.ALLOWED_URI_REGEXP)?_.ALLOWED_URI_REGEXP:Bl,Ke=typeof _.NAMESPACE=="string"?_.NAMESPACE:ke,pt=st(_,"MATHML_TEXT_INTEGRATION_POINTS")&&_.MATHML_TEXT_INTEGRATION_POINTS&&typeof _.MATHML_TEXT_INTEGRATION_POINTS=="object"?Xt(_.MATHML_TEXT_INTEGRATION_POINTS):we({},["mi","mo","mn","ms","mtext"]),Zt=st(_,"HTML_INTEGRATION_POINTS")&&_.HTML_INTEGRATION_POINTS&&typeof _.HTML_INTEGRATION_POINTS=="object"?Xt(_.HTML_INTEGRATION_POINTS):we({},["annotation-xml"]);const N=st(_,"CUSTOM_ELEMENT_HANDLING")&&_.CUSTOM_ELEMENT_HANDLING&&typeof _.CUSTOM_ELEMENT_HANDLING=="object"?Xt(_.CUSTOM_ELEMENT_HANDLING):Cr(null);if(_e=Cr(null),st(N,"tagNameCheck")&&j(N.tagNameCheck)&&(_e.tagNameCheck=N.tagNameCheck),st(N,"attributeNameCheck")&&j(N.attributeNameCheck)&&(_e.attributeNameCheck=N.attributeNameCheck),st(N,"allowCustomizedBuiltInElements")&&typeof N.allowCustomizedBuiltInElements=="boolean"&&(_e.allowCustomizedBuiltInElements=N.allowCustomizedBuiltInElements),wt&&(Se=!1),Ct&&(ft=!0),Ge&&($=we({},vo),ge=Cr(null),Ge.html===!0&&(we($,go),we(ge,mo)),Ge.svg===!0&&(we($,pi),we(ge,mi),we(ge,Ma)),Ge.svgFilters===!0&&(we($,gi),we(ge,mi),we(ge,Ma)),Ge.mathMl===!0&&(we($,vi),we(ge,_o),we(ge,Ma))),se.tagCheck=null,se.attributeCheck=null,st(_,"ADD_TAGS")&&(typeof _.ADD_TAGS=="function"?se.tagCheck=_.ADD_TAGS:Bt(_.ADD_TAGS)&&($===Ae&&($=Xt($)),we($,_.ADD_TAGS,$e))),st(_,"ADD_ATTR")&&(typeof _.ADD_ATTR=="function"?se.attributeCheck=_.ADD_ATTR:Bt(_.ADD_ATTR)&&(ge===De&&(ge=Xt(ge)),we(ge,_.ADD_ATTR,$e))),st(_,"ADD_URI_SAFE_ATTR")&&Bt(_.ADD_URI_SAFE_ATTR)&&we(Nt,_.ADD_URI_SAFE_ATTR,$e),st(_,"FORBID_CONTENTS")&&Bt(_.FORBID_CONTENTS)&&(ht===Yt&&(ht=Xt(ht)),we(ht,_.FORBID_CONTENTS,$e)),st(_,"ADD_FORBID_CONTENTS")&&Bt(_.ADD_FORBID_CONTENTS)&&(ht===Yt&&(ht=Xt(ht)),we(ht,_.ADD_FORBID_CONTENTS,$e)),Nn&&($["#text"]=!0),at&&we($,["html","head","body"]),$.table&&(we($,["tbody"]),delete Ue.tbody),_.TRUSTED_TYPES_POLICY){if(typeof _.TRUSTED_TYPES_POLICY.createHTML!="function")throw Da('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if(typeof _.TRUSTED_TYPES_POLICY.createScriptURL!="function")throw Da('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');A=_.TRUSTED_TYPES_POLICY,D=A.createHTML("")}else A===void 0&&(A=kh(w,i)),A!==null&&typeof D=="string"&&(D=A.createHTML(""));jt&&jt(_),M=_},ue=we({},[...pi,...gi,...dh]),me=we({},[...vi,...fh]),Ie=function(_){let N=E(_);(!N||!N.tagName)&&(N={namespaceURI:Ke,tagName:"template"});const ne=aa(_.tagName),Ne=aa(N.tagName);return In[_.namespaceURI]?_.namespaceURI===Ve?N.namespaceURI===ke?ne==="svg":N.namespaceURI===an?ne==="svg"&&(Ne==="annotation-xml"||pt[Ne]):!!ue[ne]:_.namespaceURI===an?N.namespaceURI===ke?ne==="math":N.namespaceURI===Ve?ne==="math"&&Zt[Ne]:!!me[ne]:_.namespaceURI===ke?N.namespaceURI===Ve&&!Zt[Ne]||N.namespaceURI===an&&!pt[Ne]?!1:!me[ne]&&(xr[ne]||!ue[ne]):!!(Rn==="application/xhtml+xml"&&In[_.namespaceURI]):!1},Le=function(_){Qr(e.removed,{element:_});try{E(_).removeChild(_)}catch{k(_)}},Ye=function(_,N){try{Qr(e.removed,{attribute:N.getAttributeNode(_),from:N})}catch{Qr(e.removed,{attribute:null,from:N})}if(N.removeAttribute(_),_==="is")if(ft||Ct)try{Le(N)}catch{}else try{N.setAttribute(_,"")}catch{}},Dt=function(_){let N=null,ne=null;if(en)_=""+_;else{const ve=uo(_,/^[\r\n\t ]+/);ne=ve&&ve[0]}Rn==="application/xhtml+xml"&&Ke===ke&&(_=''+_+"");const Ne=A?A.createHTML(_):_;if(Ke===ke)try{N=new m().parseFromString(Ne,Rn)}catch{}if(!N||!N.documentElement){N=C.createDocument(Ke,"template",null);try{N.documentElement.innerHTML=An?D:Ne}catch{}}const kt=N.body||N.documentElement;return _&&ne&&kt.insertBefore(n.createTextNode(ne),kt.childNodes[0]||null),Ke===ke?G.call(N,at?"html":"body")[0]:at?N.documentElement:kt},St=function(_){return U.call(_.ownerDocument||_,_,f.SHOW_ELEMENT|f.SHOW_COMMENT|f.SHOW_TEXT|f.SHOW_PROCESSING_INSTRUCTION|f.SHOW_CDATA_SECTION,null)},We=function(_){return _ instanceof p&&(typeof _.nodeName!="string"||typeof _.textContent!="string"||typeof _.removeChild!="function"||!(_.attributes instanceof d)||typeof _.removeAttribute!="function"||typeof _.setAttribute!="function"||typeof _.namespaceURI!="string"||typeof _.insertBefore!="function"||typeof _.hasChildNodes!="function")},gt=function(_){return typeof u=="function"&&_ instanceof u};function qt(de,_,N){Xr(de,ne=>{ne.call(e,_,N,M)})}const Yn=function(_){let N=null;if(qt(Z.beforeSanitizeElements,_,null),We(_))return Le(_),!0;const ne=$e(_.nodeName);if(qt(Z.uponSanitizeElement,_,{tagName:ne,allowedTags:$}),rt&&_.hasChildNodes()&&!gt(_.firstElementChild)&&At(/<[/\w!]/g,_.innerHTML)&&At(/<[/\w!]/g,_.textContent)||rt&&_.namespaceURI===ke&&ne==="style"&>(_.firstElementChild)||_.nodeType===$r.progressingInstruction||rt&&_.nodeType===$r.comment&&At(/<[/\w]/g,_.data))return Le(_),!0;if(Ue[ne]||!(se.tagCheck instanceof Function&&se.tagCheck(ne))&&!$[ne]){if(!Ue[ne]&&hn(ne)&&(_e.tagNameCheck instanceof RegExp&&At(_e.tagNameCheck,ne)||_e.tagNameCheck instanceof Function&&_e.tagNameCheck(ne)))return!1;if(Nn&&!ht[ne]){const Ne=E(_)||_.parentNode,kt=I(_)||_.childNodes;if(kt&&Ne){const ve=kt.length;for(let Et=ve-1;Et>=0;--Et){const Ut=x(kt[Et],!0);Ne.insertBefore(Ut,g(_))}}}return Le(_),!0}return _ instanceof l&&!Ie(_)||(ne==="noscript"||ne==="noembed"||ne==="noframes")&&At(/<\/no(script|embed|frames)/i,_.innerHTML)?(Le(_),!0):(wt&&_.nodeType===$r.text&&(N=_.textContent,Xr([Y,O,W],Ne=>{N=Rr(N,Ne," ")}),_.textContent!==N&&(Qr(e.removed,{element:_.cloneNode()}),_.textContent=N)),qt(Z.afterSanitizeElements,_,null),!1)},Tt=function(_,N,ne){if(Je[N]||Kt&&(N==="id"||N==="name")&&(ne in n||ne in H))return!1;const Ne=ge[N]||se.attributeCheck instanceof Function&&se.attributeCheck(N,_);if(!(Se&&!Je[N]&&At(J,N))){if(!(be&&At(fe,N))){if(!Ne||Je[N]){if(!(hn(_)&&(_e.tagNameCheck instanceof RegExp&&At(_e.tagNameCheck,_)||_e.tagNameCheck instanceof Function&&_e.tagNameCheck(_))&&(_e.attributeNameCheck instanceof RegExp&&At(_e.attributeNameCheck,N)||_e.attributeNameCheck instanceof Function&&_e.attributeNameCheck(N,_))||N==="is"&&_e.allowCustomizedBuiltInElements&&(_e.tagNameCheck instanceof RegExp&&At(_e.tagNameCheck,ne)||_e.tagNameCheck instanceof Function&&_e.tagNameCheck(ne))))return!1}else if(!Nt[N]){if(!At(ce,Rr(ne,B,""))){if(!((N==="src"||N==="xlink:href"||N==="href")&&_!=="script"&&fo(ne,"data:")===0&&rr[_])){if(!(nt&&!At(ie,Rr(ne,B,"")))){if(ne)return!1}}}}}}return!0},xt=we({},["annotation-xml","color-profile","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","missing-glyph"]),hn=function(_){return!xt[aa(_)]&&At(ae,_)},ar=function(_){qt(Z.beforeSanitizeAttributes,_,null);const{attributes:N}=_;if(!N||We(_))return;const ne={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:ge,forceKeepAttr:void 0};let Ne=N.length;for(;Ne--;){const kt=N[Ne],{name:ve,namespaceURI:Et,value:Ut}=kt,Mt=$e(ve),Gr=Ut;let ct=ve==="value"?Gr:ah(Gr);if(ne.attrName=Mt,ne.attrValue=ct,ne.keepAttr=!0,ne.forceKeepAttr=void 0,qt(Z.uponSanitizeAttribute,_,ne),ct=ne.attrValue,xn&&(Mt==="id"||Mt==="name")&&fo(ct,En)!==0&&(Ye(ve,_),ct=En+ct),rt&&At(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i,ct)){Ye(ve,_);continue}if(Mt==="attributename"&&uo(ct,"href")){Ye(ve,_);continue}if(ne.forceKeepAttr)continue;if(!ne.keepAttr){Ye(ve,_);continue}if(!bt&&At(/\/>/i,ct)){Ye(ve,_);continue}wt&&Xr([Y,O,W],Sa=>{ct=Rr(ct,Sa," ")});const ka=$e(_.nodeName);if(!Tt(ka,Mt,ct)){Ye(ve,_);continue}if(A&&typeof w=="object"&&typeof w.getAttributeType=="function"&&!Et)switch(w.getAttributeType(ka,Mt)){case"TrustedHTML":{ct=A.createHTML(ct);break}case"TrustedScriptURL":{ct=A.createScriptURL(ct);break}}if(ct!==Gr)try{Et?_.setAttributeNS(Et,ve,ct):_.setAttribute(ve,ct),We(_)?Le(_):co(e.removed)}catch{Ye(ve,_)}}qt(Z.afterSanitizeAttributes,_,null)},ya=function(_){let N=null;const ne=St(_);for(qt(Z.beforeSanitizeShadowDOM,_,null);N=ne.nextNode();)qt(Z.uponSanitizeShadowNode,N,null),Yn(N),ar(N),N.content instanceof s&&ya(N.content);qt(Z.afterSanitizeShadowDOM,_,null)};return e.sanitize=function(de){let _=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},N=null,ne=null,Ne=null,kt=null;if(An=!de,An&&(de=""),typeof de!="string"&&!gt(de)&&(de=ch(de),typeof de!="string"))throw Da("dirty is not a string, aborting");if(!e.isSupported)return de;if(Pe||F(_),e.removed=[],typeof de=="string"&&(rn=!1),rn){const Ut=de.nodeName;if(typeof Ut=="string"){const Mt=$e(Ut);if(!$[Mt]||Ue[Mt])throw Da("root node is forbidden and cannot be sanitized in-place")}}else if(de instanceof u)N=Dt(""),ne=N.ownerDocument.importNode(de,!0),ne.nodeType===$r.element&&ne.nodeName==="BODY"||ne.nodeName==="HTML"?N=ne:N.appendChild(ne);else{if(!ft&&!wt&&!at&&de.indexOf("<")===-1)return A&&Vt?A.createHTML(de):de;if(N=Dt(de),!N)return ft?null:Vt?D:""}N&&en&&Le(N.firstChild);const ve=St(rn?de:N);for(;Ne=ve.nextNode();)Yn(Ne),ar(Ne),Ne.content instanceof s&&ya(Ne.content);if(rn)return de;if(ft){if(wt){N.normalize();let Ut=N.innerHTML;Xr([Y,O,W],Mt=>{Ut=Rr(Ut,Mt," ")}),N.innerHTML=Ut}if(Ct)for(kt=P.call(N.ownerDocument);N.firstChild;)kt.appendChild(N.firstChild);else kt=N;return(ge.shadowroot||ge.shadowrootmode)&&(kt=K.call(r,kt,!0)),kt}let Et=at?N.outerHTML:N.innerHTML;return at&&$["!doctype"]&&N.ownerDocument&&N.ownerDocument.doctype&&N.ownerDocument.doctype.name&&At(Fl,N.ownerDocument.doctype.name)&&(Et=" +`+Et),wt&&Xr([Y,O,W],Ut=>{Et=Rr(Et,Ut," ")}),A&&Vt?A.createHTML(Et):Et},e.setConfig=function(){let de=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};F(de),Pe=!0},e.clearConfig=function(){M=null,Pe=!1},e.isValidAttribute=function(de,_,N){M||F({});const ne=$e(de),Ne=$e(_);return Tt(ne,Ne,N)},e.addHook=function(de,_){typeof _=="function"&&Qr(Z[de],_)},e.removeHook=function(de,_){if(_!==void 0){const N=nh(Z[de],_);return N===-1?void 0:rh(Z[de],N,1)[0]}return co(Z[de])},e.removeHooks=function(de){Z[de]=[]},e.removeAllHooks=function(){Z=wo()},e}var Sh=Hl();function os(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var Tr=os();function Wl(t){Tr=t}var sr={exec:()=>null};function Ce(t,e=""){let n=typeof t=="string"?t:t.source,r={replace:(i,s)=>{let o=typeof s=="string"?s:s.source;return o=o.replace(Ft.caret,"$1"),n=n.replace(i,o),r},getRegex:()=>new RegExp(n,e)};return r}var Th=(()=>{try{return!!new RegExp("(?<=1)(?/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:t=>new RegExp(`^( {0,3}${t})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),hrRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}#`),htmlBeginRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}<(?:[a-z].*>|!--)`,"i"),blockquoteBeginRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}>`)},xh=/^(?:[ \t]*(?:\n|$))+/,Eh=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,Ah=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,wa=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,Ih=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,ls=/ {0,3}(?:[*+-]|\d{1,9}[.)])/,Gl=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,jl=Ce(Gl).replace(/bull/g,ls).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),Rh=Ce(Gl).replace(/bull/g,ls).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),cs=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,Ch=/^[^\n]+/,us=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,Dh=Ce(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",us).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),Mh=Ce(/^(bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,ls).getRegex(),Za="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",ds=/|$))/,Oh=Ce("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",ds).replace("tag",Za).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),Vl=Ce(cs).replace("hr",wa).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",Za).getRegex(),Lh=Ce(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",Vl).getRegex(),fs={blockquote:Lh,code:Eh,def:Dh,fences:Ah,heading:Ih,hr:wa,html:Oh,lheading:jl,list:Mh,newline:xh,paragraph:Vl,table:sr,text:Ch},yo=Ce("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",wa).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",Za).getRegex(),Ph={...fs,lheading:Rh,table:yo,paragraph:Ce(cs).replace("hr",wa).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",yo).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)])[ \\t]").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",Za).getRegex()},Nh={...fs,html:Ce(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",ds).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:sr,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:Ce(cs).replace("hr",wa).replace("heading",` *#{1,6} *[^ ]`).replace("lheading",jl).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},qh=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,Uh=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,Kl=/^( {2,}|\\)\n(?!\s*$)/,zh=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\`+)[^`]+\k(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-",Th?"(?`+)[^`]+\k(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),Zl=/^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/,Gh=Ce(Zl,"u").replace(/punct/g,Fr).getRegex(),jh=Ce(Zl,"u").replace(/punct/g,Yl).getRegex(),Xl="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",Vh=Ce(Xl,"gu").replace(/notPunctSpace/g,hs).replace(/punctSpace/g,Xa).replace(/punct/g,Fr).getRegex(),Kh=Ce(Xl,"gu").replace(/notPunctSpace/g,Hh).replace(/punctSpace/g,Fh).replace(/punct/g,Yl).getRegex(),Yh=Ce("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,hs).replace(/punctSpace/g,Xa).replace(/punct/g,Fr).getRegex(),Zh=Ce(/^~~?(?:((?!~)punct)|[^\s~])/,"u").replace(/punct/g,Fr).getRegex(),Xh="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",Qh=Ce(Xh,"gu").replace(/notPunctSpace/g,hs).replace(/punctSpace/g,Xa).replace(/punct/g,Fr).getRegex(),Jh=Ce(/\\(punct)/,"gu").replace(/punct/g,Fr).getRegex(),$h=Ce(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),ep=Ce(ds).replace("(?:-->|$)","-->").getRegex(),tp=Ce("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",ep).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),Ha=/(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/,np=Ce(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label",Ha).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),Ql=Ce(/^!?\[(label)\]\[(ref)\]/).replace("label",Ha).replace("ref",us).getRegex(),Jl=Ce(/^!?\[(ref)\](?:\[\])?/).replace("ref",us).getRegex(),rp=Ce("reflink|nolink(?!\\()","g").replace("reflink",Ql).replace("nolink",Jl).getRegex(),ko=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,ps={_backpedal:sr,anyPunctuation:Jh,autolink:$h,blockSkip:Wh,br:Kl,code:Uh,del:sr,delLDelim:sr,delRDelim:sr,emStrongLDelim:Gh,emStrongRDelimAst:Vh,emStrongRDelimUnd:Yh,escape:qh,link:np,nolink:Jl,punctuation:Bh,reflink:Ql,reflinkSearch:rp,tag:tp,text:zh,url:sr},ap={...ps,link:Ce(/^!?\[(label)\]\((.*?)\)/).replace("label",Ha).getRegex(),reflink:Ce(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",Ha).getRegex()},Ui={...ps,emStrongRDelimAst:Kh,emStrongLDelim:jh,delLDelim:Zh,delRDelim:Qh,url:Ce(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol",ko).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/,text:Ce(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\":">",'"':""","'":"'"},So=t=>sp[t];function Dn(t,e){if(e){if(Ft.escapeTest.test(t))return t.replace(Ft.escapeReplace,So)}else if(Ft.escapeTestNoEncode.test(t))return t.replace(Ft.escapeReplaceNoEncode,So);return t}function To(t){try{t=encodeURI(t).replace(Ft.percentDecode,"%")}catch{return null}return t}function xo(t,e){let n=t.replace(Ft.findPipe,(s,o,u)=>{let l=!1,f=o;for(;--f>=0&&u[f]==="\\";)l=!l;return l?"|":" |"}),r=n.split(Ft.splitPipe),i=0;if(r[0].trim()||r.shift(),r.length>0&&!r.at(-1)?.trim()&&r.pop(),e)if(r.length>e)r.splice(e);else for(;r.length0?-2:-1}function lp(t,e=0){let n=e,r="";for(let i of t)if(i===" "){let s=4-n%4;r+=" ".repeat(s),n+=s}else r+=i,n++;return r}function Eo(t,e,n,r,i){let s=e.href,o=e.title||null,u=t[1].replace(i.other.outputLinkReplace,"$1");r.state.inLink=!0;let l={type:t[0].charAt(0)==="!"?"image":"link",raw:n,href:s,title:o,text:u,tokens:r.inlineTokens(u)};return r.state.inLink=!1,l}function cp(t,e,n){let r=t.match(n.other.indentCodeCompensation);if(r===null)return e;let i=r[1];return e.split(` `).map(s=>{let o=s.match(n.other.beginningSpace);if(o===null)return s;let[u]=o;return u.length>=i.length?s.slice(i.length):s}).join(` `)}var Wa=class{options;rules;lexer;constructor(t){this.options=t||Tr}space(t){let e=this.rules.block.newline.exec(t);if(e&&e[0].length>0)return{type:"space",raw:e[0]}}code(t){let e=this.rules.block.code.exec(t);if(e){let n=e[0].replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:e[0],codeBlockStyle:"indented",text:this.options.pedantic?n:ta(n,` @@ -19,9 +19,9 @@ ${d}`:d;let p=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTo `);continue}}return{type:"blockquote",raw:r,tokens:s,text:i}}}list(t){let e=this.rules.block.list.exec(t);if(e){let n=e[1].trim(),r=n.length>1,i={type:"list",raw:"",ordered:r,start:r?+n.slice(0,-1):"",loose:!1,items:[]};n=r?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=r?n:"[*+-]");let s=this.rules.other.listItemRegex(n),o=!1;for(;t;){let l=!1,f="",d="";if(!(e=s.exec(t))||this.rules.block.hr.test(t))break;f=e[0],t=t.substring(f.length);let p=lp(e[2].split(` `,1)[0],e[1].length),m=t.split(` `,1)[0],w=!p.trim(),y=0;if(this.options.pedantic?(y=2,d=p.trimStart()):w?y=e[1].length+1:(y=p.search(this.rules.other.nonSpaceChar),y=y>4?1:y,d=p.slice(y),y+=e[1].length),w&&this.rules.other.blankLine.test(m)&&(f+=m+` -`,t=t.substring(m.length+1),l=!0),!l){let x=this.rules.other.nextBulletRegex(y),k=this.rules.other.hrRegex(y),g=this.rules.other.fencesBeginRegex(y),A=this.rules.other.headingBeginRegex(y),E=this.rules.other.htmlBeginRegex(y),I=this.rules.other.blockquoteBeginRegex(y);for(;t;){let D=t.split(` -`,1)[0],C;if(m=D,this.options.pedantic?(m=m.replace(this.rules.other.listReplaceNesting," "),C=m):C=m.replace(this.rules.other.tabCharGlobal," "),g.test(m)||A.test(m)||E.test(m)||I.test(m)||x.test(m)||k.test(m))break;if(C.search(this.rules.other.nonSpaceChar)>=y||!m.trim())d+=` -`+C.slice(y);else{if(w||p.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||g.test(p)||A.test(p)||k.test(p))break;d+=` +`,t=t.substring(m.length+1),l=!0),!l){let x=this.rules.other.nextBulletRegex(y),k=this.rules.other.hrRegex(y),g=this.rules.other.fencesBeginRegex(y),I=this.rules.other.headingBeginRegex(y),E=this.rules.other.htmlBeginRegex(y),A=this.rules.other.blockquoteBeginRegex(y);for(;t;){let D=t.split(` +`,1)[0],C;if(m=D,this.options.pedantic?(m=m.replace(this.rules.other.listReplaceNesting," "),C=m):C=m.replace(this.rules.other.tabCharGlobal," "),g.test(m)||I.test(m)||E.test(m)||A.test(m)||x.test(m)||k.test(m))break;if(C.search(this.rules.other.nonSpaceChar)>=y||!m.trim())d+=` +`+C.slice(y);else{if(w||p.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||g.test(p)||I.test(p)||k.test(p))break;d+=` `+m}w=!m.trim(),f+=D+` `,t=t.substring(D.length+1),p=C.slice(y)}}i.loose||(o?i.loose=!0:this.rules.other.doubleBlankLine.test(f)&&(o=!0)),i.items.push({type:"list_item",raw:f,task:!!this.options.gfm&&this.rules.other.listIsTask.test(d),loose:!1,text:d,tokens:[]}),i.raw+=f}let u=i.items.at(-1);if(u)u.raw=u.raw.trimEnd(),u.text=u.text.trimEnd();else return;i.raw=i.raw.trimEnd();for(let l of i.items){if(this.lexer.state.top=!1,l.tokens=this.lexer.blockTokens(l.text,[]),l.task){if(l.text=l.text.replace(this.rules.other.listReplaceTask,""),l.tokens[0]?.type==="text"||l.tokens[0]?.type==="paragraph"){l.tokens[0].raw=l.tokens[0].raw.replace(this.rules.other.listReplaceTask,""),l.tokens[0].text=l.tokens[0].text.replace(this.rules.other.listReplaceTask,"");for(let d=this.lexer.inlineQueue.length-1;d>=0;d--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[d].src)){this.lexer.inlineQueue[d].src=this.lexer.inlineQueue[d].src.replace(this.rules.other.listReplaceTask,"");break}}let f=this.rules.other.listTaskCheckbox.exec(l.raw);if(f){let d={type:"checkbox",raw:f[0]+" ",checked:f[0]!=="[ ]"};l.checked=d.checked,i.loose?l.tokens[0]&&["paragraph","text"].includes(l.tokens[0].type)&&"tokens"in l.tokens[0]&&l.tokens[0].tokens?(l.tokens[0].raw=d.raw+l.tokens[0].raw,l.tokens[0].text=d.raw+l.tokens[0].text,l.tokens[0].tokens.unshift(d)):l.tokens.unshift({type:"paragraph",raw:d.raw,text:d.raw,tokens:[d]}):l.tokens.unshift(d)}}if(!i.loose){let f=l.tokens.filter(p=>p.type==="space"),d=f.length>0&&f.some(p=>this.rules.other.anyLine.test(p.raw));i.loose=d}}if(i.loose)for(let l of i.items){l.loose=!0;for(let f of l.tokens)f.type==="text"&&(f.type="paragraph")}return i}}html(t){let e=this.rules.block.html.exec(t);if(e)return{type:"html",block:!0,raw:e[0],pre:e[1]==="pre"||e[1]==="script"||e[1]==="style",text:e[0]}}def(t){let e=this.rules.block.def.exec(t);if(e){let n=e[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal," "),r=e[2]?e[2].replace(this.rules.other.hrefBrackets,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",i=e[3]?e[3].substring(1,e[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):e[3];return{type:"def",tag:n,raw:e[0],href:r,title:i}}}table(t){let e=this.rules.block.table.exec(t);if(!e||!this.rules.other.tableDelimiter.test(e[2]))return;let n=xo(e[1]),r=e[2].replace(this.rules.other.tableAlignChars,"").split("|"),i=e[3]?.trim()?e[3].replace(this.rules.other.tableRowBlankLine,"").split(` `):[],s={type:"table",raw:e[0],header:[],align:[],rows:[]};if(n.length===r.length){for(let o of r)this.rules.other.tableAlignRight.test(o)?s.align.push("right"):this.rules.other.tableAlignCenter.test(o)?s.align.push("center"):this.rules.other.tableAlignLeft.test(o)?s.align.push("left"):s.align.push(null);for(let o=0;o({text:u,tokens:this.lexer.inline(u),header:!1,align:s.align[l]})));return s}}lheading(t){let e=this.rules.block.lheading.exec(t);if(e){let n=e[1].trim();return{type:"heading",raw:e[0],depth:e[2].charAt(0)==="="?1:2,text:n,tokens:this.lexer.inline(n)}}}paragraph(t){let e=this.rules.block.paragraph.exec(t);if(e){let n=e[1].charAt(e[1].length-1)===` @@ -58,15 +58,15 @@ ${this.parser.parse(t)} ${t} `}tablecell(t){let e=this.parser.parseInline(t.tokens),n=t.header?"th":"td";return(t.align?`<${n} align="${t.align}">`:`<${n}>`)+e+` `}strong({tokens:t}){return`${this.parser.parseInline(t)}`}em({tokens:t}){return`${this.parser.parseInline(t)}`}codespan({text:t}){return`${Dn(t,!0)}`}br(t){return"
"}del({tokens:t}){return`${this.parser.parseInline(t)}`}link({href:t,title:e,tokens:n}){let r=this.parser.parseInline(n),i=To(t);if(i===null)return r;t=i;let s='
",s}image({href:t,title:e,text:n,tokens:r}){r&&(n=this.parser.parseInline(r,this.parser.textRenderer));let i=To(t);if(i===null)return Dn(n);t=i;let s=`${Dn(n)}{let o=i[s].flat(1/0);n=n.concat(this.walkTokens(o,e))}):i.tokens&&(n=n.concat(this.walkTokens(i.tokens,e)))}}return n}use(...t){let e=this.defaults.extensions||{renderers:{},childTokens:{}};return t.forEach(n=>{let r={...n};if(r.async=this.defaults.async||r.async||!1,n.extensions&&(n.extensions.forEach(i=>{if(!i.name)throw new Error("extension name required");if("renderer"in i){let s=e.renderers[i.name];s?e.renderers[i.name]=function(...o){let u=i.renderer.apply(this,o);return u===!1&&(u=s.apply(this,o)),u}:e.renderers[i.name]=i.renderer}if("tokenizer"in i){if(!i.level||i.level!=="block"&&i.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let s=e[i.level];s?s.unshift(i.tokenizer):e[i.level]=[i.tokenizer],i.start&&(i.level==="block"?e.startBlock?e.startBlock.push(i.start):e.startBlock=[i.start]:i.level==="inline"&&(e.startInline?e.startInline.push(i.start):e.startInline=[i.start]))}"childTokens"in i&&i.childTokens&&(e.childTokens[i.name]=i.childTokens)}),r.extensions=e),n.renderer){let i=this.defaults.renderer||new Ga(this.defaults);for(let s in n.renderer){if(!(s in i))throw new Error(`renderer '${s}' does not exist`);if(["options","parser"].includes(s))continue;let o=s,u=n.renderer[o],l=i[o];i[o]=(...f)=>{let d=u.apply(i,f);return d===!1&&(d=l.apply(i,f)),d||""}}r.renderer=i}if(n.tokenizer){let i=this.defaults.tokenizer||new Wa(this.defaults);for(let s in n.tokenizer){if(!(s in i))throw new Error(`tokenizer '${s}' does not exist`);if(["options","rules","lexer"].includes(s))continue;let o=s,u=n.tokenizer[o],l=i[o];i[o]=(...f)=>{let d=u.apply(i,f);return d===!1&&(d=l.apply(i,f)),d}}r.tokenizer=i}if(n.hooks){let i=this.defaults.hooks||new ia;for(let s in n.hooks){if(!(s in i))throw new Error(`hook '${s}' does not exist`);if(["options","block"].includes(s))continue;let o=s,u=n.hooks[o],l=i[o];ia.passThroughHooks.has(s)?i[o]=f=>{if(this.defaults.async&&ia.passThroughHooksRespectAsync.has(s))return(async()=>{let p=await u.call(i,f);return l.call(i,p)})();let d=u.call(i,f);return l.call(i,d)}:i[o]=(...f)=>{if(this.defaults.async)return(async()=>{let p=await u.apply(i,f);return p===!1&&(p=await l.apply(i,f)),p})();let d=u.apply(i,f);return d===!1&&(d=l.apply(i,f)),d}}r.hooks=i}if(n.walkTokens){let i=this.defaults.walkTokens,s=n.walkTokens;r.walkTokens=function(o){let u=[];return u.push(s.call(this,o)),i&&(u=u.concat(i.call(this,o))),u}}this.defaults={...this.defaults,...r}}),this}setOptions(t){return this.defaults={...this.defaults,...t},this}lexer(t,e){return vn.lex(t,e??this.defaults)}parser(t,e){return mn.parse(t,e??this.defaults)}parseMarkdown(t){return(e,n)=>{let r={...n},i={...this.defaults,...r},s=this.onError(!!i.silent,!!i.async);if(this.defaults.async===!0&&r.async===!1)return s(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof e>"u"||e===null)return s(new Error("marked(): input parameter is undefined or null"));if(typeof e!="string")return s(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(e)+", string expected"));if(i.hooks&&(i.hooks.options=i,i.hooks.block=t),i.async)return(async()=>{let o=i.hooks?await i.hooks.preprocess(e):e,u=await(i.hooks?await i.hooks.provideLexer(t):t?vn.lex:vn.lexInline)(o,i),l=i.hooks?await i.hooks.processAllTokens(u):u;i.walkTokens&&await Promise.all(this.walkTokens(l,i.walkTokens));let f=await(i.hooks?await i.hooks.provideParser(t):t?mn.parse:mn.parseInline)(l,i);return i.hooks?await i.hooks.postprocess(f):f})().catch(s);try{i.hooks&&(e=i.hooks.preprocess(e));let o=(i.hooks?i.hooks.provideLexer(t):t?vn.lex:vn.lexInline)(e,i);i.hooks&&(o=i.hooks.processAllTokens(o)),i.walkTokens&&this.walkTokens(o,i.walkTokens);let u=(i.hooks?i.hooks.provideParser(t):t?mn.parse:mn.parseInline)(o,i);return i.hooks&&(u=i.hooks.postprocess(u)),u}catch(o){return s(o)}}}onError(t,e){return n=>{if(n.message+=` -Please report this to https://github.com/markedjs/marked.`,t){let r="

An error occurred:

"+Dn(n.message+"",!0)+"
";return e?Promise.resolve(r):r}if(e)return Promise.reject(n);throw n}}},yr=new up;function qe(t,e){return yr.parse(t,e)}qe.options=qe.setOptions=function(t){return yr.setOptions(t),qe.defaults=yr.defaults,Wl(qe.defaults),qe};qe.getDefaults=os;qe.defaults=Tr;qe.use=function(...t){return yr.use(...t),qe.defaults=yr.defaults,Wl(qe.defaults),qe};qe.walkTokens=function(t,e){return yr.walkTokens(t,e)};qe.parseInline=yr.parseInline;qe.Parser=mn;qe.parser=mn.parse;qe.Renderer=Ga;qe.TextRenderer=gs;qe.Lexer=vn;qe.lexer=vn.lex;qe.Tokenizer=Wa;qe.Hooks=ia;qe.parse=qe;qe.options;qe.setOptions;qe.use;qe.walkTokens;qe.parseInline;mn.parse;vn.lex;function Fi(t){return Sh.sanitize(qe.parse(t,{async:!1,breaks:!0,gfm:!0}))}function ha(t){return new Intl.DateTimeFormat(void 0,{hour:"2-digit",minute:"2-digit"}).format(new Date(t))}var dp=z('
'),fp=z(''),hp=z(' ',1),pp=z('
',2),gp=z(' ');function Hi(t,e){Fe(e,!0);let n=Ee(e,"onOpenImage",3,()=>{});const r=360,i=120;let s=Be(null),o=Be(!1),u=Be(""),l=le(()=>a(u)||m(e.upload.duration_ms??0)),f=le(()=>e.upload.content_type?.startsWith("image/")??!1),d=le(()=>e.upload.content_type?.startsWith("video/")??!1),p=le(()=>{const C=e.upload.width??0,U=e.upload.height??0;if(C<=0||U<=0)return"";const P=a(f)?320:r,G=Math.min(P,Math.max(i,U));return`aspect-ratio: ${C} / ${U}; max-height: ${G}px;`});function m(C){if(!C||C<=0)return"";const U=Math.floor(C/1e3),P=Math.floor(U/60),G=U%60;return`${P}:${G.toString().padStart(2,"0")}`}function w(){v(o,!0)}function y(){!a(s)||!isFinite(a(s).duration)||v(u,m(a(s).duration*1e3),!0)}function x(){a(s)&&(v(o,!0),a(s).play())}function k(C){return C<1024?`${C} B`:C<1024*1024?`${Math.round(C/1024)} KB`:`${(C/(1024*1024)).toFixed(1)} MB`}var g=Sn(),A=Gt(g);{var E=C=>{var U=dp(),P=b(U),G=b(P),K=S(P,2),Z=b(K),Y=b(Z),O=S(Z,2);te(()=>{X(P,"aria-label",`Open image ${e.upload.filename}`),X(G,"src",e.url),X(G,"alt",e.upload.filename),X(G,"width",e.upload.width||void 0),X(G,"height",e.upload.height||void 0),wr(G,a(p)),ee(Y,e.upload.filename),X(O,"href",e.url),X(O,"download",e.upload.filename),X(O,"aria-label",`Download ${e.upload.filename}`)}),V("click",P,()=>n()(e.url,e.upload.filename)),V("click",O,W=>W.stopPropagation()),L(C,U)},I=C=>{var U=pp();let P;var G=b(U),K=b(G);gr(G,ie=>v(s,ie),()=>a(s));var Z=S(G,2);{var Y=ie=>{var B=hp(),ae=Gt(B),ce=S(ae,2);{var $=Ae=>{var ge=fp(),De=b(ge);te(()=>ee(De,a(l))),L(Ae,ge)};oe(ce,Ae=>{a(l)&&Ae($)})}te(()=>X(ae,"aria-label",`Play ${e.upload.filename}`)),V("click",ae,x),L(ie,B)};oe(Z,ie=>{a(o)||ie(Y)})}var O=S(Z,2),W=b(O),J=b(W),fe=S(W,2);te(()=>{P=lt(U,1,"media-tile media-tile--video",null,P,{"is-started":a(o)}),G.controls=a(o),X(G,"aria-label",e.upload.filename),X(G,"width",e.upload.width||void 0),X(G,"height",e.upload.height||void 0),wr(G,a(p)),X(K,"src",e.url),X(K,"type",e.upload.content_type),ee(J,e.upload.filename),X(fe,"href",e.url),X(fe,"download",e.upload.filename),X(fe,"aria-label",`Download ${e.upload.filename}`)}),dn("play",G,w),dn("loadedmetadata",G,y),V("click",fe,ie=>ie.stopPropagation()),L(C,U)},D=C=>{var U=gp(),P=S(b(U),2),G=b(P),K=b(G),Z=S(G,2),Y=b(Z);te(O=>{X(U,"href",e.url),ee(K,e.upload.filename),ee(Y,O)},[()=>k(e.upload.byte_size)]),L(C,U)};oe(A,C=>{a(f)?C(E):a(d)?C(I,1):C(D,-1)})}L(t,g),He()}Qe(["click"]);var vp=z(' '),mp=z(' '),_p=z('');function $l(t,e){Fe(e,!0);var n=Sn(),r=Gt(n);{var i=s=>{var o=_p();let u;var l=S(b(o),2),f=b(l),d=b(f),p=S(f,2);{var m=y=>{var x=vp(),k=b(x);te(g=>ee(k,g),[()=>Li(e.message.quoted_body_snapshot)]),L(y,x)},w=y=>{var x=mp(),k=b(x);te(g=>ee(k,`[original deleted] ${g??""}`),[()=>Li(e.message.quoted_body_snapshot)]),L(y,x)};oe(p,y=>{e.message.quoted_message_id?y(m):y(w,-1)})}te((y,x)=>{u=lt(o,1,"quote-block",null,u,{dangling:!e.message.quoted_message_id}),o.disabled=!e.message.quoted_message_id,X(o,"aria-label",y),ee(d,x)},[()=>e.message.quoted_message_id?`Jump to quoted message from ${ao(e.message)}`:"Original message was deleted",()=>ao(e.message)]),V("click",o,()=>e.onJump(e.message)),L(s,o)};oe(r,s=>{(e.message.quoted_message_id||e.message.quoted_body_snapshot)&&s(i)})}L(t,n),He()}Qe(["click"]);var bp=z('
'),wp=z(''),yp=z(''),kp=z(``),Sp=z('
');function Tp(t,e){Fe(e,!0);let n=le(()=>e.message.status==="pending"),r=le(()=>e.message.status==="failed");var i=Sp();let s;var o=b(i),u=b(o),l=S(o,2),f=b(l);$l(f,{get message(){return e.message},get onJump(){return e.onJumpToQuote}});var d=S(f,2);Ci(d,()=>Fi(e.message.body),!0);var p=S(d,2);{var m=A=>{var E=bp();Wt(E,21,()=>e.message.attachments,I=>I.id,(I,D)=>{{let C=le(()=>Fa(a(D)));Hi(I,{get upload(){return a(D)},get url(){return a(C)},get onOpenImage(){return e.onOpenImage}})}}),L(A,E)};oe(p,A=>{e.message.attachments?.length&&A(m)})}var w=S(p,2);{var y=A=>{var E=kp(),I=S(b(E),2);{var D=P=>{var G=wp();V("click",G,()=>e.onRetry?.(e.message)),L(P,G)};oe(I,P=>{e.onRetry&&P(D)})}var C=S(I,2);{var U=P=>{var G=yp();V("click",G,()=>e.onDiscard?.(e.message)),L(P,G)};oe(C,P=>{e.onDiscard&&P(U)})}L(A,E)};oe(w,A=>{a(r)&&A(y)})}var x=S(l,2),k=b(x),g=S(k,2);te((A,E)=>{s=lt(i,1,"message-row",null,s,{selected:e.selected,"is-pending":a(n),"is-failed":a(r)}),X(i,"data-message-id",e.message.id),ee(u,A),k.disabled=a(n)||a(r),X(g,"data-tooltip",E),g.disabled=a(n)||a(r)},[()=>e.index===0?"":ha(e.message.created_at),()=>ff(e.message,e.selectedThreadID)]),V("click",k,()=>e.onReply(e.message,e.replyContext)),V("click",g,()=>e.onOpenThread(e.message)),L(t,i),He()}Qe(["click"]);var xp=z('bot'),Ep=z(" "),Ap=z('
');function Ip(t,e){Fe(e,!0);const n=le(()=>e.group.messages[0]?.author),r=le(()=>a(n)?.kind==="bot");var i=Ap(),s=b(i);{let g=le(()=>`View profile for ${e.group.authorName}`);Pn(s,{class:"avatar avatar-button",get id(){return e.group.authorID},get name(){return e.group.authorName},get src(){return e.group.authorAvatarURL},size:38,get buttonLabel(){return a(g)},onclick:()=>e.onOpenProfile(e.group.messages[0]?.author)})}var o=S(s,2),u=b(o),l=b(u),f=b(l),d=S(l,2);{var p=g=>{var A=xp();L(g,A)};oe(d,g=>{a(r)&&g(p)})}var m=S(d,2);{var w=g=>{var A=Ep(),E=b(A);te(I=>ee(E,I),[()=>Kn(e.group.authorHandle)]),L(g,A)};oe(m,g=>{e.group.authorHandle&&g(w)})}var y=S(m,2),x=b(y),k=S(u,2);Wt(k,19,()=>e.group.messages,g=>g.id,(g,A,E)=>{{let I=le(()=>e.selectedThreadID===a(A).id);Tp(g,{get message(){return a(A)},get index(){return a(E)},get selected(){return a(I)},get replyContext(){return e.replyContext},get selectedThreadID(){return e.selectedThreadID},get onReply(){return e.onReply},get onOpenThread(){return e.onOpenThread},get onJumpToQuote(){return e.onJumpToQuote},get onOpenImage(){return e.onOpenImage},get onRetry(){return e.onRetry},get onDiscard(){return e.onDiscard}})}}),te(g=>{ee(f,e.group.authorName),ee(x,g)},[()=>ha(e.group.timestamp)]),V("click",l,()=>e.onOpenProfile(e.group.messages[0]?.author)),L(t,i),He()}Qe(["click"]);var Rp=z('
Send a message in Markdown — code fences, lists, links all work. Threads open from any message.
'),Cp=z('
'),Dp=z('
'),Mp=z('
New
'),Op=z('
'),Lp=z('
'),Pp=z('
');function Np(t,e){Fe(e,!0);let n=Ee(e,"loading",3,!1),r=Ee(e,"unreadCount",3,0),i=Ee(e,"unreadBoundarySeq",3,0),s=Ee(e,"unreadBoundaryLoaded",3,!1),o=Ee(e,"unreadSince",3,""),u=Ee(e,"hasOlder",3,!1),l=Ee(e,"hasNewer",3,!1),f=Ee(e,"loadingOlder",3,!1),d=Ee(e,"loadingNewer",3,!1),p=Ee(e,"prepending",3,!1);const m=1.5,w=160,y=260,x=180;let k=Be(void 0),g=Be(void 0),A=Be(void 0),E=Be(0),I=Be(0),D=le(()=>e.selectedDirect?"dm":"channel"),C=Be(""),U=Be(-1),P=Be(0),G=le(()=>a(C)===e.viewKey&&a(U)===i()&&r()<=a(P)?0:r()),K=Be(""),Z=Be(0),Y=Be(!1),O;function W(){O&&(window.clearTimeout(O),O=void 0)}Qt(()=>{if(a(K)&&a(K)!==e.viewKey){W(),v(Z,0),v(K,""),v(Y,!1);return}if(a(G)>0){W(),v(K,e.viewKey,!0),v(Z,a(G),!0),v(Y,!1);return}a(Z)>0&&!a(Y)&&(v(Y,!0),O=window.setTimeout(()=>{O=void 0,!(a(G)>0)&&(v(Z,0),v(K,""),v(Y,!1))},x))}),Ya(W);let J=le(()=>{const M=i()+1;if(a(Z)<=0||M<=0)return!1;let H=Number.POSITIVE_INFINITY,j=0;for(const F of e.messages){if(F.parent_message_id)continue;const ue=F.channel_seq||0;ue<=0||(H=Math.min(H,ue),j=Math.max(j,ue))}return H<=M&&j>=M}),fe=le(()=>s()&&a(J)),ie=le(()=>{const M=[];let H=!1;const j=F=>!a(fe)||F.parent_message_id||F.author?.id===e.currentUserID||F.author_id===e.currentUserID?!1:a(Z)>0&&(F.channel_seq||0)>i();for(const F of pf(e.messages)){let ue=-1;if(!H){for(let me=0;me{requestAnimationFrame(()=>{if(H===Ue){if(F<=1){_e=!1;return}j(F-1)}})};j(M)}function se(){return a(g)?a(g).scrollHeight-a(g).scrollTop-a(g).clientHeight<=m:!0}function be(){if(!a(g))return{atBottom:!0,nearOlder:!1,nearNewer:!1};const M=a(g).scrollHeight-a(g).scrollTop-a(g).clientHeight;return{atBottom:M<=m,nearOlder:a(g).scrollTop-a(E)<=w,nearNewer:M<=y}}function Se(){e.onHistorySettled?.(be())}function nt(){l()||e.onReachedBottom?.()}async function bt(){!a(g)||a(ie).length===0||(B=!0,await wt())}async function wt(){if(!a(g))return;Je(12);let M=0;for(let H=0;H<12;H++){if(!a(g))return;const j=a(g).scrollHeight;if(a(g).scrollTop=a(g).scrollHeight,await new Promise(ue=>requestAnimationFrame(ue)),!a(g))return;const F=Math.abs(a(g).scrollHeight-j)<1;if(se()&&F){if(M++,M>=2)break}else M=0}se()&&(v(ae,!0),nt()),Se()}Qt(()=>{if(!a(g))return;const M=a(g),H=()=>yt(M.scrollTop),j=F=>{F.deltaY>0&&!De&&!_e&&l()&&se()&&e.onLoadNewer?.()};return M.addEventListener("scroll",H,{passive:!0}),M.addEventListener("wheel",j,{passive:!0}),()=>{M.removeEventListener("scroll",H),M.removeEventListener("wheel",j)}}),Qt(()=>{if(!a(g))return;let M=0;const H=()=>{M||(M=requestAnimationFrame(()=>{M=0,B&&!De&&a(g)&&(a(g).scrollTop=a(g).scrollHeight)}))},j=new ResizeObserver(H),F=a(g).lastElementChild;return F&&j.observe(F),()=>{M&&cancelAnimationFrame(M),j.disconnect()}});function rt(M){return a(ie).findIndex(H=>H.kind==="group"&&H.group.messages.some(j=>j.id===M))}const at=52,Pe=3;let en=le(()=>{if(!u()||n())return 0;if(!p())return Pe;const M=Math.max(a(I),480);return Math.max(Pe+1,Math.ceil(M/at))});Qt(()=>{if(!a(g))return;const M=()=>{a(g)&&v(I,a(g).clientHeight,!0)};M();const H=new ResizeObserver(M);return H.observe(a(g)),()=>H.disconnect()});let ft=0;Qt(()=>{if(!a(A)||!a(g)){v(E,0),ft=0;return}const M=a(g),H=a(A),j=()=>{const ue=H.offsetHeight,me=ft;if(v(E,ue,!0),ft=ue,me>0&&ue!==me){const Ie=ue-me;M.scrollTop>0&&(M.scrollTop+=Ie)}};j();const F=new ResizeObserver(j);return F.observe(H),()=>{F.disconnect(),v(E,0),ft=0}});let Ct="",Vt="",Kt=null;za(()=>{const M=e.messages[0]?.id??"";e.viewKey===Vt&&M&&Ct&&M!==Ct&&e.messages.some(F=>F.id===Ct)&&a(g)&&(Kt={savedBottomDistance:a(g).scrollHeight-a(g).scrollTop,deadline:performance.now()+800}),Ct=M,Vt=e.viewKey}),Qt(()=>{if(e.messages,!Kt||!a(g))return;const M=Kt;Kt=null;const H=a(g),j=H.lastElementChild;let F=-1,ue=!1;const me=()=>{if(ue)return;if(F>=0&&Math.abs(H.scrollTop-F)>2){Dt();return}const St=H.scrollHeight-M.savedBottomDistance;Math.abs(H.scrollTop-St)>.5&&(ue=!0,H.scrollTop=St,ue=!1),F=H.scrollTop};let Ie=0;const Le=()=>{me(),performance.now()M.kind==="divider")}function En(){if(!a(fe)||a(Z)<=0)return"";for(const M of e.messages)if(!M.parent_message_id&&!(M.author?.id===e.currentUserID||M.author_id===e.currentUserID)&&(M.channel_seq||0)>i())return M.id;return""}function Nn(){let M=0;for(const H of e.messages)M=Math.max(M,H.channel_seq||0);return M}function rn(){v(C,e.viewKey,!0),v(U,i()),v(P,r()),e.onMarkRead?.(Nn())}function Ge(){return new Promise(M=>requestAnimationFrame(()=>M()))}function ht(M){if(!a(g))return!1;const H=a(g).querySelector(M);if(!H)return!1;const j=H.getBoundingClientRect().top-a(g).getBoundingClientRect().top;return Math.abs(j)<=m?!0:(a(g).scrollTop+=j,!1)}function Yt(){if(!a(g))return null;const M=a(g).getBoundingClientRect(),H=new Map(e.messages.map((ue,me)=>[ue.id,me]));let j=Number.POSITIVE_INFINITY,F=-1;for(const ue of a(g).querySelectorAll("[data-message-id]")){const me=ue.getBoundingClientRect();if(me.bottomM.bottom)continue;const Ie=H.get(ue.dataset.messageId||"");Ie!==void 0&&(j=Math.min(j,Ie),F=Math.max(F,Ie))}return F<0?null:{first:j,last:F}}function rr(M){if(!a(g))return!1;const H=e.messages.findIndex(F=>F.id===M),j=Yt();return H<0||!j?!1:j.first>H?(a(g).scrollTop-=Math.max(80,a(g).clientHeight*.85),!0):j.lastrt(M),`[data-message-id="${CSS.escape(M)}"]`,M),!0}function an(M=!0){if(!a(k)||xn()<0)return!1;B=!1;const j=e.viewKey;return Nt(j,()=>xn(),"[data-unread-divider='true']",En()).then(F=>{M&&!F&&Pt(j)&&e.onJumpToUnread?.()}),!0}function Ve(){if(!l()&&se()){rn();return}if(e.onJumpToUnread){e.onJumpToUnread();return}a(fe)&&an(!1)}function ke(){if(!a(k))return null;if(se())return{atBottom:!0};const H=a(k).getScrollOffset(),j=a(k).findItemIndex(H);for(let F=Math.max(0,j);F(e.onListRef({scrollToBottom:bt,scrollToMessage:qn,scrollToDivider:an,captureState:ke,isAtBottom:()=>se()}),()=>e.onListRef(null))),Qt(()=>{const M=e.viewKey,H=a(ie).length;if(M!==$){$=M,Ae=H,ge=e.restoreState,B=!0,v(ae,!0),v(ce,!1),De=!0,An(M,e.restoreState,!0);return}const j=e.restoreState;if(j&&j!==ge&&(ge=j,!j.atBottom&&j.anchorMessageID)){Ae=H,De=!0,An(M,j,!1);return}H>Ae&&B&&!De?wt():H!==Ae&&!De&&Ke(M),Ae=H});async function Ke(M){await ur(),await Ge(),M===$&&Se()}async function An(M,H,j){if(await ur(),await new Promise(F=>requestAnimationFrame(F)),M===$){if(H&&!H.atBottom&&H.anchorMessageID){const F=await In(M,H.anchorMessageID,H.anchorPixelOffset??0);if(M!==$)return;!F&&j?await bt():B=!1}else a(ie).findIndex(ue=>ue.kind==="divider")>=0&&a(k)?(await Nt(M,()=>xn(),"[data-unread-divider='true']",En()),B=!1):await bt();await new Promise(F=>requestAnimationFrame(F)),M===$&&(De=!1,v(ce,!0),v(ae,se(),!0),B=a(ae),a(ae)&&nt(),a(g)&&yt(a(g).scrollTop),Se())}}async function In(M,H,j){if(!a(k))return!1;const F=rt(H);if(F<0)return!1;for(let ue=0;ue<8;ue++){if(!a(k)||M!==$)return!1;const me=a(k).getItemOffset(F)+j;if(Je(),a(k).scrollTo(me),await new Promise(Ye=>requestAnimationFrame(Ye)),M!==$)return!1;const Ie=a(k).getItemOffset(F)+j,Le=a(k).getScrollOffset();if(Math.abs(Ie-me)<1&&Math.abs(Le-me)<1)break}return!0}function yt(M){if(!a(g)||De)return;const H=a(g).scrollHeight-a(g).scrollTop-a(g).clientHeight,j=H<=m;B=j,v(ae,j),!j&&u()&&a(g).scrollTop-a(E)<=w&&e.onLoadOlder?.(),!_e&&l()&&(j||H<=y)&&e.onLoadNewer?.(),j&&nt()}var pt=Pp();let Zt;var xr=b(pt);{var Rn=M=>{var H=Rp(),j=b(H),F=b(j);{var ue=We=>{var gt=Xn("@");L(We,gt)},me=We=>{var gt=Xn("#");L(We,gt)};oe(F,We=>{e.selectedDirect?We(ue):We(me,-1)})}var Ie=S(j,2),Le=b(Ie);{var Ye=We=>{var gt=Xn();te(qt=>ee(gt,`This is the start of your conversation with ${qt??""}.`),[()=>da(e.selectedDirect,e.currentUserID)]),L(We,gt)},Dt=We=>{var gt=Xn();te(()=>ee(gt,`Welcome to #${e.selectedChannel.name??""}!`)),L(We,gt)},St=We=>{var gt=Xn("Pick a channel to get started.");L(We,gt)};oe(Le,We=>{e.selectedDirect?We(Ye):e.selectedChannel?We(Dt,1):We(St,-1)})}L(M,H)},Hr=M=>{var H=Op(),j=S(b(H),2);{var F=me=>{var Ie=Cp(),Le=b(Ie);oo(Le,{direction:"older",get rows(){return a(en)}}),gr(Ie,Ye=>v(A,Ye),()=>a(A)),te(()=>X(Ie,"aria-hidden",f()?"false":"true")),L(me,Ie)};oe(j,me=>{u()&&!n()&&me(F)})}var ue=S(j,2);gr(Gf(ue,{get data(){return a(ie)},getKey:Ie=>Ie.id,get shift(){return p()},get startMargin(){return a(E)},children:(Ie,Le=_i,Ye=_i)=>{var Dt=Sn(),St=Gt(Dt);{var We=Tt=>{oo(Tt,{get direction(){return Le().direction},get rows(){return Le().rows}})},gt=Tt=>{var xt=Dp(),hn=b(xt),ar=b(hn);te(()=>ee(ar,Le().label)),L(Tt,xt)},qt=Tt=>{var xt=Mp();let hn;te(()=>hn=lt(xt,1,"new-messages-divider",null,hn,{"is-clearing":a(Y)})),L(Tt,xt)},Yn=Tt=>{Ip(Tt,{get group(){return Le().group},get selectedThreadID(){return e.selectedThreadID},get replyContext(){return a(D)},get onOpenProfile(){return e.onOpenProfile},get onReply(){return e.onReply},get onOpenThread(){return e.onOpenThread},get onJumpToQuote(){return e.onJumpToQuote},get onOpenImage(){return e.onOpenImage},get onRetry(){return e.onRetry},get onDiscard(){return e.onDiscard}})};oe(St,Tt=>{Le().kind==="loader"?Tt(We):Le().kind==="day"?Tt(gt,1):Le().kind==="divider"?Tt(qt,2):Tt(Yn,-1)})}L(Ie,Dt)},$$slots:{default:!0}}),Ie=>v(k,Ie,!0),()=>a(k)),gr(H,me=>v(g,me),()=>a(g)),L(M,H)};oe(xr,M=>{!n()&&e.messages.length===0?M(Rn):e.messages.length>0&&M(Hr,1)})}var Wr=S(xr,2);{var $e=M=>{var H=Lp();let j;var F=b(H),ue=b(F),me=b(ue),Ie=S(F,2);te(Le=>{j=lt(H,1,"unread-bar",null,j,{"is-clearing":a(Y)}),X(F,"aria-label",Le),ee(me,`${(a(Z)>99?"99+":a(Z))??""} new message${a(Z)===1?"":"s"}${o()?` since ${o()}`:""}`)},[()=>`Jump to ${a(Z)>0?a(Z):""} new message${a(Z)===1?"":"s"}`.replace(/ +/g," ")]),V("click",F,Ve),V("click",Ie,rn),L(M,H)};oe(Wr,M=>{!n()&&e.messages.length>0&&a(Z)>0&&M($e)})}te(()=>Zt=lt(pt,1,"messages",null,Zt,{"is-revealing":n()||!a(ce)&&e.messages.length>0})),V("pointerdown",pt,function(...M){e.onActivateMessageComposer?.apply(this,M)}),V("pointerup",pt,function(...M){e.onInlineImagePointerUp?.apply(this,M)}),L(t,pt),He()}Qe(["pointerdown","pointerup","click"]);const qp=6500;var Up=z('
');function zp(t,e){Fe(e,!0);let n=le(()=>e.entries.filter(f=>f.userID!==e.currentUserID));function r(f,d="Someone"){return f?.display_name?.trim()||(f?.handle?`@${f.handle}`:d)}let i=le(()=>a(n).length===0?"":a(n).length===1?`${r(a(n)[0].user)} is typing…`:a(n).length===2?`${r(a(n)[0].user)} and ${r(a(n)[1].user)} are typing…`:a(n).length===3?`${r(a(n)[0].user)}, ${r(a(n)[1].user)}, and ${r(a(n)[2].user)} are typing…`:"Several people are typing…");var s=Up();let o;var u=S(b(s),2),l=b(u);te(()=>{o=lt(s,1,"typing-indicator",null,o,{visible:a(n).length>0}),ee(l,a(i))}),L(t,s),He()}var Bp=z('

'),Fp=z('');function Hp(t,e){Fe(e,!0);var n=Fp(),r=b(n),i=S(r,2),s=b(i),o=S(b(s),2),u=S(s,2),l=b(u),f=S(b(l),2),d=S(l,2);{var p=y=>{var x=Bp(),k=b(x);te(()=>ee(k,e.status)),L(y,x)};oe(d,y=>{e.status&&y(p)})}var m=S(d,2),w=b(m);te(()=>On(f,e.channelName)),V("click",r,function(...y){e.onClose?.apply(this,y)}),V("click",o,function(...y){e.onClose?.apply(this,y)}),dn("submit",u,y=>{y.preventDefault(),e.onCreate()}),V("input",f,y=>e.onChannelName(y.currentTarget.value)),V("click",w,function(...y){e.onClose?.apply(this,y)}),L(t,n),He()}Qe(["click","input"]);var Wp=z(''),Gp=z('
No matching people yet
'),jp=z('');function Vp(t,e){Fe(e,!0);let n=le(()=>e.memberID.trim().toLowerCase()),r=le(()=>e.people.filter(A=>A.id!==e.currentUserID).filter(A=>a(n)?A.display_name.toLowerCase().includes(a(n))||A.handle?.toLowerCase().includes(a(n))||A.id.toLowerCase().includes(a(n)):!0));var i=jp(),s=b(i),o=S(s,2),u=b(o),l=S(b(u),2),f=S(u,2),d=b(f),p=S(b(d),2),m=S(d,2),w=b(m);Wt(w,17,()=>a(r),A=>A.id,(A,E)=>{var I=Wp(),D=b(I);Pn(D,{class:"dm-avatar",get id(){return a(E).id},get name(){return a(E).display_name},get src(){return a(E).avatar_url},size:32});var C=S(D,2),U=b(C),P=b(U),G=S(U,2),K=b(G);te(Z=>{ee(P,a(E).display_name),ee(K,Z)},[()=>Kn(a(E).handle)||a(E).id]),V("click",I,()=>e.onStart(a(E).id)),L(A,I)});var y=S(w,2);{var x=A=>{var E=Gp();L(A,E)};oe(y,A=>{a(r).length===0&&A(x)})}var k=S(m,2),g=b(k);te(()=>On(p,e.memberID)),V("click",s,function(...A){e.onClose?.apply(this,A)}),V("click",l,function(...A){e.onClose?.apply(this,A)}),dn("submit",f,A=>{A.preventDefault(),e.onStart(e.memberID)}),V("input",p,A=>e.onMemberID(A.currentTarget.value)),V("click",g,function(...A){e.onClose?.apply(this,A)}),L(t,i),He()}Qe(["click","input"]);var Kp=z('
'),Yp=z('
'),Zp=z('');function Xp(t,e){Fe(e,!0);var n=Zp(),r=S(b(n),4),i=b(r);Wt(i,17,()=>e.workspaces,l=>l.id,(l,f)=>{var d=Kp();let p;var m=b(d),w=b(m),y=b(w);te(x=>{p=lt(d,1,"guild-wrap",null,p,{active:a(f).id===e.selectedWorkspaceID}),X(m,"title",a(f).name),ee(y,x)},[()=>Ud(a(f).name)]),V("click",m,()=>e.onSelectWorkspace(a(f).id)),L(l,d)});var s=S(i,2),o=S(r,2);{var u=l=>{var f=Yp(),d=b(f);te(()=>On(d,e.workspaceName)),dn("submit",f,p=>{p.preventDefault(),e.onCreateWorkspace()}),V("input",d,p=>e.onWorkspaceName(p.currentTarget.value)),L(l,f)};oe(o,l=>{e.showWorkspaceCreate&&l(u)})}V("click",s,function(...l){e.onToggleWorkspaceCreate?.apply(this,l)}),L(t,n),He()}Qe(["click","input"]);var Qp=z(' '),Jp=z(''),$p=z(''),eg=z('');function tg(t,e){Fe(e,!0);var n=eg(),r=b(n),i=S(b(r),4),s=S(r,2),o=b(s);Wt(o,17,()=>e.channels,f=>f.id,(f,d)=>{const p=le(()=>a(d).unread_count||0);var m=Jp();let w;var y=S(b(m),2),x=b(y),k=S(y,2);{var g=A=>{var E=Qp(),I=b(E);te(()=>{X(E,"aria-label",`${a(p)} unread`),ee(I,a(p)>99?"99+":a(p))}),L(A,E)};oe(k,A=>{a(p)>0&&!(a(d).id===e.selectedChannelID&&!e.selectedDirectID)&&A(g)})}te(()=>{w=lt(m,1,"nav-item channel",null,w,{active:a(d).id===e.selectedChannelID&&!e.selectedDirectID,"has-unread":a(p)>0&&!(a(d).id===e.selectedChannelID&&!e.selectedDirectID)}),ee(x,a(d).name)}),V("click",m,()=>e.onSelectChannel(a(d).id)),L(f,m)});var u=S(o,2);{var l=f=>{var d=$p();L(f,d)};oe(u,f=>{e.channels.length===0&&f(l)})}V("click",i,function(...f){e.onCreateChannel?.apply(this,f)}),L(t,n),He()}Qe(["click"]);var ng=z(' '),rg=z(''),ag=z(''),ig=z(''),sg=z('');function og(t,e){Fe(e,!0);var n=sg(),r=b(n),i=S(b(r),4),s=S(r,2),o=b(s);Wt(o,17,()=>e.conversations,f=>f.id,(f,d)=>{const p=le(()=>Bd(a(d),e.currentUserID)),m=le(()=>a(d).unread_count||0),w=le(()=>a(d).id===e.selectedDirectID);var y=ag();let x;var k=b(y);{let C=le(()=>a(p)?.id||a(d).id),U=le(()=>a(p)?.display_name),P=le(()=>a(p)?.avatar_url);Pn(k,{class:"dm-avatar",get id(){return a(C)},get name(){return a(U)},get src(){return a(P)},size:22})}var g=S(k,2),A=b(g),E=S(g,2);{var I=C=>{var U=ng(),P=b(U);te(()=>{X(U,"aria-label",`${a(m)} unread`),ee(P,a(m)>99?"99+":a(m))}),L(C,U)},D=C=>{var U=rg();L(C,U)};oe(E,C=>{a(m)>0&&!a(w)?C(I):C(D,-1)})}te(C=>{x=lt(y,1,"nav-item dm",null,x,{active:a(w),"has-unread":a(m)>0&&!a(w)}),ee(A,C)},[()=>da(a(d),e.currentUserID)]),V("click",y,()=>e.onSelectDirect(a(d).id)),L(f,y)});var u=S(o,2);{var l=f=>{var d=ig();L(f,d)};oe(u,f=>{e.conversations.length===0&&f(l)})}V("click",i,function(...f){e.onCreateDirect?.apply(this,f)}),L(t,n),He()}Qe(["click"]);var lg=z(''),cg=z(''),ug=z(''),dg=z('');function fg(t,e){Fe(e,!0);var n=dg(),r=b(n),i=b(r),s=b(i),o=b(s),u=S(s,2);let l;var f=b(u),d=S(i,2),p=b(d),m=b(p),w=S(r,2),y=b(w);tg(y,{get channels(){return e.channels},get selectedChannelID(){return e.selectedChannelID},get selectedDirectID(){return e.selectedDirectID},get onSelectChannel(){return e.onSelectChannel},get onCreateChannel(){return e.onCreateChannel}});var x=S(y,2);{let U=le(()=>e.currentUser?.id);og(x,{get conversations(){return e.directConversations},get currentUserID(){return a(U)},get selectedDirectID(){return e.selectedDirectID},get onSelectDirect(){return e.onSelectDirect},get onCreateDirect(){return e.onCreateDirect}})}var k=S(x,2),g=S(b(k),2),A=b(g);Wt(A,17,()=>e.recentPeople,U=>U.id,(U,P)=>{const G=le(()=>Hd(e.directConversations,a(P).id));var K=lg();let Z;var Y=b(K);Pn(Y,{class:"dm-avatar",get id(){return a(P).id},get name(){return a(P).display_name},get src(){return a(P).avatar_url},size:22});var O=S(Y,2),W=b(O);te(()=>{Z=lt(K,1,"nav-item dm",null,Z,{active:a(G)?.id===e.selectedDirectID||e.selectedProfile?.id===a(P).id}),ee(W,a(P).display_name)}),V("click",K,()=>{a(G)?e.onSelectDirect(a(G).id):e.onOpenProfile(a(P))}),L(U,K)});var E=S(A,2);{var I=U=>{var P=cg();L(U,P)};oe(E,U=>{e.recentPeople.length===0&&U(I)})}var D=S(w,2);{var C=U=>{var P=ug(),G=b(P);Pn(G,{class:"dm-avatar",get id(){return e.currentUser.id},get name(){return e.currentUser.display_name},get src(){return e.currentUser.avatar_url},size:28,loading:"eager",fetchPriority:"auto"});var K=S(G,2),Z=b(K),Y=b(Z),O=S(Z,2),W=b(O);te((J,fe)=>{X(P,"aria-label",J),ee(Y,e.currentUser.display_name),ee(W,fe)},[()=>`Account settings for ${e.currentUser.display_name} ${Kn(e.currentUser.handle)}`,()=>e.currentUser.handle?Kn(e.currentUser.handle):e.connected?"Active":"Reconnecting…"]),V("click",P,function(...J){e.onOpenSettings?.apply(this,J)}),V("contextmenu",P,J=>{J.preventDefault(),e.onOpenSettings()}),L(U,P)};oe(D,U=>{e.currentUser&&U(C)})}te(()=>{ee(o,e.workspaceName||"Pick a workspace"),l=lt(u,1,"presence",null,l,{online:e.connected}),ee(f,e.connected?"Connected":e.status),X(d,"aria-label",e.sidebarCollapsed?"Expand sidebar":"Collapse sidebar"),X(d,"title",e.sidebarCollapsed?"Expand sidebar":"Collapse sidebar"),X(m,"d",e.sidebarCollapsed?"m9 6 6 6-6 6":"m15 6-6 6 6 6")}),V("click",d,function(...U){e.onToggleCollapse?.apply(this,U)}),L(t,n),He()}Qe(["click","contextmenu"]);var hg=z(' '),pg=z(" "),gg=z(''),vg=z(''),mg=z(''),_g=z('
User kind
'),bg=z('

Profile

Active
Contact information
Handle
User ID
About

',1);function wg(t,e){Fe(e,!0);const n=le(()=>e.profile.kind==="bot"?e.profile.owner_user_id?`Bot of ${e.profile.owner_user_id}`:"Service bot":"");var r=bg(),i=Gt(r),s=b(i),o=S(b(s),2),u=b(o),l=S(s,2),f=S(i,2),d=b(f),p=b(d);Pn(p,{class:"profile-avatar",get id(){return e.profile.id},get name(){return e.profile.display_name},get src(){return e.profile.avatar_url},size:240,loading:"eager",fetchPriority:"auto"});var m=S(d,2),w=b(m),y=b(w),x=b(y),k=b(x),g=S(x,2);{var A=se=>{var be=hg(),Se=b(be);te(()=>ee(Se,a(n))),L(se,be)};oe(g,se=>{a(n)&&se(A)})}var E=S(g,2);{var I=se=>{var be=pg(),Se=b(be);te(nt=>ee(Se,nt),[()=>Kn(e.profile.handle)]),L(se,be)};oe(E,se=>{e.profile.handle&&se(I)})}var D=S(y,2);{var C=se=>{var be=gg();V("click",be,function(...Se){e.onEdit?.apply(this,Se)}),L(se,be)};oe(D,se=>{e.currentUser?.id===e.profile.id&&se(C)})}var U=S(w,4),P=b(U);{var G=se=>{var be=vg();V("click",be,()=>e.onMessage(e.profile.id)),L(se,be)};oe(P,se=>{e.currentUser?.id!==e.profile.id&&se(G)})}var K=S(P,2),Z=S(U,2),Y=b(Z),O=S(b(Y),2);{var W=se=>{var be=mg();V("click",be,function(...Se){e.onEdit?.apply(this,Se)}),L(se,be)};oe(O,se=>{e.currentUser?.id===e.profile.id&&se(W)})}var J=S(Y,2),fe=S(b(J),2),ie=S(b(fe),2),B=b(ie),ae=S(J,2),ce=S(b(ae),2),$=S(b(ce),2),Ae=b($),ge=S(ae,2);{var De=se=>{var be=_g(),Se=S(b(be),2),nt=S(b(Se),2),bt=b(nt);te(()=>ee(bt,a(n))),L(se,be)};oe(ge,se=>{e.profile.kind==="bot"&&se(De)})}var _e=S(Z,2),Ue=S(b(_e),2),Je=b(Ue);te((se,be)=>{ee(u,e.profile.display_name),wr(d,`--hue: ${se??""}deg`),ee(k,e.profile.display_name),ee(B,be),ee(Ae,e.profile.id),ee(Je,`Member of ${(e.workspaceName||"this workspace")??""}. Click Message to keep the conversation in your sidebar.`)},[()=>Cl(e.profile.id),()=>e.profile.handle?Kn(e.profile.handle):"No handle set"]),V("click",l,function(...se){e.onClose?.apply(this,se)}),V("click",K,function(...se){e.onSetStatus?.apply(this,se)}),L(t,r),He()}Qe(["click"]);var yg=z("

"),kg=z('');function Sg(t,e){Fe(e,!0);var n=kg(),r=b(n),i=S(r,2),s=b(i),o=S(b(s),2),u=S(s,2),l=b(u),f=b(l);Pn(f,{class:"avatar large",get id(){return e.user.id},get name(){return e.displayName},get src(){return e.avatarURL},size:56,loading:"eager",fetchPriority:"auto"});var d=S(f,2),p=b(d),m=b(p),w=S(p,2),y=b(w),x=S(l,2),k=S(b(x),2),g=S(x,2),A=S(b(g),2),E=S(g,2),I=S(b(E),2),D=S(E,2),C=b(D),U=S(D,2),P=S(b(U),2),G=S(U,2);{var K=O=>{var W=yg();let J;var fe=b(W);te(()=>{J=lt(W,1,"profile-status",null,J,{error:e.statusError}),ee(fe,e.status)}),L(O,W)};oe(G,O=>{e.status&&O(K)})}var Z=S(G,2),Y=b(Z);te(O=>{ee(m,e.displayName||e.user.display_name),ee(y,O),On(k,e.displayName),On(A,e.handle),On(I,e.avatarURL),xd(C,e.pushoverEnabled),On(P,e.pushoverUserKey)},[()=>e.handle||Kn(e.user.handle)||"No handle set"]),V("click",r,function(...O){e.onClose?.apply(this,O)}),V("click",o,function(...O){e.onClose?.apply(this,O)}),dn("submit",u,O=>{O.preventDefault(),e.onSave()}),V("input",k,O=>e.onDisplayName(O.currentTarget.value)),V("input",A,O=>e.onHandle(O.currentTarget.value)),V("input",I,O=>e.onAvatarURL(O.currentTarget.value)),V("change",C,O=>e.onPushoverEnabled(O.currentTarget.checked)),V("input",P,O=>e.onPushoverUserKey(O.currentTarget.value)),V("click",Y,function(...O){e.onClose?.apply(this,O)}),L(t,n),He()}Qe(["click","input","change"]);var Tg=z(''),xg=z('
');function Eg(t,e){Fe(e,!0);var n=Sn(),r=Gt(n);{var i=s=>{var o=xg(),u=b(o),l=b(u),f=b(l),d=S(l,2),p=S(u,2);Wt(p,17,()=>e.results,m=>m.message.id,(m,w)=>{var y=Tg(),x=b(y);{let P=le(()=>a(w).message.author?.id||a(w).message.author_id),G=le(()=>a(w).message.author?.display_name),K=le(()=>a(w).message.author?.avatar_url);Pn(x,{class:"dm-avatar",get id(){return a(P)},get name(){return a(G)},get src(){return a(K)},size:30})}var k=S(x,2),g=b(k),A=b(g),E=b(A),I=S(A,2),D=b(I),C=S(g,2),U=b(C);te(P=>{ee(E,a(w).message.author?.display_name||"Local User"),ee(D,P),ee(U,a(w).message.body)},[()=>ha(a(w).message.created_at)]),V("click",y,()=>e.onOpenResult(a(w))),L(m,y)}),te(()=>ee(f,`${e.results.length??""} ${e.results.length===1?"result":"results"}`)),V("click",d,function(...m){e.onClose?.apply(this,m)}),L(s,o)};oe(r,s=>{e.results.length>0&&s(i)})}L(t,n),He()}Qe(["click"]);var Ag=z('
No thread open Hover any message and tap the bubble to keep side conversations tidy.
');function Ig(t){var e=Ag();L(t,e)}var Rg=z(" "),Cg=z('
'),Dg=z(" "),Mg=z('
'),Og=z('
'),Lg=z('

Thread

',1);function Pg(t,e){Fe(e,!0);var n=Lg(),r=Gt(n),i=b(r),s=S(b(i),2),o=b(s),u=S(i,2),l=S(r,2),f=b(l),d=b(f);{let Y=le(()=>e.root.author?.id||e.root.author_id),O=le(()=>e.root.author?.display_name),W=le(()=>e.root.author?.avatar_url);Pn(d,{class:"avatar",get id(){return a(Y)},get name(){return a(O)},get src(){return a(W)},size:38})}var p=S(d,2),m=b(p),w=b(m),y=b(w),x=S(w,2);{var k=Y=>{var O=Rg(),W=b(O);te(J=>ee(W,J),[()=>Kn(e.root.author.handle)]),L(Y,O)};oe(x,Y=>{e.root.author?.handle&&Y(k)})}var g=S(x,2),A=b(g),E=S(g,2),I=S(m,2);Ci(I,()=>Fi(e.root.body),!0);var D=S(I,2);{var C=Y=>{var O=Cg();Wt(O,21,()=>e.root.attachments,W=>W.id,(W,J)=>{{let fe=le(()=>Fa(a(J)));Hi(W,{get upload(){return a(J)},get url(){return a(fe)},get onOpenImage(){return e.onOpenImage}})}}),L(Y,O)};oe(D,Y=>{e.root.attachments?.length&&Y(C)})}var U=S(f,2),P=b(U),G=b(P),K=S(U,2);Wt(K,21,()=>e.replies,Y=>Y.id,(Y,O)=>{var W=Og(),J=b(W);{let be=le(()=>a(O).author?.id||a(O).author_id),Se=le(()=>a(O).author?.display_name),nt=le(()=>a(O).author?.avatar_url);Pn(J,{class:"avatar small",get id(){return a(be)},get name(){return a(Se)},get src(){return a(nt)},size:30})}var fe=S(J,2),ie=b(fe),B=b(ie),ae=b(B),ce=S(B,2);{var $=be=>{var Se=Dg(),nt=b(Se);te(bt=>ee(nt,bt),[()=>Kn(a(O).author.handle)]),L(be,Se)};oe(ce,be=>{a(O).author?.handle&&be($)})}var Ae=S(ce,2),ge=b(Ae),De=S(Ae,2),_e=S(ie,2);$l(_e,{get message(){return a(O)},get onJump(){return e.onJumpToQuote}});var Ue=S(_e,2);Ci(Ue,()=>Fi(a(O).body),!0);var Je=S(Ue,2);{var se=be=>{var Se=Mg();Wt(Se,21,()=>a(O).attachments,nt=>nt.id,(nt,bt)=>{{let wt=le(()=>Fa(a(bt)));Hi(nt,{get upload(){return a(bt)},get url(){return a(wt)},get onOpenImage(){return e.onOpenImage}})}}),L(be,Se)};oe(Je,be=>{a(O).attachments?.length&&be(se)})}te(be=>{X(W,"data-message-id",a(O).id),ee(ae,a(O).author?.display_name||"Local User"),ee(ge,be)},[()=>ha(a(O).created_at)]),V("click",De,()=>e.onSetReplyTarget(a(O),"thread")),L(Y,W)});var Z=S(l,2);Ml(Z,{get value(){return e.replyBody},placeholder:"Reply in thread",ariaLabel:"Reply body",submitLabel:"Reply",formClass:"composer reply-composer",get replyTarget(){return e.replyTarget},get onValue(){return e.onReplyBody},get onSubmit(){return e.onSubmitReply},get onKeydown(){return e.onReplyKeydown},get onFocus(){return e.onReplyFocus},get onInputRef(){return e.onReplyInputRef},get onClearReply(){return e.onClearReply}}),te(Y=>{ee(o,`${e.threadState?.reply_count??e.replies.length??""} ${(e.threadState?.reply_count??e.replies.length)===1?"reply":"replies"}`),X(f,"data-message-id",e.root.id),ee(y,e.root.author?.display_name||"Local User"),ee(A,Y),ee(G,`${e.replies.length??""} ${e.replies.length===1?"reply":"replies"}`)},[()=>ha(e.root.created_at)]),V("click",u,function(...Y){e.onClose?.apply(this,Y)}),V("pointerdown",l,function(...Y){e.onActivateThreadComposer?.apply(this,Y)}),V("pointerup",l,function(...Y){e.onInlineImagePointerUp?.apply(this,Y)}),V("click",E,()=>e.onSetReplyTarget(e.root,"thread")),L(t,n),He()}Qe(["click","pointerdown","pointerup"]);var Ng=z('

'),qg=z('

'),Ug=z('

ClickClack

'),zg=z(''),Bg=z('

');function Fg(t,e){Fe(e,!0);var n=Bg(),r=b(n),i=b(r);{var s=A=>{var E=Ng(),I=b(E);te(D=>ee(I,D),[()=>`@${da(e.selectedDirect,e.currentUserID)}`]),L(A,E)},o=A=>{var E=qg(),I=b(E);te(()=>ee(I,`#${e.selectedChannel.name}`)),L(A,E)},u=A=>{var E=Ug();L(A,E)};oe(i,A=>{e.selectedDirect?A(s):e.selectedChannel?A(o,1):A(u,-1)})}var l=S(i,4),f=b(l),d=S(r,2),p=S(b(d),2),m=S(p,2);{var w=A=>{var E=zg();V("click",E,function(...I){e.onResetSearch?.apply(this,I)}),L(A,E)};oe(m,A=>{e.searchQuery&&A(w)})}var y=S(d,2),x=b(y);let k;var g=S(x,2);te(()=>{ee(f,e.workspaceName||"no workspace"),On(p,e.searchQuery),X(x,"title",e.threadOpen?"Close thread":"Open a message thread"),X(x,"aria-label",e.threadOpen?"Close thread":"Open a message thread"),k=lt(x,1,"",null,k,{active:e.sidePanelOpen})}),dn("submit",d,A=>{A.preventDefault(),e.onSearch()}),V("input",p,A=>e.onSearchQuery(A.currentTarget.value)),V("click",x,function(...A){e.onToggleThread?.apply(this,A)}),V("click",g,function(...A){e.onPinnedItems?.apply(this,A)}),L(t,n),He()}Qe(["input","click"]);var Hg=z(''),Wg=z(`
cc
ClickClack OpenClaw workspace chat

Welcome back.

Workspace chat for the OpenClaw crew. Sign in with the GitHub account that's a member of the org.

Limited to active members of the OpenClaw org.

`),Gg=z(''),jg=z(''),Vg=z('
',1);function Kg(t,e){Fe(e,!1);const n=Q(),r=Q(),i=Q(),s=Q(),o=Q(),u=Q(),l=Q(),f=Q(),d=Q(),p=Q(),m=Q();let w=Q(null),y=Q([]),x=Q([]),k=Q([]),g=Q([]),A=Q([]),E=Q(""),I=Q(""),D=Q(""),C=Q(null),U=Q(null),P=Q(null),G=Q(null),K=Q(""),Z=Q(""),Y=Q(""),O=Q(""),W=Q(""),J=Q(""),fe=Q([]),ie=Q(null),B=Q(!1),ae=Q(!1),ce=Q(!1),$=Q(!1),Ae=Q(""),ge=Q(""),De=Q(""),_e=Q(""),Ue=Q(!1),Je=Q(""),se=Q(""),be=Q(!1),Se=Q("loading"),nt=Q(!1),bt=Q(!1),wt=null,rt=Q(null),at=new Map,Pe=Q(new Map),en=new Set,ft=Q("idle"),Ct="idle",Vt=!1,Kt=!1,xn=Q(!1),En=Q(!1),Nn=Q(!1),rn=Q(!1),Ge=new Map,ht=0,Yt=Q(""),rr=Q(void 0),Pt=Q(""),Nt=Q(!0),qn=Q(!1),an=Q(!1),Ve=Q(!1),ke=Q(null),Ke=Q(null),An=Q(null),In=Q(null),yt=Q("message"),pt=Q([]),Zt;is(()=>{xr()}),Ya(()=>{wt?.close(),wt=null,v(bt,!1),Ca(),Zt&&window.clearInterval(Zt)});async function xr(){try{const c=await tt("/api/me");v(w,c.user),await Wr(),v(Se,"ready")}catch(c){if(c instanceof Il&&(c.status===401||c.status===403)){v(nt,!0),v(Se,"auth");return}v(Se,c instanceof Error?c.message:"Could not load ClickClack")}}function Rn(){a(w)&&(v(ge,a(w).display_name),v(De,a(w).handle?`@${a(w).handle}`:""),v(_e,a(w).avatar_url),v(Ue,a(w).notification_settings?.pushover_enabled??!1),v(Je,a(w).notification_settings?.pushover_user_key??""),v(se,""),v(be,!1),v(ae,!0))}async function Hr(){v(se,""),v(be,!1);try{const c=await tt("/api/me",{method:"PATCH",body:JSON.stringify({display_name:a(ge),handle:a(De),avatar_url:a(_e),notification_settings:{pushover_enabled:a(Ue),pushover_user_key:a(Je)}})});v(w,c.user),Un(a(g).map(h=>h.author?.id===a(w)?.id?{...h,author:c.user}:h)),v(A,a(A).map(h=>h.author?.id===a(w)?.id?{...h,author:c.user}:h)),a(C)?.author?.id===a(w).id&&v(C,{...a(C),author:c.user}),v(se,"Saved"),v(ae,!1)}catch(c){v(se,c instanceof Error?c.message:"Could not save profile"),v(be,!0)}}async function Wr(){const c=await tt("/api/workspaces");v(y,c.workspaces),v(E,a(E)||a(y)[0]?.id||""),await H(),await ni(),a(y).length===0&&v(Se,"create a workspace"),ri()}async function $e(){if(!a(Y).trim())return;const c=await tt("/api/workspaces",{method:"POST",body:JSON.stringify({name:a(Y)})});v(Y,""),v(qn,!1),v(y,[...a(y),c.workspace]),v(E,c.workspace.id),v(Ve,!1),await H(),await ni(),ri()}async function M(c){v(E,c),v(Ve,!1),await H(),await ni(),ri()}async function H(){if(!a(E))return;const c=await tt(`/api/workspaces/${a(E)}/channels`);v(x,c.channels),v(I,a(x).find(h=>h.id===a(I))?.id||a(x)[0]?.id||""),v(C,null),v(P,null),v(yt,"message"),v(A,[]),await ue()}async function j(){if(!a(E)||!a(O).trim())return;const c=await tt(`/api/workspaces/${a(E)}/channels`,{method:"POST",body:JSON.stringify({name:a(O),kind:"public"})});v(O,""),v(x,[...a(x),c.channel]),v(I,c.channel.id),v(D,""),v(ce,!1),await ue()}async function F(c){v(I,c),v(D,""),v(C,null),v(P,null),v(yt,"message"),v(Ve,!1),await ue()}async function ue(){ws();const c=ve();c!==a(Yt)&&(hn(),v(Nt,!0));try{if(!a(D)&&!a(I)){St("",Dt({messages:[],oldest_seq:0,newest_seq:0,has_older:!1,has_newer:!1}),"replace");return}const T=await tt(Ye(Ie()));if(ve()!==c)return;St(c,Dt(T),"replace")}finally{ve()===c&&v(Nt,!1)}}async function me(){const c=ve();if(c){hn(),v(Nt,!0),at.set(c,{atBottom:!0});try{const h=await tt(Ye(`limit=${Ra}`));if(ve()!==c)return;St(c,Dt(h),"replace")}finally{ve()===c&&v(Nt,!1)}}}function Ie(){const c=Le(),h=c.unread_count||0,T=c.last_read_seq||0;return h>0?`around_seq=${encodeURIComponent(String(T+1))}&limit=${Ra}`:`limit=${Ra}`}function Le(){return a(D)?a(k).find(c=>c.id===a(D))||{}:a(I)?a(x).find(c=>c.id===a(I))||{}:{}}function Ye(c){const h=a(D)?`/api/dms/${a(D)}/messages`:`/api/channels/${a(I)}/messages`;return c?`${h}?${c}`:h}function Dt(c){return{messages:c.messages,oldest_seq:c.oldest_seq,newest_seq:c.newest_seq,has_older:c.has_older,has_newer:c.has_newer}}function St(c,h,T){const R=de(c,h.messages,T),q=R[0]?.channel_seq||0,pe=R[R.length-1]?.channel_seq||0,Te=q>(h.messages[0]?.channel_seq||q),ze=pe<(h.messages[h.messages.length-1]?.channel_seq||pe),Ze={messages:R,oldest_seq:q,newest_seq:pe,has_older:h.has_older||Te,has_newer:h.has_newer||ze};We(c,Ze),Yn(c,Ze),sc(c,R)}function We(c,h){c&&(a(Pe).delete(c),a(Pe).set(c,h),gt(c),qt(c),v(Pe,new Map(a(Pe))))}function gt(c){let h=a(Pe).size+1;for(;a(Pe).size>Ld&&h>0;){h--;const T=a(Pe).keys().next().value;if(!T)return;if(T===c){const R=a(Pe).get(T);a(Pe).delete(T),R&&a(Pe).set(T,R);continue}a(Pe).delete(T)}}function qt(c){let h=at.size+1;for(;at.size>Pd&&h>0;){h--;const T=at.keys().next().value;if(!T)return;if(T===c){const R=at.get(T);at.delete(T),R&&at.set(T,R);continue}at.delete(T)}}function Yn(c,h=a(Pe).get(c)){c===ve()&&(v(xn,h?.has_older||!1),v(En,h?.has_newer||!1))}function Tt(c){const h=a(Pe).get(c);!c||!h||(We(c,{...h,has_newer:!0}),Yn(c))}function xt(c,h){c==="older"?(v(ft,h),v(Nn,h==="loading")):(Ct=h,v(rn,h==="loading"))}function hn(){en=new Set,v(ft,"idle"),Ct="idle",Vt=!1,Kt=!1,v(Nn,!1),v(rn,!1)}function ar(c,h){const T=new Map;for(const R of[...c,...h])T.set(R.id,R);return[...T.values()].sort((R,q)=>(R.channel_seq||0)-(q.channel_seq||0))}function ya(c){const h=new Set,T=tc(c);if(T>=0){const q=Qa(c,a(g),T);q&&h.add(q.id)}const R=at.get(c)?.anchorMessageID;R&&h.add(R),a(C)&&zn(a(C),c)&&h.add(a(C).id),a(ke)&&zn(a(ke),c)&&h.add(a(ke).id);for(const q of a(g))(q.status==="pending"||q.status==="failed")&&zn(q,c)&&h.add(q.id);return h}function de(c,h,T){return Nd(h,T,ya(c))}function _(){if(a(ft)!=="idle"){Vt=!0;return}ne()}function N(){if(Ct!=="idle"){Kt=!0;return}Ne()}async function ne(){const c=ve(),h=a(Pe).get(c),T=`${c}:older`;if(a(ft)!=="idle"){Vt=!0;return}if(!c||!h?.has_older||h.oldest_seq<=0||en.has(T))return;en.add(T),Vt=!1,xt("older","loading"),ws();let R=!1;try{const q=await tt(Ye(`before_seq=${encodeURIComponent(String(h.oldest_seq))}&limit=${Mi}`));if(ve()!==c)return;const pe=ar(q.messages,a(g));St(c,{messages:pe,oldest_seq:q.oldest_seq||h.oldest_seq,newest_seq:h.newest_seq,has_older:q.has_older,has_newer:h.has_newer},"prepend"),R=!0,xt("older","settling")}catch(q){ve()===c&&v(Se,q instanceof Error?q.message:"Could not load older messages")}finally{en.delete(T),ve()===c&&!R&&xt("older","idle")}}async function Ne(){const c=ve(),h=a(Pe).get(c),T=`${c}:newer`;if(Ct!=="idle"){Kt=!0;return}if(!c||en.has(T))return;if(!h||h.newest_seq<=0){await ue();return}en.add(T),Kt=!1,xt("newer","loading");let R=!1;try{const q=await tt(Ye(`after_seq=${encodeURIComponent(String(h.newest_seq))}&limit=${Mi}`));if(ve()!==c)return;if(q.messages.length===0){St(c,{...h,has_newer:q.has_newer},"append"),R=!0,xt("newer","settling");return}const pe=ar(a(g),q.messages);St(c,{messages:pe,oldest_seq:h.oldest_seq,newest_seq:q.newest_seq||h.newest_seq,has_older:h.has_older,has_newer:q.has_newer},"append"),R=!0,xt("newer","settling")}catch(q){ve()===c&&v(Se,q instanceof Error?q.message:"Could not load newer messages")}finally{en.delete(T),ve()===c&&!R&&xt("newer","idle")}}function kt(c){const h=a(ft)==="settling"&&Vt&&c.nearOlder&&a(xn),T=Ct==="settling"&&Kt&&c.nearNewer&&a(En);a(ft)==="settling"&&xt("older","idle"),Ct==="settling"&&xt("newer","idle"),Vt=!1,Kt=!1,h&&_(),T&&N()}function ve(){return a(D)||a(I)||""}function Et(c,h=a(g)){let T=0;for(const R of h)R.channel_id===c&&(R.parent_message_id||typeof R.channel_seq=="number"&&R.channel_seq>T&&(T=R.channel_seq));return T}function Ut(c,h=a(g)){let T=0;for(const R of h)R.direct_conversation_id===c&&typeof R.channel_seq=="number"&&R.channel_seq>T&&(T=R.channel_seq);return T}function Mt(c,h){return c&&h.unread_count||0}async function Gr(c,h){const T=a(x).find(R=>R.id===c);if(T&&!(h<=0||h<=(T.last_read_seq||0))){v(x,a(x).map(R=>R.id===c?{...R,last_seq:Math.max(R.last_seq||0,h),unread_count:Math.max(0,Math.max(R.last_seq||0,h)-h),last_read_seq:h}:R));try{await tt(`/api/channels/${c}/read`,{method:"POST",body:JSON.stringify({seq:h})})}catch{}}}async function ct(c,h){const T=a(k).find(R=>R.id===c);if(T&&!(h<=0||h<=(T.last_read_seq||0))){v(k,a(k).map(R=>R.id===c?{...R,last_seq:Math.max(R.last_seq||0,h),unread_count:Math.max(0,Math.max(R.last_seq||0,h)-h),last_read_seq:h}:R));try{await tt(`/api/dms/${c}/read`,{method:"POST",body:JSON.stringify({seq:h})})}catch{}}}function ka(c){const h=a(Pe).get(c)?.newest_seq||0,T=a(x).find(q=>q.id===c);if(T)return Math.max(T.last_seq||0,(T.last_read_seq||0)+(T.unread_count||0),Et(c),h);const R=a(k).find(q=>q.id===c);return R?Math.max(R.last_seq||0,(R.last_read_seq||0)+(R.unread_count||0),Ut(c),h):0}function Sa(c){const h=a(Pe).get(c);return!h||h.has_newer?0:a(x).find(q=>q.id===c)?Et(c):a(k).find(q=>q.id===c)?Ut(c):0}function Ta(c={}){if(!c.all&&Date.now()q.id===h)){ct(h,T),c.all&&vs(h,T);return}a(x).some(q=>q.id===h)&&(Gr(h,T),c.all&&vs(h,T))}function vs(c,h){Ge.delete(c),Ge=new Map(Ge),v(x,a(x).map(T=>T.id===c?{...T,last_seq:Math.max(T.last_seq||0,h),last_read_seq:Math.max(T.last_read_seq||0,h),unread_count:0}:T)),v(k,a(k).map(T=>T.id===c?{...T,last_seq:Math.max(T.last_seq||0,h),last_read_seq:Math.max(T.last_read_seq||0,h),unread_count:0}:T))}function ec(c){const h=a(x).find(R=>R.id===c);return h?h.last_read_seq||0:a(k).find(R=>R.id===c)?.last_read_seq||0}function tc(c){const h=a(x).find(R=>R.id===c);if(h)return Mt(c,h)>0?h.last_read_seq||0:-1;const T=a(k).find(R=>R.id===c);return T&&Mt(c,T)>0?T.last_read_seq||0:-1}function Qa(c,h,T){for(const R of h){if(!zn(R,c)||R.parent_message_id||R.author?.id===a(w)?.id||R.author_id===a(w)?.id)continue;const q=R.channel_seq;if(typeof q=="number"&&q>T)return R}return null}function nc(c,h){if(!c)return;const T=ac(c);if(Mt(c,T)<=0){Ge.delete(c),Ge=new Map(Ge);return}const q=T.last_read_seq||0,pe=Ge.get(c);if(pe?.boundarySeq===q&&pe.since||!Ja(c,q))return;const Te=Qa(c,h,q);Te&&(Ge=new Map(Ge).set(c,{boundarySeq:q,since:$a(Te.created_at)}))}function ms(c,h,T){if(!c||!T)return;const R=Ge.get(c);R?.boundarySeq===h&&R.since||(Ge=new Map(Ge).set(c,{boundarySeq:h,since:$a(T)}))}function _s(c){const h=c.payload,T=c.seq??h.channel_seq??h.seq;return typeof T=="number"?T:Number(T)||0}function bs(c){const h=c.payload;return{channelID:c.channel_id||(typeof h.channel_id=="string"?h.channel_id:""),dmID:typeof h.direct_conversation_id=="string"?h.direct_conversation_id:""}}function rc(c){if(c.type!=="message.created")return!1;const h=_s(c);if(h<=0)return!1;const{channelID:T,dmID:R}=bs(c);if(T){const q=a(x).find(pe=>pe.id===T);return h<=(q?.last_seq||0)}if(R){const q=a(k).find(pe=>pe.id===R);return h<=(q?.last_seq||0)}return!1}function ac(c){return a(x).find(h=>h.id===c)||a(k).find(h=>h.id===c)||{}}function Ja(c,h,T=a(Pe)){if(!c||h<0)return!1;const R=T.get(c);if(!R||R.messages.length===0)return!1;const q=h+1;return R.oldest_seq<=q&&R.newest_seq>=q}function ic(c,h,T=a(Pe)){const R=Ge.get(c);if(R?.boundarySeq===h)return R.since;if(!Ja(c,h,T))return"";const q=Qa(c,a(g),h);return q?$a(q.created_at):""}function $a(c){const h=new Date(c);return Number.isNaN(h.getTime())?"":new Intl.DateTimeFormat(void 0,{hour:"numeric",minute:"2-digit"}).format(h)}function ws(){if(!a(Yt)||!a(rt))return;const c=a(rt).captureState();c&&at.set(a(Yt),c)}function sc(c,h){const T=c!==a(Yt);v(rr,at.get(c));const R=a(g).filter(re=>(re.status==="pending"||re.status==="failed")&&zn(re,c)),q=new Map(R.map(re=>[re.id,re])),pe=new Map(R.filter(re=>re.nonce).map(re=>[re.nonce,re])),Te=h.map(re=>{const xe=q.get(re.id)||(re.nonce?pe.get(re.nonce):void 0);return xe?re.nonce&&Er.has(re.nonce)?{...re,nonce:xe.nonce,status:xe.status,attachments:xe.attachments?.length?xe.attachments:re.attachments}:{...re,nonce:xe.nonce,attachments:xe.attachments?.length?xe.attachments:re.attachments}:re}),ze=new Set(Te.map(re=>re.id)),Ze=new Set(Te.map(re=>re.nonce).filter(Boolean)),it=a(g).filter(re=>(re.status==="pending"||re.status==="failed")&&re.id.startsWith("tmp_")&&!ze.has(re.id)&&!(re.nonce&&Ze.has(re.nonce))&&zn(re,c));v(g,it.length>0?[...Te,...it]:Te),v(Yt,c),nc(c,a(g)),T&&(v(pt,[]),Ca())}function Un(c,h="append"){const T=ve(),R=T?a(Pe).get(T):void 0;if(!T||!R){v(g,c);return}const q=c.filter(xe=>zn(xe,T)),pe=de(T,q,h),Te=pe.filter(xe=>(xe.channel_seq||0)>0),ze=Te[0]?.channel_seq||R.oldest_seq,Ze=Te[Te.length-1]?.channel_seq||R.newest_seq,it=xa(pe[0])>xa(q[0]),re=xa(pe[pe.length-1])0)&&await me(),await ei(),Ta({all:!0})}catch(c){v(Se,c instanceof Error?c.message:"Could not jump to latest messages")}}let Er=new Map;function lc(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID().replace(/-/g,""):`${Date.now().toString(36)}${Math.random().toString(36).slice(2,10)}`}function cc(c,h,T=`tmp_${c}`){const R=new Date().toISOString();return{id:T,workspace_id:h.workspaceID,channel_id:h.channelID,direct_conversation_id:h.directConversationID,author_id:a(w)?.id||"",thread_root_id:T,body:h.body,body_format:"markdown",created_at:R,author:a(w)||void 0,attachments:h.upload?[h.upload]:[],quoted_message_id:h.quotedMessageID,nonce:c,status:"pending"}}async function ys(){const c=a(K).trim();if(!c)return;if(!a(I)&&!a(D)){v(Se,"pick or create a channel");return}Ca();const h=a(D)?"dm":"channel",T=a(ke)&&a(Ke)===h?a(ke):null,R={body:c,quotedMessageID:T?.id,upload:a(ie)||void 0,workspaceID:a(E),channelID:a(I)||void 0,directConversationID:a(D)||void 0,viewKey:ve()};v(K,""),T&&pn(),v(ie,null),await ks(R)}async function ks(c,h,T){const R=h??lc(),q=`tmp_${R}`,pe=T??q;Er.set(R,c);const Te=cc(R,c,pe);if(h)Un(a(g).map(it=>it.id===pe?Te:it));else if(ve()===c.viewKey){const it=a(rt)?.isAtBottom()!==!1;Un([...a(g),Te]),it&&ei()}const ze=c.directConversationID?`/api/dms/${c.directConversationID}/messages`:`/api/channels/${c.channelID}/messages`,Ze={body:c.body,nonce:R};c.quotedMessageID&&(Ze.quoted_message_id=c.quotedMessageID);try{let re=(await tt(ze,{method:"POST",body:JSON.stringify(Ze)})).message;if(c.upload)try{await tt(`/api/messages/${re.id}/attachments`,{method:"POST",body:JSON.stringify({upload_id:c.upload.id})}),re={...re,attachments:[...re.attachments||[],c.upload]}}catch(et){console.warn("attachment failed",et);const Cn={...re,nonce:R,status:"failed",attachments:c.upload?[...re.attachments||[],c.upload]:re.attachments};Un(a(g).map(Bn=>Bn.id===pe?Cn:Bn));return}Er.delete(R),a(g).findIndex(et=>et.id===pe)>=0?Un(a(g).map(et=>et.id===pe?re:et)):a(g).some(et=>et.id===re.id)?Un(a(g).map(et=>et.id===re.id?re:et)):zn(re,ve())&&!a(g).some(et=>et.id===re.id)&&Un([...a(g),re])}catch(it){console.warn("send failed",it),Un(a(g).map(re=>re.id===pe?{...re,status:"failed"}:re))}}function uc(c){if(!c.nonce)return;const h=Er.get(c.nonce);if(!h){Ss(c);return}ks({...h,viewKey:h.viewKey},c.nonce,c.id)}function Ss(c){c.nonce&&Er.delete(c.nonce),Un(a(g).filter(h=>h.id!==c.id))}async function Ts(c){v(P,null),v(C,c),v(yt,"thread");const h=await tt(`/api/messages/${c.id}/thread`);v(C,h.root),v(A,h.replies),v(U,h.thread_state)}async function xs(){const c=a(Z).trim();if(!c||!a(C))return;const h=a(ke)&&a(Ke)==="thread"?a(ke):null;v(Z,"");const T={body:c};h&&(T.quoted_message_id=h.id);const R=await tt(`/api/messages/${a(C).id}/thread/replies`,{method:"POST",body:JSON.stringify(T)});h&&pn(),a(A).some(q=>q.id===R.message.id)||v(A,[...a(A),R.message]),v(U,R.thread_state)}function Es(c,h){v(ke,c),v(Ke,h),v(yt,h==="thread"?"thread":"message")}function As(){return a(G)!==null||a(ae)||a(ce)||a($)}function dc(){return a(yt)==="thread"&&a(C)&&a(In)?a(In):a(An)}function pn(){v(ke,null),v(Ke,null)}async function Is(c){const h=c.quoted_message_id;if(!h)return;if(a(rt)?.scrollToMessage(h)??!1){await Rs(h);return}const R=await tt(`/api/messages/${h}`);zn(R.message,ve())&&await ti(R.message)}async function fc(){ht=Date.now()+1200,!(a(l)&&a(rt)?.scrollToDivider(!1))&&await hc()}async function hc(){const c=ve();if(!c)return;ht=Date.now()+1200;const h=ec(c),T=Ge.get(c),q=(T?.boundarySeq===h?T.boundarySeq:h)+1;q<=0||(await Cs(q),await ur(),a(rt)?.scrollToDivider(!1))}async function Rs(c){await ur();const h=document.querySelector(`[data-message-id="${CSS.escape(c)}"]`);h&&(h.classList.add("highlight"),window.setTimeout(()=>h.classList.remove("highlight"),1500))}async function pc(){if(!a(E)||!a(J).trim()){v(fe,[]);return}const c=await tt(`/api/search?workspace_id=${encodeURIComponent(a(E))}&q=${encodeURIComponent(a(J).trim())}`);v(fe,c.results)}function gc(){v(J,""),v(fe,[])}async function vc(c){v(fe,[]),c.message.channel_id&&(v(I,c.message.channel_id),v(D,""),await ti(c.message)),c.message.direct_conversation_id&&(v(D,c.message.direct_conversation_id),v(I,""),await ti(c.message))}async function ti(c){const h=c.channel_seq||0;if(h<=0){await ue();return}await Cs(h,c.id)}async function Cs(c,h=""){const T=ve();if(!T)return;h&&at.set(T,{atBottom:!1,anchorMessageID:h,anchorPixelOffset:0}),T!==a(Yt)&&(hn(),v(Nt,!0));try{const q=await tt(Ye(`around_seq=${encodeURIComponent(String(c))}&limit=${Ra}`));if(ve()!==T)return;St(T,Dt(q),"around"),await ur(),h&&(a(rt)?.scrollToMessage(h),await Rs(h))}finally{ve()===T&&v(Nt,!1)}}async function mc(c){const h=c.currentTarget,T=h.files?.[0];if(!T||!a(E))return;const R=await Cd(T),q=new FormData;q.set("workspace_id",a(E)),q.set("file",T),R.width>0&&q.set("width",String(R.width)),R.height>0&&q.set("height",String(R.height)),R.durationMS>0&&q.set("duration_ms",String(R.durationMS));const pe=await tt("/api/uploads",{method:"POST",body:q});v(ie,pe.upload),h.value=""}async function ni(){if(!a(E))return;const c=await tt(`/api/dms?workspace_id=${a(E)}`);v(k,c.conversations)}async function _c(c){const h=c.trim();h&&(await Ds(h),v(W,""),v($,!1))}async function bc(c){v(D,c),v(I,""),v(C,null),v(P,null),v(yt,"message"),v(Ve,!1),await ue()}async function Ds(c){const h=c.trim();if(!a(E)||!h)return;const T=a(k).find(q=>q.members.some(pe=>pe.id===h));if(T){v(D,T.id),v(I,""),v(C,null),v(P,null),v(yt,"message"),v(Ve,!1),await ue();return}const R=await tt("/api/dms",{method:"POST",body:JSON.stringify({workspace_id:a(E),member_ids:[h]})});v(k,[...a(k),R.conversation]),v(D,R.conversation.id),v(I,""),v(C,null),v(P,null),v(yt,"message"),v(Ve,!1),await ue()}function ri(){wt?.close(),wt=null,v(bt,!1),a(E)&&(wt=Qd({workspaceID:a(E),onEvent:c=>{wc(c)},onStatusChange:c=>v(bt,c)}))}async function wc(c){if(c.type==="typing.started"||c.type==="typing.stopped"){kc(c);return}if(c.type==="channel.read"||c.type==="dm.read"){yc(c);return}if((c.type==="channel.created"||c.type==="channel.updated")&&c.workspace_id===a(E)){await H();return}if(rc(c))return;const h=c.channel_id===a(I)||c.payload.direct_conversation_id===a(D);if(c.type==="message.created"&&!h&&Ms(c),h&&(c.type==="message.created"||c.type==="message.updated"||c.type==="message.deleted")){const R=c.payload.nonce;if(c.type==="message.created"&&R&&Er.has(R))return;const q=a(rt)?.isAtBottom()!==!1;c.type==="message.created"&&!q?(ht=Date.now()+1200,Tt(ve())):c.type==="message.created"?await Ne():await ue(),c.type==="message.created"&&Ms(c,q),c.type==="message.created"&&q&&ei(),c.type==="message.created"&&q&&Ta()}const T=c.payload.root_message_id||c.payload.message_id;a(C)&&T===a(C).id&&await Ts(a(C))}function yc(c){const h=c.payload,T=typeof h.user_id=="string"?h.user_id:"";if(!T||T!==a(w)?.id)return;const R=c.seq??h.last_read_seq??h.seq,q=typeof R=="number"?R:Number(R)||0;if(c.type==="channel.read"){const pe=typeof h.channel_id=="string"?h.channel_id:c.channel_id||"";if(!pe)return;v(x,a(x).map(Te=>{if(Te.id!==pe)return Te;const ze=Math.max(Te.last_read_seq||0,q);return{...Te,last_read_seq:ze,unread_count:Math.max(0,(Te.last_seq||0)-ze)}}))}else{const pe=typeof h.direct_conversation_id=="string"?h.direct_conversation_id:"";if(!pe)return;v(k,a(k).map(Te=>{if(Te.id!==pe)return Te;const ze=Math.max(Te.last_read_seq||0,q);return{...Te,last_read_seq:ze,unread_count:Math.max(0,(Te.last_seq||0)-ze)}}))}}function Ms(c,h){const T=c.payload,R=typeof T.author_id=="string"?T.author_id:"";if(R&&R===a(w)?.id||T.parent_message_id)return;const q=_s(c),{channelID:pe,dmID:Te}=bs(c);if(pe){const ze=pe===a(I)&&!a(D),Ze=ze?h??a(rt)?.isAtBottom()!==!1:!1,it=a(x).find(xe=>xe.id===pe),re=q>0?q:(it?.last_seq||0)+1;ze&&!Ze&&(it?.unread_count||0)===0&&ms(pe,it?.last_read_seq||0,c.created_at),v(x,a(x).map(xe=>{if(xe.id!==pe)return xe;const et=Math.max(xe.last_seq||0,re),Cn=ze&&!Ze&&(xe.unread_count||0)===0?Math.max(xe.last_read_seq||0,re-1):xe.last_read_seq||0,Bn=ze&&Ze?xe.unread_count||0:Math.max(0,et-Cn);return{...xe,last_seq:et,last_read_seq:Cn,unread_count:Bn}}))}else if(Te){const ze=Te===a(D),Ze=ze?h??a(rt)?.isAtBottom()!==!1:!1,it=a(k).find(xe=>xe.id===Te),re=q>0?q:(it?.last_seq||0)+1;ze&&!Ze&&(it?.unread_count||0)===0&&ms(Te,it?.last_read_seq||0,c.created_at),v(k,a(k).map(xe=>{if(xe.id!==Te)return xe;const et=Math.max(xe.last_seq||0,re),Cn=ze&&!Ze&&(xe.unread_count||0)===0?Math.max(xe.last_read_seq||0,re-1):xe.last_read_seq||0,Bn=ze&&Ze?xe.unread_count||0:Math.max(0,et-Cn);return{...xe,last_seq:et,last_read_seq:Cn,unread_count:Bn}}))}}function kc(c){const h=c.payload,T=typeof h.user_id=="string"?h.user_id:"";if(!T||T===a(w)?.id)return;const R=c.channel_id||(typeof h.channel_id=="string"?h.channel_id:""),q=typeof h.direct_conversation_id=="string"?h.direct_conversation_id:"";if(!(a(I)&&R===a(I)||a(D)&&q===a(D)))return;if(c.type==="typing.stopped"){v(pt,a(pt).filter(Ze=>Ze.userID!==T));return}const Te=Sc(T),ze=a(pt).filter(Ze=>Ze.userID!==T);ze.push({userID:T,user:Te,expiresAt:Date.now()+qp}),v(pt,ze),Tc()}function Sc(c){if(a(w)?.id===c)return a(w);const h=a(g).find(T=>T.author?.id===c)?.author;if(h)return h;for(const T of a(k)){const R=T.members.find(q=>q.id===c);if(R)return R}}function Tc(){Zt||(Zt=window.setInterval(()=>{const c=Date.now(),h=a(pt).filter(T=>T.expiresAt>c);h.length!==a(pt).length&&v(pt,h),h.length===0&&Zt&&(window.clearInterval(Zt),Zt=void 0)},1e3))}function xc(){a(E)&&(!a(I)&&!a(D)||nf({workspaceID:a(E),channelID:a(I)||void 0,directConversationID:a(D)||void 0}))}function Os(c){c&&(v(C,null),v(P,c))}function Ec(c){if(c.key==="Escape"&&a(ke)&&a(Ke)!=="thread"){c.preventDefault(),pn();return}c.key==="Enter"&&!c.shiftKey&&(c.preventDefault(),ys())}function Ac(c){if(c.key==="Escape"&&a(ke)&&a(Ke)==="thread"){c.preventDefault(),pn();return}c.key==="Enter"&&!c.shiftKey&&(c.preventDefault(),xs())}function ai(c,h){v(G,{url:c,title:h})}function Ls(c){const h=c.target;h instanceof HTMLImageElement&&h.closest(".markdown")&&(c.preventDefault(),ai(h.currentSrc||h.src,h.alt||"Image"))}function ii(c){const h=a(K)&&!a(K).endsWith(` +Please report this to https://github.com/markedjs/marked.`,t){let r="

An error occurred:

"+Dn(n.message+"",!0)+"
";return e?Promise.resolve(r):r}if(e)return Promise.reject(n);throw n}}},yr=new up;function qe(t,e){return yr.parse(t,e)}qe.options=qe.setOptions=function(t){return yr.setOptions(t),qe.defaults=yr.defaults,Wl(qe.defaults),qe};qe.getDefaults=os;qe.defaults=Tr;qe.use=function(...t){return yr.use(...t),qe.defaults=yr.defaults,Wl(qe.defaults),qe};qe.walkTokens=function(t,e){return yr.walkTokens(t,e)};qe.parseInline=yr.parseInline;qe.Parser=mn;qe.parser=mn.parse;qe.Renderer=Ga;qe.TextRenderer=gs;qe.Lexer=vn;qe.lexer=vn.lex;qe.Tokenizer=Wa;qe.Hooks=ia;qe.parse=qe;qe.options;qe.setOptions;qe.use;qe.walkTokens;qe.parseInline;mn.parse;vn.lex;function Fi(t){return Sh.sanitize(qe.parse(t,{async:!1,breaks:!0,gfm:!0}))}function ha(t){return new Intl.DateTimeFormat(void 0,{hour:"2-digit",minute:"2-digit"}).format(new Date(t))}var dp=z('
'),fp=z(''),hp=z(' ',1),pp=z('
',2),gp=z(' ');function Hi(t,e){Fe(e,!0);let n=Ee(e,"onOpenImage",3,()=>{});const r=360,i=120;let s=Be(null),o=Be(!1),u=Be(""),l=le(()=>a(u)||m(e.upload.duration_ms??0)),f=le(()=>e.upload.content_type?.startsWith("image/")??!1),d=le(()=>e.upload.content_type?.startsWith("video/")??!1),p=le(()=>{const C=e.upload.width??0,U=e.upload.height??0;if(C<=0||U<=0)return"";const P=a(f)?320:r,G=Math.min(P,Math.max(i,U));return`aspect-ratio: ${C} / ${U}; max-height: ${G}px;`});function m(C){if(!C||C<=0)return"";const U=Math.floor(C/1e3),P=Math.floor(U/60),G=U%60;return`${P}:${G.toString().padStart(2,"0")}`}function w(){v(o,!0)}function y(){!a(s)||!isFinite(a(s).duration)||v(u,m(a(s).duration*1e3),!0)}function x(){a(s)&&(v(o,!0),a(s).play())}function k(C){return C<1024?`${C} B`:C<1024*1024?`${Math.round(C/1024)} KB`:`${(C/(1024*1024)).toFixed(1)} MB`}var g=Sn(),I=Gt(g);{var E=C=>{var U=dp(),P=b(U),G=b(P),K=S(P,2),Z=b(K),Y=b(Z),O=S(Z,2);te(()=>{X(P,"aria-label",`Open image ${e.upload.filename}`),X(G,"src",e.url),X(G,"alt",e.upload.filename),X(G,"width",e.upload.width||void 0),X(G,"height",e.upload.height||void 0),wr(G,a(p)),ee(Y,e.upload.filename),X(O,"href",e.url),X(O,"download",e.upload.filename),X(O,"aria-label",`Download ${e.upload.filename}`)}),V("click",P,()=>n()(e.url,e.upload.filename)),V("click",O,W=>W.stopPropagation()),L(C,U)},A=C=>{var U=pp();let P;var G=b(U),K=b(G);gr(G,ie=>v(s,ie),()=>a(s));var Z=S(G,2);{var Y=ie=>{var B=hp(),ae=Gt(B),ce=S(ae,2);{var $=Ae=>{var ge=fp(),De=b(ge);te(()=>ee(De,a(l))),L(Ae,ge)};oe(ce,Ae=>{a(l)&&Ae($)})}te(()=>X(ae,"aria-label",`Play ${e.upload.filename}`)),V("click",ae,x),L(ie,B)};oe(Z,ie=>{a(o)||ie(Y)})}var O=S(Z,2),W=b(O),J=b(W),fe=S(W,2);te(()=>{P=lt(U,1,"media-tile media-tile--video",null,P,{"is-started":a(o)}),G.controls=a(o),X(G,"aria-label",e.upload.filename),X(G,"width",e.upload.width||void 0),X(G,"height",e.upload.height||void 0),wr(G,a(p)),X(K,"src",e.url),X(K,"type",e.upload.content_type),ee(J,e.upload.filename),X(fe,"href",e.url),X(fe,"download",e.upload.filename),X(fe,"aria-label",`Download ${e.upload.filename}`)}),dn("play",G,w),dn("loadedmetadata",G,y),V("click",fe,ie=>ie.stopPropagation()),L(C,U)},D=C=>{var U=gp(),P=S(b(U),2),G=b(P),K=b(G),Z=S(G,2),Y=b(Z);te(O=>{X(U,"href",e.url),ee(K,e.upload.filename),ee(Y,O)},[()=>k(e.upload.byte_size)]),L(C,U)};oe(I,C=>{a(f)?C(E):a(d)?C(A,1):C(D,-1)})}L(t,g),He()}Qe(["click"]);var vp=z(' '),mp=z(' '),_p=z('');function $l(t,e){Fe(e,!0);var n=Sn(),r=Gt(n);{var i=s=>{var o=_p();let u;var l=S(b(o),2),f=b(l),d=b(f),p=S(f,2);{var m=y=>{var x=vp(),k=b(x);te(g=>ee(k,g),[()=>Li(e.message.quoted_body_snapshot)]),L(y,x)},w=y=>{var x=mp(),k=b(x);te(g=>ee(k,`[original deleted] ${g??""}`),[()=>Li(e.message.quoted_body_snapshot)]),L(y,x)};oe(p,y=>{e.message.quoted_message_id?y(m):y(w,-1)})}te((y,x)=>{u=lt(o,1,"quote-block",null,u,{dangling:!e.message.quoted_message_id}),o.disabled=!e.message.quoted_message_id,X(o,"aria-label",y),ee(d,x)},[()=>e.message.quoted_message_id?`Jump to quoted message from ${ao(e.message)}`:"Original message was deleted",()=>ao(e.message)]),V("click",o,()=>e.onJump(e.message)),L(s,o)};oe(r,s=>{(e.message.quoted_message_id||e.message.quoted_body_snapshot)&&s(i)})}L(t,n),He()}Qe(["click"]);var bp=z('
'),wp=z(''),yp=z(''),kp=z(``),Sp=z('
');function Tp(t,e){Fe(e,!0);let n=le(()=>e.message.status==="pending"),r=le(()=>e.message.status==="failed");var i=Sp();let s;var o=b(i),u=b(o),l=S(o,2),f=b(l);$l(f,{get message(){return e.message},get onJump(){return e.onJumpToQuote}});var d=S(f,2);Ci(d,()=>Fi(e.message.body),!0);var p=S(d,2);{var m=I=>{var E=bp();Wt(E,21,()=>e.message.attachments,A=>A.id,(A,D)=>{{let C=le(()=>Fa(a(D)));Hi(A,{get upload(){return a(D)},get url(){return a(C)},get onOpenImage(){return e.onOpenImage}})}}),L(I,E)};oe(p,I=>{e.message.attachments?.length&&I(m)})}var w=S(p,2);{var y=I=>{var E=kp(),A=S(b(E),2);{var D=P=>{var G=wp();V("click",G,()=>e.onRetry?.(e.message)),L(P,G)};oe(A,P=>{e.onRetry&&P(D)})}var C=S(A,2);{var U=P=>{var G=yp();V("click",G,()=>e.onDiscard?.(e.message)),L(P,G)};oe(C,P=>{e.onDiscard&&P(U)})}L(I,E)};oe(w,I=>{a(r)&&I(y)})}var x=S(l,2),k=b(x),g=S(k,2);te((I,E)=>{s=lt(i,1,"message-row",null,s,{selected:e.selected,"is-pending":a(n),"is-failed":a(r)}),X(i,"data-message-id",e.message.id),ee(u,I),k.disabled=a(n)||a(r),X(g,"data-tooltip",E),g.disabled=a(n)||a(r)},[()=>e.index===0?"":ha(e.message.created_at),()=>ff(e.message,e.selectedThreadID)]),V("click",k,()=>e.onReply(e.message,e.replyContext)),V("click",g,()=>e.onOpenThread(e.message)),L(t,i),He()}Qe(["click"]);var xp=z('bot'),Ep=z(" "),Ap=z('
');function Ip(t,e){Fe(e,!0);const n=le(()=>e.group.messages[0]?.author),r=le(()=>a(n)?.kind==="bot");var i=Ap(),s=b(i);{let g=le(()=>`View profile for ${e.group.authorName}`);Pn(s,{class:"avatar avatar-button",get id(){return e.group.authorID},get name(){return e.group.authorName},get src(){return e.group.authorAvatarURL},size:38,get buttonLabel(){return a(g)},onclick:()=>e.onOpenProfile(e.group.messages[0]?.author)})}var o=S(s,2),u=b(o),l=b(u),f=b(l),d=S(l,2);{var p=g=>{var I=xp();L(g,I)};oe(d,g=>{a(r)&&g(p)})}var m=S(d,2);{var w=g=>{var I=Ep(),E=b(I);te(A=>ee(E,A),[()=>Kn(e.group.authorHandle)]),L(g,I)};oe(m,g=>{e.group.authorHandle&&g(w)})}var y=S(m,2),x=b(y),k=S(u,2);Wt(k,19,()=>e.group.messages,g=>g.id,(g,I,E)=>{{let A=le(()=>e.selectedThreadID===a(I).id);Tp(g,{get message(){return a(I)},get index(){return a(E)},get selected(){return a(A)},get replyContext(){return e.replyContext},get selectedThreadID(){return e.selectedThreadID},get onReply(){return e.onReply},get onOpenThread(){return e.onOpenThread},get onJumpToQuote(){return e.onJumpToQuote},get onOpenImage(){return e.onOpenImage},get onRetry(){return e.onRetry},get onDiscard(){return e.onDiscard}})}}),te(g=>{ee(f,e.group.authorName),ee(x,g)},[()=>ha(e.group.timestamp)]),V("click",l,()=>e.onOpenProfile(e.group.messages[0]?.author)),L(t,i),He()}Qe(["click"]);var Rp=z('
Send a message in Markdown — code fences, lists, links all work. Threads open from any message.
'),Cp=z('
'),Dp=z('
'),Mp=z('
New
'),Op=z('
'),Lp=z('
'),Pp=z('
');function Np(t,e){Fe(e,!0);let n=Ee(e,"loading",3,!1),r=Ee(e,"unreadCount",3,0),i=Ee(e,"unreadBoundarySeq",3,0),s=Ee(e,"unreadBoundaryLoaded",3,!1),o=Ee(e,"unreadSince",3,""),u=Ee(e,"hasOlder",3,!1),l=Ee(e,"hasNewer",3,!1),f=Ee(e,"loadingOlder",3,!1),d=Ee(e,"loadingNewer",3,!1),p=Ee(e,"prepending",3,!1);const m=1.5,w=160,y=260,x=180;let k=Be(void 0),g=Be(void 0),I=Be(void 0),E=Be(0),A=Be(0),D=le(()=>e.selectedDirect?"dm":"channel"),C=Be(""),U=Be(-1),P=Be(0),G=le(()=>a(C)===e.viewKey&&a(U)===i()&&r()<=a(P)?0:r()),K=Be(""),Z=Be(0),Y=Be(!1),O;function W(){O&&(window.clearTimeout(O),O=void 0)}Qt(()=>{if(a(K)&&a(K)!==e.viewKey){W(),v(Z,0),v(K,""),v(Y,!1);return}if(a(G)>0){W(),v(K,e.viewKey,!0),v(Z,a(G),!0),v(Y,!1);return}a(Z)>0&&!a(Y)&&(v(Y,!0),O=window.setTimeout(()=>{O=void 0,!(a(G)>0)&&(v(Z,0),v(K,""),v(Y,!1))},x))}),Ya(W);let J=le(()=>{const M=i()+1;if(a(Z)<=0||M<=0)return!1;let H=Number.POSITIVE_INFINITY,j=0;for(const F of e.messages){if(F.parent_message_id)continue;const ue=F.channel_seq||0;ue<=0||(H=Math.min(H,ue),j=Math.max(j,ue))}return H<=M&&j>=M}),fe=le(()=>s()&&a(J)),ie=le(()=>{const M=[];let H=!1;const j=F=>!a(fe)||F.parent_message_id||F.author?.id===e.currentUserID||F.author_id===e.currentUserID?!1:a(Z)>0&&(F.channel_seq||0)>i();for(const F of pf(e.messages)){let ue=-1;if(!H){for(let me=0;me{requestAnimationFrame(()=>{if(H===Ue){if(F<=1){_e=!1;return}j(F-1)}})};j(M)}function se(){return a(g)?a(g).scrollHeight-a(g).scrollTop-a(g).clientHeight<=m:!0}function be(){if(!a(g))return{atBottom:!0,nearOlder:!1,nearNewer:!1};const M=a(g).scrollHeight-a(g).scrollTop-a(g).clientHeight;return{atBottom:M<=m,nearOlder:a(g).scrollTop-a(E)<=w,nearNewer:M<=y}}function Se(){e.onHistorySettled?.(be())}function nt(){l()||e.onReachedBottom?.()}async function bt(){!a(g)||a(ie).length===0||(B=!0,await wt())}async function wt(){if(!a(g))return;Je(12);let M=0;for(let H=0;H<12;H++){if(!a(g))return;const j=a(g).scrollHeight;if(a(g).scrollTop=a(g).scrollHeight,await new Promise(ue=>requestAnimationFrame(ue)),!a(g))return;const F=Math.abs(a(g).scrollHeight-j)<1;if(se()&&F){if(M++,M>=2)break}else M=0}se()&&(v(ae,!0),nt()),Se()}Qt(()=>{if(!a(g))return;const M=a(g),H=()=>yt(M.scrollTop),j=F=>{F.deltaY>0&&!De&&!_e&&l()&&se()&&e.onLoadNewer?.()};return M.addEventListener("scroll",H,{passive:!0}),M.addEventListener("wheel",j,{passive:!0}),()=>{M.removeEventListener("scroll",H),M.removeEventListener("wheel",j)}}),Qt(()=>{if(!a(g))return;let M=0;const H=()=>{M||(M=requestAnimationFrame(()=>{M=0,B&&!De&&a(g)&&(a(g).scrollTop=a(g).scrollHeight)}))},j=new ResizeObserver(H),F=a(g).lastElementChild;return F&&j.observe(F),()=>{M&&cancelAnimationFrame(M),j.disconnect()}});function rt(M){return a(ie).findIndex(H=>H.kind==="group"&&H.group.messages.some(j=>j.id===M))}const at=52,Pe=3;let en=le(()=>{if(!u()||n())return 0;if(!p())return Pe;const M=Math.max(a(A),480);return Math.max(Pe+1,Math.ceil(M/at))});Qt(()=>{if(!a(g))return;const M=()=>{a(g)&&v(A,a(g).clientHeight,!0)};M();const H=new ResizeObserver(M);return H.observe(a(g)),()=>H.disconnect()});let ft=0;Qt(()=>{if(!a(I)||!a(g)){v(E,0),ft=0;return}const M=a(g),H=a(I),j=()=>{const ue=H.offsetHeight,me=ft;if(v(E,ue,!0),ft=ue,me>0&&ue!==me){const Ie=ue-me;M.scrollTop>0&&(M.scrollTop+=Ie)}};j();const F=new ResizeObserver(j);return F.observe(H),()=>{F.disconnect(),v(E,0),ft=0}});let Ct="",Vt="",Kt=null;za(()=>{const M=e.messages[0]?.id??"";e.viewKey===Vt&&M&&Ct&&M!==Ct&&e.messages.some(F=>F.id===Ct)&&a(g)&&(Kt={savedBottomDistance:a(g).scrollHeight-a(g).scrollTop,deadline:performance.now()+800}),Ct=M,Vt=e.viewKey}),Qt(()=>{if(e.messages,!Kt||!a(g))return;const M=Kt;Kt=null;const H=a(g),j=H.lastElementChild;let F=-1,ue=!1;const me=()=>{if(ue)return;if(F>=0&&Math.abs(H.scrollTop-F)>2){Dt();return}const St=H.scrollHeight-M.savedBottomDistance;Math.abs(H.scrollTop-St)>.5&&(ue=!0,H.scrollTop=St,ue=!1),F=H.scrollTop};let Ie=0;const Le=()=>{me(),performance.now()M.kind==="divider")}function En(){if(!a(fe)||a(Z)<=0)return"";for(const M of e.messages)if(!M.parent_message_id&&!(M.author?.id===e.currentUserID||M.author_id===e.currentUserID)&&(M.channel_seq||0)>i())return M.id;return""}function Nn(){let M=0;for(const H of e.messages)M=Math.max(M,H.channel_seq||0);return M}function rn(){v(C,e.viewKey,!0),v(U,i()),v(P,r()),e.onMarkRead?.(Nn())}function Ge(){return new Promise(M=>requestAnimationFrame(()=>M()))}function ht(M){if(!a(g))return!1;const H=a(g).querySelector(M);if(!H)return!1;const j=H.getBoundingClientRect().top-a(g).getBoundingClientRect().top;return Math.abs(j)<=m?!0:(a(g).scrollTop+=j,!1)}function Yt(){if(!a(g))return null;const M=a(g).getBoundingClientRect(),H=new Map(e.messages.map((ue,me)=>[ue.id,me]));let j=Number.POSITIVE_INFINITY,F=-1;for(const ue of a(g).querySelectorAll("[data-message-id]")){const me=ue.getBoundingClientRect();if(me.bottomM.bottom)continue;const Ie=H.get(ue.dataset.messageId||"");Ie!==void 0&&(j=Math.min(j,Ie),F=Math.max(F,Ie))}return F<0?null:{first:j,last:F}}function rr(M){if(!a(g))return!1;const H=e.messages.findIndex(F=>F.id===M),j=Yt();return H<0||!j?!1:j.first>H?(a(g).scrollTop-=Math.max(80,a(g).clientHeight*.85),!0):j.lastrt(M),`[data-message-id="${CSS.escape(M)}"]`,M),!0}function an(M=!0){if(!a(k)||xn()<0)return!1;B=!1;const j=e.viewKey;return Nt(j,()=>xn(),"[data-unread-divider='true']",En()).then(F=>{M&&!F&&Pt(j)&&e.onJumpToUnread?.()}),!0}function Ve(){if(!l()&&se()){rn();return}if(e.onJumpToUnread){e.onJumpToUnread();return}a(fe)&&an(!1)}function ke(){if(!a(k))return null;if(se())return{atBottom:!0};const H=a(k).getScrollOffset(),j=a(k).findItemIndex(H);for(let F=Math.max(0,j);F(e.onListRef({scrollToBottom:bt,scrollToMessage:qn,scrollToDivider:an,captureState:ke,isAtBottom:()=>se()}),()=>e.onListRef(null))),Qt(()=>{const M=e.viewKey,H=a(ie).length;if(M!==$){$=M,Ae=H,ge=e.restoreState,B=!0,v(ae,!0),v(ce,!1),De=!0,An(M,e.restoreState,!0);return}const j=e.restoreState;if(j&&j!==ge&&(ge=j,!j.atBottom&&j.anchorMessageID)){Ae=H,De=!0,An(M,j,!1);return}H>Ae&&B&&!De?wt():H!==Ae&&!De&&Ke(M),Ae=H});async function Ke(M){await ur(),await Ge(),M===$&&Se()}async function An(M,H,j){if(await ur(),await new Promise(F=>requestAnimationFrame(F)),M===$){if(H&&!H.atBottom&&H.anchorMessageID){const F=await In(M,H.anchorMessageID,H.anchorPixelOffset??0);if(M!==$)return;!F&&j?await bt():B=!1}else a(ie).findIndex(ue=>ue.kind==="divider")>=0&&a(k)?(await Nt(M,()=>xn(),"[data-unread-divider='true']",En()),B=!1):await bt();await new Promise(F=>requestAnimationFrame(F)),M===$&&(De=!1,v(ce,!0),v(ae,se(),!0),B=a(ae),a(ae)&&nt(),a(g)&&yt(a(g).scrollTop),Se())}}async function In(M,H,j){if(!a(k))return!1;const F=rt(H);if(F<0)return!1;for(let ue=0;ue<8;ue++){if(!a(k)||M!==$)return!1;const me=a(k).getItemOffset(F)+j;if(Je(),a(k).scrollTo(me),await new Promise(Ye=>requestAnimationFrame(Ye)),M!==$)return!1;const Ie=a(k).getItemOffset(F)+j,Le=a(k).getScrollOffset();if(Math.abs(Ie-me)<1&&Math.abs(Le-me)<1)break}return!0}function yt(M){if(!a(g)||De)return;const H=a(g).scrollHeight-a(g).scrollTop-a(g).clientHeight,j=H<=m;B=j,v(ae,j),!j&&u()&&a(g).scrollTop-a(E)<=w&&e.onLoadOlder?.(),!_e&&l()&&(j||H<=y)&&e.onLoadNewer?.(),j&&nt()}var pt=Pp();let Zt;var xr=b(pt);{var Rn=M=>{var H=Rp(),j=b(H),F=b(j);{var ue=We=>{var gt=Xn("@");L(We,gt)},me=We=>{var gt=Xn("#");L(We,gt)};oe(F,We=>{e.selectedDirect?We(ue):We(me,-1)})}var Ie=S(j,2),Le=b(Ie);{var Ye=We=>{var gt=Xn();te(qt=>ee(gt,`This is the start of your conversation with ${qt??""}.`),[()=>da(e.selectedDirect,e.currentUserID)]),L(We,gt)},Dt=We=>{var gt=Xn();te(()=>ee(gt,`Welcome to #${e.selectedChannel.name??""}!`)),L(We,gt)},St=We=>{var gt=Xn("Pick a channel to get started.");L(We,gt)};oe(Le,We=>{e.selectedDirect?We(Ye):e.selectedChannel?We(Dt,1):We(St,-1)})}L(M,H)},Hr=M=>{var H=Op(),j=S(b(H),2);{var F=me=>{var Ie=Cp(),Le=b(Ie);oo(Le,{direction:"older",get rows(){return a(en)}}),gr(Ie,Ye=>v(I,Ye),()=>a(I)),te(()=>X(Ie,"aria-hidden",f()?"false":"true")),L(me,Ie)};oe(j,me=>{u()&&!n()&&me(F)})}var ue=S(j,2);gr(Gf(ue,{get data(){return a(ie)},getKey:Ie=>Ie.id,get shift(){return p()},get startMargin(){return a(E)},children:(Ie,Le=_i,Ye=_i)=>{var Dt=Sn(),St=Gt(Dt);{var We=Tt=>{oo(Tt,{get direction(){return Le().direction},get rows(){return Le().rows}})},gt=Tt=>{var xt=Dp(),hn=b(xt),ar=b(hn);te(()=>ee(ar,Le().label)),L(Tt,xt)},qt=Tt=>{var xt=Mp();let hn;te(()=>hn=lt(xt,1,"new-messages-divider",null,hn,{"is-clearing":a(Y)})),L(Tt,xt)},Yn=Tt=>{Ip(Tt,{get group(){return Le().group},get selectedThreadID(){return e.selectedThreadID},get replyContext(){return a(D)},get onOpenProfile(){return e.onOpenProfile},get onReply(){return e.onReply},get onOpenThread(){return e.onOpenThread},get onJumpToQuote(){return e.onJumpToQuote},get onOpenImage(){return e.onOpenImage},get onRetry(){return e.onRetry},get onDiscard(){return e.onDiscard}})};oe(St,Tt=>{Le().kind==="loader"?Tt(We):Le().kind==="day"?Tt(gt,1):Le().kind==="divider"?Tt(qt,2):Tt(Yn,-1)})}L(Ie,Dt)},$$slots:{default:!0}}),Ie=>v(k,Ie,!0),()=>a(k)),gr(H,me=>v(g,me),()=>a(g)),L(M,H)};oe(xr,M=>{!n()&&e.messages.length===0?M(Rn):e.messages.length>0&&M(Hr,1)})}var Wr=S(xr,2);{var $e=M=>{var H=Lp();let j;var F=b(H),ue=b(F),me=b(ue),Ie=S(F,2);te(Le=>{j=lt(H,1,"unread-bar",null,j,{"is-clearing":a(Y)}),X(F,"aria-label",Le),ee(me,`${(a(Z)>99?"99+":a(Z))??""} new message${a(Z)===1?"":"s"}${o()?` since ${o()}`:""}`)},[()=>`Jump to ${a(Z)>0?a(Z):""} new message${a(Z)===1?"":"s"}`.replace(/ +/g," ")]),V("click",F,Ve),V("click",Ie,rn),L(M,H)};oe(Wr,M=>{!n()&&e.messages.length>0&&a(Z)>0&&M($e)})}te(()=>Zt=lt(pt,1,"messages",null,Zt,{"is-revealing":n()||!a(ce)&&e.messages.length>0})),V("pointerdown",pt,function(...M){e.onActivateMessageComposer?.apply(this,M)}),V("pointerup",pt,function(...M){e.onInlineImagePointerUp?.apply(this,M)}),L(t,pt),He()}Qe(["pointerdown","pointerup","click"]);const qp=6500;var Up=z('
');function zp(t,e){Fe(e,!0);let n=le(()=>e.entries.filter(f=>f.userID!==e.currentUserID));function r(f,d="Someone"){return f?.display_name?.trim()||(f?.handle?`@${f.handle}`:d)}let i=le(()=>a(n).length===0?"":a(n).length===1?`${r(a(n)[0].user)} is typing…`:a(n).length===2?`${r(a(n)[0].user)} and ${r(a(n)[1].user)} are typing…`:a(n).length===3?`${r(a(n)[0].user)}, ${r(a(n)[1].user)}, and ${r(a(n)[2].user)} are typing…`:"Several people are typing…");var s=Up();let o;var u=S(b(s),2),l=b(u);te(()=>{o=lt(s,1,"typing-indicator",null,o,{visible:a(n).length>0}),ee(l,a(i))}),L(t,s),He()}var Bp=z('

'),Fp=z('');function Hp(t,e){Fe(e,!0);var n=Fp(),r=b(n),i=S(r,2),s=b(i),o=S(b(s),2),u=S(s,2),l=b(u),f=S(b(l),2),d=S(l,2);{var p=y=>{var x=Bp(),k=b(x);te(()=>ee(k,e.status)),L(y,x)};oe(d,y=>{e.status&&y(p)})}var m=S(d,2),w=b(m);te(()=>On(f,e.channelName)),V("click",r,function(...y){e.onClose?.apply(this,y)}),V("click",o,function(...y){e.onClose?.apply(this,y)}),dn("submit",u,y=>{y.preventDefault(),e.onCreate()}),V("input",f,y=>e.onChannelName(y.currentTarget.value)),V("click",w,function(...y){e.onClose?.apply(this,y)}),L(t,n),He()}Qe(["click","input"]);var Wp=z(''),Gp=z('
No matching people yet
'),jp=z('');function Vp(t,e){Fe(e,!0);let n=le(()=>e.memberID.trim().toLowerCase()),r=le(()=>e.people.filter(I=>I.id!==e.currentUserID).filter(I=>a(n)?I.display_name.toLowerCase().includes(a(n))||I.handle?.toLowerCase().includes(a(n))||I.id.toLowerCase().includes(a(n)):!0));var i=jp(),s=b(i),o=S(s,2),u=b(o),l=S(b(u),2),f=S(u,2),d=b(f),p=S(b(d),2),m=S(d,2),w=b(m);Wt(w,17,()=>a(r),I=>I.id,(I,E)=>{var A=Wp(),D=b(A);Pn(D,{class:"dm-avatar",get id(){return a(E).id},get name(){return a(E).display_name},get src(){return a(E).avatar_url},size:32});var C=S(D,2),U=b(C),P=b(U),G=S(U,2),K=b(G);te(Z=>{ee(P,a(E).display_name),ee(K,Z)},[()=>Kn(a(E).handle)||a(E).id]),V("click",A,()=>e.onStart(a(E).id)),L(I,A)});var y=S(w,2);{var x=I=>{var E=Gp();L(I,E)};oe(y,I=>{a(r).length===0&&I(x)})}var k=S(m,2),g=b(k);te(()=>On(p,e.memberID)),V("click",s,function(...I){e.onClose?.apply(this,I)}),V("click",l,function(...I){e.onClose?.apply(this,I)}),dn("submit",f,I=>{I.preventDefault(),e.onStart(e.memberID)}),V("input",p,I=>e.onMemberID(I.currentTarget.value)),V("click",g,function(...I){e.onClose?.apply(this,I)}),L(t,i),He()}Qe(["click","input"]);var Kp=z('
'),Yp=z('
'),Zp=z('');function Xp(t,e){Fe(e,!0);var n=Zp(),r=S(b(n),4),i=b(r);Wt(i,17,()=>e.workspaces,l=>l.id,(l,f)=>{var d=Kp();let p;var m=b(d),w=b(m),y=b(w);te(x=>{p=lt(d,1,"guild-wrap",null,p,{active:a(f).id===e.selectedWorkspaceID}),X(m,"title",a(f).name),ee(y,x)},[()=>Ud(a(f).name)]),V("click",m,()=>e.onSelectWorkspace(a(f).id)),L(l,d)});var s=S(i,2),o=S(r,2);{var u=l=>{var f=Yp(),d=b(f);te(()=>On(d,e.workspaceName)),dn("submit",f,p=>{p.preventDefault(),e.onCreateWorkspace()}),V("input",d,p=>e.onWorkspaceName(p.currentTarget.value)),L(l,f)};oe(o,l=>{e.showWorkspaceCreate&&l(u)})}V("click",s,function(...l){e.onToggleWorkspaceCreate?.apply(this,l)}),L(t,n),He()}Qe(["click","input"]);var Qp=z(' '),Jp=z(''),$p=z(''),eg=z('');function tg(t,e){Fe(e,!0);var n=eg(),r=b(n),i=S(b(r),4),s=S(r,2),o=b(s);Wt(o,17,()=>e.channels,f=>f.id,(f,d)=>{const p=le(()=>a(d).unread_count||0);var m=Jp();let w;var y=S(b(m),2),x=b(y),k=S(y,2);{var g=I=>{var E=Qp(),A=b(E);te(()=>{X(E,"aria-label",`${a(p)} unread`),ee(A,a(p)>99?"99+":a(p))}),L(I,E)};oe(k,I=>{a(p)>0&&!(a(d).id===e.selectedChannelID&&!e.selectedDirectID)&&I(g)})}te(()=>{w=lt(m,1,"nav-item channel",null,w,{active:a(d).id===e.selectedChannelID&&!e.selectedDirectID,"has-unread":a(p)>0&&!(a(d).id===e.selectedChannelID&&!e.selectedDirectID)}),ee(x,a(d).name)}),V("click",m,()=>e.onSelectChannel(a(d).id)),L(f,m)});var u=S(o,2);{var l=f=>{var d=$p();L(f,d)};oe(u,f=>{e.channels.length===0&&f(l)})}V("click",i,function(...f){e.onCreateChannel?.apply(this,f)}),L(t,n),He()}Qe(["click"]);var ng=z(' '),rg=z(''),ag=z(''),ig=z(''),sg=z('');function og(t,e){Fe(e,!0);var n=sg(),r=b(n),i=S(b(r),4),s=S(r,2),o=b(s);Wt(o,17,()=>e.conversations,f=>f.id,(f,d)=>{const p=le(()=>Bd(a(d),e.currentUserID)),m=le(()=>a(d).unread_count||0),w=le(()=>a(d).id===e.selectedDirectID);var y=ag();let x;var k=b(y);{let C=le(()=>a(p)?.id||a(d).id),U=le(()=>a(p)?.display_name),P=le(()=>a(p)?.avatar_url);Pn(k,{class:"dm-avatar",get id(){return a(C)},get name(){return a(U)},get src(){return a(P)},size:22})}var g=S(k,2),I=b(g),E=S(g,2);{var A=C=>{var U=ng(),P=b(U);te(()=>{X(U,"aria-label",`${a(m)} unread`),ee(P,a(m)>99?"99+":a(m))}),L(C,U)},D=C=>{var U=rg();L(C,U)};oe(E,C=>{a(m)>0&&!a(w)?C(A):C(D,-1)})}te(C=>{x=lt(y,1,"nav-item dm",null,x,{active:a(w),"has-unread":a(m)>0&&!a(w)}),ee(I,C)},[()=>da(a(d),e.currentUserID)]),V("click",y,()=>e.onSelectDirect(a(d).id)),L(f,y)});var u=S(o,2);{var l=f=>{var d=ig();L(f,d)};oe(u,f=>{e.conversations.length===0&&f(l)})}V("click",i,function(...f){e.onCreateDirect?.apply(this,f)}),L(t,n),He()}Qe(["click"]);var lg=z(''),cg=z(''),ug=z(''),dg=z('');function fg(t,e){Fe(e,!0);var n=dg(),r=b(n),i=b(r),s=b(i),o=b(s),u=S(s,2);let l;var f=b(u),d=S(i,2),p=b(d),m=b(p),w=S(r,2),y=b(w);tg(y,{get channels(){return e.channels},get selectedChannelID(){return e.selectedChannelID},get selectedDirectID(){return e.selectedDirectID},get onSelectChannel(){return e.onSelectChannel},get onCreateChannel(){return e.onCreateChannel}});var x=S(y,2);{let U=le(()=>e.currentUser?.id);og(x,{get conversations(){return e.directConversations},get currentUserID(){return a(U)},get selectedDirectID(){return e.selectedDirectID},get onSelectDirect(){return e.onSelectDirect},get onCreateDirect(){return e.onCreateDirect}})}var k=S(x,2),g=S(b(k),2),I=b(g);Wt(I,17,()=>e.recentPeople,U=>U.id,(U,P)=>{const G=le(()=>Hd(e.directConversations,a(P).id));var K=lg();let Z;var Y=b(K);Pn(Y,{class:"dm-avatar",get id(){return a(P).id},get name(){return a(P).display_name},get src(){return a(P).avatar_url},size:22});var O=S(Y,2),W=b(O);te(()=>{Z=lt(K,1,"nav-item dm",null,Z,{active:a(G)?.id===e.selectedDirectID||e.selectedProfile?.id===a(P).id}),ee(W,a(P).display_name)}),V("click",K,()=>{a(G)?e.onSelectDirect(a(G).id):e.onOpenProfile(a(P))}),L(U,K)});var E=S(I,2);{var A=U=>{var P=cg();L(U,P)};oe(E,U=>{e.recentPeople.length===0&&U(A)})}var D=S(w,2);{var C=U=>{var P=ug(),G=b(P);Pn(G,{class:"dm-avatar",get id(){return e.currentUser.id},get name(){return e.currentUser.display_name},get src(){return e.currentUser.avatar_url},size:28,loading:"eager",fetchPriority:"auto"});var K=S(G,2),Z=b(K),Y=b(Z),O=S(Z,2),W=b(O);te((J,fe)=>{X(P,"aria-label",J),ee(Y,e.currentUser.display_name),ee(W,fe)},[()=>`Account settings for ${e.currentUser.display_name} ${Kn(e.currentUser.handle)}`,()=>e.currentUser.handle?Kn(e.currentUser.handle):e.connected?"Active":"Reconnecting…"]),V("click",P,function(...J){e.onOpenSettings?.apply(this,J)}),V("contextmenu",P,J=>{J.preventDefault(),e.onOpenSettings()}),L(U,P)};oe(D,U=>{e.currentUser&&U(C)})}te(()=>{ee(o,e.workspaceName||"Pick a workspace"),l=lt(u,1,"presence",null,l,{online:e.connected}),ee(f,e.connected?"Connected":e.status),X(d,"aria-label",e.sidebarCollapsed?"Expand sidebar":"Collapse sidebar"),X(d,"title",e.sidebarCollapsed?"Expand sidebar":"Collapse sidebar"),X(m,"d",e.sidebarCollapsed?"m9 6 6 6-6 6":"m15 6-6 6 6 6")}),V("click",d,function(...U){e.onToggleCollapse?.apply(this,U)}),L(t,n),He()}Qe(["click","contextmenu"]);var hg=z(' '),pg=z(" "),gg=z(''),vg=z(''),mg=z(''),_g=z('
User kind
'),bg=z('

Profile

Active
Contact information
Handle
User ID
About

',1);function wg(t,e){Fe(e,!0);const n=le(()=>e.profile.kind==="bot"?e.profile.owner_user_id?`Bot of ${e.profile.owner_user_id}`:"Service bot":"");var r=bg(),i=Gt(r),s=b(i),o=S(b(s),2),u=b(o),l=S(s,2),f=S(i,2),d=b(f),p=b(d);Pn(p,{class:"profile-avatar",get id(){return e.profile.id},get name(){return e.profile.display_name},get src(){return e.profile.avatar_url},size:240,loading:"eager",fetchPriority:"auto"});var m=S(d,2),w=b(m),y=b(w),x=b(y),k=b(x),g=S(x,2);{var I=se=>{var be=hg(),Se=b(be);te(()=>ee(Se,a(n))),L(se,be)};oe(g,se=>{a(n)&&se(I)})}var E=S(g,2);{var A=se=>{var be=pg(),Se=b(be);te(nt=>ee(Se,nt),[()=>Kn(e.profile.handle)]),L(se,be)};oe(E,se=>{e.profile.handle&&se(A)})}var D=S(y,2);{var C=se=>{var be=gg();V("click",be,function(...Se){e.onEdit?.apply(this,Se)}),L(se,be)};oe(D,se=>{e.currentUser?.id===e.profile.id&&se(C)})}var U=S(w,4),P=b(U);{var G=se=>{var be=vg();V("click",be,()=>e.onMessage(e.profile.id)),L(se,be)};oe(P,se=>{e.currentUser?.id!==e.profile.id&&se(G)})}var K=S(P,2),Z=S(U,2),Y=b(Z),O=S(b(Y),2);{var W=se=>{var be=mg();V("click",be,function(...Se){e.onEdit?.apply(this,Se)}),L(se,be)};oe(O,se=>{e.currentUser?.id===e.profile.id&&se(W)})}var J=S(Y,2),fe=S(b(J),2),ie=S(b(fe),2),B=b(ie),ae=S(J,2),ce=S(b(ae),2),$=S(b(ce),2),Ae=b($),ge=S(ae,2);{var De=se=>{var be=_g(),Se=S(b(be),2),nt=S(b(Se),2),bt=b(nt);te(()=>ee(bt,a(n))),L(se,be)};oe(ge,se=>{e.profile.kind==="bot"&&se(De)})}var _e=S(Z,2),Ue=S(b(_e),2),Je=b(Ue);te((se,be)=>{ee(u,e.profile.display_name),wr(d,`--hue: ${se??""}deg`),ee(k,e.profile.display_name),ee(B,be),ee(Ae,e.profile.id),ee(Je,`Member of ${(e.workspaceName||"this workspace")??""}. Click Message to keep the conversation in your sidebar.`)},[()=>Cl(e.profile.id),()=>e.profile.handle?Kn(e.profile.handle):"No handle set"]),V("click",l,function(...se){e.onClose?.apply(this,se)}),V("click",K,function(...se){e.onSetStatus?.apply(this,se)}),L(t,r),He()}Qe(["click"]);var yg=z("

"),kg=z('');function Sg(t,e){Fe(e,!0);var n=kg(),r=b(n),i=S(r,2),s=b(i),o=S(b(s),2),u=S(s,2),l=b(u),f=b(l);Pn(f,{class:"avatar large",get id(){return e.user.id},get name(){return e.displayName},get src(){return e.avatarURL},size:56,loading:"eager",fetchPriority:"auto"});var d=S(f,2),p=b(d),m=b(p),w=S(p,2),y=b(w),x=S(l,2),k=S(b(x),2),g=S(x,2),I=S(b(g),2),E=S(g,2),A=S(b(E),2),D=S(E,2),C=b(D),U=S(D,2),P=S(b(U),2),G=S(U,2);{var K=O=>{var W=yg();let J;var fe=b(W);te(()=>{J=lt(W,1,"profile-status",null,J,{error:e.statusError}),ee(fe,e.status)}),L(O,W)};oe(G,O=>{e.status&&O(K)})}var Z=S(G,2),Y=b(Z);te(O=>{ee(m,e.displayName||e.user.display_name),ee(y,O),On(k,e.displayName),On(I,e.handle),On(A,e.avatarURL),xd(C,e.pushoverEnabled),On(P,e.pushoverUserKey)},[()=>e.handle||Kn(e.user.handle)||"No handle set"]),V("click",r,function(...O){e.onClose?.apply(this,O)}),V("click",o,function(...O){e.onClose?.apply(this,O)}),dn("submit",u,O=>{O.preventDefault(),e.onSave()}),V("input",k,O=>e.onDisplayName(O.currentTarget.value)),V("input",I,O=>e.onHandle(O.currentTarget.value)),V("input",A,O=>e.onAvatarURL(O.currentTarget.value)),V("change",C,O=>e.onPushoverEnabled(O.currentTarget.checked)),V("input",P,O=>e.onPushoverUserKey(O.currentTarget.value)),V("click",Y,function(...O){e.onClose?.apply(this,O)}),L(t,n),He()}Qe(["click","input","change"]);var Tg=z(''),xg=z('
');function Eg(t,e){Fe(e,!0);var n=Sn(),r=Gt(n);{var i=s=>{var o=xg(),u=b(o),l=b(u),f=b(l),d=S(l,2),p=S(u,2);Wt(p,17,()=>e.results,m=>m.message.id,(m,w)=>{var y=Tg(),x=b(y);{let P=le(()=>a(w).message.author?.id||a(w).message.author_id),G=le(()=>a(w).message.author?.display_name),K=le(()=>a(w).message.author?.avatar_url);Pn(x,{class:"dm-avatar",get id(){return a(P)},get name(){return a(G)},get src(){return a(K)},size:30})}var k=S(x,2),g=b(k),I=b(g),E=b(I),A=S(I,2),D=b(A),C=S(g,2),U=b(C);te(P=>{ee(E,a(w).message.author?.display_name||"Local User"),ee(D,P),ee(U,a(w).message.body)},[()=>ha(a(w).message.created_at)]),V("click",y,()=>e.onOpenResult(a(w))),L(m,y)}),te(()=>ee(f,`${e.results.length??""} ${e.results.length===1?"result":"results"}`)),V("click",d,function(...m){e.onClose?.apply(this,m)}),L(s,o)};oe(r,s=>{e.results.length>0&&s(i)})}L(t,n),He()}Qe(["click"]);var Ag=z('
No thread open Hover any message and tap the bubble to keep side conversations tidy.
');function Ig(t){var e=Ag();L(t,e)}var Rg=z(" "),Cg=z('
'),Dg=z(" "),Mg=z('
'),Og=z('
'),Lg=z('

Thread

',1);function Pg(t,e){Fe(e,!0);var n=Lg(),r=Gt(n),i=b(r),s=S(b(i),2),o=b(s),u=S(i,2),l=S(r,2),f=b(l),d=b(f);{let Y=le(()=>e.root.author?.id||e.root.author_id),O=le(()=>e.root.author?.display_name),W=le(()=>e.root.author?.avatar_url);Pn(d,{class:"avatar",get id(){return a(Y)},get name(){return a(O)},get src(){return a(W)},size:38})}var p=S(d,2),m=b(p),w=b(m),y=b(w),x=S(w,2);{var k=Y=>{var O=Rg(),W=b(O);te(J=>ee(W,J),[()=>Kn(e.root.author.handle)]),L(Y,O)};oe(x,Y=>{e.root.author?.handle&&Y(k)})}var g=S(x,2),I=b(g),E=S(g,2),A=S(m,2);Ci(A,()=>Fi(e.root.body),!0);var D=S(A,2);{var C=Y=>{var O=Cg();Wt(O,21,()=>e.root.attachments,W=>W.id,(W,J)=>{{let fe=le(()=>Fa(a(J)));Hi(W,{get upload(){return a(J)},get url(){return a(fe)},get onOpenImage(){return e.onOpenImage}})}}),L(Y,O)};oe(D,Y=>{e.root.attachments?.length&&Y(C)})}var U=S(f,2),P=b(U),G=b(P),K=S(U,2);Wt(K,21,()=>e.replies,Y=>Y.id,(Y,O)=>{var W=Og(),J=b(W);{let be=le(()=>a(O).author?.id||a(O).author_id),Se=le(()=>a(O).author?.display_name),nt=le(()=>a(O).author?.avatar_url);Pn(J,{class:"avatar small",get id(){return a(be)},get name(){return a(Se)},get src(){return a(nt)},size:30})}var fe=S(J,2),ie=b(fe),B=b(ie),ae=b(B),ce=S(B,2);{var $=be=>{var Se=Dg(),nt=b(Se);te(bt=>ee(nt,bt),[()=>Kn(a(O).author.handle)]),L(be,Se)};oe(ce,be=>{a(O).author?.handle&&be($)})}var Ae=S(ce,2),ge=b(Ae),De=S(Ae,2),_e=S(ie,2);$l(_e,{get message(){return a(O)},get onJump(){return e.onJumpToQuote}});var Ue=S(_e,2);Ci(Ue,()=>Fi(a(O).body),!0);var Je=S(Ue,2);{var se=be=>{var Se=Mg();Wt(Se,21,()=>a(O).attachments,nt=>nt.id,(nt,bt)=>{{let wt=le(()=>Fa(a(bt)));Hi(nt,{get upload(){return a(bt)},get url(){return a(wt)},get onOpenImage(){return e.onOpenImage}})}}),L(be,Se)};oe(Je,be=>{a(O).attachments?.length&&be(se)})}te(be=>{X(W,"data-message-id",a(O).id),ee(ae,a(O).author?.display_name||"Local User"),ee(ge,be)},[()=>ha(a(O).created_at)]),V("click",De,()=>e.onSetReplyTarget(a(O),"thread")),L(Y,W)});var Z=S(l,2);Ml(Z,{get value(){return e.replyBody},placeholder:"Reply in thread",ariaLabel:"Reply body",submitLabel:"Reply",formClass:"composer reply-composer",get replyTarget(){return e.replyTarget},get onValue(){return e.onReplyBody},get onSubmit(){return e.onSubmitReply},get onKeydown(){return e.onReplyKeydown},get onFocus(){return e.onReplyFocus},get onInputRef(){return e.onReplyInputRef},get onClearReply(){return e.onClearReply}}),te(Y=>{ee(o,`${e.threadState?.reply_count??e.replies.length??""} ${(e.threadState?.reply_count??e.replies.length)===1?"reply":"replies"}`),X(f,"data-message-id",e.root.id),ee(y,e.root.author?.display_name||"Local User"),ee(I,Y),ee(G,`${e.replies.length??""} ${e.replies.length===1?"reply":"replies"}`)},[()=>ha(e.root.created_at)]),V("click",u,function(...Y){e.onClose?.apply(this,Y)}),V("pointerdown",l,function(...Y){e.onActivateThreadComposer?.apply(this,Y)}),V("pointerup",l,function(...Y){e.onInlineImagePointerUp?.apply(this,Y)}),V("click",E,()=>e.onSetReplyTarget(e.root,"thread")),L(t,n),He()}Qe(["click","pointerdown","pointerup"]);var Ng=z('

'),qg=z('

'),Ug=z('

ClickClack

'),zg=z(''),Bg=z('

');function Fg(t,e){Fe(e,!0);var n=Bg(),r=b(n),i=b(r);{var s=I=>{var E=Ng(),A=b(E);te(D=>ee(A,D),[()=>`@${da(e.selectedDirect,e.currentUserID)}`]),L(I,E)},o=I=>{var E=qg(),A=b(E);te(()=>ee(A,`#${e.selectedChannel.name}`)),L(I,E)},u=I=>{var E=Ug();L(I,E)};oe(i,I=>{e.selectedDirect?I(s):e.selectedChannel?I(o,1):I(u,-1)})}var l=S(i,4),f=b(l),d=S(r,2),p=S(b(d),2),m=S(p,2);{var w=I=>{var E=zg();V("click",E,function(...A){e.onResetSearch?.apply(this,A)}),L(I,E)};oe(m,I=>{e.searchQuery&&I(w)})}var y=S(d,2),x=b(y);let k;var g=S(x,2);te(()=>{ee(f,e.workspaceName||"no workspace"),On(p,e.searchQuery),X(x,"title",e.threadOpen?"Close thread":"Open a message thread"),X(x,"aria-label",e.threadOpen?"Close thread":"Open a message thread"),k=lt(x,1,"",null,k,{active:e.sidePanelOpen})}),dn("submit",d,I=>{I.preventDefault(),e.onSearch()}),V("input",p,I=>e.onSearchQuery(I.currentTarget.value)),V("click",x,function(...I){e.onToggleThread?.apply(this,I)}),V("click",g,function(...I){e.onPinnedItems?.apply(this,I)}),L(t,n),He()}Qe(["input","click"]);var Hg=z(''),Wg=z(`
cc
ClickClack OpenClaw workspace chat

Welcome back.

Workspace chat for the OpenClaw crew. Sign in with the GitHub account that's a member of the org.

Limited to active members of the OpenClaw org.

`),Gg=z(''),jg=z(''),Vg=z('
',1);function Kg(t,e){Fe(e,!1);const n=Q(),r=Q(),i=Q(),s=Q(),o=Q(),u=Q(),l=Q(),f=Q(),d=Q(),p=Q(),m=Q();let w=Q(null),y=Q([]),x=Q([]),k=Q([]),g=Q([]),I=Q([]),E=Q(""),A=Q(""),D=Q(""),C=Q(null),U=Q(null),P=Q(null),G=Q(null),K=Q(""),Z=Q(""),Y=Q(""),O=Q(""),W=Q(""),J=Q(""),fe=Q([]),ie=Q(null),B=Q(!1),ae=Q(!1),ce=Q(!1),$=Q(!1),Ae=Q(""),ge=Q(""),De=Q(""),_e=Q(""),Ue=Q(!1),Je=Q(""),se=Q(""),be=Q(!1),Se=Q("loading"),nt=Q(!1),bt=Q(!1),wt=null,rt=Q(null),at=new Map,Pe=Q(new Map),en=new Set,ft=Q("idle"),Ct="idle",Vt=!1,Kt=!1,xn=Q(!1),En=Q(!1),Nn=Q(!1),rn=Q(!1),Ge=new Map,ht=0,Yt=Q(""),rr=Q(void 0),Pt=Q(""),Nt=Q(!0),qn=Q(!1),an=Q(!1),Ve=Q(!1),ke=Q(null),Ke=Q(null),An=Q(null),In=Q(null),yt=Q("message"),pt=Q([]),Zt;is(()=>{xr()}),Ya(()=>{wt?.close(),wt=null,v(bt,!1),Ca(),Zt&&window.clearInterval(Zt)});async function xr(){try{const c=await tt("/api/me");v(w,c.user),await Wr(),v(Se,"ready")}catch(c){if(c instanceof Il&&(c.status===401||c.status===403)){v(nt,!0),v(Se,"auth");return}v(Se,c instanceof Error?c.message:"Could not load ClickClack")}}function Rn(){a(w)&&(v(ge,a(w).display_name),v(De,a(w).handle?`@${a(w).handle}`:""),v(_e,a(w).avatar_url),v(Ue,a(w).notification_settings?.pushover_enabled??!1),v(Je,a(w).notification_settings?.pushover_user_key??""),v(se,""),v(be,!1),v(ae,!0))}async function Hr(){v(se,""),v(be,!1);try{const c=await tt("/api/me",{method:"PATCH",body:JSON.stringify({display_name:a(ge),handle:a(De),avatar_url:a(_e),notification_settings:{pushover_enabled:a(Ue),pushover_user_key:a(Je)}})});v(w,c.user),Un(a(g).map(h=>h.author?.id===a(w)?.id?{...h,author:c.user}:h)),v(I,a(I).map(h=>h.author?.id===a(w)?.id?{...h,author:c.user}:h)),a(C)?.author?.id===a(w).id&&v(C,{...a(C),author:c.user}),v(se,"Saved"),v(ae,!1)}catch(c){v(se,c instanceof Error?c.message:"Could not save profile"),v(be,!0)}}async function Wr(){const c=await tt("/api/workspaces");v(y,c.workspaces),v(E,a(E)||a(y)[0]?.id||""),await H(),await ni(),a(y).length===0&&v(Se,"create a workspace"),ri()}async function $e(){if(!a(Y).trim())return;const c=await tt("/api/workspaces",{method:"POST",body:JSON.stringify({name:a(Y)})});v(Y,""),v(qn,!1),v(y,[...a(y),c.workspace]),v(E,c.workspace.id),v(Ve,!1),await H(),await ni(),ri()}async function M(c){v(E,c),v(Ve,!1),await H(),await ni(),ri()}async function H(){if(!a(E))return;const c=await tt(`/api/workspaces/${a(E)}/channels`);v(x,c.channels),v(A,a(x).find(h=>h.id===a(A))?.id||a(x)[0]?.id||""),v(C,null),v(P,null),v(yt,"message"),v(I,[]),await ue()}async function j(){if(!a(E)||!a(O).trim())return;const c=await tt(`/api/workspaces/${a(E)}/channels`,{method:"POST",body:JSON.stringify({name:a(O),kind:"public"})});v(O,""),v(x,[...a(x),c.channel]),v(A,c.channel.id),v(D,""),v(ce,!1),await ue()}async function F(c){v(A,c),v(D,""),v(C,null),v(P,null),v(yt,"message"),v(Ve,!1),await ue()}async function ue(){ws();const c=ve();c!==a(Yt)&&(hn(),v(Nt,!0));try{if(!a(D)&&!a(A)){St("",Dt({messages:[],oldest_seq:0,newest_seq:0,has_older:!1,has_newer:!1}),"replace");return}const T=await tt(Ye(Ie()));if(ve()!==c)return;St(c,Dt(T),"replace")}finally{ve()===c&&v(Nt,!1)}}async function me(){const c=ve();if(c){hn(),v(Nt,!0),at.set(c,{atBottom:!0});try{const h=await tt(Ye(`limit=${Ra}`));if(ve()!==c)return;St(c,Dt(h),"replace")}finally{ve()===c&&v(Nt,!1)}}}function Ie(){const c=Le(),h=c.unread_count||0,T=c.last_read_seq||0;return h>0?`around_seq=${encodeURIComponent(String(T+1))}&limit=${Ra}`:`limit=${Ra}`}function Le(){return a(D)?a(k).find(c=>c.id===a(D))||{}:a(A)?a(x).find(c=>c.id===a(A))||{}:{}}function Ye(c){const h=a(D)?`/api/dms/${a(D)}/messages`:`/api/channels/${a(A)}/messages`;return c?`${h}?${c}`:h}function Dt(c){return{messages:c.messages,oldest_seq:c.oldest_seq,newest_seq:c.newest_seq,has_older:c.has_older,has_newer:c.has_newer}}function St(c,h,T){const R=de(c,h.messages,T),q=R[0]?.channel_seq||0,pe=R[R.length-1]?.channel_seq||0,Te=q>(h.messages[0]?.channel_seq||q),ze=pe<(h.messages[h.messages.length-1]?.channel_seq||pe),Ze={messages:R,oldest_seq:q,newest_seq:pe,has_older:h.has_older||Te,has_newer:h.has_newer||ze};We(c,Ze),Yn(c,Ze),sc(c,R)}function We(c,h){c&&(a(Pe).delete(c),a(Pe).set(c,h),gt(c),qt(c),v(Pe,new Map(a(Pe))))}function gt(c){let h=a(Pe).size+1;for(;a(Pe).size>Ld&&h>0;){h--;const T=a(Pe).keys().next().value;if(!T)return;if(T===c){const R=a(Pe).get(T);a(Pe).delete(T),R&&a(Pe).set(T,R);continue}a(Pe).delete(T)}}function qt(c){let h=at.size+1;for(;at.size>Pd&&h>0;){h--;const T=at.keys().next().value;if(!T)return;if(T===c){const R=at.get(T);at.delete(T),R&&at.set(T,R);continue}at.delete(T)}}function Yn(c,h=a(Pe).get(c)){c===ve()&&(v(xn,h?.has_older||!1),v(En,h?.has_newer||!1))}function Tt(c){const h=a(Pe).get(c);!c||!h||(We(c,{...h,has_newer:!0}),Yn(c))}function xt(c,h){c==="older"?(v(ft,h),v(Nn,h==="loading")):(Ct=h,v(rn,h==="loading"))}function hn(){en=new Set,v(ft,"idle"),Ct="idle",Vt=!1,Kt=!1,v(Nn,!1),v(rn,!1)}function ar(c,h){const T=new Map;for(const R of[...c,...h])T.set(R.id,R);return[...T.values()].sort((R,q)=>(R.channel_seq||0)-(q.channel_seq||0))}function ya(c){const h=new Set,T=tc(c);if(T>=0){const q=Qa(c,a(g),T);q&&h.add(q.id)}const R=at.get(c)?.anchorMessageID;R&&h.add(R),a(C)&&zn(a(C),c)&&h.add(a(C).id),a(ke)&&zn(a(ke),c)&&h.add(a(ke).id);for(const q of a(g))(q.status==="pending"||q.status==="failed")&&zn(q,c)&&h.add(q.id);return h}function de(c,h,T){return Nd(h,T,ya(c))}function _(){if(a(ft)!=="idle"){Vt=!0;return}ne()}function N(){if(Ct!=="idle"){Kt=!0;return}Ne()}async function ne(){const c=ve(),h=a(Pe).get(c),T=`${c}:older`;if(a(ft)!=="idle"){Vt=!0;return}if(!c||!h?.has_older||h.oldest_seq<=0||en.has(T))return;en.add(T),Vt=!1,xt("older","loading"),ws();let R=!1;try{const q=await tt(Ye(`before_seq=${encodeURIComponent(String(h.oldest_seq))}&limit=${Mi}`));if(ve()!==c)return;const pe=ar(q.messages,a(g));St(c,{messages:pe,oldest_seq:q.oldest_seq||h.oldest_seq,newest_seq:h.newest_seq,has_older:q.has_older,has_newer:h.has_newer},"prepend"),R=!0,xt("older","settling")}catch(q){ve()===c&&v(Se,q instanceof Error?q.message:"Could not load older messages")}finally{en.delete(T),ve()===c&&!R&&xt("older","idle")}}async function Ne(){const c=ve(),h=a(Pe).get(c),T=`${c}:newer`;if(Ct!=="idle"){Kt=!0;return}if(!c||en.has(T))return;if(!h||h.newest_seq<=0){await ue();return}en.add(T),Kt=!1,xt("newer","loading");let R=!1;try{const q=await tt(Ye(`after_seq=${encodeURIComponent(String(h.newest_seq))}&limit=${Mi}`));if(ve()!==c)return;if(q.messages.length===0){St(c,{...h,has_newer:q.has_newer},"append"),R=!0,xt("newer","settling");return}const pe=ar(a(g),q.messages);St(c,{messages:pe,oldest_seq:h.oldest_seq,newest_seq:q.newest_seq||h.newest_seq,has_older:h.has_older,has_newer:q.has_newer},"append"),R=!0,xt("newer","settling")}catch(q){ve()===c&&v(Se,q instanceof Error?q.message:"Could not load newer messages")}finally{en.delete(T),ve()===c&&!R&&xt("newer","idle")}}function kt(c){const h=a(ft)==="settling"&&Vt&&c.nearOlder&&a(xn),T=Ct==="settling"&&Kt&&c.nearNewer&&a(En);a(ft)==="settling"&&xt("older","idle"),Ct==="settling"&&xt("newer","idle"),Vt=!1,Kt=!1,h&&_(),T&&N()}function ve(){return a(D)||a(A)||""}function Et(c,h=a(g)){let T=0;for(const R of h)R.channel_id===c&&(R.parent_message_id||typeof R.channel_seq=="number"&&R.channel_seq>T&&(T=R.channel_seq));return T}function Ut(c,h=a(g)){let T=0;for(const R of h)R.direct_conversation_id===c&&typeof R.channel_seq=="number"&&R.channel_seq>T&&(T=R.channel_seq);return T}function Mt(c,h){return c&&h.unread_count||0}async function Gr(c,h){const T=a(x).find(R=>R.id===c);if(T&&!(h<=0||h<=(T.last_read_seq||0))){v(x,a(x).map(R=>R.id===c?{...R,last_seq:Math.max(R.last_seq||0,h),unread_count:Math.max(0,Math.max(R.last_seq||0,h)-h),last_read_seq:h}:R));try{await tt(`/api/channels/${c}/read`,{method:"POST",body:JSON.stringify({seq:h})})}catch{}}}async function ct(c,h){const T=a(k).find(R=>R.id===c);if(T&&!(h<=0||h<=(T.last_read_seq||0))){v(k,a(k).map(R=>R.id===c?{...R,last_seq:Math.max(R.last_seq||0,h),unread_count:Math.max(0,Math.max(R.last_seq||0,h)-h),last_read_seq:h}:R));try{await tt(`/api/dms/${c}/read`,{method:"POST",body:JSON.stringify({seq:h})})}catch{}}}function ka(c){const h=a(Pe).get(c)?.newest_seq||0,T=a(x).find(q=>q.id===c);if(T)return Math.max(T.last_seq||0,(T.last_read_seq||0)+(T.unread_count||0),Et(c),h);const R=a(k).find(q=>q.id===c);return R?Math.max(R.last_seq||0,(R.last_read_seq||0)+(R.unread_count||0),Ut(c),h):0}function Sa(c){const h=a(Pe).get(c);return!h||h.has_newer?0:a(x).find(q=>q.id===c)?Et(c):a(k).find(q=>q.id===c)?Ut(c):0}function Ta(c={}){if(!c.all&&Date.now()q.id===h)){ct(h,T),c.all&&vs(h,T);return}a(x).some(q=>q.id===h)&&(Gr(h,T),c.all&&vs(h,T))}function vs(c,h){Ge.delete(c),Ge=new Map(Ge),v(x,a(x).map(T=>T.id===c?{...T,last_seq:Math.max(T.last_seq||0,h),last_read_seq:Math.max(T.last_read_seq||0,h),unread_count:0}:T)),v(k,a(k).map(T=>T.id===c?{...T,last_seq:Math.max(T.last_seq||0,h),last_read_seq:Math.max(T.last_read_seq||0,h),unread_count:0}:T))}function ec(c){const h=a(x).find(R=>R.id===c);return h?h.last_read_seq||0:a(k).find(R=>R.id===c)?.last_read_seq||0}function tc(c){const h=a(x).find(R=>R.id===c);if(h)return Mt(c,h)>0?h.last_read_seq||0:-1;const T=a(k).find(R=>R.id===c);return T&&Mt(c,T)>0?T.last_read_seq||0:-1}function Qa(c,h,T){for(const R of h){if(!zn(R,c)||R.parent_message_id||R.author?.id===a(w)?.id||R.author_id===a(w)?.id)continue;const q=R.channel_seq;if(typeof q=="number"&&q>T)return R}return null}function nc(c,h){if(!c)return;const T=ac(c);if(Mt(c,T)<=0){Ge.delete(c),Ge=new Map(Ge);return}const q=T.last_read_seq||0,pe=Ge.get(c);if(pe?.boundarySeq===q&&pe.since||!Ja(c,q))return;const Te=Qa(c,h,q);Te&&(Ge=new Map(Ge).set(c,{boundarySeq:q,since:$a(Te.created_at)}))}function ms(c,h,T){if(!c||!T)return;const R=Ge.get(c);R?.boundarySeq===h&&R.since||(Ge=new Map(Ge).set(c,{boundarySeq:h,since:$a(T)}))}function _s(c){const h=c.payload,T=c.seq??h.channel_seq??h.seq;return typeof T=="number"?T:Number(T)||0}function bs(c){const h=c.payload;return{channelID:c.channel_id||(typeof h.channel_id=="string"?h.channel_id:""),dmID:typeof h.direct_conversation_id=="string"?h.direct_conversation_id:""}}function rc(c){if(c.type!=="message.created")return!1;const h=_s(c);if(h<=0)return!1;const{channelID:T,dmID:R}=bs(c);if(T){const q=a(x).find(pe=>pe.id===T);return h<=(q?.last_seq||0)}if(R){const q=a(k).find(pe=>pe.id===R);return h<=(q?.last_seq||0)}return!1}function ac(c){return a(x).find(h=>h.id===c)||a(k).find(h=>h.id===c)||{}}function Ja(c,h,T=a(Pe)){if(!c||h<0)return!1;const R=T.get(c);if(!R||R.messages.length===0)return!1;const q=h+1;return R.oldest_seq<=q&&R.newest_seq>=q}function ic(c,h,T=a(Pe)){const R=Ge.get(c);if(R?.boundarySeq===h)return R.since;if(!Ja(c,h,T))return"";const q=Qa(c,a(g),h);return q?$a(q.created_at):""}function $a(c){const h=new Date(c);return Number.isNaN(h.getTime())?"":new Intl.DateTimeFormat(void 0,{hour:"numeric",minute:"2-digit"}).format(h)}function ws(){if(!a(Yt)||!a(rt))return;const c=a(rt).captureState();c&&at.set(a(Yt),c)}function sc(c,h){const T=c!==a(Yt);v(rr,at.get(c));const R=a(g).filter(re=>(re.status==="pending"||re.status==="failed")&&zn(re,c)),q=new Map(R.map(re=>[re.id,re])),pe=new Map(R.filter(re=>re.nonce).map(re=>[re.nonce,re])),Te=h.map(re=>{const xe=q.get(re.id)||(re.nonce?pe.get(re.nonce):void 0);return xe?re.nonce&&Er.has(re.nonce)?{...re,nonce:xe.nonce,status:xe.status,attachments:xe.attachments?.length?xe.attachments:re.attachments}:{...re,nonce:xe.nonce,attachments:xe.attachments?.length?xe.attachments:re.attachments}:re}),ze=new Set(Te.map(re=>re.id)),Ze=new Set(Te.map(re=>re.nonce).filter(Boolean)),it=a(g).filter(re=>(re.status==="pending"||re.status==="failed")&&re.id.startsWith("tmp_")&&!ze.has(re.id)&&!(re.nonce&&Ze.has(re.nonce))&&zn(re,c));v(g,it.length>0?[...Te,...it]:Te),v(Yt,c),nc(c,a(g)),T&&(v(pt,[]),Ca())}function Un(c,h="append"){const T=ve(),R=T?a(Pe).get(T):void 0;if(!T||!R){v(g,c);return}const q=c.filter(xe=>zn(xe,T)),pe=de(T,q,h),Te=pe.filter(xe=>(xe.channel_seq||0)>0),ze=Te[0]?.channel_seq||R.oldest_seq,Ze=Te[Te.length-1]?.channel_seq||R.newest_seq,it=xa(pe[0])>xa(q[0]),re=xa(pe[pe.length-1])0)&&await me(),await ei(),Ta({all:!0})}catch(c){v(Se,c instanceof Error?c.message:"Could not jump to latest messages")}}let Er=new Map;function lc(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID().replace(/-/g,""):`${Date.now().toString(36)}${Math.random().toString(36).slice(2,10)}`}function cc(c,h,T=`tmp_${c}`){const R=new Date().toISOString();return{id:T,workspace_id:h.workspaceID,channel_id:h.channelID,direct_conversation_id:h.directConversationID,author_id:a(w)?.id||"",thread_root_id:T,body:h.body,body_format:"markdown",created_at:R,author:a(w)||void 0,attachments:h.upload?[h.upload]:[],quoted_message_id:h.quotedMessageID,nonce:c,status:"pending"}}async function ys(){const c=a(K).trim();if(!c)return;if(!a(A)&&!a(D)){v(Se,"pick or create a channel");return}Ca();const h=a(D)?"dm":"channel",T=a(ke)&&a(Ke)===h?a(ke):null,R={body:c,quotedMessageID:T?.id,upload:a(ie)||void 0,workspaceID:a(E),channelID:a(A)||void 0,directConversationID:a(D)||void 0,viewKey:ve()};v(K,""),T&&pn(),v(ie,null),await ks(R)}async function ks(c,h,T){const R=h??lc(),q=`tmp_${R}`,pe=T??q;Er.set(R,c);const Te=cc(R,c,pe);if(h)Un(a(g).map(it=>it.id===pe?Te:it));else if(ve()===c.viewKey){const it=a(rt)?.isAtBottom()!==!1;Un([...a(g),Te]),it&&ei()}const ze=c.directConversationID?`/api/dms/${c.directConversationID}/messages`:`/api/channels/${c.channelID}/messages`,Ze={body:c.body,nonce:R};c.quotedMessageID&&(Ze.quoted_message_id=c.quotedMessageID);try{let re=(await tt(ze,{method:"POST",body:JSON.stringify(Ze)})).message;if(c.upload)try{await tt(`/api/messages/${re.id}/attachments`,{method:"POST",body:JSON.stringify({upload_id:c.upload.id})}),re={...re,attachments:[...re.attachments||[],c.upload]}}catch(et){console.warn("attachment failed",et);const Cn={...re,nonce:R,status:"failed",attachments:c.upload?[...re.attachments||[],c.upload]:re.attachments};Un(a(g).map(Bn=>Bn.id===pe?Cn:Bn));return}Er.delete(R),a(g).findIndex(et=>et.id===pe)>=0?Un(a(g).map(et=>et.id===pe?re:et)):a(g).some(et=>et.id===re.id)?Un(a(g).map(et=>et.id===re.id?re:et)):zn(re,ve())&&!a(g).some(et=>et.id===re.id)&&Un([...a(g),re])}catch(it){console.warn("send failed",it),Un(a(g).map(re=>re.id===pe?{...re,status:"failed"}:re))}}function uc(c){if(!c.nonce)return;const h=Er.get(c.nonce);if(!h){Ss(c);return}ks({...h,viewKey:h.viewKey},c.nonce,c.id)}function Ss(c){c.nonce&&Er.delete(c.nonce),Un(a(g).filter(h=>h.id!==c.id))}async function Ts(c){v(P,null),v(C,c),v(yt,"thread");const h=await tt(`/api/messages/${c.id}/thread`);v(C,h.root),v(I,h.replies),v(U,h.thread_state)}async function xs(){const c=a(Z).trim();if(!c||!a(C))return;const h=a(ke)&&a(Ke)==="thread"?a(ke):null;v(Z,"");const T={body:c};h&&(T.quoted_message_id=h.id);const R=await tt(`/api/messages/${a(C).id}/thread/replies`,{method:"POST",body:JSON.stringify(T)});h&&pn(),a(I).some(q=>q.id===R.message.id)||v(I,[...a(I),R.message]),v(U,R.thread_state)}function Es(c,h){v(ke,c),v(Ke,h),v(yt,h==="thread"?"thread":"message")}function As(){return a(G)!==null||a(ae)||a(ce)||a($)}function dc(){return a(yt)==="thread"&&a(C)&&a(In)?a(In):a(An)}function pn(){v(ke,null),v(Ke,null)}async function Is(c){const h=c.quoted_message_id;if(!h)return;if(a(rt)?.scrollToMessage(h)??!1){await Rs(h);return}const R=await tt(`/api/messages/${h}`);zn(R.message,ve())&&await ti(R.message)}async function fc(){ht=Date.now()+1200,!(a(l)&&a(rt)?.scrollToDivider(!1))&&await hc()}async function hc(){const c=ve();if(!c)return;ht=Date.now()+1200;const h=ec(c),T=Ge.get(c),q=(T?.boundarySeq===h?T.boundarySeq:h)+1;q<=0||(await Cs(q),await ur(),a(rt)?.scrollToDivider(!1))}async function Rs(c){await ur();const h=document.querySelector(`[data-message-id="${CSS.escape(c)}"]`);h&&(h.classList.add("highlight"),window.setTimeout(()=>h.classList.remove("highlight"),1500))}async function pc(){if(!a(E)||!a(J).trim()){v(fe,[]);return}if(a(D)){v(fe,[]);return}const c=new URLSearchParams({workspace_id:a(E),q:a(J).trim()});a(A)&&c.set("channel_id",a(A));const h=await tt(`/api/search?${c.toString()}`);v(fe,h.results)}function gc(){v(J,""),v(fe,[])}async function vc(c){v(fe,[]),c.message.channel_id&&(v(A,c.message.channel_id),v(D,""),await ti(c.message)),c.message.direct_conversation_id&&(v(D,c.message.direct_conversation_id),v(A,""),await ti(c.message))}async function ti(c){const h=c.channel_seq||0;if(h<=0){await ue();return}await Cs(h,c.id)}async function Cs(c,h=""){const T=ve();if(!T)return;h&&at.set(T,{atBottom:!1,anchorMessageID:h,anchorPixelOffset:0}),T!==a(Yt)&&(hn(),v(Nt,!0));try{const q=await tt(Ye(`around_seq=${encodeURIComponent(String(c))}&limit=${Ra}`));if(ve()!==T)return;St(T,Dt(q),"around"),await ur(),h&&(a(rt)?.scrollToMessage(h),await Rs(h))}finally{ve()===T&&v(Nt,!1)}}async function mc(c){const h=c.currentTarget,T=h.files?.[0];if(!T||!a(E))return;const R=await Cd(T),q=new FormData;q.set("workspace_id",a(E)),q.set("file",T),R.width>0&&q.set("width",String(R.width)),R.height>0&&q.set("height",String(R.height)),R.durationMS>0&&q.set("duration_ms",String(R.durationMS));const pe=await tt("/api/uploads",{method:"POST",body:q});v(ie,pe.upload),h.value=""}async function ni(){if(!a(E))return;const c=await tt(`/api/dms?workspace_id=${a(E)}`);v(k,c.conversations)}async function _c(c){const h=c.trim();h&&(await Ds(h),v(W,""),v($,!1))}async function bc(c){v(D,c),v(A,""),v(C,null),v(P,null),v(yt,"message"),v(Ve,!1),await ue()}async function Ds(c){const h=c.trim();if(!a(E)||!h)return;const T=a(k).find(q=>q.members.some(pe=>pe.id===h));if(T){v(D,T.id),v(A,""),v(C,null),v(P,null),v(yt,"message"),v(Ve,!1),await ue();return}const R=await tt("/api/dms",{method:"POST",body:JSON.stringify({workspace_id:a(E),member_ids:[h]})});v(k,[...a(k),R.conversation]),v(D,R.conversation.id),v(A,""),v(C,null),v(P,null),v(yt,"message"),v(Ve,!1),await ue()}function ri(){wt?.close(),wt=null,v(bt,!1),a(E)&&(wt=Qd({workspaceID:a(E),onEvent:c=>{wc(c)},onStatusChange:c=>v(bt,c)}))}async function wc(c){if(c.type==="typing.started"||c.type==="typing.stopped"){kc(c);return}if(c.type==="channel.read"||c.type==="dm.read"){yc(c);return}if((c.type==="channel.created"||c.type==="channel.updated")&&c.workspace_id===a(E)){await H();return}if(rc(c))return;const h=c.channel_id===a(A)||c.payload.direct_conversation_id===a(D);if(c.type==="message.created"&&!h&&Ms(c),h&&(c.type==="message.created"||c.type==="message.updated"||c.type==="message.deleted")){const R=c.payload.nonce;if(c.type==="message.created"&&R&&Er.has(R))return;const q=a(rt)?.isAtBottom()!==!1;c.type==="message.created"&&!q?(ht=Date.now()+1200,Tt(ve())):c.type==="message.created"?await Ne():await ue(),c.type==="message.created"&&Ms(c,q),c.type==="message.created"&&q&&ei(),c.type==="message.created"&&q&&Ta()}const T=c.payload.root_message_id||c.payload.message_id;a(C)&&T===a(C).id&&await Ts(a(C))}function yc(c){const h=c.payload,T=typeof h.user_id=="string"?h.user_id:"";if(!T||T!==a(w)?.id)return;const R=c.seq??h.last_read_seq??h.seq,q=typeof R=="number"?R:Number(R)||0;if(c.type==="channel.read"){const pe=typeof h.channel_id=="string"?h.channel_id:c.channel_id||"";if(!pe)return;v(x,a(x).map(Te=>{if(Te.id!==pe)return Te;const ze=Math.max(Te.last_read_seq||0,q);return{...Te,last_read_seq:ze,unread_count:Math.max(0,(Te.last_seq||0)-ze)}}))}else{const pe=typeof h.direct_conversation_id=="string"?h.direct_conversation_id:"";if(!pe)return;v(k,a(k).map(Te=>{if(Te.id!==pe)return Te;const ze=Math.max(Te.last_read_seq||0,q);return{...Te,last_read_seq:ze,unread_count:Math.max(0,(Te.last_seq||0)-ze)}}))}}function Ms(c,h){const T=c.payload,R=typeof T.author_id=="string"?T.author_id:"";if(R&&R===a(w)?.id||T.parent_message_id)return;const q=_s(c),{channelID:pe,dmID:Te}=bs(c);if(pe){const ze=pe===a(A)&&!a(D),Ze=ze?h??a(rt)?.isAtBottom()!==!1:!1,it=a(x).find(xe=>xe.id===pe),re=q>0?q:(it?.last_seq||0)+1;ze&&!Ze&&(it?.unread_count||0)===0&&ms(pe,it?.last_read_seq||0,c.created_at),v(x,a(x).map(xe=>{if(xe.id!==pe)return xe;const et=Math.max(xe.last_seq||0,re),Cn=ze&&!Ze&&(xe.unread_count||0)===0?Math.max(xe.last_read_seq||0,re-1):xe.last_read_seq||0,Bn=ze&&Ze?xe.unread_count||0:Math.max(0,et-Cn);return{...xe,last_seq:et,last_read_seq:Cn,unread_count:Bn}}))}else if(Te){const ze=Te===a(D),Ze=ze?h??a(rt)?.isAtBottom()!==!1:!1,it=a(k).find(xe=>xe.id===Te),re=q>0?q:(it?.last_seq||0)+1;ze&&!Ze&&(it?.unread_count||0)===0&&ms(Te,it?.last_read_seq||0,c.created_at),v(k,a(k).map(xe=>{if(xe.id!==Te)return xe;const et=Math.max(xe.last_seq||0,re),Cn=ze&&!Ze&&(xe.unread_count||0)===0?Math.max(xe.last_read_seq||0,re-1):xe.last_read_seq||0,Bn=ze&&Ze?xe.unread_count||0:Math.max(0,et-Cn);return{...xe,last_seq:et,last_read_seq:Cn,unread_count:Bn}}))}}function kc(c){const h=c.payload,T=typeof h.user_id=="string"?h.user_id:"";if(!T||T===a(w)?.id)return;const R=c.channel_id||(typeof h.channel_id=="string"?h.channel_id:""),q=typeof h.direct_conversation_id=="string"?h.direct_conversation_id:"";if(!(a(A)&&R===a(A)||a(D)&&q===a(D)))return;if(c.type==="typing.stopped"){v(pt,a(pt).filter(Ze=>Ze.userID!==T));return}const Te=Sc(T),ze=a(pt).filter(Ze=>Ze.userID!==T);ze.push({userID:T,user:Te,expiresAt:Date.now()+qp}),v(pt,ze),Tc()}function Sc(c){if(a(w)?.id===c)return a(w);const h=a(g).find(T=>T.author?.id===c)?.author;if(h)return h;for(const T of a(k)){const R=T.members.find(q=>q.id===c);if(R)return R}}function Tc(){Zt||(Zt=window.setInterval(()=>{const c=Date.now(),h=a(pt).filter(T=>T.expiresAt>c);h.length!==a(pt).length&&v(pt,h),h.length===0&&Zt&&(window.clearInterval(Zt),Zt=void 0)},1e3))}function xc(){a(E)&&(!a(A)&&!a(D)||nf({workspaceID:a(E),channelID:a(A)||void 0,directConversationID:a(D)||void 0}))}function Os(c){c&&(v(C,null),v(P,c))}function Ec(c){if(c.key==="Escape"&&a(ke)&&a(Ke)!=="thread"){c.preventDefault(),pn();return}c.key==="Enter"&&!c.shiftKey&&(c.preventDefault(),ys())}function Ac(c){if(c.key==="Escape"&&a(ke)&&a(Ke)==="thread"){c.preventDefault(),pn();return}c.key==="Enter"&&!c.shiftKey&&(c.preventDefault(),xs())}function ai(c,h){v(G,{url:c,title:h})}function Ls(c){const h=c.target;h instanceof HTMLImageElement&&h.closest(".markdown")&&(c.preventDefault(),ai(h.currentSrc||h.src,h.alt||"Image"))}function ii(c){const h=a(K)&&!a(K).endsWith(` `)?` `:"";v(K,`${a(K)}${h}${c}`)}function Ic(c,h=c){ii(`${c}${c==="```"?` code -`:"text"}${h}`)}function Rc(c,h){ii(`![${h}](${c})`),v(B,!1),v(Ae,"")}function si(){a(Ke)==="thread"&&pn(),v(C,null),v(P,null),v(yt,"message"),v(A,[])}function Cc(){a(d)?si():v(Se,"pick a message to open its thread")}function jr(){v(G,null),v(ae,!1),v(ce,!1),v($,!1)}function Ps(){v(Ve,!1)}zt(()=>(a(y),a(E)),()=>{v(n,a(y).find(c=>c.id===a(E)))}),zt(()=>(a(x),a(I)),()=>{v(r,a(x).find(c=>c.id===a(I)))}),zt(()=>(a(k),a(D)),()=>{v(i,a(k).find(c=>c.id===a(D)))}),zt(()=>(a(D),a(I)),()=>{v(Pt,a(D)||a(I)||"")}),zt(()=>(a(D),a(k),a(I),a(x)),()=>{v(s,a(D)?a(k).find(c=>c.id===a(D))||{}:a(I)?a(x).find(c=>c.id===a(I))||{}:{})}),zt(()=>(a(Pt),a(s)),()=>{v(o,Mt(a(Pt),a(s)))}),zt(()=>(a(o),a(s)),()=>{v(u,a(o)>0&&a(s).last_read_seq||0)}),zt(()=>(a(o),a(Pt),a(u),a(Pe)),()=>{v(l,a(o)>0?Ja(a(Pt),a(u),a(Pe)):!1)}),zt(()=>(a(o),a(Pt),a(u),a(Pe)),()=>{v(f,a(o)>0?ic(a(Pt),a(u),a(Pe)):"")}),zt(()=>(a(C),a(P)),()=>{v(d,a(C)!==null||a(P)!==null)}),zt(()=>(a(g),a(k),a(w)),()=>{v(p,Fd(a(g),a(k),a(w)?.id||""))}),zt(()=>(a(Ke),a(ke),a(g)),()=>{a(Ke)==="channel"&&a(ke)&&!a(g).some(c=>c.id===a(ke)?.id)&&pn()}),zt(()=>(a(Ke),a(ke),a(g)),()=>{a(Ke)==="dm"&&a(ke)&&!a(g).some(c=>c.id===a(ke)?.id)&&pn()}),zt(()=>(a(Ke),a(ke),a(C),a(A)),()=>{a(Ke)==="thread"&&a(ke)&&a(C)&&a(ke).id!==a(C).id&&!a(A).some(c=>c.id===a(ke)?.id)&&pn()}),zt(()=>(a(B),a(Ae)),()=>{v(m,a(B)?Od.filter(c=>{const h=a(Ae).trim().toLowerCase();return!h||c.title.toLowerCase().includes(h)||c.tags.some(T=>T.includes(h))}):[])}),Yu(),Al();var Ns=Sn();yl("1oa2eo8",c=>{var h=Hg();L(c,h)}),dn("keydown",xi,c=>{if(c.key==="Escape")if(As())jr();else if(a(Ve)){c.preventDefault(),Ps();return}else if(a(ke)){c.preventDefault(),pn();return}else{c.preventDefault(),oc();return}Xd(c,{authRequired:a(nt),isModalOpen:()=>As()||a(Ve),messageInput:a(An),replyInput:a(In),target:dc})});var Dc=Gt(Ns);{var Mc=c=>{var h=Wg();L(c,h)},Oc=c=>{var h=Vg(),T=Gt(h);let R;var q=b(T),pe=b(q);{var Te=he=>{var Re=Xn("×");L(he,Re)},ze=he=>{var Re=Gg();L(he,Re)};oe(pe,he=>{a(Ve)?he(Te):he(ze,-1)})}var Ze=S(q,2);{var it=he=>{var Re=jg();V("click",Re,Ps),L(he,Re)};oe(Ze,he=>{a(Ve)&&he(it)})}var re=S(Ze,2);Xp(re,{get workspaces(){return a(y)},get selectedWorkspaceID(){return a(E)},get workspaceName(){return a(Y)},get showWorkspaceCreate(){return a(qn)},onSelectWorkspace:he=>{M(he)},onToggleWorkspaceCreate:()=>v(qn,!a(qn)),onWorkspaceName:he=>v(Y,he),onCreateWorkspace:()=>{$e()}});var xe=S(re,2);{let he=Ot(()=>(a(n),_t(()=>a(n)?.name)));fg(xe,{get workspaceName(){return a(he)},get status(){return a(Se)},get connected(){return a(bt)},get sidebarCollapsed(){return a(an)},get channels(){return a(x)},get directConversations(){return a(k)},get recentPeople(){return a(p)},get currentUser(){return a(w)},get selectedChannelID(){return a(I)},get selectedDirectID(){return a(D)},get selectedProfile(){return a(P)},onToggleCollapse:()=>v(an,!a(an)),onSelectChannel:Re=>{F(Re)},onCreateChannel:()=>v(ce,!0),onSelectDirect:Re=>{bc(Re)},onCreateDirect:()=>v($,!0),onOpenProfile:Os,onOpenSettings:Rn})}var et=S(xe,2),Cn=b(et);{let he=Ot(()=>(a(n),_t(()=>a(n)?.name))),Re=Ot(()=>(a(w),_t(()=>a(w)?.id))),Xe=Ot(()=>a(C)!==null);Fg(Cn,{get selectedDirect(){return a(i)},get selectedChannel(){return a(r)},get workspaceName(){return a(he)},get currentUserID(){return a(Re)},get searchQuery(){return a(J)},get sidePanelOpen(){return a(d)},get threadOpen(){return a(Xe)},onSearchQuery:Fn=>v(J,Fn),onSearch:()=>{pc()},onResetSearch:gc,onToggleThread:Cc,onPinnedItems:()=>v(Se,"no pinned items")})}var Bn=S(Cn,2);Eg(Bn,{get results(){return a(fe)},onClose:()=>v(fe,[]),onOpenResult:he=>{vc(he)}});var qs=S(Bn,2);{let he=Ot(()=>a(ft)!=="idle"),Re=Ot(()=>(a(C),_t(()=>a(C)?.id))),Xe=Ot(()=>(a(w),_t(()=>a(w)?.id)));Np(qs,{get messages(){return a(g)},get selectedDirect(){return a(i)},get selectedChannel(){return a(r)},get restoreState(){return a(rr)},get viewKey(){return a(Yt)},get loading(){return a(Nt)},get unreadCount(){return a(o)},get unreadBoundarySeq(){return a(u)},get unreadBoundaryLoaded(){return a(l)},get unreadSince(){return a(f)},get hasOlder(){return a(xn)},get hasNewer(){return a(En)},get loadingOlder(){return a(Nn)},get loadingNewer(){return a(rn)},get prepending(){return a(he)},get selectedThreadID(){return a(Re)},get currentUserID(){return a(Xe)},onListRef:Fn=>v(rt,Fn),onActivateMessageComposer:()=>v(yt,"message"),onInlineImagePointerUp:Ls,onOpenProfile:Os,onReply:Es,onOpenThread:Ts,onJumpToQuote:Fn=>{Is(Fn)},onOpenImage:ai,onLoadOlder:_,onLoadNewer:()=>N(),onJumpToUnread:()=>{fc()},onHistorySettled:kt,onReachedBottom:Ta,onMarkRead:Fn=>{Ta({all:!0,seq:Fn})},onRetry:uc,onDiscard:Ss})}var Us=S(qs,2);{let he=Ot(()=>(a(w),_t(()=>a(w)?.id)));zp(Us,{get entries(){return a(pt)},get currentUserID(){return a(he)}})}var Lc=S(Us,2);{let he=Ot(()=>(a(i),rs(da),a(w),a(r),_t(()=>a(i)?`Message ${da(a(i),a(w)?.id)}`:a(r)?`Message #${a(r).name}`:"Pick a channel to start"))),Re=Ot(()=>a(ke)&&a(Ke)===(a(D)?"dm":"channel")?a(ke):null);Ml(Lc,{get value(){return a(K)},get placeholder(){return a(he)},ariaLabel:"Message body",submitLabel:"Send",get pendingUpload(){return a(ie)},get replyTarget(){return a(Re)},showUpload:!0,showToolbar:!0,get showGifPicker(){return a(B)},get gifQuery(){return a(Ae)},get filteredGifs(){return a(m)},onValue:Xe=>{const Fn=a(K);v(K,Xe),Xe.trim()&&Xe!==Fn?xc():Xe.trim()||Ca()},onSubmit:()=>{ys()},onKeydown:Ec,onFocus:()=>v(yt,"message"),onInputRef:Xe=>v(An,Xe),onUploadFile:mc,onRemoveUpload:()=>v(ie,null),onClearReply:pn,onApplyMarkdownWrap:Ic,onAppendToComposer:ii,onToggleGif:()=>v(B,!a(B)),onGifQuery:Xe=>v(Ae,Xe),onPickGif:Rc})}var Ea=S(et,2);let zs;var Pc=b(Ea);{var Nc=he=>{{let Re=Ot(()=>a(ke)&&a(Ke)==="thread"?a(ke):null);Pg(he,{get root(){return a(C)},get replies(){return a(A)},get threadState(){return a(U)},get replyBody(){return a(Z)},get replyTarget(){return a(Re)},onClose:si,onReplyBody:Xe=>v(Z,Xe),onSubmitReply:()=>{xs()},onReplyKeydown:Ac,onReplyFocus:()=>v(yt,"thread"),onReplyInputRef:Xe=>v(In,Xe),onSetReplyTarget:Es,onClearReply:pn,onActivateThreadComposer:()=>v(yt,"thread"),onInlineImagePointerUp:Ls,onJumpToQuote:Xe=>{Is(Xe)},onOpenImage:ai})}},qc=he=>{{let Re=Ot(()=>(a(n),_t(()=>a(n)?.name)));wg(he,{get profile(){return a(P)},get currentUser(){return a(w)},get workspaceName(){return a(Re)},onClose:si,onEdit:Rn,onMessage:Xe=>{Ds(Xe)},onSetStatus:()=>v(Se,"status messages are coming soon")})}},Uc=he=>{Ig(he)};oe(Pc,he=>{a(C)?he(Nc):a(P)?he(qc,1):he(Uc,-1)})}var Bs=S(T,2);{var zc=he=>{Sg(he,{get user(){return a(w)},get displayName(){return a(ge)},get handle(){return a(De)},get avatarURL(){return a(_e)},get pushoverEnabled(){return a(Ue)},get pushoverUserKey(){return a(Je)},get status(){return a(se)},get statusError(){return a(be)},onDisplayName:Re=>v(ge,Re),onHandle:Re=>v(De,Re),onAvatarURL:Re=>v(_e,Re),onPushoverEnabled:Re=>v(Ue,Re),onPushoverUserKey:Re=>v(Je,Re),onClose:jr,onSave:()=>{Hr()}})};oe(Bs,he=>{a(ae)&&a(w)&&he(zc)})}var Fs=S(Bs,2);{var Bc=he=>{Hp(he,{get channelName(){return a(O)},status:"",onChannelName:Re=>v(O,Re),onClose:jr,onCreate:()=>{j()}})};oe(Fs,he=>{a(ce)&&he(Bc)})}var Hs=S(Fs,2);{var Fc=he=>{{let Re=Ot(()=>(a(w),_t(()=>a(w)?.id)));Vp(he,{get people(){return a(p)},get currentUserID(){return a(Re)},get memberID(){return a(W)},onMemberID:Xe=>v(W,Xe),onClose:jr,onStart:Xe=>{_c(Xe)}})}};oe(Hs,he=>{a($)&&he(Fc)})}var Hc=S(Hs,2);{var Wc=he=>{kf(he,{get url(){return a(G),_t(()=>a(G).url)},get title(){return a(G),_t(()=>a(G).title)},onClose:jr})};oe(Hc,he=>{a(G)&&he(Wc)})}te(()=>{R=lt(T,1,"shell",null,R,{"nav-open":a(Ve),"sidebar-collapsed":a(an),"thread-open":a(d)}),X(q,"aria-expanded",a(Ve)),et.inert=a(Ve),zs=lt(Ea,1,"thread",null,zs,{open:a(d)}),Ea.inert=a(Ve),X(Ea,"aria-label",a(P)?"Profile pane":"Thread pane")}),V("click",q,()=>v(Ve,!a(Ve))),L(c,h)};oe(Dc,c=>{a(nt)?c(Mc):c(Oc,-1)})}L(t,Ns),He()}Qe(["click"]);var Yg=z(' ',1),Zg=z("

"),Xg=z(`

Self-hostable chat. Serious tool. Mild brine.

ClickClack

A single-binary chat app for teams, communities, bots, and agents: +`:"text"}${h}`)}function Rc(c,h){ii(`![${h}](${c})`),v(B,!1),v(Ae,"")}function si(){a(Ke)==="thread"&&pn(),v(C,null),v(P,null),v(yt,"message"),v(I,[])}function Cc(){a(d)?si():v(Se,"pick a message to open its thread")}function jr(){v(G,null),v(ae,!1),v(ce,!1),v($,!1)}function Ps(){v(Ve,!1)}zt(()=>(a(y),a(E)),()=>{v(n,a(y).find(c=>c.id===a(E)))}),zt(()=>(a(x),a(A)),()=>{v(r,a(x).find(c=>c.id===a(A)))}),zt(()=>(a(k),a(D)),()=>{v(i,a(k).find(c=>c.id===a(D)))}),zt(()=>(a(D),a(A)),()=>{v(Pt,a(D)||a(A)||"")}),zt(()=>(a(D),a(k),a(A),a(x)),()=>{v(s,a(D)?a(k).find(c=>c.id===a(D))||{}:a(A)?a(x).find(c=>c.id===a(A))||{}:{})}),zt(()=>(a(Pt),a(s)),()=>{v(o,Mt(a(Pt),a(s)))}),zt(()=>(a(o),a(s)),()=>{v(u,a(o)>0&&a(s).last_read_seq||0)}),zt(()=>(a(o),a(Pt),a(u),a(Pe)),()=>{v(l,a(o)>0?Ja(a(Pt),a(u),a(Pe)):!1)}),zt(()=>(a(o),a(Pt),a(u),a(Pe)),()=>{v(f,a(o)>0?ic(a(Pt),a(u),a(Pe)):"")}),zt(()=>(a(C),a(P)),()=>{v(d,a(C)!==null||a(P)!==null)}),zt(()=>(a(g),a(k),a(w)),()=>{v(p,Fd(a(g),a(k),a(w)?.id||""))}),zt(()=>(a(Ke),a(ke),a(g)),()=>{a(Ke)==="channel"&&a(ke)&&!a(g).some(c=>c.id===a(ke)?.id)&&pn()}),zt(()=>(a(Ke),a(ke),a(g)),()=>{a(Ke)==="dm"&&a(ke)&&!a(g).some(c=>c.id===a(ke)?.id)&&pn()}),zt(()=>(a(Ke),a(ke),a(C),a(I)),()=>{a(Ke)==="thread"&&a(ke)&&a(C)&&a(ke).id!==a(C).id&&!a(I).some(c=>c.id===a(ke)?.id)&&pn()}),zt(()=>(a(B),a(Ae)),()=>{v(m,a(B)?Od.filter(c=>{const h=a(Ae).trim().toLowerCase();return!h||c.title.toLowerCase().includes(h)||c.tags.some(T=>T.includes(h))}):[])}),Yu(),Al();var Ns=Sn();yl("1oa2eo8",c=>{var h=Hg();L(c,h)}),dn("keydown",xi,c=>{if(c.key==="Escape")if(As())jr();else if(a(Ve)){c.preventDefault(),Ps();return}else if(a(ke)){c.preventDefault(),pn();return}else{c.preventDefault(),oc();return}Xd(c,{authRequired:a(nt),isModalOpen:()=>As()||a(Ve),messageInput:a(An),replyInput:a(In),target:dc})});var Dc=Gt(Ns);{var Mc=c=>{var h=Wg();L(c,h)},Oc=c=>{var h=Vg(),T=Gt(h);let R;var q=b(T),pe=b(q);{var Te=he=>{var Re=Xn("×");L(he,Re)},ze=he=>{var Re=Gg();L(he,Re)};oe(pe,he=>{a(Ve)?he(Te):he(ze,-1)})}var Ze=S(q,2);{var it=he=>{var Re=jg();V("click",Re,Ps),L(he,Re)};oe(Ze,he=>{a(Ve)&&he(it)})}var re=S(Ze,2);Xp(re,{get workspaces(){return a(y)},get selectedWorkspaceID(){return a(E)},get workspaceName(){return a(Y)},get showWorkspaceCreate(){return a(qn)},onSelectWorkspace:he=>{M(he)},onToggleWorkspaceCreate:()=>v(qn,!a(qn)),onWorkspaceName:he=>v(Y,he),onCreateWorkspace:()=>{$e()}});var xe=S(re,2);{let he=Ot(()=>(a(n),_t(()=>a(n)?.name)));fg(xe,{get workspaceName(){return a(he)},get status(){return a(Se)},get connected(){return a(bt)},get sidebarCollapsed(){return a(an)},get channels(){return a(x)},get directConversations(){return a(k)},get recentPeople(){return a(p)},get currentUser(){return a(w)},get selectedChannelID(){return a(A)},get selectedDirectID(){return a(D)},get selectedProfile(){return a(P)},onToggleCollapse:()=>v(an,!a(an)),onSelectChannel:Re=>{F(Re)},onCreateChannel:()=>v(ce,!0),onSelectDirect:Re=>{bc(Re)},onCreateDirect:()=>v($,!0),onOpenProfile:Os,onOpenSettings:Rn})}var et=S(xe,2),Cn=b(et);{let he=Ot(()=>(a(n),_t(()=>a(n)?.name))),Re=Ot(()=>(a(w),_t(()=>a(w)?.id))),Xe=Ot(()=>a(C)!==null);Fg(Cn,{get selectedDirect(){return a(i)},get selectedChannel(){return a(r)},get workspaceName(){return a(he)},get currentUserID(){return a(Re)},get searchQuery(){return a(J)},get sidePanelOpen(){return a(d)},get threadOpen(){return a(Xe)},onSearchQuery:Fn=>v(J,Fn),onSearch:()=>{pc()},onResetSearch:gc,onToggleThread:Cc,onPinnedItems:()=>v(Se,"no pinned items")})}var Bn=S(Cn,2);Eg(Bn,{get results(){return a(fe)},onClose:()=>v(fe,[]),onOpenResult:he=>{vc(he)}});var qs=S(Bn,2);{let he=Ot(()=>a(ft)!=="idle"),Re=Ot(()=>(a(C),_t(()=>a(C)?.id))),Xe=Ot(()=>(a(w),_t(()=>a(w)?.id)));Np(qs,{get messages(){return a(g)},get selectedDirect(){return a(i)},get selectedChannel(){return a(r)},get restoreState(){return a(rr)},get viewKey(){return a(Yt)},get loading(){return a(Nt)},get unreadCount(){return a(o)},get unreadBoundarySeq(){return a(u)},get unreadBoundaryLoaded(){return a(l)},get unreadSince(){return a(f)},get hasOlder(){return a(xn)},get hasNewer(){return a(En)},get loadingOlder(){return a(Nn)},get loadingNewer(){return a(rn)},get prepending(){return a(he)},get selectedThreadID(){return a(Re)},get currentUserID(){return a(Xe)},onListRef:Fn=>v(rt,Fn),onActivateMessageComposer:()=>v(yt,"message"),onInlineImagePointerUp:Ls,onOpenProfile:Os,onReply:Es,onOpenThread:Ts,onJumpToQuote:Fn=>{Is(Fn)},onOpenImage:ai,onLoadOlder:_,onLoadNewer:()=>N(),onJumpToUnread:()=>{fc()},onHistorySettled:kt,onReachedBottom:Ta,onMarkRead:Fn=>{Ta({all:!0,seq:Fn})},onRetry:uc,onDiscard:Ss})}var Us=S(qs,2);{let he=Ot(()=>(a(w),_t(()=>a(w)?.id)));zp(Us,{get entries(){return a(pt)},get currentUserID(){return a(he)}})}var Lc=S(Us,2);{let he=Ot(()=>(a(i),rs(da),a(w),a(r),_t(()=>a(i)?`Message ${da(a(i),a(w)?.id)}`:a(r)?`Message #${a(r).name}`:"Pick a channel to start"))),Re=Ot(()=>a(ke)&&a(Ke)===(a(D)?"dm":"channel")?a(ke):null);Ml(Lc,{get value(){return a(K)},get placeholder(){return a(he)},ariaLabel:"Message body",submitLabel:"Send",get pendingUpload(){return a(ie)},get replyTarget(){return a(Re)},showUpload:!0,showToolbar:!0,get showGifPicker(){return a(B)},get gifQuery(){return a(Ae)},get filteredGifs(){return a(m)},onValue:Xe=>{const Fn=a(K);v(K,Xe),Xe.trim()&&Xe!==Fn?xc():Xe.trim()||Ca()},onSubmit:()=>{ys()},onKeydown:Ec,onFocus:()=>v(yt,"message"),onInputRef:Xe=>v(An,Xe),onUploadFile:mc,onRemoveUpload:()=>v(ie,null),onClearReply:pn,onApplyMarkdownWrap:Ic,onAppendToComposer:ii,onToggleGif:()=>v(B,!a(B)),onGifQuery:Xe=>v(Ae,Xe),onPickGif:Rc})}var Ea=S(et,2);let zs;var Pc=b(Ea);{var Nc=he=>{{let Re=Ot(()=>a(ke)&&a(Ke)==="thread"?a(ke):null);Pg(he,{get root(){return a(C)},get replies(){return a(I)},get threadState(){return a(U)},get replyBody(){return a(Z)},get replyTarget(){return a(Re)},onClose:si,onReplyBody:Xe=>v(Z,Xe),onSubmitReply:()=>{xs()},onReplyKeydown:Ac,onReplyFocus:()=>v(yt,"thread"),onReplyInputRef:Xe=>v(In,Xe),onSetReplyTarget:Es,onClearReply:pn,onActivateThreadComposer:()=>v(yt,"thread"),onInlineImagePointerUp:Ls,onJumpToQuote:Xe=>{Is(Xe)},onOpenImage:ai})}},qc=he=>{{let Re=Ot(()=>(a(n),_t(()=>a(n)?.name)));wg(he,{get profile(){return a(P)},get currentUser(){return a(w)},get workspaceName(){return a(Re)},onClose:si,onEdit:Rn,onMessage:Xe=>{Ds(Xe)},onSetStatus:()=>v(Se,"status messages are coming soon")})}},Uc=he=>{Ig(he)};oe(Pc,he=>{a(C)?he(Nc):a(P)?he(qc,1):he(Uc,-1)})}var Bs=S(T,2);{var zc=he=>{Sg(he,{get user(){return a(w)},get displayName(){return a(ge)},get handle(){return a(De)},get avatarURL(){return a(_e)},get pushoverEnabled(){return a(Ue)},get pushoverUserKey(){return a(Je)},get status(){return a(se)},get statusError(){return a(be)},onDisplayName:Re=>v(ge,Re),onHandle:Re=>v(De,Re),onAvatarURL:Re=>v(_e,Re),onPushoverEnabled:Re=>v(Ue,Re),onPushoverUserKey:Re=>v(Je,Re),onClose:jr,onSave:()=>{Hr()}})};oe(Bs,he=>{a(ae)&&a(w)&&he(zc)})}var Fs=S(Bs,2);{var Bc=he=>{Hp(he,{get channelName(){return a(O)},status:"",onChannelName:Re=>v(O,Re),onClose:jr,onCreate:()=>{j()}})};oe(Fs,he=>{a(ce)&&he(Bc)})}var Hs=S(Fs,2);{var Fc=he=>{{let Re=Ot(()=>(a(w),_t(()=>a(w)?.id)));Vp(he,{get people(){return a(p)},get currentUserID(){return a(Re)},get memberID(){return a(W)},onMemberID:Xe=>v(W,Xe),onClose:jr,onStart:Xe=>{_c(Xe)}})}};oe(Hs,he=>{a($)&&he(Fc)})}var Hc=S(Hs,2);{var Wc=he=>{kf(he,{get url(){return a(G),_t(()=>a(G).url)},get title(){return a(G),_t(()=>a(G).title)},onClose:jr})};oe(Hc,he=>{a(G)&&he(Wc)})}te(()=>{R=lt(T,1,"shell",null,R,{"nav-open":a(Ve),"sidebar-collapsed":a(an),"thread-open":a(d)}),X(q,"aria-expanded",a(Ve)),et.inert=a(Ve),zs=lt(Ea,1,"thread",null,zs,{open:a(d)}),Ea.inert=a(Ve),X(Ea,"aria-label",a(P)?"Profile pane":"Thread pane")}),V("click",q,()=>v(Ve,!a(Ve))),L(c,h)};oe(Dc,c=>{a(nt)?c(Mc):c(Oc,-1)})}L(t,Ns),He()}Qe(["click"]);var Yg=z(' ',1),Zg=z("

"),Xg=z(`

Self-hostable chat. Serious tool. Mild brine.

ClickClack

A single-binary chat app for teams, communities, bots, and agents: Slack-style threads, durable realtime, OpenAPI, SQLite, and a CLI that can drive the whole thing from a shell.

What it is

Chat infrastructure that stays boring when the socket drops.

WebSocket is the pipe. The database is the truth. Every durable message, thread reply, reaction, and channel update can be recovered over HTTP with a cursor, so clients and agents can reconnect without drama.

Agent path

A friendly CLI, no LLM baked in.

External agents, CI jobs, and humans use the same public API as the web app. Tokens and workspace defaults are scoped per server, so switching - hosts does not leak credentials or stale IDs.

 

Destinations

Product at the root. Docs and app where people expect them.

`);function Qg(t,e){Fe(e,!1);const n="https://docs.clickclack.chat",r=["localhost","127.0.0.1","::1"].includes(window.location.hostname)?"/app":"https://app.clickclack.chat",i="https://github.com/openclaw/clickclack",s=[["Single binary","Go server, embedded Svelte app, embedded migrations, local SQLite and uploads."],["Threads that recover","Slack-style one-level threads with durable event replay after reconnects."],["Agent-friendly","A CLI, OpenAPI contract, TypeScript SDK, webhooks, and slash-command shapes."],["Self-host first","SQLite is the default, not the demo. Postgres can arrive behind the store layer."]],o=["clickclack serve --data ./data","clickclack login --magic-token mgt_...",'clickclack send --channel general "deploy started"',"clickclack threads reply msg_... --stdin {var O=Yg();_a(()=>{Qo.title="ClickClack - Self-hostable chat with claws"}),L(Y,O)});var l=b(u),f=S(b(l),2),d=S(b(f),2),p=b(d);X(p,"href",n);var m=S(p,2),w=S(m,2);X(w,"href",i);var y=S(f,2),x=S(b(y),6),k=b(x),g=S(k,2);X(g,"href",n);var A=S(g,2);X(A,"href",i);var E=S(l,4);Wt(E,5,()=>s,bl,(Y,O)=>{var W=Zg(),J=b(W),fe=b(J),ie=S(J,2),B=b(ie);te(()=>{ee(fe,a(O)[0]),ee(B,a(O)[1])}),L(Y,W)});var I=S(E,2),D=S(b(I),2),C=b(D),U=S(I,2),P=S(b(U),2),G=S(b(P),2);X(G,"href",n);var K=S(G,2),Z=S(K,2);X(Z,"href",i),te(Y=>{X(m,"href",r),X(k,"href",r),ee(C,Y),X(K,"href",r)},[()=>o.join(` + hosts does not leak credentials or stale IDs.

 

Destinations

Product at the root. Docs and app where people expect them.

`);function Qg(t,e){Fe(e,!1);const n="https://docs.clickclack.chat",r=["localhost","127.0.0.1","::1"].includes(window.location.hostname)?"/app":"https://app.clickclack.chat",i="https://github.com/openclaw/clickclack",s=[["Single binary","Go server, embedded Svelte app, embedded migrations, local SQLite and uploads."],["Threads that recover","Slack-style one-level threads with durable event replay after reconnects."],["Agent-friendly","A CLI, OpenAPI contract, TypeScript SDK, webhooks, and slash-command shapes."],["Self-host first","SQLite is the default, not the demo. Postgres can arrive behind the store layer."]],o=["clickclack serve --data ./data","clickclack login --magic-token mgt_...",'clickclack send --channel general "deploy started"',"clickclack threads reply msg_... --stdin {var O=Yg();_a(()=>{Qo.title="ClickClack - Self-hostable chat with claws"}),L(Y,O)});var l=b(u),f=S(b(l),2),d=S(b(f),2),p=b(d);X(p,"href",n);var m=S(p,2),w=S(m,2);X(w,"href",i);var y=S(f,2),x=S(b(y),6),k=b(x),g=S(k,2);X(g,"href",n);var I=S(g,2);X(I,"href",i);var E=S(l,4);Wt(E,5,()=>s,bl,(Y,O)=>{var W=Zg(),J=b(W),fe=b(J),ie=S(J,2),B=b(ie);te(()=>{ee(fe,a(O)[0]),ee(B,a(O)[1])}),L(Y,W)});var A=S(E,2),D=S(b(A),2),C=b(D),U=S(A,2),P=S(b(U),2),G=S(b(P),2);X(G,"href",n);var K=S(G,2),Z=S(K,2);X(Z,"href",i),te(Y=>{X(m,"href",r),X(k,"href",r),ee(C,Y),X(K,"href",r)},[()=>o.join(` `)]),L(t,u),He()}function Jg(t){const e=window.location.pathname,r=window.location.hostname.startsWith("app.")||e==="/app"||e.startsWith("/app/");var i=Sn(),s=Gt(i);{var o=l=>{Kg(l,{})},u=l=>{Qg(l,{})};oe(s,l=>{r?l(o):l(u,-1)})}L(t,i)}cd(Jg,{target:document.getElementById("app")}); diff --git a/apps/api/internal/webassets/dist/index.html b/apps/api/internal/webassets/dist/index.html index de0d6f4..d8814d9 100644 --- a/apps/api/internal/webassets/dist/index.html +++ b/apps/api/internal/webassets/dist/index.html @@ -4,7 +4,7 @@ ClickClack - + diff --git a/apps/web/src/ChatApp.svelte b/apps/web/src/ChatApp.svelte index cc1d521..626d6c8 100644 --- a/apps/web/src/ChatApp.svelte +++ b/apps/web/src/ChatApp.svelte @@ -1222,9 +1222,13 @@ searchResults = []; return; } - const data = await api<{ results: SearchResult[] }>( - `/api/search?workspace_id=${encodeURIComponent(selectedWorkspaceID)}&q=${encodeURIComponent(searchQuery.trim())}` - ); + if (selectedDirectID) { + searchResults = []; + return; + } + const params = new URLSearchParams({ workspace_id: selectedWorkspaceID, q: searchQuery.trim() }); + if (selectedChannelID) params.set("channel_id", selectedChannelID); + const data = await api<{ results: SearchResult[] }>(`/api/search?${params.toString()}`); searchResults = data.results; } diff --git a/docs/cli.md b/docs/cli.md index 8e35f0e..daa1e55 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -17,7 +17,7 @@ clickclack [flags] Commands: serve run the HTTP/WebSocket server (default if no command given) migrate apply embedded SQL migrations - admin bootstrap, user create, invite create, magic-link create + admin bootstrap, user create, invite create, bot create, events prune, magic-link create backup write a SQLite backup file export write a JSON dump to a file or stdout login consume a magic-link token and store/print a session token @@ -155,6 +155,21 @@ Mints a magic-link token. Hand it to the user; they POST it to `/api/auth/magic/consume` to get a session. See [features/auth.md](features/auth.md). +### `admin events prune` + +```sh +clickclack admin events prune \ + --workspace wsp_... \ + --older-than-days 30 \ + --keep-latest 10000 +``` + +Deletes old durable realtime events for one workspace. At least one retention +bound is required: `--older-than-days`, `--before RFC3339`, or +`--keep-latest`. `--keep-latest` preserves the newest N events by cursor even +when they are older than the cutoff. Private event recipient rows are deleted +by cascade with their events. + ## `backup` ```sh diff --git a/docs/data-model.md b/docs/data-model.md index 08a4a40..94df3fd 100644 --- a/docs/data-model.md +++ b/docs/data-model.md @@ -37,6 +37,7 @@ channels messages thread_state reactions events auth_magic_links / sessions +event_recipients uploads message_attachments direct_conversations direct_conversation_members invites @@ -56,9 +57,11 @@ For any row in `messages`: `channel_seq IS NOT NULL`, `thread_seq IS NULL`. - Reply: `parent_message_id = root.id`, `thread_root_id = root.id`, `channel_seq IS NULL`, `thread_seq IS NOT NULL`. -- DM: `direct_conversation_id IS NOT NULL`, `channel_id IS NULL`, +- DM root: `direct_conversation_id IS NOT NULL`, `channel_id IS NULL`, `parent_message_id IS NULL`, `channel_seq` used as the per-conversation sequence. +- DM reply: `direct_conversation_id IS NOT NULL`, `channel_id IS NULL`, + `parent_message_id IS NOT NULL`, `channel_seq IS NULL`, `thread_seq IS NOT NULL`. Nested replies are forbidden — the API rejects replies to non-root messages. @@ -71,6 +74,14 @@ Nested replies are forbidden — the API rejects replies to non-root messages. - `events.cursor`: globally sortable opaque cursor used by realtime recovery. +## Private durable events + +`events.is_private` is the durable privacy bit for replay filtering. +`event_recipients(event_id, user_id)` is the allow-list for private durable +events. Public events have `is_private = 0`; private events have +`is_private = 1` and are returned only to listed users during replay. Recipient +rows cascade when old events are pruned. + ## Soft-deletes Messages set `deleted_at` instead of removing the row. This keeps diff --git a/docs/deployment.md b/docs/deployment.md index f4ca79a..9c1aaea 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -127,6 +127,19 @@ of that org. See [features/auth.md](features/auth.md). unexpected tables. Migrations live in `apps/api/internal/store/sqlite/migrations/` and are append-only. +## Event retention + +The durable realtime event log is for reconnect recovery, not permanent +message history. Message history stays in `messages`; old events can be +removed after the offline-recovery window you operate against: + +```sh +clickclack admin events prune --workspace wsp_... --older-than-days 30 --keep-latest 10000 +``` + +Run this from maintenance automation after backups. Clients with cursors older +than the retained event window should resync through the message APIs. + ## Backups and restore ```sh diff --git a/docs/features/dms.md b/docs/features/dms.md index 2403e44..6d8a2fb 100644 --- a/docs/features/dms.md +++ b/docs/features/dms.md @@ -28,9 +28,10 @@ conversation context is loaded; clicking a person opens their DM when one exists, otherwise it opens the profile pane with a Message action. `POST` to `/dms/{id}/messages` increments a per-conversation sequence on -`messages.channel_seq` and emits a durable event into the workspace event -stream so DM lists and unread counts stay live. `nonce` has the same -retry-safe idempotency behavior as channel message creation. +`messages.channel_seq` and emits a durable private event into the workspace +event stream so DM lists and unread counts stay live for conversation members. +`nonce` has the same retry-safe idempotency behavior as channel message +creation. `POST /dms/{id}/read` updates the caller's monotonic read pointer for that conversation and emits a private `dm.read` event only to the caller's own @@ -43,11 +44,20 @@ sessions. (`direct_conversation_members`). - DM creation requires that all `member_ids` are members of the same workspace. +- Editing, deleting, reacting to, attaching uploads to, or opening threads on + a DM message requires direct conversation membership. Edits and deletes are + author-only. + +## Threads + +DM root messages support the same one-level thread model as channel messages. +Thread replies carry `direct_conversation_id`, use `thread_seq`, and do not +appear in the root DM timeline or unread root-message sequence. ## What is intentionally missing - DM-only auth tokens. - One-on-one vs group distinctions in the API surface — the client decides based on member count. -- Message reactions/edits in DMs. The schema supports it, but the API surface - for DM-specific mutations is intentionally minimal in V1. +- DM-only search. Workspace/channel search excludes DMs; DM search needs a + separate endpoint so private messages never leak into channel results. diff --git a/docs/features/realtime.md b/docs/features/realtime.md index 3a0dac9..057a908 100644 --- a/docs/features/realtime.md +++ b/docs/features/realtime.md @@ -18,6 +18,8 @@ to drop events. send. - `events` table — append-only log scoped to a workspace, with a sortable `cursor`. +- `event_recipients` table — optional per-event recipient rows for durable + private events such as DMs and read receipts. - `httpapi.websocket` — accepts a connection, validates membership, drains backlog from `events`, then forwards live publishes from the hub. @@ -67,7 +69,8 @@ Inserted in the same transaction as the underlying mutation: - `reaction.added`, `reaction.removed` Direct messages also publish into the workspace event stream so DM lists stay -fresh. +fresh, but they are persisted with recipient rows and replay only to direct +conversation members. `message.created` carries the message sequence in top-level `seq` and includes `message_id`, `author_id`, optional `direct_conversation_id`, and optional @@ -100,6 +103,10 @@ payload with `user_id` from the caller before publishing. - The websocket itself does not drop durable events — they are always in `events`. A buffered hub channel that overflows simply stops receiving live events; the next reconnect with `after_cursor` will fill in. +- Operators can prune old durable events with + `clickclack admin events prune`. Message history is not stored in the event + log, so clients with cursors outside the retained window should reload + through the message APIs. ## Implementation pointers diff --git a/docs/features/search.md b/docs/features/search.md index 6649b38..e2a4563 100644 --- a/docs/features/search.md +++ b/docs/features/search.md @@ -10,7 +10,7 @@ Workspace-scoped full-text search backed by SQLite FTS5. ## Endpoint ```http -GET /api/search?workspace_id=&q=&limit= +GET /api/search?workspace_id=&channel_id=&q=&limit= ``` Returns: @@ -22,6 +22,10 @@ Returns: `limit` is clamped to `1..100` (default 50). Empty `q` returns an empty list without hitting FTS. Membership is required for `workspace_id`. +Search is channel-message-only. DM rows are explicitly excluded from this +endpoint. When `channel_id` is supplied, results are limited to that channel; +without it, results span channel messages in the workspace. + ## Indexing A virtual table `messages_fts` mirrors `messages.body` with the `porter @@ -45,7 +49,7 @@ return an error from SQLite — clients should sanitise user input or ## What is intentionally missing - Cross-workspace global search. -- Per-channel scoping at the API layer (filter client-side from - `result.message.channel_id`). +- DM search. It needs a separate endpoint scoped to direct conversation + membership. - Highlighting/snippet generation. Add `snippet(messages_fts, ...)` if/when the UI needs it. diff --git a/infra/migrations/sqlite/0005_upload_dimensions.sql b/infra/migrations/sqlite/0005_upload_dimensions.sql new file mode 100644 index 0000000..21bc916 --- /dev/null +++ b/infra/migrations/sqlite/0005_upload_dimensions.sql @@ -0,0 +1,3 @@ +ALTER TABLE uploads ADD COLUMN width INTEGER NOT NULL DEFAULT 0; +ALTER TABLE uploads ADD COLUMN height INTEGER NOT NULL DEFAULT 0; +ALTER TABLE uploads ADD COLUMN duration_ms INTEGER NOT NULL DEFAULT 0; diff --git a/infra/migrations/sqlite/0006_message_client_nonce.sql b/infra/migrations/sqlite/0006_message_client_nonce.sql new file mode 100644 index 0000000..e03e455 --- /dev/null +++ b/infra/migrations/sqlite/0006_message_client_nonce.sql @@ -0,0 +1,5 @@ +ALTER TABLE messages ADD COLUMN client_nonce TEXT NOT NULL DEFAULT ''; + +CREATE UNIQUE INDEX IF NOT EXISTS idx_messages_author_client_nonce + ON messages(author_id, client_nonce) + WHERE client_nonce <> ''; diff --git a/infra/migrations/sqlite/0007_unread.sql b/infra/migrations/sqlite/0007_unread.sql new file mode 100644 index 0000000..bb54a65 --- /dev/null +++ b/infra/migrations/sqlite/0007_unread.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS channel_reads ( + channel_id TEXT NOT NULL REFERENCES channels(id) ON DELETE CASCADE, + user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE, + last_read_seq INTEGER NOT NULL DEFAULT 0, + last_read_at TEXT NOT NULL, + PRIMARY KEY (channel_id, user_id) +); + +CREATE TABLE IF NOT EXISTS direct_reads ( + conversation_id TEXT NOT NULL REFERENCES direct_conversations(id) ON DELETE CASCADE, + user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE, + last_read_seq INTEGER NOT NULL DEFAULT 0, + last_read_at TEXT NOT NULL, + PRIMARY KEY (conversation_id, user_id) +); diff --git a/infra/migrations/sqlite/0008_message_paging_indexes.sql b/infra/migrations/sqlite/0008_message_paging_indexes.sql new file mode 100644 index 0000000..a18d46c --- /dev/null +++ b/infra/migrations/sqlite/0008_message_paging_indexes.sql @@ -0,0 +1,7 @@ +CREATE INDEX IF NOT EXISTS idx_messages_channel_root_page + ON messages(channel_id, parent_message_id, channel_seq) + WHERE channel_id IS NOT NULL AND parent_message_id IS NULL; + +CREATE INDEX IF NOT EXISTS idx_messages_direct_page + ON messages(direct_conversation_id, channel_seq) + WHERE direct_conversation_id IS NOT NULL; diff --git a/infra/migrations/sqlite/0008_user_notification_settings.sql b/infra/migrations/sqlite/0008_user_notification_settings.sql new file mode 100644 index 0000000..ec9f1f7 --- /dev/null +++ b/infra/migrations/sqlite/0008_user_notification_settings.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS user_notification_settings ( + user_id TEXT PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE, + pushover_enabled INTEGER NOT NULL DEFAULT 0, + pushover_user_key TEXT NOT NULL DEFAULT '' +); diff --git a/infra/migrations/sqlite/0009_bots.sql b/infra/migrations/sqlite/0009_bots.sql new file mode 100644 index 0000000..93e0547 --- /dev/null +++ b/infra/migrations/sqlite/0009_bots.sql @@ -0,0 +1,19 @@ +ALTER TABLE users ADD COLUMN kind TEXT NOT NULL DEFAULT 'human'; +ALTER TABLE users ADD COLUMN owner_user_id TEXT REFERENCES users(id) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS bot_tokens ( + id TEXT PRIMARY KEY, + token_hash TEXT NOT NULL UNIQUE, + bot_user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE, + workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE, + owner_user_id TEXT REFERENCES users(id) ON DELETE SET NULL, + name TEXT NOT NULL, + scopes_json TEXT NOT NULL, + created_by TEXT REFERENCES users(id), + created_at TEXT NOT NULL, + last_used_at TEXT, + revoked_at TEXT +); + +CREATE INDEX IF NOT EXISTS idx_bot_tokens_hash ON bot_tokens(token_hash); +CREATE INDEX IF NOT EXISTS idx_bot_tokens_bot ON bot_tokens(bot_user_id); diff --git a/infra/migrations/sqlite/0010_message_privacy_scaling.sql b/infra/migrations/sqlite/0010_message_privacy_scaling.sql new file mode 100644 index 0000000..3ad9d1c --- /dev/null +++ b/infra/migrations/sqlite/0010_message_privacy_scaling.sql @@ -0,0 +1,296 @@ +CREATE INDEX IF NOT EXISTS idx_direct_conversation_members_user + ON direct_conversation_members(user_id, conversation_id); + +CREATE INDEX IF NOT EXISTS idx_message_attachments_message_created + ON message_attachments(message_id, created_at, upload_id); + +DROP INDEX IF EXISTS idx_messages_direct_page; + +CREATE INDEX IF NOT EXISTS idx_messages_direct_page + ON messages(direct_conversation_id, parent_message_id, channel_seq) + WHERE direct_conversation_id IS NOT NULL + AND parent_message_id IS NULL; + +CREATE UNIQUE INDEX IF NOT EXISTS idx_messages_channel_root_unique_seq + ON messages(channel_id, channel_seq) + WHERE channel_id IS NOT NULL + AND parent_message_id IS NULL + AND channel_seq IS NOT NULL; + +CREATE UNIQUE INDEX IF NOT EXISTS idx_messages_direct_unique_seq + ON messages(direct_conversation_id, channel_seq) + WHERE direct_conversation_id IS NOT NULL + AND parent_message_id IS NULL + AND channel_seq IS NOT NULL; + +CREATE UNIQUE INDEX IF NOT EXISTS idx_messages_thread_unique_seq + ON messages(thread_root_id, thread_seq) + WHERE parent_message_id IS NOT NULL + AND thread_seq IS NOT NULL; + +ALTER TABLE events ADD COLUMN is_private INTEGER NOT NULL DEFAULT 0 CHECK (is_private IN (0, 1)); + +CREATE TABLE IF NOT EXISTS event_recipients ( + event_id TEXT NOT NULL REFERENCES events(id) ON DELETE CASCADE, + user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE, + PRIMARY KEY (event_id, user_id) +); + +CREATE INDEX IF NOT EXISTS idx_event_recipients_user_event + ON event_recipients(user_id, event_id); + +UPDATE messages +SET channel_id = NULL, + direct_conversation_id = ( + SELECT root.direct_conversation_id + FROM messages root + WHERE root.id = messages.thread_root_id + ) +WHERE parent_message_id IS NOT NULL + AND (direct_conversation_id IS NULL OR direct_conversation_id = '') + AND EXISTS ( + SELECT 1 + FROM messages root + WHERE root.id = messages.thread_root_id + AND root.parent_message_id IS NULL + AND root.direct_conversation_id IS NOT NULL + AND root.direct_conversation_id <> '' + ); + +INSERT OR IGNORE INTO event_recipients (event_id, user_id) +SELECT e.id, dcm.user_id +FROM events e +JOIN direct_conversation_members dcm + ON dcm.conversation_id = json_extract(e.payload_json, '$.direct_conversation_id') +WHERE json_extract(e.payload_json, '$.direct_conversation_id') IS NOT NULL + AND json_extract(e.payload_json, '$.direct_conversation_id') <> ''; + +INSERT OR IGNORE INTO event_recipients (event_id, user_id) +SELECT e.id, dcm.user_id +FROM events e +JOIN messages m + ON m.id = json_extract(e.payload_json, '$.message_id') +JOIN direct_conversation_members dcm + ON dcm.conversation_id = m.direct_conversation_id +WHERE json_extract(e.payload_json, '$.message_id') IS NOT NULL + AND json_extract(e.payload_json, '$.message_id') <> '' + AND m.direct_conversation_id IS NOT NULL + AND m.direct_conversation_id <> ''; + +INSERT OR IGNORE INTO event_recipients (event_id, user_id) +SELECT e.id, dcm.user_id +FROM events e +JOIN messages root + ON root.id = json_extract(e.payload_json, '$.root_message_id') +JOIN direct_conversation_members dcm + ON dcm.conversation_id = root.direct_conversation_id +WHERE json_extract(e.payload_json, '$.root_message_id') IS NOT NULL + AND json_extract(e.payload_json, '$.root_message_id') <> '' + AND root.parent_message_id IS NULL + AND root.direct_conversation_id IS NOT NULL + AND root.direct_conversation_id <> ''; + +INSERT OR IGNORE INTO event_recipients (event_id, user_id) +SELECT e.id, u.id +FROM events e +JOIN users u + ON u.id = json_extract(e.payload_json, '$.user_id') +WHERE e.type IN ('channel.read', 'dm.read') + AND json_extract(e.payload_json, '$.user_id') IS NOT NULL + AND json_extract(e.payload_json, '$.user_id') <> ''; + +UPDATE events +SET is_private = 1 +WHERE json_extract(payload_json, '$.direct_conversation_id') IS NOT NULL + AND json_extract(payload_json, '$.direct_conversation_id') <> ''; + +UPDATE events +SET is_private = 1 +WHERE type IN ('channel.read', 'dm.read') + AND json_extract(payload_json, '$.user_id') IS NOT NULL + AND json_extract(payload_json, '$.user_id') <> ''; + +UPDATE events +SET is_private = 1 +WHERE EXISTS ( + SELECT 1 + FROM event_recipients er + WHERE er.event_id = events.id +); + +UPDATE events +SET is_private = 1 +WHERE EXISTS ( + SELECT 1 + FROM messages m + WHERE m.id = json_extract(events.payload_json, '$.message_id') + AND m.direct_conversation_id IS NOT NULL + AND m.direct_conversation_id <> '' +); + +UPDATE events +SET is_private = 1 +WHERE EXISTS ( + SELECT 1 + FROM messages root + WHERE root.id = json_extract(events.payload_json, '$.root_message_id') + AND root.parent_message_id IS NULL + AND root.direct_conversation_id IS NOT NULL + AND root.direct_conversation_id <> '' +); + +CREATE TRIGGER IF NOT EXISTS event_recipients_mark_private +AFTER INSERT ON event_recipients +BEGIN + UPDATE events SET is_private = 1 WHERE id = NEW.event_id; +END; + +CREATE TRIGGER IF NOT EXISTS messages_shape_insert +BEFORE INSERT ON messages +WHEN NOT ( + ( + NEW.parent_message_id IS NULL + AND NEW.channel_id IS NOT NULL + AND NEW.direct_conversation_id IS NULL + AND NEW.thread_root_id = NEW.id + AND NEW.channel_seq IS NOT NULL + AND NEW.thread_seq IS NULL + AND EXISTS ( + SELECT 1 + FROM channels c + WHERE c.id = NEW.channel_id + AND c.workspace_id = NEW.workspace_id + ) + ) + OR + ( + NEW.parent_message_id IS NULL + AND NEW.channel_id IS NULL + AND NEW.direct_conversation_id IS NOT NULL + AND NEW.thread_root_id = NEW.id + AND NEW.channel_seq IS NOT NULL + AND NEW.thread_seq IS NULL + AND EXISTS ( + SELECT 1 + FROM direct_conversations dc + WHERE dc.id = NEW.direct_conversation_id + AND dc.workspace_id = NEW.workspace_id + ) + ) + OR + ( + NEW.parent_message_id IS NOT NULL + AND NEW.parent_message_id = NEW.thread_root_id + AND NEW.channel_seq IS NULL + AND NEW.thread_seq IS NOT NULL + AND ( + ( + NEW.channel_id IS NOT NULL + AND NEW.direct_conversation_id IS NULL + AND EXISTS ( + SELECT 1 + FROM messages root + WHERE root.id = NEW.thread_root_id + AND root.parent_message_id IS NULL + AND root.thread_root_id = root.id + AND root.workspace_id = NEW.workspace_id + AND root.channel_id = NEW.channel_id + AND root.direct_conversation_id IS NULL + ) + ) + OR + ( + NEW.channel_id IS NULL + AND NEW.direct_conversation_id IS NOT NULL + AND EXISTS ( + SELECT 1 + FROM messages root + WHERE root.id = NEW.thread_root_id + AND root.parent_message_id IS NULL + AND root.thread_root_id = root.id + AND root.workspace_id = NEW.workspace_id + AND root.channel_id IS NULL + AND root.direct_conversation_id = NEW.direct_conversation_id + ) + ) + ) + ) +) +BEGIN + SELECT RAISE(ABORT, 'invalid message shape'); +END; + +CREATE TRIGGER IF NOT EXISTS messages_shape_update +BEFORE UPDATE OF channel_id, direct_conversation_id, parent_message_id, thread_root_id, channel_seq, thread_seq ON messages +WHEN NOT ( + ( + NEW.parent_message_id IS NULL + AND NEW.channel_id IS NOT NULL + AND NEW.direct_conversation_id IS NULL + AND NEW.thread_root_id = NEW.id + AND NEW.channel_seq IS NOT NULL + AND NEW.thread_seq IS NULL + AND EXISTS ( + SELECT 1 + FROM channels c + WHERE c.id = NEW.channel_id + AND c.workspace_id = NEW.workspace_id + ) + ) + OR + ( + NEW.parent_message_id IS NULL + AND NEW.channel_id IS NULL + AND NEW.direct_conversation_id IS NOT NULL + AND NEW.thread_root_id = NEW.id + AND NEW.channel_seq IS NOT NULL + AND NEW.thread_seq IS NULL + AND EXISTS ( + SELECT 1 + FROM direct_conversations dc + WHERE dc.id = NEW.direct_conversation_id + AND dc.workspace_id = NEW.workspace_id + ) + ) + OR + ( + NEW.parent_message_id IS NOT NULL + AND NEW.parent_message_id = NEW.thread_root_id + AND NEW.channel_seq IS NULL + AND NEW.thread_seq IS NOT NULL + AND ( + ( + NEW.channel_id IS NOT NULL + AND NEW.direct_conversation_id IS NULL + AND EXISTS ( + SELECT 1 + FROM messages root + WHERE root.id = NEW.thread_root_id + AND root.parent_message_id IS NULL + AND root.thread_root_id = root.id + AND root.workspace_id = NEW.workspace_id + AND root.channel_id = NEW.channel_id + AND root.direct_conversation_id IS NULL + ) + ) + OR + ( + NEW.channel_id IS NULL + AND NEW.direct_conversation_id IS NOT NULL + AND EXISTS ( + SELECT 1 + FROM messages root + WHERE root.id = NEW.thread_root_id + AND root.parent_message_id IS NULL + AND root.thread_root_id = root.id + AND root.workspace_id = NEW.workspace_id + AND root.channel_id IS NULL + AND root.direct_conversation_id = NEW.direct_conversation_id + ) + ) + ) + ) +) +BEGIN + SELECT RAISE(ABORT, 'invalid message shape'); +END; diff --git a/packages/protocol/openapi.yaml b/packages/protocol/openapi.yaml index 8bbbac3..b9111ef 100644 --- a/packages/protocol/openapi.yaml +++ b/packages/protocol/openapi.yaml @@ -349,6 +349,11 @@ paths: required: true schema: type: string + - name: channel_id + in: query + required: false + schema: + type: string responses: "200": description: Search results diff --git a/packages/sdk-ts/src/generated/openapi.d.ts b/packages/sdk-ts/src/generated/openapi.d.ts index 3099a22..6909178 100644 --- a/packages/sdk-ts/src/generated/openapi.d.ts +++ b/packages/sdk-ts/src/generated/openapi.d.ts @@ -1190,6 +1190,7 @@ export interface operations { query: { workspace_id: string; q: string; + channel_id?: string; }; header?: never; path?: never; diff --git a/packages/sdk-ts/src/index.ts b/packages/sdk-ts/src/index.ts index 104ba5e..5808baf 100644 --- a/packages/sdk-ts/src/index.ts +++ b/packages/sdk-ts/src/index.ts @@ -279,10 +279,10 @@ export class ClickClackClient { }, }; - search = async (workspaceId: string, query: string) => { - return this.request( - `/api/search?workspace_id=${encodeURIComponent(workspaceId)}&q=${encodeURIComponent(query)}`, - ); + search = async (workspaceId: string, query: string, options: { channelId?: string } = {}) => { + const params = new URLSearchParams({ workspace_id: workspaceId, q: query }); + if (options.channelId) params.set("channel_id", options.channelId); + return this.request(`/api/search?${params.toString()}`); }; uploads = {