From 623066377ddb7c90fda8ff6341960f4451b050f7 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 18 Oct 2026 09:38:24 +0000 Subject: [PATCH] Prompt Amplifier: count down to the weekly reset, not the 1st of the month Lykos credits move to a weekly allowance that resets for everyone on Monday 00:00 UTC. The low-usage hint and the out-of-usage dialog counted days to the 1st of next month, so they would show the wrong reset. They now count to the next Monday 00:00 UTC and phrase it as days, hours, or "less than an hour", since a weekly countdown regularly drops under a day. The de/fr/ja/ko translations of the out-of-usage message promised a monthly reset on the 1st; they are removed so those locales fall back to the corrected English until they are re-translated. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01K8PyehGS4YG75TejPPRKPo --- .../Languages/Resources.Designer.cs | 2 +- .../Languages/Resources.de.resx | 3 -- .../Languages/Resources.fr-FR.resx | 3 -- .../Languages/Resources.ja-JP.resx | 3 -- .../Languages/Resources.ko-KR.resx | 3 -- .../Languages/Resources.resx | 4 +- .../Inference/PromptCardViewModel.cs | 4 +- StabilityMatrix.Core/Helper/Utilities.cs | 41 ++++++++++++++++--- .../Helper/WeeklyResetTests.cs | 34 +++++++++++++++ 9 files changed, 75 insertions(+), 22 deletions(-) create mode 100644 StabilityMatrix.Tests/Helper/WeeklyResetTests.cs diff --git a/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs b/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs index 44bca5b52..61d019fed 100644 --- a/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs +++ b/StabilityMatrix.Avalonia/Languages/Resources.Designer.cs @@ -3292,7 +3292,7 @@ public static string Label_PromptAmplifierError { } /// - /// Looks up a localized string similar to You have no Prompt Amplifier usage left this month. Usage resets on the 1st of each month. ({0} days left). + /// Looks up a localized string similar to You have no Prompt Amplifier usage left this week. Usage resets every Monday at 00:00 UTC (in {0}).. /// public static string Label_PromptAmplifierRateLimitMessage { get { diff --git a/StabilityMatrix.Avalonia/Languages/Resources.de.resx b/StabilityMatrix.Avalonia/Languages/Resources.de.resx index b48614e7b..e0a3af1f4 100644 --- a/StabilityMatrix.Avalonia/Languages/Resources.de.resx +++ b/StabilityMatrix.Avalonia/Languages/Resources.de.resx @@ -1137,9 +1137,6 @@ Konto-Tokens sind nach dem Speichern nicht mehr einsehbar. Bitte notiere sie, we Nutzungslimit erreicht - - Du hast diesen Monat keine Prompt-Amplifier-Nutzung mehr übrig. Die Nutzung wird am 1. jedes Monats zurückgesetzt. (noch {0} Tage) - Prompt-Amplifier-Fehler diff --git a/StabilityMatrix.Avalonia/Languages/Resources.fr-FR.resx b/StabilityMatrix.Avalonia/Languages/Resources.fr-FR.resx index 3e67c967f..2a6f60989 100644 --- a/StabilityMatrix.Avalonia/Languages/Resources.fr-FR.resx +++ b/StabilityMatrix.Avalonia/Languages/Resources.fr-FR.resx @@ -1229,9 +1229,6 @@ Les jetons de compte ne seront plus visibles après l'enregistrement. Veuillez e Limite d'utilisation atteinte - - Vous n'avez plus d'utilisation Prompt Amplifier ce mois-ci. L'utilisation est réinitialisée le 1er de chaque mois. ({0} jours restants) - Erreur Prompt Amplifier diff --git a/StabilityMatrix.Avalonia/Languages/Resources.ja-JP.resx b/StabilityMatrix.Avalonia/Languages/Resources.ja-JP.resx index 2aac03425..681b98a23 100644 --- a/StabilityMatrix.Avalonia/Languages/Resources.ja-JP.resx +++ b/StabilityMatrix.Avalonia/Languages/Resources.ja-JP.resx @@ -1550,9 +1550,6 @@ Sparkは兆レベルのパラメータを持つ基盤モデルで、膨大なパ 利用上限に達しました - - 今月のプロンプトアンプリファイアの利用回数がなくなりました。利用回数は毎月1日にリセットされます。(残り{0}日) - プロンプトアンプリファイアエラー diff --git a/StabilityMatrix.Avalonia/Languages/Resources.ko-KR.resx b/StabilityMatrix.Avalonia/Languages/Resources.ko-KR.resx index 7fbe06ac6..4007b0e10 100644 --- a/StabilityMatrix.Avalonia/Languages/Resources.ko-KR.resx +++ b/StabilityMatrix.Avalonia/Languages/Resources.ko-KR.resx @@ -1376,9 +1376,6 @@ 사용 한도 도달 - - 이번 달 프롬프트 증폭기 사용량이 모두 소진되었습니다. 사용량은 매월 1일에 초기화됩니다. ({0}일 남음) - 프롬프트 증폭기 오류 diff --git a/StabilityMatrix.Avalonia/Languages/Resources.resx b/StabilityMatrix.Avalonia/Languages/Resources.resx index ede9d4b94..92bdc89bb 100644 --- a/StabilityMatrix.Avalonia/Languages/Resources.resx +++ b/StabilityMatrix.Avalonia/Languages/Resources.resx @@ -1687,8 +1687,8 @@ Account tokens will not be viewable after saving, please make a note of them if Rate Limit Reached - You have no Prompt Amplifier usage left this month. Usage resets on the 1st of each month. ({0} days left) - {0} = days remaining until next month + You have no Prompt Amplifier usage left this week. Usage resets every Monday at 00:00 UTC (in {0}). + {0} = time left until the weekly reset, already formatted in English, e.g. "3 days" or "5 hours" Prompt Amplifier Error diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/PromptCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/PromptCardViewModel.cs index 12c106926..392cd3a62 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Inference/PromptCardViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/PromptCardViewModel.cs @@ -115,7 +115,7 @@ public partial class PromptCardViewModel public bool ShowLowTokenWarning => TokensRemaining <= LowTokenThreshold && TokensRemaining >= 0; public string LowTokenWarningText => - $"{TokensRemaining} amplification{(TokensRemaining == 1 ? "" : "s")} remaining (resets in {Utilities.GetNumDaysTilBeginningOfNextMonth()} days)"; + $"{TokensRemaining} amplification{(TokensRemaining == 1 ? "" : "s")} remaining (resets in {Utilities.FormatTimeUntilNextWeeklyReset()})"; /// public PromptCardViewModel( @@ -661,7 +661,7 @@ private async Task AmplifyPrompt() var dialog = DialogHelper.CreateMarkdownDialog( string.Format( Resources.Label_PromptAmplifierRateLimitMessage, - Utilities.GetNumDaysTilBeginningOfNextMonth() + Utilities.FormatTimeUntilNextWeeklyReset() ), Resources.Label_PromptAmplifierRateLimitTitle ); diff --git a/StabilityMatrix.Core/Helper/Utilities.cs b/StabilityMatrix.Core/Helper/Utilities.cs index 6e7f6d7d2..e47b50620 100644 --- a/StabilityMatrix.Core/Helper/Utilities.cs +++ b/StabilityMatrix.Core/Helper/Utilities.cs @@ -82,12 +82,43 @@ public static async Task WhichAsync(string arg) return await process.StandardOutput.ReadToEndAsync().ConfigureAwait(false); } - public static int GetNumDaysTilBeginningOfNextMonth() + /// + /// Day the Lykos weekly credit allowance resets for everyone, at 00:00 UTC. + /// + public const DayOfWeek WeeklyResetDay = DayOfWeek.Monday; + + /// + /// Time left until the next Lykos weekly credit reset (, 00:00 UTC). + /// Exactly at the reset instant, the next one is a full week away. + /// + public static TimeSpan GetTimeUntilNextWeeklyReset(DateTimeOffset? now = null) + { + var utcNow = (now ?? DateTimeOffset.UtcNow).ToUniversalTime(); + var daysAhead = ((int)WeeklyResetDay - (int)utcNow.DayOfWeek + 7) % 7; + var nextReset = new DateTimeOffset(utcNow.Date, TimeSpan.Zero).AddDays(daysAhead); + if (nextReset <= utcNow) + nextReset = nextReset.AddDays(7); + return nextReset - utcNow; + } + + /// + /// "3 days", "1 day", "5 hours", "1 hour" or "less than an hour" until the next weekly reset, + /// for "resets in …" copy. + /// + public static string FormatTimeUntilNextWeeklyReset(DateTimeOffset? now = null) { - var now = DateTimeOffset.UtcNow; - var firstDayOfNextMonth = new DateTime(now.Year, now.Month, 1).AddMonths(1); - var daysUntilNextMonth = (firstDayOfNextMonth - now).Days; - return daysUntilNextMonth; + var left = GetTimeUntilNextWeeklyReset(now); + if (left.TotalDays >= 1) + { + var days = (int)left.TotalDays; + return days == 1 ? "1 day" : $"{days} days"; + } + if (left.TotalHours >= 1) + { + var hours = (int)left.TotalHours; + return hours == 1 ? "1 hour" : $"{hours} hours"; + } + return "less than an hour"; } public static string RemoveHtml(string? stringWithHtml) diff --git a/StabilityMatrix.Tests/Helper/WeeklyResetTests.cs b/StabilityMatrix.Tests/Helper/WeeklyResetTests.cs new file mode 100644 index 000000000..3c444dae7 --- /dev/null +++ b/StabilityMatrix.Tests/Helper/WeeklyResetTests.cs @@ -0,0 +1,34 @@ +using StabilityMatrix.Core.Helper; + +namespace StabilityMatrix.Tests.Helper; + +[TestClass] +public class WeeklyResetTests +{ + // 2026-10-14 is a Wednesday. + [DataTestMethod] + [DataRow("2026-10-14T12:00:00Z", "4 days")] + [DataRow("2026-10-18T12:00:00Z", "12 hours")] + [DataRow("2026-10-18T23:30:00Z", "less than an hour")] + [DataRow("2026-10-18T22:30:00Z", "1 hour")] + [DataRow("2026-10-18T00:00:00Z", "1 day")] + [DataRow("2026-10-19T00:00:00Z", "7 days")] + [DataRow("2026-10-19T00:00:01Z", "6 days")] + public void FormatTimeUntilNextWeeklyReset_CountsToMondayMidnightUtc(string now, string expected) + { + var result = Utilities.FormatTimeUntilNextWeeklyReset(DateTimeOffset.Parse(now)); + + Assert.AreEqual(expected, result); + } + + [TestMethod] + public void GetTimeUntilNextWeeklyReset_UsesUtcRegardlessOfOffset() + { + // Sunday 20:00 at -05:00 is Monday 01:00 UTC, just after a reset. + var now = new DateTimeOffset(2026, 10, 18, 20, 0, 0, TimeSpan.FromHours(-5)); + + var result = Utilities.GetTimeUntilNextWeeklyReset(now); + + Assert.AreEqual(TimeSpan.FromDays(7) - TimeSpan.FromHours(1), result); + } +}