memside 0.1.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,11 @@
1
+ # Memside Python SDK License
2
+
3
+ Copyright (c) 2026 Memside. All rights reserved.
4
+
5
+ This package is provided to help developers connect applications, scripts, and tools to the public Memside API.
6
+
7
+ You may use this package to integrate with Memside. You may not use this package, its documentation, or its structure to build or market a competing product or service.
8
+
9
+ This package does not grant rights to private Memside application source code, backend services, APIs outside the public API contract, infrastructure, trademarks, product designs, databases, private documentation, or proprietary systems.
10
+
11
+ This package is provided without warranties or guarantees of any kind.
memside-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,80 @@
1
+ Metadata-Version: 2.4
2
+ Name: memside
3
+ Version: 0.1.0
4
+ Summary: Lightweight Python client for the public Memside API.
5
+ Author-email: Memside <support@memside.com>
6
+ License: # Memside Python SDK License
7
+
8
+ Copyright (c) 2026 Memside. All rights reserved.
9
+
10
+ This package is provided to help developers connect applications, scripts, and tools to the public Memside API.
11
+
12
+ You may use this package to integrate with Memside. You may not use this package, its documentation, or its structure to build or market a competing product or service.
13
+
14
+ This package does not grant rights to private Memside application source code, backend services, APIs outside the public API contract, infrastructure, trademarks, product designs, databases, private documentation, or proprietary systems.
15
+
16
+ This package is provided without warranties or guarantees of any kind.
17
+
18
+ Project-URL: Homepage, https://github.com/memside/memside
19
+ Project-URL: Repository, https://github.com/memside/memside
20
+ Project-URL: Issues, https://github.com/memside/memside/issues
21
+ Keywords: memside,ai,memory,mcp,sdk
22
+ Classifier: Development Status :: 3 - Alpha
23
+ Classifier: Intended Audience :: Developers
24
+ Classifier: Programming Language :: Python :: 3
25
+ Classifier: Programming Language :: Python :: 3.9
26
+ Classifier: Programming Language :: Python :: 3.10
27
+ Classifier: Programming Language :: Python :: 3.11
28
+ Classifier: Programming Language :: Python :: 3.12
29
+ Classifier: Programming Language :: Python :: 3.13
30
+ Requires-Python: >=3.9
31
+ Description-Content-Type: text/markdown
32
+ License-File: LICENSE.md
33
+ Dynamic: license-file
34
+
35
+ # Memside Python SDK
36
+
37
+ Lightweight Python client for the public Memside API.
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ pip install memside
43
+ ```
44
+
45
+ ## Usage
46
+
47
+ ```python
48
+ from memside import MemsideClient
49
+
50
+ client = MemsideClient(api_key="mem_sk_your_key_here")
51
+
52
+ startup = client.context_startup()
53
+ print(startup)
54
+ ```
55
+
56
+ You can also set the API key through the environment:
57
+
58
+ ```bash
59
+ MEMSIDE_API_KEY=mem_sk_your_key_here
60
+ ```
61
+
62
+ ## Supported API Areas
63
+
64
+ This package wraps public Memside API-key routes:
65
+
66
+ - startup context
67
+ - resume context
68
+ - workspace profile
69
+ - memory listing
70
+ - memory search
71
+ - memory fetch
72
+ - memory create
73
+ - memory update
74
+ - memory delete, when allowed by the API
75
+
76
+ This package does not include private Memside application source, account/session internals, billing internals, admin routes, database details, or MCP server implementation.
77
+
78
+ ## Requirements
79
+
80
+ Python 3.9 or newer.
@@ -0,0 +1,46 @@
1
+ # Memside Python SDK
2
+
3
+ Lightweight Python client for the public Memside API.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install memside
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```python
14
+ from memside import MemsideClient
15
+
16
+ client = MemsideClient(api_key="mem_sk_your_key_here")
17
+
18
+ startup = client.context_startup()
19
+ print(startup)
20
+ ```
21
+
22
+ You can also set the API key through the environment:
23
+
24
+ ```bash
25
+ MEMSIDE_API_KEY=mem_sk_your_key_here
26
+ ```
27
+
28
+ ## Supported API Areas
29
+
30
+ This package wraps public Memside API-key routes:
31
+
32
+ - startup context
33
+ - resume context
34
+ - workspace profile
35
+ - memory listing
36
+ - memory search
37
+ - memory fetch
38
+ - memory create
39
+ - memory update
40
+ - memory delete, when allowed by the API
41
+
42
+ This package does not include private Memside application source, account/session internals, billing internals, admin routes, database details, or MCP server implementation.
43
+
44
+ ## Requirements
45
+
46
+ Python 3.9 or newer.
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "memside"
7
+ version = "0.1.0"
8
+ description = "Lightweight Python client for the public Memside API."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { file = "LICENSE.md" }
12
+ authors = [
13
+ { name = "Memside", email = "support@memside.com" }
14
+ ]
15
+ keywords = ["memside", "ai", "memory", "mcp", "sdk"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.9",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13"
25
+ ]
26
+
27
+ [project.urls]
28
+ Homepage = "https://github.com/memside/memside"
29
+ Repository = "https://github.com/memside/memside"
30
+ Issues = "https://github.com/memside/memside/issues"
31
+
32
+ [tool.setuptools.packages.find]
33
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ from .client import MemsideClient, MemsideError
2
+
3
+ __all__ = ["MemsideClient", "MemsideError"]
@@ -0,0 +1,155 @@
1
+ import json
2
+ import os
3
+ from urllib.error import HTTPError
4
+ from urllib.parse import urlencode
5
+ from urllib.request import Request, urlopen
6
+
7
+
8
+ DEFAULT_BASE_URL = "https://api.memside.com"
9
+
10
+
11
+ class MemsideError(Exception):
12
+ def __init__(
13
+ self,
14
+ message,
15
+ *,
16
+ status=None,
17
+ code=None,
18
+ retryable=None,
19
+ request_id=None,
20
+ details=None,
21
+ ):
22
+ super().__init__(message)
23
+ self.status = status
24
+ self.code = code
25
+ self.retryable = retryable
26
+ self.request_id = request_id
27
+ self.details = details
28
+
29
+
30
+ class MemsideClient:
31
+ def __init__(self, api_key=None, base_url=DEFAULT_BASE_URL, timeout=30, transport=None):
32
+ self.api_key = api_key or os.getenv("MEMSIDE_API_KEY")
33
+ if not self.api_key:
34
+ raise MemsideError(
35
+ "Missing Memside API key",
36
+ status=401,
37
+ code="missing_api_key",
38
+ retryable=False,
39
+ )
40
+
41
+ self.base_url = base_url.rstrip("/")
42
+ self.timeout = timeout
43
+ self.transport = transport
44
+
45
+ def context_startup(self, **params):
46
+ return self.request("GET", "/context/startup", params=params)
47
+
48
+ def context_resume(self, **params):
49
+ return self.request("GET", "/context/resume", params=params)
50
+
51
+ def context_workspace_profile(self, **params):
52
+ return self.request("GET", "/context/workspace-profile", params=params)
53
+
54
+ def memories_list(self, **params):
55
+ return self.request("GET", "/memories", params=params)
56
+
57
+ def memories_search(self, **params):
58
+ return self.request("GET", "/memories/search", params=params)
59
+
60
+ def memories_get(self, memory_id):
61
+ return self.request("GET", f"/memories/{memory_id}")
62
+
63
+ def memories_create(self, memory):
64
+ return self.request("POST", "/memories", json_body=memory)
65
+
66
+ def memories_update(self, memory_id, patch):
67
+ return self.request("PATCH", f"/memories/{memory_id}", json_body=patch)
68
+
69
+ def memories_delete(self, memory_id):
70
+ return self.request("DELETE", f"/memories/{memory_id}")
71
+
72
+ def request(self, method, path, *, params=None, json_body=None, headers=None):
73
+ url = self._build_url(path, params)
74
+ request_headers = {
75
+ "Accept": "application/json",
76
+ "Authorization": f"Bearer {self.api_key}",
77
+ **(headers or {}),
78
+ }
79
+ body = None
80
+
81
+ if json_body is not None:
82
+ body = json.dumps(json_body).encode("utf-8")
83
+ request_headers["Content-Type"] = "application/json"
84
+
85
+ if self.transport:
86
+ status, response_headers, response_body = self.transport(
87
+ method,
88
+ url,
89
+ request_headers,
90
+ body,
91
+ self.timeout,
92
+ )
93
+ payload = _read_payload(response_body)
94
+ if status >= 400:
95
+ raise _to_memside_error(status, payload)
96
+ return payload
97
+
98
+ request = Request(url, data=body, headers=request_headers, method=method)
99
+
100
+ try:
101
+ with urlopen(request, timeout=self.timeout) as response:
102
+ payload = _read_payload(response.read())
103
+ return payload
104
+ except HTTPError as error:
105
+ payload = _read_payload(error.read())
106
+ raise _to_memside_error(error.code, payload) from error
107
+
108
+ def _build_url(self, path, params=None):
109
+ clean_params = {
110
+ key: value
111
+ for key, value in (params or {}).items()
112
+ if value is not None
113
+ }
114
+
115
+ query = urlencode(clean_params, doseq=True)
116
+ url = f"{self.base_url}{path}"
117
+ return f"{url}?{query}" if query else url
118
+
119
+
120
+ def _read_payload(body):
121
+ if body is None or body == b"":
122
+ return None
123
+
124
+ if isinstance(body, bytes):
125
+ body = body.decode("utf-8")
126
+
127
+ if body == "":
128
+ return None
129
+
130
+ try:
131
+ return json.loads(body)
132
+ except json.JSONDecodeError:
133
+ return body
134
+
135
+
136
+ def _to_memside_error(status, payload):
137
+ error = payload.get("error") if isinstance(payload, dict) else None
138
+ message = None
139
+ code = "request_failed"
140
+ retryable = False
141
+
142
+ if isinstance(error, dict):
143
+ message = error.get("message")
144
+ code = error.get("code") or code
145
+ status = error.get("status") or status
146
+ retryable = bool(error.get("retryable"))
147
+
148
+ return MemsideError(
149
+ message or "Memside API request failed",
150
+ status=status,
151
+ code=code,
152
+ retryable=retryable,
153
+ request_id=payload.get("request_id") if isinstance(payload, dict) else None,
154
+ details=payload,
155
+ )
@@ -0,0 +1,80 @@
1
+ Metadata-Version: 2.4
2
+ Name: memside
3
+ Version: 0.1.0
4
+ Summary: Lightweight Python client for the public Memside API.
5
+ Author-email: Memside <support@memside.com>
6
+ License: # Memside Python SDK License
7
+
8
+ Copyright (c) 2026 Memside. All rights reserved.
9
+
10
+ This package is provided to help developers connect applications, scripts, and tools to the public Memside API.
11
+
12
+ You may use this package to integrate with Memside. You may not use this package, its documentation, or its structure to build or market a competing product or service.
13
+
14
+ This package does not grant rights to private Memside application source code, backend services, APIs outside the public API contract, infrastructure, trademarks, product designs, databases, private documentation, or proprietary systems.
15
+
16
+ This package is provided without warranties or guarantees of any kind.
17
+
18
+ Project-URL: Homepage, https://github.com/memside/memside
19
+ Project-URL: Repository, https://github.com/memside/memside
20
+ Project-URL: Issues, https://github.com/memside/memside/issues
21
+ Keywords: memside,ai,memory,mcp,sdk
22
+ Classifier: Development Status :: 3 - Alpha
23
+ Classifier: Intended Audience :: Developers
24
+ Classifier: Programming Language :: Python :: 3
25
+ Classifier: Programming Language :: Python :: 3.9
26
+ Classifier: Programming Language :: Python :: 3.10
27
+ Classifier: Programming Language :: Python :: 3.11
28
+ Classifier: Programming Language :: Python :: 3.12
29
+ Classifier: Programming Language :: Python :: 3.13
30
+ Requires-Python: >=3.9
31
+ Description-Content-Type: text/markdown
32
+ License-File: LICENSE.md
33
+ Dynamic: license-file
34
+
35
+ # Memside Python SDK
36
+
37
+ Lightweight Python client for the public Memside API.
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ pip install memside
43
+ ```
44
+
45
+ ## Usage
46
+
47
+ ```python
48
+ from memside import MemsideClient
49
+
50
+ client = MemsideClient(api_key="mem_sk_your_key_here")
51
+
52
+ startup = client.context_startup()
53
+ print(startup)
54
+ ```
55
+
56
+ You can also set the API key through the environment:
57
+
58
+ ```bash
59
+ MEMSIDE_API_KEY=mem_sk_your_key_here
60
+ ```
61
+
62
+ ## Supported API Areas
63
+
64
+ This package wraps public Memside API-key routes:
65
+
66
+ - startup context
67
+ - resume context
68
+ - workspace profile
69
+ - memory listing
70
+ - memory search
71
+ - memory fetch
72
+ - memory create
73
+ - memory update
74
+ - memory delete, when allowed by the API
75
+
76
+ This package does not include private Memside application source, account/session internals, billing internals, admin routes, database details, or MCP server implementation.
77
+
78
+ ## Requirements
79
+
80
+ Python 3.9 or newer.
@@ -0,0 +1,10 @@
1
+ LICENSE.md
2
+ README.md
3
+ pyproject.toml
4
+ src/memside/__init__.py
5
+ src/memside/client.py
6
+ src/memside.egg-info/PKG-INFO
7
+ src/memside.egg-info/SOURCES.txt
8
+ src/memside.egg-info/dependency_links.txt
9
+ src/memside.egg-info/top_level.txt
10
+ tests/test_client.py
@@ -0,0 +1 @@
1
+ memside
@@ -0,0 +1,69 @@
1
+ import unittest
2
+
3
+ from memside import MemsideClient, MemsideError
4
+
5
+
6
+ class MemsideClientTests(unittest.TestCase):
7
+ def test_startup_sends_bearer_auth(self):
8
+ calls = []
9
+
10
+ def transport(method, url, headers, body, timeout):
11
+ calls.append((method, url, headers, body, timeout))
12
+ return 200, {}, b'{"ok": true}'
13
+
14
+ client = MemsideClient(api_key="mem_sk_test_key", transport=transport)
15
+
16
+ self.assertEqual(client.context_startup(), {"ok": True})
17
+ self.assertEqual(calls[0][0], "GET")
18
+ self.assertEqual(calls[0][1], "https://api.memside.com/context/startup")
19
+ self.assertEqual(calls[0][2]["Authorization"], "Bearer mem_sk_test_key")
20
+
21
+ def test_search_serializes_query_params(self):
22
+ calls = []
23
+
24
+ def transport(method, url, headers, body, timeout):
25
+ calls.append((method, url, headers, body, timeout))
26
+ return 200, {}, b'{"matches": []}'
27
+
28
+ client = MemsideClient(api_key="mem_sk_test_key", transport=transport)
29
+
30
+ self.assertEqual(client.memories_search(q="launch", limit=5), {"matches": []})
31
+ self.assertEqual(
32
+ calls[0][1],
33
+ "https://api.memside.com/memories/search?q=launch&limit=5",
34
+ )
35
+
36
+ def test_create_sends_json_body(self):
37
+ calls = []
38
+
39
+ def transport(method, url, headers, body, timeout):
40
+ calls.append((method, url, headers, body, timeout))
41
+ return 201, {}, b'{"id": "mem_123"}'
42
+
43
+ client = MemsideClient(api_key="mem_sk_test_key", transport=transport)
44
+
45
+ self.assertEqual(client.memories_create({"content": "Remember this"}), {"id": "mem_123"})
46
+ self.assertEqual(calls[0][0], "POST")
47
+ self.assertEqual(calls[0][2]["Content-Type"], "application/json")
48
+ self.assertEqual(calls[0][3], b'{"content": "Remember this"}')
49
+
50
+ def test_failed_requests_raise_memside_error(self):
51
+ def transport(method, url, headers, body, timeout):
52
+ return (
53
+ 401,
54
+ {},
55
+ b'{"ok": false, "request_id": "req_test", "error": {"code": "unauthorized", "message": "Invalid API key", "status": 401, "retryable": false}}',
56
+ )
57
+
58
+ client = MemsideClient(api_key="mem_sk_test_key", transport=transport)
59
+
60
+ with self.assertRaises(MemsideError) as raised:
61
+ client.context_startup()
62
+
63
+ self.assertEqual(raised.exception.status, 401)
64
+ self.assertEqual(raised.exception.code, "unauthorized")
65
+ self.assertEqual(raised.exception.request_id, "req_test")
66
+
67
+
68
+ if __name__ == "__main__":
69
+ unittest.main()