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 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.
@@ -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)
@@ -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,6 @@
1
+ """CogmemAi — Persistent memory for AI coding assistants."""
2
+
3
+ from cogmemai.client import CogmemAi
4
+
5
+ __version__ = "1.0.0"
6
+ __all__ = ["CogmemAi"]
@@ -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"