Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 24 additions & 16 deletions src/OpenClaw.Shared/NotificationCategorizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,29 +87,37 @@ public class NotificationCategorizer
/// </summary>
public static (string title, string type) ClassifyByKeywords(string text)
{
var lower = text.ToLowerInvariant();
if (lower.Contains("blood sugar") || lower.Contains("glucose") ||
lower.Contains("cgm") || lower.Contains("mg/dl"))
// Use OrdinalIgnoreCase overloads to avoid allocating a lowercased copy of `text`.
if (text.Contains("blood sugar", StringComparison.OrdinalIgnoreCase) ||
text.Contains("glucose", StringComparison.OrdinalIgnoreCase) ||
text.Contains("cgm", StringComparison.OrdinalIgnoreCase) ||
text.Contains("mg/dl", StringComparison.OrdinalIgnoreCase))
return ("🩸 Blood Sugar Alert", "health");
if (lower.Contains("urgent") || lower.Contains("critical") ||
lower.Contains("emergency"))
if (text.Contains("urgent", StringComparison.OrdinalIgnoreCase) ||
text.Contains("critical", StringComparison.OrdinalIgnoreCase) ||
text.Contains("emergency", StringComparison.OrdinalIgnoreCase))
return ("🚨 Urgent Alert", "urgent");
if (lower.Contains("reminder"))
if (text.Contains("reminder", StringComparison.OrdinalIgnoreCase))
return ("⏰ Reminder", "reminder");
if (lower.Contains("stock") || lower.Contains("in stock") ||
lower.Contains("available now"))
if (text.Contains("stock", StringComparison.OrdinalIgnoreCase) ||
text.Contains("in stock", StringComparison.OrdinalIgnoreCase) ||
text.Contains("available now", StringComparison.OrdinalIgnoreCase))
return ("📦 Stock Alert", "stock");
if (lower.Contains("email") || lower.Contains("inbox") ||
lower.Contains("gmail"))
if (text.Contains("email", StringComparison.OrdinalIgnoreCase) ||
text.Contains("inbox", StringComparison.OrdinalIgnoreCase) ||
text.Contains("gmail", StringComparison.OrdinalIgnoreCase))
return ("📧 Email", "email");
if (lower.Contains("calendar") || lower.Contains("meeting") ||
lower.Contains("event"))
if (text.Contains("calendar", StringComparison.OrdinalIgnoreCase) ||
text.Contains("meeting", StringComparison.OrdinalIgnoreCase) ||
text.Contains("event", StringComparison.OrdinalIgnoreCase))
return ("📅 Calendar", "calendar");
if (lower.Contains("error") || lower.Contains("failed") ||
lower.Contains("exception"))
if (text.Contains("error", StringComparison.OrdinalIgnoreCase) ||
text.Contains("failed", StringComparison.OrdinalIgnoreCase) ||
text.Contains("exception", StringComparison.OrdinalIgnoreCase))
return ("⚠️ Error", "error");
if (lower.Contains("build") || lower.Contains("ci ") ||
lower.Contains("deploy"))
if (text.Contains("build", StringComparison.OrdinalIgnoreCase) ||
text.Contains("ci ", StringComparison.OrdinalIgnoreCase) ||
text.Contains("deploy", StringComparison.OrdinalIgnoreCase))
return ("🔨 Build", "build");
return ("🤖 OpenClaw", "info");
}
Expand Down
37 changes: 20 additions & 17 deletions src/OpenClaw.Shared/OpenClawGatewayClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading;
Expand Down Expand Up @@ -1569,23 +1570,25 @@ private static (string title, string type) ClassifyNotification(string text)

// --- Utility ---

private static ActivityKind ClassifyTool(string toolName)
{
return toolName.ToLowerInvariant() switch
{
"exec" => ActivityKind.Exec,
"read" => ActivityKind.Read,
"write" => ActivityKind.Write,
"edit" => ActivityKind.Edit,
"web_search" => ActivityKind.Search,
"web_fetch" => ActivityKind.Search,
"browser" => ActivityKind.Browser,
"message" => ActivityKind.Message,
"tts" => ActivityKind.Tool,
"image" => ActivityKind.Tool,
_ => ActivityKind.Tool
};
}
// FrozenDictionary gives O(1) case-insensitive lookup without allocating a
// lowercased copy of toolName on every call.
private static readonly FrozenDictionary<string, ActivityKind> s_toolKindMap =
new Dictionary<string, ActivityKind>(StringComparer.OrdinalIgnoreCase)
{
["exec"] = ActivityKind.Exec,
["read"] = ActivityKind.Read,
["write"] = ActivityKind.Write,
["edit"] = ActivityKind.Edit,
["web_search"] = ActivityKind.Search,
["web_fetch"] = ActivityKind.Search,
["browser"] = ActivityKind.Browser,
["message"] = ActivityKind.Message,
["tts"] = ActivityKind.Tool,
["image"] = ActivityKind.Tool,
}.ToFrozenDictionary(StringComparer.OrdinalIgnoreCase);

private static ActivityKind ClassifyTool(string toolName) =>
s_toolKindMap.TryGetValue(toolName, out var kind) ? kind : ActivityKind.Tool;

private static string ShortenPath(string path)
{
Expand Down