SendMessage inserts a user message and optionally queues it while the chat is busy, then publishes stream + pubsub updates.
( ctx context.Context, opts SendMessageOptions, )
| 1707 | // SendMessage inserts a user message and optionally queues it while the chat |
| 1708 | // is busy, then publishes stream + pubsub updates. |
| 1709 | func (p *Server) SendMessage( |
| 1710 | ctx context.Context, |
| 1711 | opts SendMessageOptions, |
| 1712 | ) (SendMessageResult, error) { |
| 1713 | if opts.ChatID == uuid.Nil { |
| 1714 | return SendMessageResult{}, xerrors.New("chat_id is required") |
| 1715 | } |
| 1716 | if len(opts.Content) == 0 { |
| 1717 | return SendMessageResult{}, xerrors.New("content is required") |
| 1718 | } |
| 1719 | |
| 1720 | busyBehavior := opts.BusyBehavior |
| 1721 | if busyBehavior == "" { |
| 1722 | busyBehavior = SendMessageBusyBehaviorQueue |
| 1723 | } |
| 1724 | switch busyBehavior { |
| 1725 | case SendMessageBusyBehaviorQueue, SendMessageBusyBehaviorInterrupt: |
| 1726 | default: |
| 1727 | return SendMessageResult{}, xerrors.Errorf("invalid busy behavior %q", opts.BusyBehavior) |
| 1728 | } |
| 1729 | |
| 1730 | content, err := chatprompt.MarshalParts(opts.Content) |
| 1731 | if err != nil { |
| 1732 | return SendMessageResult{}, xerrors.Errorf("marshal message content: %w", err) |
| 1733 | } |
| 1734 | |
| 1735 | requestedPlanMode := opts.PlanMode |
| 1736 | |
| 1737 | var ( |
| 1738 | result SendMessageResult |
| 1739 | queuedMessagesSDK []codersdk.ChatQueuedMessage |
| 1740 | ) |
| 1741 | |
| 1742 | txErr := p.db.InTx(func(tx database.Store) error { |
| 1743 | lockedChat, err := tx.GetChatByIDForUpdate(ctx, opts.ChatID) |
| 1744 | if err != nil { |
| 1745 | return xerrors.Errorf("lock chat: %w", err) |
| 1746 | } |
| 1747 | |
| 1748 | if lockedChat.Archived { |
| 1749 | return ErrChatArchived |
| 1750 | } |
| 1751 | |
| 1752 | // Enforce usage limits before queueing or inserting. |
| 1753 | if limitErr := p.checkUsageLimit(ctx, tx, lockedChat.OwnerID, uuid.NullUUID{UUID: lockedChat.OrganizationID, Valid: true}); limitErr != nil { |
| 1754 | return limitErr |
| 1755 | } |
| 1756 | |
| 1757 | if requestedPlanMode != nil { |
| 1758 | lockedChat, err = tx.UpdateChatPlanModeByID(ctx, database.UpdateChatPlanModeByIDParams{ |
| 1759 | PlanMode: *requestedPlanMode, |
| 1760 | ID: opts.ChatID, |
| 1761 | }) |
| 1762 | if err != nil { |
| 1763 | return xerrors.Errorf("update chat plan mode: %w", err) |
| 1764 | } |
| 1765 | } |
| 1766 |