oghma 0.0.1__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
oghma/watcher.py ADDED
@@ -0,0 +1,97 @@
1
+ import logging
2
+ from pathlib import Path
3
+ from typing import Any, cast
4
+
5
+ from oghma.config import Config
6
+ from oghma.parsers import Message, get_parser_for_file
7
+ from oghma.storage import Storage
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ class Watcher:
13
+ """Discovers and tracks transcript files."""
14
+
15
+ BLOCKED_DIRS = {".venv", "node_modules", ".git", "__pycache__", "dist", "build"}
16
+
17
+ def __init__(self, config: Config, storage: Storage):
18
+ self.config = config
19
+ self.storage = storage
20
+
21
+ def discover_files(self) -> list[Path]:
22
+ """Find all transcript files from configured tool paths."""
23
+ all_files: list[Path] = []
24
+ tools = cast(dict[str, Any], self.config.get("tools") or {})
25
+
26
+ for tool_name, tool_config in tools.items():
27
+ if not tool_config.get("enabled", False):
28
+ continue
29
+
30
+ paths = tool_config.get("paths") or []
31
+ for pattern in paths:
32
+ files = self._expand_glob_pattern(Path(pattern).expanduser(), tool_name)
33
+ all_files.extend(files)
34
+
35
+ return sorted(set(all_files))
36
+
37
+ def _expand_glob_pattern(self, pattern: Path, tool_name: str) -> list[Path]:
38
+ """Expand a glob pattern and filter blocked directories."""
39
+ files: list[Path] = []
40
+
41
+ try:
42
+ base_path = pattern.parent
43
+ glob_pattern = pattern.name
44
+
45
+ if "*" in str(base_path):
46
+ matched_paths = Path(str(base_path)).parent.glob(base_path.name)
47
+ for matched_dir in matched_paths:
48
+ if matched_dir.is_dir():
49
+ files.extend(matched_dir.glob(glob_pattern))
50
+ else:
51
+ if base_path.exists():
52
+ files.extend(base_path.glob(glob_pattern))
53
+
54
+ files = [f for f in files if f.is_file() and self._is_allowed(f)]
55
+ except (OSError, PermissionError):
56
+ logger.warning(f"Failed to expand pattern: {pattern}")
57
+
58
+ return files
59
+
60
+ def _is_allowed(self, path: Path) -> bool:
61
+ """Check if path is allowed (not in blocked directories)."""
62
+ parts = path.parts
63
+ return not any(part in self.BLOCKED_DIRS for part in parts)
64
+
65
+ def get_changed_files(self) -> list[Path]:
66
+ """Return files that changed since last check (based on mtime)."""
67
+ all_files = self.discover_files()
68
+ changed_files: list[Path] = []
69
+
70
+ for file_path in all_files:
71
+ if not file_path.exists():
72
+ continue
73
+
74
+ current_mtime = file_path.stat().st_mtime
75
+ current_size = file_path.stat().st_size
76
+
77
+ state = self.storage.get_extraction_state(str(file_path))
78
+
79
+ if state is None:
80
+ changed_files.append(file_path)
81
+ elif current_mtime > state["last_mtime"] or current_size != state["last_size"]:
82
+ changed_files.append(file_path)
83
+
84
+ return changed_files
85
+
86
+ def parse_file(self, file_path: Path) -> list[Message]:
87
+ """Parse a transcript file using appropriate parser."""
88
+ parser = get_parser_for_file(file_path)
89
+ if parser:
90
+ return parser.parse(file_path)
91
+ return []
92
+
93
+ def should_process(self, messages: list[Message]) -> bool:
94
+ """Check if file has enough messages to process."""
95
+ daemon_config = cast(dict[str, Any], self.config.get("daemon") or {})
96
+ min_messages = daemon_config.get("min_messages", 6)
97
+ return len(messages) >= min_messages
@@ -0,0 +1,26 @@
1
+ Metadata-Version: 2.4
2
+ Name: oghma
3
+ Version: 0.3.0
4
+ Summary: Unified AI memory layer for coding assistants
5
+ Author: Oghma Contributors
6
+ License: MIT
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Requires-Python: >=3.10
15
+ Requires-Dist: click>=8.0
16
+ Requires-Dist: pyyaml>=6.0
17
+ Requires-Dist: openai>=1.0
18
+ Requires-Dist: rich>=13.0
19
+ Requires-Dist: mcp[cli]>=1.0
20
+ Requires-Dist: sqlite-vec>=0.1.0
21
+ Provides-Extra: local
22
+ Requires-Dist: sentence-transformers>=2.0; extra == "local"
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest>=8.0; extra == "dev"
25
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
26
+ Requires-Dist: ruff>=0.1; extra == "dev"
@@ -0,0 +1,22 @@
1
+ oghma/__init__.py,sha256=VrXpHDu3erkzwl_WXrqINBm9xWkcyUy53IQOj042dOs,22
2
+ oghma/cli.py,sha256=2eb6TZKTj5UiaSID3LD-WyG0ozET2akZSU95aV6Ud_M,11965
3
+ oghma/config.py,sha256=AAaeIkzJEGJGWmJQJGtwQGpN661XoVB5Ih3hGV0VAjI,7663
4
+ oghma/daemon.py,sha256=FBxUzMqcgMhJEaGo3aZWuRE7OdoClIXL4w7wp0-g1Rg,6397
5
+ oghma/embedder.py,sha256=vtTENDoLM2yZL8eGb_itlHj7nDLalo2eiV-_W_-HuLk,3397
6
+ oghma/exporter.py,sha256=npBN_qsxQINy79A9pxa8XmtBOgYsUtdkAywka12O_4Q,6319
7
+ oghma/extractor.py,sha256=pqBCoWeMJK-paGcax8mZZcvJa7DmKrRJUGsHkqivRCE,6137
8
+ oghma/mcp_server.py,sha256=SShDGvaJ0wXLS2Gosnv9XW9RLHej-IQDnseEfqRMiGc,3189
9
+ oghma/migration.py,sha256=gb9ExvAW4nGm4-yJy2F7xuMF4DyzGK0x3F21OVg5XwM,1613
10
+ oghma/storage.py,sha256=lS7qC00O7Sa2P5FbKKg2ole66MrD2hNA_I8AGKKV3rs,26614
11
+ oghma/watcher.py,sha256=gcjuFCPMBLjt9IYHeveh_JmoKIK_AlqE9d5CSWKGrP0,3497
12
+ oghma/parsers/__init__.py,sha256=y2ymSDU2tuJByXyyMb3e6wRWSy8huR10vrSvegzn3Ak,703
13
+ oghma/parsers/base.py,sha256=3ZJOVtGobgCfjIL5zs5cGdo8FL5zeuINkVl3KOFiFvk,445
14
+ oghma/parsers/claude_code.py,sha256=Y28t7Y9Fn2iaUOtuiGugej7UsiEUirrxcUxEgIhuV9E,2001
15
+ oghma/parsers/codex.py,sha256=QaF5qhtCuPgKBXqVM-dJv0Fr5HZXsN4rYD6N65yJy54,2854
16
+ oghma/parsers/openclaw.py,sha256=F4PLsTDwOd7_7kdOhVBF5GZ0bpgdtPW-MN3GvbOdAwo,2028
17
+ oghma/parsers/opencode.py,sha256=Oz7NmH3hzTQ26JfwJTLuqwagcQUzhE7Du2N-kAj8_Dg,2738
18
+ oghma-0.3.0.dist-info/METADATA,sha256=KXrUxq3VDJU9-ykw_tKGgqWPJQh9az1gG2zjL3g6BjE,909
19
+ oghma-0.3.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
20
+ oghma-0.3.0.dist-info/entry_points.txt,sha256=1-W3Whiw00K0K63mYCazzNmlkxqSQjZ1A-6yyhq3fl0,75
21
+ oghma-0.3.0.dist-info/top_level.txt,sha256=i-cl63fF-H6gwspRwyLbnuQpMTymwaiib6B5YvQPuos,6
22
+ oghma-0.3.0.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.28.0
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ oghma = oghma.cli:main
3
+ oghma-mcp = oghma.mcp_server:main
@@ -0,0 +1 @@
1
+ oghma
@@ -1,33 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: oghma
3
- Version: 0.0.1
4
- Summary: Unified AI memory layer — aggregate context across coding tools
5
- Project-URL: Homepage, https://github.com/terry-li-hm/oghma
6
- Project-URL: Repository, https://github.com/terry-li-hm/oghma
7
- Author-email: Terry Li <terry.li.hm@gmail.com>
8
- License-Expression: MIT
9
- Keywords: ai,claude,coding-assistant,context,llm,memory
10
- Classifier: Development Status :: 1 - Planning
11
- Classifier: Environment :: Console
12
- Classifier: Intended Audience :: Developers
13
- Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Topic :: Software Development :: Libraries
16
- Requires-Python: >=3.10
17
- Description-Content-Type: text/markdown
18
-
19
- # Oghma
20
-
21
- Unified AI memory layer — aggregate context across coding tools.
22
-
23
- 🚧 **Coming soon** — package name reserved.
24
-
25
- ## Vision
26
-
27
- AI memory should be user-owned and tool-agnostic, not locked into provider silos.
28
-
29
- Oghma passively watches conversation transcripts from multiple AI coding tools (Claude Code, Codex, OpenClaw, OpenCode, Cursor) and extracts memories, so any tool can access your full context.
30
-
31
- ## Links
32
-
33
- - [GitHub](https://github.com/terry-li-hm/oghma)
@@ -1,4 +0,0 @@
1
- oghma/__init__.py,sha256=LAU5q2GOG4tWxcsHGqqw_KEnVIP_TGIQcdSIQ5wO26g,64
2
- oghma-0.0.1.dist-info/METADATA,sha256=m0Fc5KvQxtqY4N_ZrH2jexRGNuJraRa1qELZmqfhab4,1191
3
- oghma-0.0.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
4
- oghma-0.0.1.dist-info/RECORD,,