Files
Playa/hosts/Volcanic.AgenticCore.Telegram/Triggers/JevStates.cs

78 lines
3.3 KiB
C#

using System.Globalization;
using System.Text.Json.Nodes;
using Volcanic.AgenticCore.Telegram.Groups;
namespace Volcanic.AgenticCore.Telegram.Triggers;
/// <summary>What Jev is asked: the state for one message or a snooze batch, and each trigger's question.</summary>
public static class JevStates
{
/// <summary><c>{ group, sender, text, reply_to? }</c>.</summary>
public static JsonObject Single(GroupMessage message)
{
ArgumentNullException.ThrowIfNull(message);
var state = new JsonObject { ["group"] = message.GroupTitle, ["sender"] = message.Sender, ["text"] = message.Text ?? "" };
AddReply(state, message);
return state;
}
/// <summary>
/// <c>{ group, messages: [ { time, sender, text, reply_to? } ] }</c>, split so each state stays under
/// <paramref name="maxChars"/> characters of JSON (one oversized message still gets a state of its own).
/// </summary>
public static IReadOnlyList<JsonObject> Batches(string groupTitle, IReadOnlyList<GroupMessage> messages, TimeZoneInfo zone, int maxChars)
{
ArgumentNullException.ThrowIfNull(messages);
ArgumentNullException.ThrowIfNull(zone);
var states = new List<JsonObject>();
JsonArray? current = null;
var size = 0;
foreach (var message in messages)
{
var item = new JsonObject
{
["time"] = TimeZoneInfo.ConvertTime(message.Time, zone).ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture),
["sender"] = message.Sender,
["text"] = message.Text ?? "",
};
AddReply(item, message);
var itemSize = item.ToJsonString().Length + 1;
if (current is null || (size + itemSize > maxChars && current.Count > 0))
{
current = [];
states.Add(new JsonObject { ["group"] = groupTitle, ["messages"] = current });
size = groupTitle.Length + 30;
}
current.Add(item);
size += itemSize;
}
return states;
}
public static JevQuestion Question(string id, Trigger trigger)
{
ArgumentNullException.ThrowIfNull(trigger);
return new JevQuestion(id, trigger.Instructions, trigger.CriteriaTrue, trigger.CriteriaFalse);
}
/// <summary>
/// The trigger's one-message question wrapped for a batch: asked plainly, a batch scores high on loosely related
/// chatter and lower on the real thing (measured: 0.92 vs 0.99 plain, 0.12 vs 0.99 wrapped).
/// </summary>
public static JevQuestion BatchQuestion(string id, Trigger trigger)
{
ArgumentNullException.ThrowIfNull(trigger);
var both = !string.IsNullOrWhiteSpace(trigger.CriteriaTrue) && !string.IsNullOrWhiteSpace(trigger.CriteriaFalse);
return new JevQuestion(id,
"Answer yes if at least one message in the batch passes this check: " + trigger.Instructions,
both ? "At least one message: " + trigger.CriteriaTrue : null,
both ? "No message does; all are like: " + trigger.CriteriaFalse : null);
}
private static void AddReply(JsonObject target, GroupMessage message)
{
if (message.ReplyTo is { } reply)
target["reply_to"] = new JsonObject { ["sender"] = reply.Sender, ["text"] = reply.Text ?? "" };
}
}