memcell 0.1.1__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,34 @@
1
+ # Dependencies
2
+ node_modules/
3
+ .pnpm-store/
4
+
5
+ # Build artifacts
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+ .eggs/
10
+
11
+ # Python
12
+ __pycache__/
13
+ *.py[cod]
14
+ *$py.class
15
+ .venv/
16
+ env/
17
+ venv/
18
+ .mypy_cache/
19
+ .pytest_cache/
20
+ .ruff_cache/
21
+ .coverage
22
+ htmlcov/
23
+
24
+ # Logs & Environment
25
+ *.log
26
+ .env
27
+ .env.*
28
+ !.env.example
29
+
30
+ # OS & Editors
31
+ .DS_Store
32
+ .vscode/
33
+ .idea/
34
+ *.swp
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ ## [0.1.1](https://github.com/memcell-ai/sdk/compare/python-v0.1.0...python-v0.1.1) (2026-09-17)
4
+
5
+
6
+ ### Features
7
+
8
+ * initialize multi-language sdk monorepo for typescript and python ([d5da445](https://github.com/memcell-ai/sdk/commit/d5da4457c5f6f3f87287f41f21acb921592f0d0a))
memcell-0.1.1/PKG-INFO ADDED
@@ -0,0 +1,112 @@
1
+ Metadata-Version: 2.5
2
+ Name: memcell
3
+ Version: 0.1.1
4
+ Summary: Official Python SDK for MemCell persistent cognitive memory and reasoning engine
5
+ Author-email: MemCell Team <engineering@memcell.io>
6
+ License-Expression: Apache-2.0
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: Apache Software 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
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: httpx>=0.27.0
19
+ Requires-Dist: pydantic>=2.0.0
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
22
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
23
+ Requires-Dist: respx>=0.21.0; extra == 'dev'
24
+ Requires-Dist: ruff>=0.3.0; extra == 'dev'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # memcell
28
+
29
+ Official Python SDK for [MemCell](https://memcell.io)—persistent cognitive memory and reasoning substrate for AI coding agents.
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ pip install memcell
35
+ # or
36
+ uv add memcell
37
+ # or
38
+ poetry add memcell
39
+ ```
40
+
41
+ ## Quickstart
42
+
43
+ ### Asynchronous Client (`AsyncMemCell`)
44
+
45
+ ```python
46
+ import asyncio
47
+ from memcell import AsyncMemCell
48
+
49
+ async def main():
50
+ async with AsyncMemCell(api_key="mc_live_...") as memory:
51
+ # Pre-flight recall before an agent acts
52
+ recall = await memory.recall(
53
+ namespace="acme/devops",
54
+ query="how to deploy the canary pipeline"
55
+ )
56
+ print(recall.prompt_context)
57
+
58
+ # In-flight scoped execution with automatic reinforcement
59
+ devops = memory.scope("acme/devops", subject="pipeline:canary")
60
+ result = await devops.wrap_execution(
61
+ action="deploy_canary",
62
+ external_ref="ci:run:1049",
63
+ fn=lambda ctx: print("Deploying with context:", ctx.prompt_context)
64
+ )
65
+
66
+ asyncio.run(main())
67
+ ```
68
+
69
+ ### Synchronous Client (`MemCell`)
70
+
71
+ ```python
72
+ from memcell import MemCell
73
+
74
+ memory = MemCell(api_key="mc_live_...")
75
+
76
+ recall = memory.recall(
77
+ namespace="acme/backend",
78
+ query="database connection pool configuration"
79
+ )
80
+ for statement in recall.statements:
81
+ print(f"[{statement.kind}] {statement.title} (confidence: {statement.confidence})")
82
+ ```
83
+
84
+ ### OAuth 2.0 Machine-to-Machine (M2M)
85
+
86
+ ```python
87
+ from memcell import AsyncMemCell
88
+
89
+ memory = AsyncMemCell(
90
+ client_id="client_xyz",
91
+ client_secret="secret_xyz",
92
+ scope="memory:read:acme/* memory:write:acme/backend"
93
+ )
94
+ # Automatically handles token exchange and proactively refreshes before expiration!
95
+ ```
96
+
97
+ ### Rate Limiting & Resilience
98
+
99
+ ```python
100
+ from memcell import AsyncMemCell
101
+
102
+ memory = AsyncMemCell(
103
+ api_key="mc_live_...",
104
+ max_retries=3,
105
+ on_rate_limit_warning=lambda warning, response: print(f"Warning: {warning}")
106
+ )
107
+ # Automatically performs jittered exponential backoff respecting server Retry-After!
108
+ ```
109
+
110
+ ## License
111
+
112
+ Apache-2.0 © [MemCell](https://memcell.io)
@@ -0,0 +1,86 @@
1
+ # memcell
2
+
3
+ Official Python SDK for [MemCell](https://memcell.io)—persistent cognitive memory and reasoning substrate for AI coding agents.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install memcell
9
+ # or
10
+ uv add memcell
11
+ # or
12
+ poetry add memcell
13
+ ```
14
+
15
+ ## Quickstart
16
+
17
+ ### Asynchronous Client (`AsyncMemCell`)
18
+
19
+ ```python
20
+ import asyncio
21
+ from memcell import AsyncMemCell
22
+
23
+ async def main():
24
+ async with AsyncMemCell(api_key="mc_live_...") as memory:
25
+ # Pre-flight recall before an agent acts
26
+ recall = await memory.recall(
27
+ namespace="acme/devops",
28
+ query="how to deploy the canary pipeline"
29
+ )
30
+ print(recall.prompt_context)
31
+
32
+ # In-flight scoped execution with automatic reinforcement
33
+ devops = memory.scope("acme/devops", subject="pipeline:canary")
34
+ result = await devops.wrap_execution(
35
+ action="deploy_canary",
36
+ external_ref="ci:run:1049",
37
+ fn=lambda ctx: print("Deploying with context:", ctx.prompt_context)
38
+ )
39
+
40
+ asyncio.run(main())
41
+ ```
42
+
43
+ ### Synchronous Client (`MemCell`)
44
+
45
+ ```python
46
+ from memcell import MemCell
47
+
48
+ memory = MemCell(api_key="mc_live_...")
49
+
50
+ recall = memory.recall(
51
+ namespace="acme/backend",
52
+ query="database connection pool configuration"
53
+ )
54
+ for statement in recall.statements:
55
+ print(f"[{statement.kind}] {statement.title} (confidence: {statement.confidence})")
56
+ ```
57
+
58
+ ### OAuth 2.0 Machine-to-Machine (M2M)
59
+
60
+ ```python
61
+ from memcell import AsyncMemCell
62
+
63
+ memory = AsyncMemCell(
64
+ client_id="client_xyz",
65
+ client_secret="secret_xyz",
66
+ scope="memory:read:acme/* memory:write:acme/backend"
67
+ )
68
+ # Automatically handles token exchange and proactively refreshes before expiration!
69
+ ```
70
+
71
+ ### Rate Limiting & Resilience
72
+
73
+ ```python
74
+ from memcell import AsyncMemCell
75
+
76
+ memory = AsyncMemCell(
77
+ api_key="mc_live_...",
78
+ max_retries=3,
79
+ on_rate_limit_warning=lambda warning, response: print(f"Warning: {warning}")
80
+ )
81
+ # Automatically performs jittered exponential backoff respecting server Retry-After!
82
+ ```
83
+
84
+ ## License
85
+
86
+ Apache-2.0 © [MemCell](https://memcell.io)
@@ -0,0 +1,65 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "memcell"
7
+ version = "0.1.1"
8
+ description = "Official Python SDK for MemCell persistent cognitive memory and reasoning engine"
9
+ readme = "README.md"
10
+ license = "Apache-2.0"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "MemCell Team", email = "engineering@memcell.io" }
14
+ ]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: Apache Software License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Topic :: Software Development :: Libraries :: Python Modules",
25
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
26
+ ]
27
+ dependencies = [
28
+ "httpx>=0.27.0",
29
+ "pydantic>=2.0.0",
30
+ ]
31
+
32
+ [project.optional-dependencies]
33
+ dev = [
34
+ "pytest>=8.0.0",
35
+ "pytest-asyncio>=0.23.0",
36
+ "respx>=0.21.0",
37
+ "ruff>=0.3.0",
38
+ ]
39
+
40
+ [tool.ruff]
41
+ line-length = 100
42
+ target-version = "py310"
43
+ include = ["src/**/*.py", "tests/**/*.py"]
44
+
45
+ [tool.ruff.lint]
46
+ select = [
47
+ "E",
48
+ "F",
49
+ "W",
50
+ "I",
51
+ "UP",
52
+ "RUF",
53
+ ]
54
+ ignore = [
55
+ "E501",
56
+ ]
57
+
58
+ [tool.ruff.lint.per-file-ignores]
59
+ "tests/*" = ["S101"]
60
+
61
+ [tool.pytest.ini_options]
62
+ asyncio_mode = "auto"
63
+ testpaths = ["tests"]
64
+ pythonpath = ["src"]
65
+
@@ -0,0 +1,45 @@
1
+ from .auth import AuthManager
2
+ from .client import AsyncMemCell, MemCell
3
+ from .exceptions import MemCellError, RateLimitError
4
+ from .models import (
5
+ FeedbackResponse,
6
+ JobEvent,
7
+ MemoryKind,
8
+ MemoryStatus,
9
+ OrganizationItem,
10
+ OutcomeVerdict,
11
+ RecallResponse,
12
+ RememberResponse,
13
+ ReportResponse,
14
+ ScopedExecutionContext,
15
+ StatementItem,
16
+ )
17
+ from .organization import AsyncOrganizationMemCell, OrganizationMemCell
18
+ from .scoped import AsyncScopedMemCell, ScopedExecutionResult, ScopedMemCell
19
+
20
+ __version__ = "0.1.1"
21
+
22
+ __all__ = [
23
+ "AsyncMemCell",
24
+ "AsyncOrganizationMemCell",
25
+ "AsyncScopedMemCell",
26
+ "AuthManager",
27
+ "FeedbackResponse",
28
+ "JobEvent",
29
+ "MemCell",
30
+ "MemCellError",
31
+ "MemoryKind",
32
+ "MemoryStatus",
33
+ "OrganizationItem",
34
+ "OrganizationMemCell",
35
+ "OutcomeVerdict",
36
+ "RateLimitError",
37
+ "RecallResponse",
38
+ "RememberResponse",
39
+ "ReportResponse",
40
+ "ScopedExecutionContext",
41
+ "ScopedExecutionResult",
42
+ "ScopedMemCell",
43
+ "StatementItem",
44
+ "__version__",
45
+ ]
@@ -0,0 +1,137 @@
1
+ import time
2
+ from typing import Any
3
+
4
+ import httpx
5
+
6
+ from .exceptions import MemCellError
7
+
8
+
9
+ class AuthManager:
10
+ """Manages authentication tokens, API keys, and OAuth 2.0 M2M client credentials."""
11
+
12
+ def __init__(
13
+ self,
14
+ base_url: str,
15
+ api_key: str | None = None,
16
+ access_token: str | None = None,
17
+ client_id: str | None = None,
18
+ client_secret: str | None = None,
19
+ scope: str | None = None,
20
+ ) -> None:
21
+ self.base_url = base_url.rstrip("/")
22
+ self.api_key = api_key
23
+ self.access_token = access_token
24
+ self.client_id = client_id
25
+ self.client_secret = client_secret
26
+ self.scope = scope
27
+
28
+ self._cached_token: str | None = None
29
+ self._token_expires_at: float = 0.0
30
+
31
+ def clear_cache(self) -> None:
32
+ """Clears cached OAuth M2M access token."""
33
+ self._cached_token = None
34
+ self._token_expires_at = 0.0
35
+
36
+ def get_authorization_header(self, client: httpx.Client | None = None) -> str | None:
37
+ """Synchronously resolves Authorization header value."""
38
+ if self.api_key:
39
+ return f"Bearer {self.api_key}"
40
+ if self.access_token:
41
+ return f"Bearer {self.access_token}"
42
+ if self.client_id and self.client_secret:
43
+ # Check proactive 60s pre-expiry window
44
+ now = time.time()
45
+ if self._cached_token and (now + 60.0) < self._token_expires_at:
46
+ return f"Bearer {self._cached_token}"
47
+
48
+ c = client or httpx.Client()
49
+ should_close = client is None
50
+ try:
51
+ data = {
52
+ "grant_type": "client_credentials",
53
+ "client_id": self.client_id,
54
+ "client_secret": self.client_secret,
55
+ }
56
+ if self.scope:
57
+ data["scope"] = self.scope
58
+
59
+ resp = c.post(
60
+ f"{self.base_url}/oauth2/token",
61
+ data=data,
62
+ headers={
63
+ "Content-Type": "application/x-www-form-urlencoded",
64
+ "Accept": "application/json",
65
+ },
66
+ )
67
+ if not resp.is_success:
68
+ raise MemCellError(
69
+ f"OAuth M2M token exchange failed: HTTP {resp.status_code} {resp.text}",
70
+ status=resp.status_code,
71
+ )
72
+ payload: dict[str, Any] = resp.json()
73
+ token = payload.get("access_token")
74
+ expires_in = payload.get("expires_in", 3600)
75
+ if not token:
76
+ raise MemCellError("OAuth token endpoint returned empty access_token.")
77
+
78
+ self._cached_token = str(token)
79
+ self._token_expires_at = time.time() + float(expires_in)
80
+ return f"Bearer {self._cached_token}"
81
+ finally:
82
+ if should_close:
83
+ c.close()
84
+
85
+ return None
86
+
87
+ async def get_authorization_header_async(
88
+ self, client: httpx.AsyncClient | None = None
89
+ ) -> str | None:
90
+ """Asynchronously resolves Authorization header value."""
91
+ if self.api_key:
92
+ return f"Bearer {self.api_key}"
93
+ if self.access_token:
94
+ return f"Bearer {self.access_token}"
95
+ if self.client_id and self.client_secret:
96
+ now = time.time()
97
+ if self._cached_token and (now + 60.0) < self._token_expires_at:
98
+ return f"Bearer {self._cached_token}"
99
+
100
+ c = client or httpx.AsyncClient()
101
+ should_close = client is None
102
+ try:
103
+ data = {
104
+ "grant_type": "client_credentials",
105
+ "client_id": self.client_id,
106
+ "client_secret": self.client_secret,
107
+ }
108
+ if self.scope:
109
+ data["scope"] = self.scope
110
+
111
+ resp = await c.post(
112
+ f"{self.base_url}/oauth2/token",
113
+ data=data,
114
+ headers={
115
+ "Content-Type": "application/x-www-form-urlencoded",
116
+ "Accept": "application/json",
117
+ },
118
+ )
119
+ if not resp.is_success:
120
+ raise MemCellError(
121
+ f"OAuth M2M token exchange failed: HTTP {resp.status_code} {resp.text}",
122
+ status=resp.status_code,
123
+ )
124
+ payload: dict[str, Any] = resp.json()
125
+ token = payload.get("access_token")
126
+ expires_in = payload.get("expires_in", 3600)
127
+ if not token:
128
+ raise MemCellError("OAuth token endpoint returned empty access_token.")
129
+
130
+ self._cached_token = str(token)
131
+ self._token_expires_at = time.time() + float(expires_in)
132
+ return f"Bearer {self._cached_token}"
133
+ finally:
134
+ if should_close:
135
+ await c.aclose()
136
+
137
+ return None