cogmemai 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.
- cogmemai-1.0.0/LICENSE +21 -0
- cogmemai-1.0.0/PKG-INFO +120 -0
- cogmemai-1.0.0/README.md +94 -0
- cogmemai-1.0.0/cogmemai/__init__.py +6 -0
- cogmemai-1.0.0/cogmemai/client.py +465 -0
- cogmemai-1.0.0/pyproject.toml +32 -0
cogmemai-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 HiFriendbot
|
|
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.
|
cogmemai-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cogmemai
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: CogmemAi — Persistent memory for AI coding assistants
|
|
5
|
+
Project-URL: Homepage, https://hifriendbot.com/developer/
|
|
6
|
+
Project-URL: Documentation, https://hifriendbot.com/developer/
|
|
7
|
+
Project-URL: Repository, https://github.com/hifriendbot/cogmemai-python
|
|
8
|
+
Project-URL: Issues, https://github.com/hifriendbot/cogmemai-python/issues
|
|
9
|
+
Author-email: HiFriendbot <developers@hifriendbot.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: ai,claude,coding-assistant,developer-tools,mcp,memory
|
|
13
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Requires-Dist: requests>=2.28
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# CogmemAi Python SDK
|
|
28
|
+
|
|
29
|
+
Persistent memory for AI coding assistants. Give your AI tools memory that persists across sessions.
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install cogmemai
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from cogmemai import CogmemAi
|
|
41
|
+
|
|
42
|
+
client = CogmemAi("cm_your_api_key_here")
|
|
43
|
+
|
|
44
|
+
# Save a memory
|
|
45
|
+
client.save_memory(
|
|
46
|
+
content="This project uses React with TypeScript",
|
|
47
|
+
memory_type="architecture",
|
|
48
|
+
category="frontend",
|
|
49
|
+
importance=8,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Search memories
|
|
53
|
+
results = client.recall_memories("what framework does this project use?")
|
|
54
|
+
for memory in results["memories"]:
|
|
55
|
+
print(f"[{memory['importance']}] {memory['content']}")
|
|
56
|
+
|
|
57
|
+
# Load project context
|
|
58
|
+
context = client.get_project_context(project_id="my-project")
|
|
59
|
+
|
|
60
|
+
# Extract memories from conversation
|
|
61
|
+
client.extract_memories(
|
|
62
|
+
user_message="Let's use PostgreSQL for the database",
|
|
63
|
+
assistant_response="Good choice. I'll set up the schema with...",
|
|
64
|
+
)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## All Methods
|
|
68
|
+
|
|
69
|
+
### Core Memory
|
|
70
|
+
- `save_memory(content, memory_type, category, subject, importance, scope, project_id)` — Save a memory
|
|
71
|
+
- `recall_memories(query, limit, memory_type, scope)` — Semantic search
|
|
72
|
+
- `extract_memories(user_message, assistant_response, previous_context)` — Ai extracts facts from conversation
|
|
73
|
+
- `get_project_context(project_id, include_global, context)` — Load top memories with smart ranking
|
|
74
|
+
- `list_memories(memory_type, category, scope, limit, offset)` — Browse with filters
|
|
75
|
+
- `update_memory(memory_id, content, importance, scope)` — Edit a memory
|
|
76
|
+
- `delete_memory(memory_id)` — Delete permanently
|
|
77
|
+
- `get_usage()` — Check usage stats and tier
|
|
78
|
+
|
|
79
|
+
### Documents & Sessions
|
|
80
|
+
- `ingest_document(text, document_type, project_id)` — Extract memories from docs
|
|
81
|
+
- `save_session_summary(summary, project_id)` — Capture session accomplishments
|
|
82
|
+
|
|
83
|
+
### Import / Export
|
|
84
|
+
- `export_memories()` — Back up memories as JSON
|
|
85
|
+
- `import_memories(memories)` — Bulk import from JSON
|
|
86
|
+
- `get_memory_versions(memory_id)` — Version history
|
|
87
|
+
|
|
88
|
+
### Team & Collaboration
|
|
89
|
+
- `get_team_members(project_id)` — List team members
|
|
90
|
+
- `invite_team_member(email, project_id, role)` — Invite a member
|
|
91
|
+
- `remove_team_member(member_id)` — Remove a member
|
|
92
|
+
|
|
93
|
+
### Memory Relationships & Promotion
|
|
94
|
+
- `link_memories(memory_id, related_memory_id, relationship_type)` — Link related memories
|
|
95
|
+
- `get_memory_links(memory_id)` — Get linked memories
|
|
96
|
+
- `get_promotion_candidates()` — Find cross-project patterns
|
|
97
|
+
- `promote_to_global(memory_id)` — Promote to global scope
|
|
98
|
+
|
|
99
|
+
## Error Handling
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from cogmemai.client import CogmemAiError
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
client.save_memory(content="test")
|
|
106
|
+
except CogmemAiError as e:
|
|
107
|
+
print(f"Error {e.status_code}: {e}")
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Get an API Key
|
|
111
|
+
|
|
112
|
+
1. Sign up at [hifriendbot.com/developer/](https://hifriendbot.com/developer/)
|
|
113
|
+
2. Generate an API key
|
|
114
|
+
3. Start saving memories
|
|
115
|
+
|
|
116
|
+
## Links
|
|
117
|
+
|
|
118
|
+
- [Developer Dashboard](https://hifriendbot.com/developer/)
|
|
119
|
+
- [MCP Server (npm)](https://www.npmjs.com/package/cogmemai-mcp)
|
|
120
|
+
- [GitHub](https://github.com/hifriendbot/cogmemai-python)
|
cogmemai-1.0.0/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# CogmemAi Python SDK
|
|
2
|
+
|
|
3
|
+
Persistent memory for AI coding assistants. Give your AI tools memory that persists across sessions.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install cogmemai
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from cogmemai import CogmemAi
|
|
15
|
+
|
|
16
|
+
client = CogmemAi("cm_your_api_key_here")
|
|
17
|
+
|
|
18
|
+
# Save a memory
|
|
19
|
+
client.save_memory(
|
|
20
|
+
content="This project uses React with TypeScript",
|
|
21
|
+
memory_type="architecture",
|
|
22
|
+
category="frontend",
|
|
23
|
+
importance=8,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Search memories
|
|
27
|
+
results = client.recall_memories("what framework does this project use?")
|
|
28
|
+
for memory in results["memories"]:
|
|
29
|
+
print(f"[{memory['importance']}] {memory['content']}")
|
|
30
|
+
|
|
31
|
+
# Load project context
|
|
32
|
+
context = client.get_project_context(project_id="my-project")
|
|
33
|
+
|
|
34
|
+
# Extract memories from conversation
|
|
35
|
+
client.extract_memories(
|
|
36
|
+
user_message="Let's use PostgreSQL for the database",
|
|
37
|
+
assistant_response="Good choice. I'll set up the schema with...",
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## All Methods
|
|
42
|
+
|
|
43
|
+
### Core Memory
|
|
44
|
+
- `save_memory(content, memory_type, category, subject, importance, scope, project_id)` — Save a memory
|
|
45
|
+
- `recall_memories(query, limit, memory_type, scope)` — Semantic search
|
|
46
|
+
- `extract_memories(user_message, assistant_response, previous_context)` — Ai extracts facts from conversation
|
|
47
|
+
- `get_project_context(project_id, include_global, context)` — Load top memories with smart ranking
|
|
48
|
+
- `list_memories(memory_type, category, scope, limit, offset)` — Browse with filters
|
|
49
|
+
- `update_memory(memory_id, content, importance, scope)` — Edit a memory
|
|
50
|
+
- `delete_memory(memory_id)` — Delete permanently
|
|
51
|
+
- `get_usage()` — Check usage stats and tier
|
|
52
|
+
|
|
53
|
+
### Documents & Sessions
|
|
54
|
+
- `ingest_document(text, document_type, project_id)` — Extract memories from docs
|
|
55
|
+
- `save_session_summary(summary, project_id)` — Capture session accomplishments
|
|
56
|
+
|
|
57
|
+
### Import / Export
|
|
58
|
+
- `export_memories()` — Back up memories as JSON
|
|
59
|
+
- `import_memories(memories)` — Bulk import from JSON
|
|
60
|
+
- `get_memory_versions(memory_id)` — Version history
|
|
61
|
+
|
|
62
|
+
### Team & Collaboration
|
|
63
|
+
- `get_team_members(project_id)` — List team members
|
|
64
|
+
- `invite_team_member(email, project_id, role)` — Invite a member
|
|
65
|
+
- `remove_team_member(member_id)` — Remove a member
|
|
66
|
+
|
|
67
|
+
### Memory Relationships & Promotion
|
|
68
|
+
- `link_memories(memory_id, related_memory_id, relationship_type)` — Link related memories
|
|
69
|
+
- `get_memory_links(memory_id)` — Get linked memories
|
|
70
|
+
- `get_promotion_candidates()` — Find cross-project patterns
|
|
71
|
+
- `promote_to_global(memory_id)` — Promote to global scope
|
|
72
|
+
|
|
73
|
+
## Error Handling
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from cogmemai.client import CogmemAiError
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
client.save_memory(content="test")
|
|
80
|
+
except CogmemAiError as e:
|
|
81
|
+
print(f"Error {e.status_code}: {e}")
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Get an API Key
|
|
85
|
+
|
|
86
|
+
1. Sign up at [hifriendbot.com/developer/](https://hifriendbot.com/developer/)
|
|
87
|
+
2. Generate an API key
|
|
88
|
+
3. Start saving memories
|
|
89
|
+
|
|
90
|
+
## Links
|
|
91
|
+
|
|
92
|
+
- [Developer Dashboard](https://hifriendbot.com/developer/)
|
|
93
|
+
- [MCP Server (npm)](https://www.npmjs.com/package/cogmemai-mcp)
|
|
94
|
+
- [GitHub](https://github.com/hifriendbot/cogmemai-python)
|
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
"""CogmemAi Python SDK client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Optional
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CogmemAiError(Exception):
|
|
11
|
+
"""Base exception for CogmemAi API errors."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, message: str, status_code: int | None = None):
|
|
14
|
+
super().__init__(message)
|
|
15
|
+
self.status_code = status_code
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CogmemAi:
|
|
19
|
+
"""Client for the CogmemAi REST API.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
api_key: Your CogmemAi API key (starts with ``cm_``).
|
|
23
|
+
base_url: API base URL. Defaults to the hosted CogmemAi service.
|
|
24
|
+
timeout: Request timeout in seconds. Defaults to 30.
|
|
25
|
+
|
|
26
|
+
Example::
|
|
27
|
+
|
|
28
|
+
from cogmemai import CogmemAi
|
|
29
|
+
|
|
30
|
+
client = CogmemAi("cm_your_api_key_here")
|
|
31
|
+
|
|
32
|
+
# Save a memory
|
|
33
|
+
client.save_memory(
|
|
34
|
+
content="This project uses React with TypeScript",
|
|
35
|
+
memory_type="architecture",
|
|
36
|
+
category="frontend",
|
|
37
|
+
importance=8,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Search memories
|
|
41
|
+
results = client.recall_memories("what framework does this project use?")
|
|
42
|
+
|
|
43
|
+
# Load project context
|
|
44
|
+
context = client.get_project_context(project_id="my-project")
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
DEFAULT_BASE_URL = "https://hifriendbot.com/wp-json/hifriendbot/v1"
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
api_key: str,
|
|
52
|
+
base_url: str | None = None,
|
|
53
|
+
timeout: int = 30,
|
|
54
|
+
):
|
|
55
|
+
if not api_key or not api_key.startswith("cm_"):
|
|
56
|
+
raise ValueError("API key must start with 'cm_'")
|
|
57
|
+
|
|
58
|
+
self.api_key = api_key
|
|
59
|
+
self.base_url = (base_url or self.DEFAULT_BASE_URL).rstrip("/")
|
|
60
|
+
self.timeout = timeout
|
|
61
|
+
self._session = requests.Session()
|
|
62
|
+
self._session.headers.update(
|
|
63
|
+
{
|
|
64
|
+
"Authorization": f"Bearer {api_key}",
|
|
65
|
+
"Content-Type": "application/json",
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# ── Internal helpers ───────────────────────────────
|
|
70
|
+
|
|
71
|
+
def _request(self, method: str, path: str, **kwargs: Any) -> dict:
|
|
72
|
+
url = f"{self.base_url}/cogmemai/{path}"
|
|
73
|
+
kwargs.setdefault("timeout", self.timeout)
|
|
74
|
+
resp = self._session.request(method, url, **kwargs)
|
|
75
|
+
try:
|
|
76
|
+
data = resp.json()
|
|
77
|
+
except ValueError:
|
|
78
|
+
raise CogmemAiError(f"Invalid JSON response: {resp.text}", resp.status_code)
|
|
79
|
+
if resp.status_code >= 400:
|
|
80
|
+
msg = data.get("error") or data.get("message") or resp.text
|
|
81
|
+
raise CogmemAiError(msg, resp.status_code)
|
|
82
|
+
return data
|
|
83
|
+
|
|
84
|
+
def _get(self, path: str, params: dict | None = None) -> dict:
|
|
85
|
+
return self._request("GET", path, params=params)
|
|
86
|
+
|
|
87
|
+
def _post(self, path: str, data: dict | None = None) -> dict:
|
|
88
|
+
return self._request("POST", path, json=data)
|
|
89
|
+
|
|
90
|
+
def _patch(self, path: str, data: dict | None = None) -> dict:
|
|
91
|
+
return self._request("PATCH", path, json=data)
|
|
92
|
+
|
|
93
|
+
def _delete(self, path: str) -> dict:
|
|
94
|
+
return self._request("DELETE", path)
|
|
95
|
+
|
|
96
|
+
# ── Core Memory ────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
def save_memory(
|
|
99
|
+
self,
|
|
100
|
+
content: str,
|
|
101
|
+
*,
|
|
102
|
+
memory_type: str = "context",
|
|
103
|
+
category: str = "general",
|
|
104
|
+
subject: str = "",
|
|
105
|
+
importance: int = 5,
|
|
106
|
+
scope: str = "project",
|
|
107
|
+
project_id: str = "",
|
|
108
|
+
) -> dict:
|
|
109
|
+
"""Save a memory.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
content: The fact to remember (5-500 chars).
|
|
113
|
+
memory_type: Type of memory (e.g. architecture, decision, bug, pattern).
|
|
114
|
+
category: Category (e.g. frontend, backend, database, devops).
|
|
115
|
+
subject: What this memory is about (max 100 chars).
|
|
116
|
+
importance: Importance 1-10 (default 5). Reserve 9-10 for core architecture.
|
|
117
|
+
scope: ``"project"`` or ``"global"``.
|
|
118
|
+
project_id: Project identifier.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Dict with ``memory_id``, ``stored``, and optional ``deduplicated``,
|
|
122
|
+
``conflict_detected``, ``warning`` fields.
|
|
123
|
+
"""
|
|
124
|
+
return self._post(
|
|
125
|
+
"store",
|
|
126
|
+
{
|
|
127
|
+
"content": content,
|
|
128
|
+
"memory_type": memory_type,
|
|
129
|
+
"category": category,
|
|
130
|
+
"subject": subject,
|
|
131
|
+
"importance": importance,
|
|
132
|
+
"scope": scope,
|
|
133
|
+
"project_id": project_id,
|
|
134
|
+
},
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
def recall_memories(
|
|
138
|
+
self,
|
|
139
|
+
query: str,
|
|
140
|
+
*,
|
|
141
|
+
limit: int = 10,
|
|
142
|
+
memory_type: str = "",
|
|
143
|
+
scope: str = "all",
|
|
144
|
+
) -> dict:
|
|
145
|
+
"""Semantic search across memories.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
query: Natural language search query (2-500 chars).
|
|
149
|
+
limit: Max results (1-20, default 10).
|
|
150
|
+
memory_type: Filter by type.
|
|
151
|
+
scope: ``"global"``, ``"project"``, or ``"all"``.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
Dict with ``memories`` array ranked by relevance.
|
|
155
|
+
"""
|
|
156
|
+
payload: dict[str, Any] = {"query": query, "limit": limit, "scope": scope}
|
|
157
|
+
if memory_type:
|
|
158
|
+
payload["memory_type"] = memory_type
|
|
159
|
+
return self._post("recall", payload)
|
|
160
|
+
|
|
161
|
+
def extract_memories(
|
|
162
|
+
self,
|
|
163
|
+
user_message: str,
|
|
164
|
+
*,
|
|
165
|
+
assistant_response: str = "",
|
|
166
|
+
previous_context: str = "",
|
|
167
|
+
) -> dict:
|
|
168
|
+
"""Extract memories from a conversation exchange using Ai.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
user_message: The developer's message (1-4000 chars).
|
|
172
|
+
assistant_response: The assistant's response (max 4000 chars).
|
|
173
|
+
previous_context: Previous exchange for context (max 2000 chars).
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
Dict with ``extracted`` count and ``memories`` array.
|
|
177
|
+
"""
|
|
178
|
+
payload: dict[str, Any] = {"user_message": user_message}
|
|
179
|
+
if assistant_response:
|
|
180
|
+
payload["assistant_response"] = assistant_response
|
|
181
|
+
if previous_context:
|
|
182
|
+
payload["previous_context"] = previous_context
|
|
183
|
+
return self._post("extract", payload)
|
|
184
|
+
|
|
185
|
+
def get_project_context(
|
|
186
|
+
self,
|
|
187
|
+
*,
|
|
188
|
+
project_id: str = "",
|
|
189
|
+
include_global: bool = True,
|
|
190
|
+
context: str = "",
|
|
191
|
+
) -> dict:
|
|
192
|
+
"""Load project context with smart ranking.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
project_id: Project identifier.
|
|
196
|
+
include_global: Include global memories (default True).
|
|
197
|
+
context: Current context for semantic ranking blend.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
Dict with ``memories`` array sorted by blended score.
|
|
201
|
+
"""
|
|
202
|
+
params: dict[str, Any] = {"include_global": str(include_global).lower()}
|
|
203
|
+
if project_id:
|
|
204
|
+
params["project_id"] = project_id
|
|
205
|
+
if context:
|
|
206
|
+
params["context"] = context
|
|
207
|
+
return self._get("context", params)
|
|
208
|
+
|
|
209
|
+
def list_memories(
|
|
210
|
+
self,
|
|
211
|
+
*,
|
|
212
|
+
memory_type: str = "",
|
|
213
|
+
category: str = "",
|
|
214
|
+
scope: str = "all",
|
|
215
|
+
limit: int = 50,
|
|
216
|
+
offset: int = 0,
|
|
217
|
+
) -> dict:
|
|
218
|
+
"""List memories with filters.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
memory_type: Filter by type.
|
|
222
|
+
category: Filter by category.
|
|
223
|
+
scope: ``"global"``, ``"project"``, or ``"all"``.
|
|
224
|
+
limit: Max results (default 50, max 100).
|
|
225
|
+
offset: Pagination offset.
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
Dict with ``memories`` array and pagination info.
|
|
229
|
+
"""
|
|
230
|
+
params: dict[str, Any] = {"limit": limit, "offset": offset, "scope": scope}
|
|
231
|
+
if memory_type:
|
|
232
|
+
params["memory_type"] = memory_type
|
|
233
|
+
if category:
|
|
234
|
+
params["category"] = category
|
|
235
|
+
return self._get("memories", params)
|
|
236
|
+
|
|
237
|
+
def update_memory(
|
|
238
|
+
self,
|
|
239
|
+
memory_id: int,
|
|
240
|
+
*,
|
|
241
|
+
content: str = "",
|
|
242
|
+
importance: int | None = None,
|
|
243
|
+
scope: str = "",
|
|
244
|
+
) -> dict:
|
|
245
|
+
"""Update a memory.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
memory_id: ID of the memory to update.
|
|
249
|
+
content: New content.
|
|
250
|
+
importance: New importance (1-10).
|
|
251
|
+
scope: New scope.
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
Dict with ``updated`` status.
|
|
255
|
+
"""
|
|
256
|
+
payload: dict[str, Any] = {}
|
|
257
|
+
if content:
|
|
258
|
+
payload["content"] = content
|
|
259
|
+
if importance is not None:
|
|
260
|
+
payload["importance"] = importance
|
|
261
|
+
if scope:
|
|
262
|
+
payload["scope"] = scope
|
|
263
|
+
return self._patch(f"memory/{memory_id}", payload)
|
|
264
|
+
|
|
265
|
+
def delete_memory(self, memory_id: int) -> dict:
|
|
266
|
+
"""Delete a memory permanently.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
memory_id: ID of the memory to delete.
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
Dict with ``deleted`` status.
|
|
273
|
+
"""
|
|
274
|
+
return self._delete(f"memory/{memory_id}")
|
|
275
|
+
|
|
276
|
+
def get_usage(self) -> dict:
|
|
277
|
+
"""Get usage stats and tier info.
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
Dict with memory count, extraction count, tier limits, etc.
|
|
281
|
+
"""
|
|
282
|
+
return self._get("usage")
|
|
283
|
+
|
|
284
|
+
# ── Documents & Sessions ───────────────────────────
|
|
285
|
+
|
|
286
|
+
def ingest_document(
|
|
287
|
+
self,
|
|
288
|
+
text: str,
|
|
289
|
+
*,
|
|
290
|
+
document_type: str = "",
|
|
291
|
+
project_id: str = "",
|
|
292
|
+
) -> dict:
|
|
293
|
+
"""Extract memories from a document.
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
text: Document text (up to 50K chars).
|
|
297
|
+
document_type: e.g. "README", "architecture doc", "meeting notes".
|
|
298
|
+
project_id: Project identifier.
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
Dict with ``chunks_processed``, ``extracted``, and ``memories`` array.
|
|
302
|
+
"""
|
|
303
|
+
payload: dict[str, Any] = {"text": text}
|
|
304
|
+
if document_type:
|
|
305
|
+
payload["document_type"] = document_type
|
|
306
|
+
if project_id:
|
|
307
|
+
payload["project_id"] = project_id
|
|
308
|
+
return self._post("ingest", payload)
|
|
309
|
+
|
|
310
|
+
def save_session_summary(
|
|
311
|
+
self,
|
|
312
|
+
summary: str,
|
|
313
|
+
*,
|
|
314
|
+
project_id: str = "",
|
|
315
|
+
) -> dict:
|
|
316
|
+
"""Save a session summary.
|
|
317
|
+
|
|
318
|
+
Args:
|
|
319
|
+
summary: Session summary text (up to 2K chars).
|
|
320
|
+
project_id: Project identifier.
|
|
321
|
+
|
|
322
|
+
Returns:
|
|
323
|
+
Dict with ``memory_id`` and ``stored`` status.
|
|
324
|
+
"""
|
|
325
|
+
payload: dict[str, Any] = {"summary": summary}
|
|
326
|
+
if project_id:
|
|
327
|
+
payload["project_id"] = project_id
|
|
328
|
+
return self._post("session-summary", payload)
|
|
329
|
+
|
|
330
|
+
# ── Import / Export / Versions ─────────────────────
|
|
331
|
+
|
|
332
|
+
def export_memories(self) -> dict:
|
|
333
|
+
"""Export all memories as JSON.
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
Dict with ``version``, ``exported_at``, ``memory_count``, and ``memories``.
|
|
337
|
+
"""
|
|
338
|
+
return self._get("export")
|
|
339
|
+
|
|
340
|
+
def import_memories(self, memories: list[dict]) -> dict:
|
|
341
|
+
"""Bulk import memories.
|
|
342
|
+
|
|
343
|
+
Args:
|
|
344
|
+
memories: List of memory objects with ``content`` and optional fields.
|
|
345
|
+
|
|
346
|
+
Returns:
|
|
347
|
+
Dict with ``imported``, ``skipped``, and ``errors`` counts.
|
|
348
|
+
"""
|
|
349
|
+
return self._post("import", {"memories": memories})
|
|
350
|
+
|
|
351
|
+
def get_memory_versions(self, memory_id: int) -> dict:
|
|
352
|
+
"""Get version history for a memory.
|
|
353
|
+
|
|
354
|
+
Args:
|
|
355
|
+
memory_id: ID of the memory.
|
|
356
|
+
|
|
357
|
+
Returns:
|
|
358
|
+
Dict with ``versions`` array (content, importance, scope, changed_by, timestamp).
|
|
359
|
+
"""
|
|
360
|
+
return self._get(f"memory/{memory_id}/versions")
|
|
361
|
+
|
|
362
|
+
# ── Team & Collaboration ──────────────────────────
|
|
363
|
+
|
|
364
|
+
def get_team_members(self, *, project_id: str = "") -> dict:
|
|
365
|
+
"""List team members. Requires Team or Enterprise tier.
|
|
366
|
+
|
|
367
|
+
Args:
|
|
368
|
+
project_id: Filter by project.
|
|
369
|
+
|
|
370
|
+
Returns:
|
|
371
|
+
Dict with ``members`` array.
|
|
372
|
+
"""
|
|
373
|
+
params = {}
|
|
374
|
+
if project_id:
|
|
375
|
+
params["project_id"] = project_id
|
|
376
|
+
return self._get("team/members", params)
|
|
377
|
+
|
|
378
|
+
def invite_team_member(
|
|
379
|
+
self,
|
|
380
|
+
email: str,
|
|
381
|
+
project_id: str,
|
|
382
|
+
*,
|
|
383
|
+
role: str = "member",
|
|
384
|
+
) -> dict:
|
|
385
|
+
"""Invite a team member. Requires Team or Enterprise tier.
|
|
386
|
+
|
|
387
|
+
Args:
|
|
388
|
+
email: Email of the user to invite.
|
|
389
|
+
project_id: Project to share.
|
|
390
|
+
role: ``"member"`` or ``"viewer"`` (default ``"member"``).
|
|
391
|
+
|
|
392
|
+
Returns:
|
|
393
|
+
Dict with invitation status.
|
|
394
|
+
"""
|
|
395
|
+
return self._post(
|
|
396
|
+
"team/invite",
|
|
397
|
+
{"email": email, "project_id": project_id, "role": role},
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
def remove_team_member(self, member_id: int) -> dict:
|
|
401
|
+
"""Remove a team member.
|
|
402
|
+
|
|
403
|
+
Args:
|
|
404
|
+
member_id: ID of the team member record.
|
|
405
|
+
|
|
406
|
+
Returns:
|
|
407
|
+
Dict with removal status.
|
|
408
|
+
"""
|
|
409
|
+
return self._delete(f"team/remove/{member_id}")
|
|
410
|
+
|
|
411
|
+
# ── Memory Relationships & Promotion ──────────────
|
|
412
|
+
|
|
413
|
+
def link_memories(
|
|
414
|
+
self,
|
|
415
|
+
memory_id: int,
|
|
416
|
+
related_memory_id: int,
|
|
417
|
+
relationship_type: str,
|
|
418
|
+
) -> dict:
|
|
419
|
+
"""Link two related memories.
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
memory_id: Source memory ID.
|
|
423
|
+
related_memory_id: Target memory ID.
|
|
424
|
+
relationship_type: ``"led_to"``, ``"contradicts"``, ``"extends"``, or ``"related"``.
|
|
425
|
+
|
|
426
|
+
Returns:
|
|
427
|
+
Dict with link status.
|
|
428
|
+
"""
|
|
429
|
+
return self._post(
|
|
430
|
+
f"memory/{memory_id}/link",
|
|
431
|
+
{
|
|
432
|
+
"related_memory_id": related_memory_id,
|
|
433
|
+
"relationship_type": relationship_type,
|
|
434
|
+
},
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
def get_memory_links(self, memory_id: int) -> dict:
|
|
438
|
+
"""Get linked memories.
|
|
439
|
+
|
|
440
|
+
Args:
|
|
441
|
+
memory_id: ID of the memory.
|
|
442
|
+
|
|
443
|
+
Returns:
|
|
444
|
+
Dict with ``links`` array.
|
|
445
|
+
"""
|
|
446
|
+
return self._get(f"memory/{memory_id}/links")
|
|
447
|
+
|
|
448
|
+
def get_promotion_candidates(self) -> dict:
|
|
449
|
+
"""Find cross-project patterns eligible for global promotion.
|
|
450
|
+
|
|
451
|
+
Returns:
|
|
452
|
+
Dict with ``candidates`` array.
|
|
453
|
+
"""
|
|
454
|
+
return self._get("promotion-candidates")
|
|
455
|
+
|
|
456
|
+
def promote_to_global(self, memory_id: int) -> dict:
|
|
457
|
+
"""Promote a project memory to global scope.
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
memory_id: ID of the memory to promote.
|
|
461
|
+
|
|
462
|
+
Returns:
|
|
463
|
+
Dict with promotion status.
|
|
464
|
+
"""
|
|
465
|
+
return self._post(f"memory/{memory_id}/promote", {})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cogmemai"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "CogmemAi — Persistent memory for AI coding assistants"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [{ name = "HiFriendbot", email = "developers@hifriendbot.com" }]
|
|
13
|
+
keywords = ["ai", "memory", "claude", "coding-assistant", "mcp", "developer-tools"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 5 - Production/Stable",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.9",
|
|
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",
|
|
25
|
+
]
|
|
26
|
+
dependencies = ["requests>=2.28"]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://hifriendbot.com/developer/"
|
|
30
|
+
Documentation = "https://hifriendbot.com/developer/"
|
|
31
|
+
Repository = "https://github.com/hifriendbot/cogmemai-python"
|
|
32
|
+
Issues = "https://github.com/hifriendbot/cogmemai-python/issues"
|