A Zulip bot agent to sit in our Black Sun. Ever evolving
at main 67 lines 2.7 kB view raw
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2026 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 SPDX-License-Identifier: ISC 4 ---------------------------------------------------------------------------*) 5 6(** Per-channel and per-DM Claude session management. 7 8 Sessions maintain conversation context independently for each Zulip 9 channel or DM thread, enabling multi-turn conversations with Claude. *) 10 11val src : Logs.Src.t 12(** Log source for session management. *) 13 14(** Role in a conversation turn *) 15type role = User | Assistant 16 17(** A conversation turn in a session *) 18type turn = { role : role; content : string; timestamp : float } 19 20(** Session scope - either a channel+topic or a DM with a user *) 21type scope = 22 | Channel of { stream : string; topic : string } 23 | Direct of { user_email : string; user_full_name : string } 24 25val scope_to_string : scope -> string 26(** [scope_to_string scope] returns a human-readable description of the scope. *) 27 28val scope_to_mention : scope -> string 29(** [scope_to_mention scope] returns a Zulip-compatible linked mention. 30 For channels, returns [#**stream>topic**] format. 31 For DMs, returns [DM with `email`] format. *) 32 33(** Session data *) 34type t 35 36val empty : now:float -> t 37(** [empty ~now] creates an empty session. *) 38 39val max_turns : int 40(** Maximum turns to keep in a session for context window management. *) 41 42val scope_of_message : Zulip_bot.Message.t -> scope 43(** [scope_of_message msg] extracts the session scope from a Zulip message. 44 Channel messages use stream+topic as scope, DMs use sender email. *) 45 46val load : Zulip_bot.Storage.t -> scope:scope -> now:float -> t 47(** [load storage ~scope ~now] loads a session from storage. 48 Returns an empty session if none exists or if the session has expired. *) 49 50val save : Zulip_bot.Storage.t -> scope:scope -> t -> unit 51(** [save storage ~scope session] persists the session to storage. *) 52 53val add_user_message : t -> content:string -> now:float -> t 54(** [add_user_message session ~content ~now] adds a user message to the session. *) 55 56val add_assistant_message : t -> content:string -> now:float -> t 57(** [add_assistant_message session ~content ~now] adds an assistant response. *) 58 59val clear : Zulip_bot.Storage.t -> scope:scope -> unit 60(** [clear storage ~scope] removes the session from storage. *) 61 62val build_context : t -> string option 63(** [build_context session] builds a context string from the session history 64 for inclusion in Claude prompts. Returns [None] if the session is empty. *) 65 66val stats : t -> string 67(** [stats session] returns human-readable session statistics. *)