Skip to content

feat(categorize): add AI-powered auto-categorization watcher with mul… - #1410

Open
abdelrhmanabdelmonsef wants to merge 1 commit into
ActivityWatch:masterfrom
abdelrhmanabdelmonsef:feat/auto-categorize-watcher
Open

feat(categorize): add AI-powered auto-categorization watcher with mul…#1410
abdelrhmanabdelmonsef wants to merge 1 commit into
ActivityWatch:masterfrom
abdelrhmanabdelmonsef:feat/auto-categorize-watcher

Conversation

@abdelrhmanabdelmonsef

Copy link
Copy Markdown

…ti-level taxonomy

Introduces aw-watcher-categorize package supporting multi-provider AI models (OpenAI, Ollama, Gemini, Claude), deep 3-4 tier category taxonomy, real-time heartbeat emission, batch rule learning, and built-in offline heuristics.

…ti-level taxonomy

Introduces aw-watcher-categorize package supporting multi-provider AI models (OpenAI, Ollama, Gemini, Claude), deep 3-4 tier category taxonomy, real-time heartbeat emission, batch rule learning, and built-in offline heuristics.
@greptile-apps

greptile-apps Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Introduces an AI-powered categorization watcher with offline heuristics, multiple model providers, real-time category heartbeats, and batch rule learning.

  • Adds OpenAI-compatible, Ollama, Gemini, and Anthropic clients with response parsing and caching.
  • Adds hierarchical rule matching, historical uncategorized-event aggregation, and optional server rule updates.
  • Adds package metadata, documentation, a PowerShell implementation, and unit tests.
  • The rule-persistence serialization and repository packaging integration need correction before release.

Confidence Score: 3/5

The PR is not ready to merge because learned rules are persisted in an unusable form and the new watcher is omitted from standard build and release bundles.

The settings update double-encodes the classes list, preventing generated rules from surviving or loading correctly, while the repository's explicit build and packaging paths never include the new executable.

Files Needing Attention: aw-watcher-categorize/aw_watcher_categorize/learner.py, aw-watcher-categorize/pyproject.toml, Makefile, and aw.spec

Important Files Changed

Filename Overview
aw-watcher-categorize/aw_watcher_categorize/learner.py Adds historical rule learning, but double-encodes the classes setting when persisting generated rules.
aw-watcher-categorize/aw_watcher_categorize/main.py Adds the real-time watcher loop and automatic rule updates, which reload the malformed setting written by the learner.
aw-watcher-categorize/aw_watcher_categorize/ai_client.py Adds multi-provider AI inference, parsing, and an unprofiled LRU classification cache.
aw-watcher-categorize/aw_watcher_categorize/classifier.py Implements ordered server-rule, heuristic, AI, and uncategorized classification tiers without an accepted defect.
aw-watcher-categorize/pyproject.toml Defines the standalone package and executable, but the package is absent from the repository build and release integration points.
aw-watcher-categorize/run_watcher.ps1 Provides a separate Windows/Gemini watcher implementation; no independently publishable defect was established.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  W[Window/Web events] --> C[Multi-tier classifier]
  R[Server rules] --> C
  H[Built-in heuristics] --> C
  C -->|fallback| AI[Configured AI provider]
  C --> E[Categorization heartbeat]
  AI --> L[Suggested regex]
  L -->|learn/apply or auto-update| S[Server classes setting]
Loading

Reviews (1): Last reviewed commit: "feat(categorize): add AI-powered auto-ca..." | Re-trigger Greptile

existing_map[cat_tuple] = new_item

try:
client.set_setting("classes", json.dumps(raw_classes))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Classes setting is double-encoded

When generated rules are applied, json.dumps(raw_classes) passes a string to set_setting, which serializes its value again. The server consequently stores classes as a JSON string instead of an array, preventing the learned rules from loading and causing later updates to fall back to the defaults.

Suggested change
client.set_setting("classes", json.dumps(raw_classes))
client.set_setting("classes", raw_classes)

Comment on lines +1 to +10
[tool.poetry]
name = "aw-watcher-categorize"
version = "0.1.0"
description = "Automated AI-powered categorization watcher and rule learner for ActivityWatch"
authors = ["ActivityWatch Contributors <erik@bjareho.lt>"]
license = "MPL-2.0"
readme = "README.md"

[tool.poetry.scripts]
aw-watcher-categorize = "aw_watcher_categorize.main:main"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Watcher is omitted from packaging

The new executable is not registered in the root Makefile module lists or the PyInstaller specification. Standard repository builds therefore neither build nor test this watcher, and released ActivityWatch bundles do not contain the advertised aw-watcher-categorize command.

Knowledge Base Used: Packaging assets

Comment on lines +42 to +59

class LRUCache:
def __init__(self, capacity: int = 2000):
self.capacity = capacity
self.cache: OrderedDict[str, ClassificationResult] = OrderedDict()

def get(self, key: str) -> Optional[ClassificationResult]:
if key not in self.cache:
return None
self.cache.move_to_end(key)
return self.cache[key]

def put(self, key: str, value: ClassificationResult) -> None:
if key in self.cache:
self.cache.move_to_end(key)
self.cache[key] = value
if len(self.cache) > self.capacity:
self.cache.popitem(last=False)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Cache lacks required profiling

This introduces a custom 2,000-entry LRU cache without profiling that identifies classification caching as a bottleneck. That adds memory use and maintenance complexity without a measured performance justification.

Rule Used: Before implementing performance optimizations, mea... (source)

Learned From
gptme/gptme#707

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants