diff --git a/hosts/Volcanic.AgenticCore.Telegram/Chats/ChatRegistry.cs b/hosts/Volcanic.AgenticCore.Telegram/Chats/ChatRegistry.cs
index 97e6e16..7d6dade 100644
--- a/hosts/Volcanic.AgenticCore.Telegram/Chats/ChatRegistry.cs
+++ b/hosts/Volcanic.AgenticCore.Telegram/Chats/ChatRegistry.cs
@@ -82,7 +82,11 @@ public sealed class ChatRegistry(
public static string ScopeFor(long chatId) => $"telegram-{chatId}";
- public string WorkspaceFor(long chatId) => Path.Combine(options.WorkspaceRoot, chatId.ToString(System.Globalization.CultureInfo.InvariantCulture));
+ public string WorkspaceFor(long chatId) => WorkspaceFor(options, chatId);
+
+ /// <WorkspaceRoot>/<chatId>, for services that can't depend on the registry (it would close a DI cycle).
+ public static string WorkspaceFor(TelegramOptions options, long chatId) =>
+ Path.Combine(options.WorkspaceRoot, chatId.ToString(System.Globalization.CultureInfo.InvariantCulture));
/// The chat's context if it was already created, without creating it.
public ChatContext? Find(long chatId) =>
diff --git a/hosts/Volcanic.AgenticCore.Telegram/Scheduling/CalendarScriptEnvironment.cs b/hosts/Volcanic.AgenticCore.Telegram/Scheduling/CalendarScriptEnvironment.cs
index 2f24f76..e0dd56a 100644
--- a/hosts/Volcanic.AgenticCore.Telegram/Scheduling/CalendarScriptEnvironment.cs
+++ b/hosts/Volcanic.AgenticCore.Telegram/Scheduling/CalendarScriptEnvironment.cs
@@ -9,8 +9,10 @@ namespace Volcanic.AgenticCore.Telegram.Scheduling;
/// Gives a chat's watcher scripts GOOGLE_ACCESS_TOKEN: an access token for that chat's calendar, valid for the
/// run's timeout plus a minute (as far as Google's one-hour lifetime allows). The bot refreshes it; the refresh token
/// and the client secret never reach the script. A chat without a connected calendar gets nothing.
+/// Takes , not : the registry depends on the scheduler, which
+/// depends on this.
///
-public sealed class CalendarScriptEnvironment(ChatRegistry chats, GoogleCalendarOptions calendar) : IScriptEnvironment
+public sealed class CalendarScriptEnvironment(TelegramOptions options, GoogleCalendarOptions calendar) : IScriptEnvironment
{
public const string AccessTokenVariable = "GOOGLE_ACCESS_TOKEN";
private static readonly TimeSpan Margin = TimeSpan.FromMinutes(1);
@@ -20,7 +22,7 @@ public sealed class CalendarScriptEnvironment(ChatRegistry chats, GoogleCalendar
{
if (!long.TryParse(target, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out var chatId)) return None;
var token = await (calendar.Connections ?? GoogleCalendarConnections.Shared)
- .TryGetAccessTokenAsync(calendar, ChatRegistry.ScopeFor(chatId), chats.WorkspaceFor(chatId), timeout + Margin, cancellationToken)
+ .TryGetAccessTokenAsync(calendar, ChatRegistry.ScopeFor(chatId), ChatRegistry.WorkspaceFor(options, chatId), timeout + Margin, cancellationToken)
.ConfigureAwait(false);
return token is null ? None : new Dictionary { [AccessTokenVariable] = token };
}
diff --git a/tests/Volcanic.AgenticCore.Telegram.Tests/GoogleCalendarHostTests.cs b/tests/Volcanic.AgenticCore.Telegram.Tests/GoogleCalendarHostTests.cs
index 8908d6d..59fe5e8 100644
--- a/tests/Volcanic.AgenticCore.Telegram.Tests/GoogleCalendarHostTests.cs
+++ b/tests/Volcanic.AgenticCore.Telegram.Tests/GoogleCalendarHostTests.cs
@@ -166,7 +166,7 @@ public class GoogleCalendarHostTests : IDisposable
{
var calendar = Calendar();
await using var host = new ChatHost(calendar: calendar);
- var environment = new Volcanic.AgenticCore.Telegram.Scheduling.CalendarScriptEnvironment(host.Chats, calendar);
+ var environment = new Volcanic.AgenticCore.Telegram.Scheduling.CalendarScriptEnvironment(host.Options, calendar);
var target = Updates.AllowedUser.ToString(System.Globalization.CultureInfo.InvariantCulture);
Assert.Empty(await environment.ForRunAsync(target, TimeSpan.FromMinutes(5), CancellationToken.None)); // not connected yet