autourgos-token-memory 1.0.0__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Jitin Kumar Sengar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: autourgos-token-memory
3
+ Version: 1.0.0
4
+ Summary: Token-bounded short-term memory for Autourgos agents — TokenBufferedMemory.
5
+ Author-email: Jitin Kumar Sengar <devxjitin@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/devxjitin/autourgos-token-memory
8
+ Project-URL: Repository, https://github.com/devxjitin/autourgos-token-memory
9
+ Project-URL: Issues, https://github.com/devxjitin/autourgos-token-memory/issues
10
+ Keywords: autourgos,agent,memory,llm
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Provides-Extra: tiktoken
23
+ Requires-Dist: tiktoken>=0.5; extra == "tiktoken"
24
+ Dynamic: license-file
25
+
26
+ # autourgos-token-memory
27
+
28
+ Token-bounded short-term memory for [Autourgos](https://github.com/devxjitin) agents.
29
+
30
+ Keeps messages in RAM and evicts the oldest ones when the total token count exceeds a budget. Automatically uses `tiktoken` for accurate counts if installed, with a fast character-based heuristic as fallback.
31
+
32
+ ---
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ pip install autourgos-token-memory
38
+
39
+ # For accurate tiktoken counts (recommended for OpenAI models)
40
+ pip install 'autourgos-token-memory[tiktoken]'
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Quick Start
46
+
47
+ ```python
48
+ from autourgos_token_memory import TokenBufferedMemory
49
+ from autourgos_react_agent import ReactAgent
50
+
51
+ memory = TokenBufferedMemory(max_tokens=4000)
52
+ agent = ReactAgent(llm=my_llm, memory=memory)
53
+ agent.invoke("Long conversation task...")
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Parameters
59
+
60
+ | Parameter | Type | Default | Description |
61
+ |---|---|---|---|
62
+ | `max_tokens` | int | `2000` | Token budget. Oldest messages evicted when exceeded. |
63
+ | `token_estimator` | callable | `None` | Custom `(text: str) -> int`. Defaults to tiktoken / heuristic. |
64
+
65
+ ---
66
+
67
+ ## Custom token estimator
68
+
69
+ ```python
70
+ from autourgos_token_memory import TokenBufferedMemory
71
+
72
+ def my_estimator(text: str) -> int:
73
+ return len(text.split()) # word count
74
+
75
+ memory = TokenBufferedMemory(max_tokens=500, token_estimator=my_estimator)
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Token counting
81
+
82
+ - **tiktoken installed**: uses `cl100k_base` encoding (accurate for GPT-3.5/4/4o).
83
+ - **tiktoken not installed**: Unicode-aware heuristic — ~0.25 tokens per ASCII char, ~1.5 per CJK character.
84
+
85
+ Check current usage:
86
+
87
+ ```python
88
+ print(memory.total_tokens) # → int
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Links
94
+
95
+ - PyPI: https://pypi.org/project/autourgos-token-memory/
96
+ - GitHub: https://github.com/devxjitin/autourgos-token-memory
97
+ - Issues: https://github.com/devxjitin/autourgos-token-memory/issues
98
+
99
+ ---
100
+
101
+ ## License
102
+
103
+ MIT — see [LICENSE](LICENSE)
@@ -0,0 +1,78 @@
1
+ # autourgos-token-memory
2
+
3
+ Token-bounded short-term memory for [Autourgos](https://github.com/devxjitin) agents.
4
+
5
+ Keeps messages in RAM and evicts the oldest ones when the total token count exceeds a budget. Automatically uses `tiktoken` for accurate counts if installed, with a fast character-based heuristic as fallback.
6
+
7
+ ---
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pip install autourgos-token-memory
13
+
14
+ # For accurate tiktoken counts (recommended for OpenAI models)
15
+ pip install 'autourgos-token-memory[tiktoken]'
16
+ ```
17
+
18
+ ---
19
+
20
+ ## Quick Start
21
+
22
+ ```python
23
+ from autourgos_token_memory import TokenBufferedMemory
24
+ from autourgos_react_agent import ReactAgent
25
+
26
+ memory = TokenBufferedMemory(max_tokens=4000)
27
+ agent = ReactAgent(llm=my_llm, memory=memory)
28
+ agent.invoke("Long conversation task...")
29
+ ```
30
+
31
+ ---
32
+
33
+ ## Parameters
34
+
35
+ | Parameter | Type | Default | Description |
36
+ |---|---|---|---|
37
+ | `max_tokens` | int | `2000` | Token budget. Oldest messages evicted when exceeded. |
38
+ | `token_estimator` | callable | `None` | Custom `(text: str) -> int`. Defaults to tiktoken / heuristic. |
39
+
40
+ ---
41
+
42
+ ## Custom token estimator
43
+
44
+ ```python
45
+ from autourgos_token_memory import TokenBufferedMemory
46
+
47
+ def my_estimator(text: str) -> int:
48
+ return len(text.split()) # word count
49
+
50
+ memory = TokenBufferedMemory(max_tokens=500, token_estimator=my_estimator)
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Token counting
56
+
57
+ - **tiktoken installed**: uses `cl100k_base` encoding (accurate for GPT-3.5/4/4o).
58
+ - **tiktoken not installed**: Unicode-aware heuristic — ~0.25 tokens per ASCII char, ~1.5 per CJK character.
59
+
60
+ Check current usage:
61
+
62
+ ```python
63
+ print(memory.total_tokens) # → int
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Links
69
+
70
+ - PyPI: https://pypi.org/project/autourgos-token-memory/
71
+ - GitHub: https://github.com/devxjitin/autourgos-token-memory
72
+ - Issues: https://github.com/devxjitin/autourgos-token-memory/issues
73
+
74
+ ---
75
+
76
+ ## License
77
+
78
+ MIT — see [LICENSE](LICENSE)
@@ -0,0 +1,18 @@
1
+ """
2
+ autourgos-token-memory — Token-bounded short-term memory for Autourgos agents.
3
+
4
+ from autourgos_token_memory import TokenBufferedMemory
5
+
6
+ Install with tiktoken for accurate counts::
7
+
8
+ pip install 'autourgos-token-memory[tiktoken]'
9
+ """
10
+ from .memory import TokenBufferedMemory, _default_token_estimator
11
+
12
+ try:
13
+ from importlib.metadata import version as _v
14
+ __version__ = _v("autourgos-token-memory")
15
+ except Exception:
16
+ __version__ = "1.0.2"
17
+
18
+ __all__ = ["TokenBufferedMemory"]
@@ -0,0 +1,101 @@
1
+ """
2
+ base.py — Self-contained base classes. No external dependencies.
3
+ """
4
+ from __future__ import annotations
5
+
6
+ import warnings
7
+ from abc import ABC, abstractmethod
8
+ from dataclasses import dataclass, field
9
+ from datetime import datetime, timezone
10
+ from typing import Any, Dict, List, Optional
11
+
12
+ _ALLOWED_ROLES = {"user", "agent", "system", "tool"}
13
+
14
+
15
+ @dataclass(frozen=True)
16
+ class MemoryMessage:
17
+ """A single message in memory."""
18
+ role: str
19
+ content: str
20
+ timestamp: datetime
21
+
22
+ def __post_init__(self) -> None:
23
+ if self.role not in _ALLOWED_ROLES:
24
+ raise ValueError(f"Invalid role {self.role!r}. Allowed: {sorted(_ALLOWED_ROLES)}")
25
+ if not isinstance(self.content, str):
26
+ raise ValueError("content must be a string")
27
+ if not isinstance(self.timestamp, datetime):
28
+ raise ValueError("timestamp must be a datetime")
29
+
30
+ def to_dict(self) -> Dict[str, str]:
31
+ return {
32
+ "role": self.role,
33
+ "content": self.content,
34
+ "timestamp": self.timestamp.astimezone(timezone.utc).isoformat(),
35
+ }
36
+
37
+ @classmethod
38
+ def from_dict(cls, payload: Dict[str, Any]) -> "MemoryMessage":
39
+ ts = payload.get("timestamp")
40
+ if not isinstance(ts, str):
41
+ raise ValueError("timestamp must be a string")
42
+ dt = datetime.fromisoformat(ts)
43
+ if dt.tzinfo is None:
44
+ dt = dt.replace(tzinfo=timezone.utc)
45
+ return cls(role=str(payload.get("role", "")), content=str(payload.get("content", "")), timestamp=dt)
46
+
47
+
48
+ class BaseMemory(ABC):
49
+ """Abstract interface for agent memory."""
50
+
51
+ @abstractmethod
52
+ def add_user_message(self, content: str) -> MemoryMessage: ...
53
+
54
+ def add_ai_message(self, content: str) -> MemoryMessage:
55
+ warnings.warn("add_ai_message() is deprecated; use add_agent_message().", DeprecationWarning, stacklevel=2)
56
+ return self.add_agent_message(content)
57
+
58
+ def add_agent_message(self, content: str) -> MemoryMessage:
59
+ if type(self).add_ai_message is not BaseMemory.add_ai_message:
60
+ return self.add_ai_message(content)
61
+ raise NotImplementedError("Subclasses must implement add_agent_message")
62
+
63
+ @abstractmethod
64
+ def add_tool_message(self, tool_name: str, result: str) -> MemoryMessage: ...
65
+
66
+ def get_context(self, query: Optional[str] = None) -> str:
67
+ warnings.warn("get_context() is deprecated; use format_for_llm().", DeprecationWarning, stacklevel=2)
68
+ return self.format_for_llm(query)
69
+
70
+ def format_for_llm(self, query: Optional[str] = None) -> str:
71
+ if type(self).get_context is not BaseMemory.get_context:
72
+ return self.get_context(query)
73
+ raise NotImplementedError("Subclasses must implement format_for_llm")
74
+
75
+ @abstractmethod
76
+ def clear(self) -> None: ...
77
+
78
+
79
+ @dataclass
80
+ class Document:
81
+ """A retrieved document chunk."""
82
+ content: str
83
+ metadata: Dict[str, Any] = field(default_factory=dict)
84
+ score: float = 0.0
85
+ source: str = ""
86
+
87
+ def __str__(self) -> str:
88
+ src = f" (source: {self.source})" if self.source else ""
89
+ return f"{self.content}{src}"
90
+
91
+
92
+ class BaseRetriever(ABC):
93
+ """Abstract retriever interface."""
94
+
95
+ @abstractmethod
96
+ def retrieve(self, query: str, top_k: int = 5) -> List[Document]: ...
97
+
98
+ async def aretrieve(self, query: str, top_k: int = 5) -> List[Document]:
99
+ import asyncio
100
+ return await asyncio.to_thread(self.retrieve, query, top_k)
101
+
@@ -0,0 +1,110 @@
1
+ """
2
+ memory.py — Token-bounded short-term memory.
3
+ """
4
+ from __future__ import annotations
5
+
6
+ import threading
7
+ from datetime import datetime, timezone
8
+ from typing import Callable, List, Optional
9
+
10
+ from .base import BaseMemory, MemoryMessage
11
+
12
+
13
+ def _default_token_estimator(text: Optional[str]) -> int:
14
+ """Estimate tokens. Uses tiktoken if installed, otherwise a heuristic."""
15
+ if not text:
16
+ return 0
17
+ try:
18
+ import tiktoken
19
+ enc = tiktoken.get_encoding("cl100k_base")
20
+ return len(enc.encode(text, disallowed_special=()))
21
+ except Exception:
22
+ pass
23
+ # Unicode-aware heuristic
24
+ total = 0.0
25
+ for ch in text:
26
+ o = ord(ch)
27
+ if (0x4E00 <= o <= 0x9FFF or 0x3040 <= o <= 0x309F or
28
+ 0x30A0 <= o <= 0x30FF or 0x1100 <= o <= 0x11FF or
29
+ 0xAC00 <= o <= 0xD7AF):
30
+ total += 1.5
31
+ elif ch in ('{', '}', '[', ']', '"', "'", ':', ',', ';', '=', '+', '-', '*', '/', '<', '>', '&', '|', '^', '%'):
32
+ total += 0.5
33
+ else:
34
+ total += 0.25
35
+ return max(1, int(total))
36
+
37
+
38
+ class TokenBufferedMemory(BaseMemory):
39
+ """Short-term memory bounded by maximum token count.
40
+
41
+ Oldest messages are evicted from the front whenever the total token
42
+ count exceeds ``max_tokens``. Optionally uses ``tiktoken`` for accurate
43
+ counts; falls back to a character-based heuristic if not installed.
44
+
45
+ Parameters
46
+ ----------
47
+ max_tokens : int
48
+ Token budget. Default 2000.
49
+ token_estimator : callable, optional
50
+ Custom ``(text: str) -> int`` estimator. Defaults to tiktoken / heuristic.
51
+ """
52
+
53
+ def __init__(
54
+ self,
55
+ max_tokens: int = 2000,
56
+ token_estimator: Optional[Callable[[str], int]] = None,
57
+ ) -> None:
58
+ if not isinstance(max_tokens, int) or max_tokens < 1:
59
+ raise ValueError("max_tokens must be an integer >= 1")
60
+ self.max_tokens = max_tokens
61
+ self.token_estimator = token_estimator or _default_token_estimator
62
+ self._messages: List[MemoryMessage] = []
63
+ self._total_tokens = 0
64
+ self._lock = threading.RLock()
65
+
66
+ def _msg_tokens(self, msg: MemoryMessage) -> int:
67
+ return self.token_estimator(msg.role) + self.token_estimator(msg.content)
68
+
69
+ def _enforce_limit(self) -> None:
70
+ while self._messages and self._total_tokens > self.max_tokens:
71
+ removed = self._messages.pop(0)
72
+ self._total_tokens -= self._msg_tokens(removed)
73
+
74
+ def add_message(self, role: str, content: str, timestamp: Optional[datetime] = None) -> MemoryMessage:
75
+ with self._lock:
76
+ msg = MemoryMessage(role=role, content=content, timestamp=timestamp or datetime.now(timezone.utc))
77
+ self._messages.append(msg)
78
+ self._total_tokens += self._msg_tokens(msg)
79
+ self._enforce_limit()
80
+ return msg
81
+
82
+ def add_user_message(self, content: str) -> MemoryMessage:
83
+ return self.add_message("user", content)
84
+
85
+ def add_agent_message(self, content: str) -> MemoryMessage:
86
+ return self.add_message("agent", content)
87
+
88
+ def add_tool_message(self, tool_name: str, result: str) -> MemoryMessage:
89
+ return self.add_message("tool", f"[{tool_name} returned]: {result}")
90
+
91
+ def get_messages(self) -> List[MemoryMessage]:
92
+ with self._lock:
93
+ return list(self._messages)
94
+
95
+ @property
96
+ def total_tokens(self) -> int:
97
+ with self._lock:
98
+ return self._total_tokens
99
+
100
+ def format_for_llm(self, query: Optional[str] = None) -> str:
101
+ with self._lock:
102
+ if not self._messages:
103
+ return ""
104
+ lines = "\n".join(f"[{m.timestamp.isoformat()}] {m.role}: {m.content}" for m in self._messages)
105
+ return f"\n--- Previous Conversation Context ---\n{lines}\n--------------------------------------\n"
106
+
107
+ def clear(self) -> None:
108
+ with self._lock:
109
+ self._messages.clear()
110
+ self._total_tokens = 0
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: autourgos-token-memory
3
+ Version: 1.0.0
4
+ Summary: Token-bounded short-term memory for Autourgos agents — TokenBufferedMemory.
5
+ Author-email: Jitin Kumar Sengar <devxjitin@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/devxjitin/autourgos-token-memory
8
+ Project-URL: Repository, https://github.com/devxjitin/autourgos-token-memory
9
+ Project-URL: Issues, https://github.com/devxjitin/autourgos-token-memory/issues
10
+ Keywords: autourgos,agent,memory,llm
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Provides-Extra: tiktoken
23
+ Requires-Dist: tiktoken>=0.5; extra == "tiktoken"
24
+ Dynamic: license-file
25
+
26
+ # autourgos-token-memory
27
+
28
+ Token-bounded short-term memory for [Autourgos](https://github.com/devxjitin) agents.
29
+
30
+ Keeps messages in RAM and evicts the oldest ones when the total token count exceeds a budget. Automatically uses `tiktoken` for accurate counts if installed, with a fast character-based heuristic as fallback.
31
+
32
+ ---
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ pip install autourgos-token-memory
38
+
39
+ # For accurate tiktoken counts (recommended for OpenAI models)
40
+ pip install 'autourgos-token-memory[tiktoken]'
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Quick Start
46
+
47
+ ```python
48
+ from autourgos_token_memory import TokenBufferedMemory
49
+ from autourgos_react_agent import ReactAgent
50
+
51
+ memory = TokenBufferedMemory(max_tokens=4000)
52
+ agent = ReactAgent(llm=my_llm, memory=memory)
53
+ agent.invoke("Long conversation task...")
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Parameters
59
+
60
+ | Parameter | Type | Default | Description |
61
+ |---|---|---|---|
62
+ | `max_tokens` | int | `2000` | Token budget. Oldest messages evicted when exceeded. |
63
+ | `token_estimator` | callable | `None` | Custom `(text: str) -> int`. Defaults to tiktoken / heuristic. |
64
+
65
+ ---
66
+
67
+ ## Custom token estimator
68
+
69
+ ```python
70
+ from autourgos_token_memory import TokenBufferedMemory
71
+
72
+ def my_estimator(text: str) -> int:
73
+ return len(text.split()) # word count
74
+
75
+ memory = TokenBufferedMemory(max_tokens=500, token_estimator=my_estimator)
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Token counting
81
+
82
+ - **tiktoken installed**: uses `cl100k_base` encoding (accurate for GPT-3.5/4/4o).
83
+ - **tiktoken not installed**: Unicode-aware heuristic — ~0.25 tokens per ASCII char, ~1.5 per CJK character.
84
+
85
+ Check current usage:
86
+
87
+ ```python
88
+ print(memory.total_tokens) # → int
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Links
94
+
95
+ - PyPI: https://pypi.org/project/autourgos-token-memory/
96
+ - GitHub: https://github.com/devxjitin/autourgos-token-memory
97
+ - Issues: https://github.com/devxjitin/autourgos-token-memory/issues
98
+
99
+ ---
100
+
101
+ ## License
102
+
103
+ MIT — see [LICENSE](LICENSE)
@@ -0,0 +1,12 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ autourgos_token_memory/__init__.py
5
+ autourgos_token_memory/base.py
6
+ autourgos_token_memory/memory.py
7
+ autourgos_token_memory/py.typed
8
+ autourgos_token_memory.egg-info/PKG-INFO
9
+ autourgos_token_memory.egg-info/SOURCES.txt
10
+ autourgos_token_memory.egg-info/dependency_links.txt
11
+ autourgos_token_memory.egg-info/requires.txt
12
+ autourgos_token_memory.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+
2
+ [tiktoken]
3
+ tiktoken>=0.5
@@ -0,0 +1 @@
1
+ autourgos_token_memory
@@ -0,0 +1,40 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "autourgos-token-memory"
7
+ version = "1.0.0"
8
+ description = "Token-bounded short-term memory for Autourgos agents — TokenBufferedMemory."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "Jitin Kumar Sengar", email = "devxjitin@gmail.com"}
14
+ ]
15
+ keywords = ["autourgos", "agent", "memory", "llm"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ ]
26
+ dependencies = []
27
+ [project.optional-dependencies]
28
+ tiktoken = ["tiktoken>=0.5"]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/devxjitin/autourgos-token-memory"
32
+ Repository = "https://github.com/devxjitin/autourgos-token-memory"
33
+ Issues = "https://github.com/devxjitin/autourgos-token-memory/issues"
34
+
35
+ [tool.setuptools.packages.find]
36
+ where = ["."]
37
+ include = ["autourgos_token_memory*"]
38
+
39
+ [tool.setuptools.package-data]
40
+ autourgos_token_memory = ["py.typed"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+