feat(telegram): log trigger changes and the trigger count at startup
This commit is contained in:
@@ -65,6 +65,16 @@ public sealed class TriggerStore
|
||||
|
||||
public static string PathIn(string workspace) => Path.Combine(DirectoryIn(workspace), "triggers.json");
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { lock (_lock) return _byOwner.Values.Sum(l => l.Count); }
|
||||
}
|
||||
|
||||
public int OwnerCount
|
||||
{
|
||||
get { lock (_lock) return _byOwner.Values.Count(l => l.Count > 0); }
|
||||
}
|
||||
|
||||
public IReadOnlyList<Trigger> List(long owner)
|
||||
{
|
||||
lock (_lock) return _byOwner.TryGetValue(owner, out var list) ? [.. list] : [];
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Volcanic.AgenticCore.Abstractions.Extensions;
|
||||
using Volcanic.AgenticCore.Abstractions.Tools;
|
||||
using Volcanic.AgenticCore.Telegram.Groups;
|
||||
@@ -8,8 +10,12 @@ using Volcanic.AgenticCore.Telegram.Groups;
|
||||
namespace Volcanic.AgenticCore.Telegram.Triggers;
|
||||
|
||||
/// <summary>What the trigger tool, the extension and <c>/triggers</c> share; registered only when triggers are on.</summary>
|
||||
public sealed class TriggerServices(TriggerEngine engine, GroupRegistry groups, IGroupMembership membership, TriggerOptions options)
|
||||
public sealed class TriggerServices(TriggerEngine engine, GroupRegistry groups, IGroupMembership membership, TriggerOptions options,
|
||||
ILogger<TriggerServices>? logger = null)
|
||||
{
|
||||
/// <summary>Every change the tool makes is logged here.</summary>
|
||||
public ILogger Logger { get; } = logger ?? NullLogger<TriggerServices>.Instance;
|
||||
|
||||
public TriggerEngine Engine => engine;
|
||||
public TriggerStore Store => engine.Store;
|
||||
public GroupRegistry Groups => groups;
|
||||
@@ -120,6 +126,8 @@ public sealed class TriggerTool(long owner, TriggerServices services, Func<TimeZ
|
||||
throw Error($"The user isn't a member of \"{group.Title}\" (or the bot can't check), so no trigger can watch it for them.");
|
||||
var created = await services.Store.AddAsync(owner, new NewTrigger(args.Name.Trim(), group.Id, group.Title, args.Instructions.Trim(),
|
||||
Clean(args.CriteriaTrue), Clean(args.CriteriaFalse), threshold), cancellationToken).ConfigureAwait(false);
|
||||
services.Logger.LogInformation("Chat {Owner}: trigger {TriggerId} \"{Name}\" created on group {GroupId} \"{Title}\", threshold {Threshold:0.00}: {Instructions}",
|
||||
owner, created.Id, created.Name, group.Id, group.Title, created.Threshold, created.Instructions);
|
||||
return ToolResult.Text("Created: " + TriggerPrompts.Line(created, zone(), services.Engine.Now, 0));
|
||||
}
|
||||
|
||||
@@ -138,6 +146,8 @@ public sealed class TriggerTool(long owner, TriggerServices services, Func<TimeZ
|
||||
Threshold = threshold ?? t.Threshold,
|
||||
Enabled = args.Enabled ?? t.Enabled,
|
||||
}, cancellationToken).ConfigureAwait(false) ?? throw Error($"No trigger {id} in this chat.");
|
||||
services.Logger.LogInformation("Chat {Owner}: trigger {TriggerId} \"{Name}\" updated: threshold {Threshold:0.00}, {State}: {Instructions}",
|
||||
owner, updated.Id, updated.Name, updated.Threshold, updated.Enabled ? "on" : "off", updated.Instructions);
|
||||
return ToolResult.Text("Updated: " + TriggerPrompts.Line(updated, zone(), services.Engine.Now, services.Engine.Queued(owner, updated.Id)));
|
||||
}
|
||||
|
||||
@@ -145,6 +155,7 @@ public sealed class TriggerTool(long owner, TriggerServices services, Func<TimeZ
|
||||
{
|
||||
var id = RequireId(args.Id, "delete");
|
||||
var removed = await services.Engine.DeleteAsync(owner, id, cancellationToken).ConfigureAwait(false) ?? throw Error($"No trigger {id} in this chat.");
|
||||
services.Logger.LogInformation("Chat {Owner}: trigger {TriggerId} \"{Name}\" deleted", owner, removed.Id, removed.Name);
|
||||
return ToolResult.Text($"Deleted {removed.Id} (\"{removed.Name}\").");
|
||||
}
|
||||
|
||||
@@ -166,6 +177,7 @@ public sealed class TriggerTool(long owner, TriggerServices services, Func<TimeZ
|
||||
|
||||
var snoozed = await services.Engine.SnoozeAsync(owner, Id(args.Id), until, cancellationToken).ConfigureAwait(false);
|
||||
if (snoozed.Count == 0) throw Error(args.Id is null ? "This chat has no triggers." : $"No trigger {args.Id.Trim()} in this chat.");
|
||||
services.Logger.LogInformation("Chat {Owner}: {Triggers} snoozed until {Until:O}", owner, string.Join(", ", snoozed.Select(t => t.Id)), until);
|
||||
return ToolResult.Text($"Snoozed {string.Join(", ", snoozed.Select(t => t.Id))} until {TriggerPrompts.Stamp(until, tz)} ({tz.Id}). " +
|
||||
"Messages are collected meanwhile and checked as one batch when the snooze ends; you get one prompt if anything is related.");
|
||||
}
|
||||
|
||||
@@ -46,9 +46,14 @@ public static class TriggersSetup
|
||||
}
|
||||
|
||||
/// <summary>Flushes snoozes that ended while the host was down and arms the snooze timer.</summary>
|
||||
public sealed class TriggersHostedService(TriggerEngine engine) : IHostedService
|
||||
public sealed class TriggersHostedService(TriggerEngine engine, GroupRegistry groups, ILogger<TriggersHostedService> logger) : IHostedService
|
||||
{
|
||||
public Task StartAsync(CancellationToken cancellationToken) => engine.StartAsync(cancellationToken);
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
logger.LogInformation("Group triggers: {Count} trigger(s) loaded for {Chats} chat(s), {Groups} watched group(s)",
|
||||
engine.Store.Count, engine.Store.OwnerCount, groups.All().Count(g => g.Active));
|
||||
return engine.StartAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user