remdb 0.3.242__py3-none-any.whl

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.

Potentially problematic release.


This version of remdb might be problematic. Click here for more details.

Files changed (235) hide show
  1. rem/__init__.py +129 -0
  2. rem/agentic/README.md +760 -0
  3. rem/agentic/__init__.py +54 -0
  4. rem/agentic/agents/README.md +155 -0
  5. rem/agentic/agents/__init__.py +38 -0
  6. rem/agentic/agents/agent_manager.py +311 -0
  7. rem/agentic/agents/sse_simulator.py +502 -0
  8. rem/agentic/context.py +425 -0
  9. rem/agentic/context_builder.py +360 -0
  10. rem/agentic/llm_provider_models.py +301 -0
  11. rem/agentic/mcp/__init__.py +0 -0
  12. rem/agentic/mcp/tool_wrapper.py +273 -0
  13. rem/agentic/otel/__init__.py +5 -0
  14. rem/agentic/otel/setup.py +240 -0
  15. rem/agentic/providers/phoenix.py +926 -0
  16. rem/agentic/providers/pydantic_ai.py +854 -0
  17. rem/agentic/query.py +117 -0
  18. rem/agentic/query_helper.py +89 -0
  19. rem/agentic/schema.py +737 -0
  20. rem/agentic/serialization.py +245 -0
  21. rem/agentic/tools/__init__.py +5 -0
  22. rem/agentic/tools/rem_tools.py +242 -0
  23. rem/api/README.md +657 -0
  24. rem/api/deps.py +253 -0
  25. rem/api/main.py +460 -0
  26. rem/api/mcp_router/prompts.py +182 -0
  27. rem/api/mcp_router/resources.py +820 -0
  28. rem/api/mcp_router/server.py +243 -0
  29. rem/api/mcp_router/tools.py +1605 -0
  30. rem/api/middleware/tracking.py +172 -0
  31. rem/api/routers/admin.py +520 -0
  32. rem/api/routers/auth.py +898 -0
  33. rem/api/routers/chat/__init__.py +5 -0
  34. rem/api/routers/chat/child_streaming.py +394 -0
  35. rem/api/routers/chat/completions.py +702 -0
  36. rem/api/routers/chat/json_utils.py +76 -0
  37. rem/api/routers/chat/models.py +202 -0
  38. rem/api/routers/chat/otel_utils.py +33 -0
  39. rem/api/routers/chat/sse_events.py +546 -0
  40. rem/api/routers/chat/streaming.py +950 -0
  41. rem/api/routers/chat/streaming_utils.py +327 -0
  42. rem/api/routers/common.py +18 -0
  43. rem/api/routers/dev.py +87 -0
  44. rem/api/routers/feedback.py +276 -0
  45. rem/api/routers/messages.py +620 -0
  46. rem/api/routers/models.py +86 -0
  47. rem/api/routers/query.py +362 -0
  48. rem/api/routers/shared_sessions.py +422 -0
  49. rem/auth/README.md +258 -0
  50. rem/auth/__init__.py +36 -0
  51. rem/auth/jwt.py +367 -0
  52. rem/auth/middleware.py +318 -0
  53. rem/auth/providers/__init__.py +16 -0
  54. rem/auth/providers/base.py +376 -0
  55. rem/auth/providers/email.py +215 -0
  56. rem/auth/providers/google.py +163 -0
  57. rem/auth/providers/microsoft.py +237 -0
  58. rem/cli/README.md +517 -0
  59. rem/cli/__init__.py +8 -0
  60. rem/cli/commands/README.md +299 -0
  61. rem/cli/commands/__init__.py +3 -0
  62. rem/cli/commands/ask.py +549 -0
  63. rem/cli/commands/cluster.py +1808 -0
  64. rem/cli/commands/configure.py +495 -0
  65. rem/cli/commands/db.py +828 -0
  66. rem/cli/commands/dreaming.py +324 -0
  67. rem/cli/commands/experiments.py +1698 -0
  68. rem/cli/commands/mcp.py +66 -0
  69. rem/cli/commands/process.py +388 -0
  70. rem/cli/commands/query.py +109 -0
  71. rem/cli/commands/scaffold.py +47 -0
  72. rem/cli/commands/schema.py +230 -0
  73. rem/cli/commands/serve.py +106 -0
  74. rem/cli/commands/session.py +453 -0
  75. rem/cli/dreaming.py +363 -0
  76. rem/cli/main.py +123 -0
  77. rem/config.py +244 -0
  78. rem/mcp_server.py +41 -0
  79. rem/models/core/__init__.py +49 -0
  80. rem/models/core/core_model.py +70 -0
  81. rem/models/core/engram.py +333 -0
  82. rem/models/core/experiment.py +672 -0
  83. rem/models/core/inline_edge.py +132 -0
  84. rem/models/core/rem_query.py +246 -0
  85. rem/models/entities/__init__.py +68 -0
  86. rem/models/entities/domain_resource.py +38 -0
  87. rem/models/entities/feedback.py +123 -0
  88. rem/models/entities/file.py +57 -0
  89. rem/models/entities/image_resource.py +88 -0
  90. rem/models/entities/message.py +64 -0
  91. rem/models/entities/moment.py +123 -0
  92. rem/models/entities/ontology.py +181 -0
  93. rem/models/entities/ontology_config.py +131 -0
  94. rem/models/entities/resource.py +95 -0
  95. rem/models/entities/schema.py +87 -0
  96. rem/models/entities/session.py +84 -0
  97. rem/models/entities/shared_session.py +180 -0
  98. rem/models/entities/subscriber.py +175 -0
  99. rem/models/entities/user.py +93 -0
  100. rem/py.typed +0 -0
  101. rem/registry.py +373 -0
  102. rem/schemas/README.md +507 -0
  103. rem/schemas/__init__.py +6 -0
  104. rem/schemas/agents/README.md +92 -0
  105. rem/schemas/agents/core/agent-builder.yaml +235 -0
  106. rem/schemas/agents/core/moment-builder.yaml +178 -0
  107. rem/schemas/agents/core/rem-query-agent.yaml +226 -0
  108. rem/schemas/agents/core/resource-affinity-assessor.yaml +99 -0
  109. rem/schemas/agents/core/simple-assistant.yaml +19 -0
  110. rem/schemas/agents/core/user-profile-builder.yaml +163 -0
  111. rem/schemas/agents/examples/contract-analyzer.yaml +317 -0
  112. rem/schemas/agents/examples/contract-extractor.yaml +134 -0
  113. rem/schemas/agents/examples/cv-parser.yaml +263 -0
  114. rem/schemas/agents/examples/hello-world.yaml +37 -0
  115. rem/schemas/agents/examples/query.yaml +54 -0
  116. rem/schemas/agents/examples/simple.yaml +21 -0
  117. rem/schemas/agents/examples/test.yaml +29 -0
  118. rem/schemas/agents/rem.yaml +132 -0
  119. rem/schemas/evaluators/hello-world/default.yaml +77 -0
  120. rem/schemas/evaluators/rem/faithfulness.yaml +219 -0
  121. rem/schemas/evaluators/rem/lookup-correctness.yaml +182 -0
  122. rem/schemas/evaluators/rem/retrieval-precision.yaml +199 -0
  123. rem/schemas/evaluators/rem/retrieval-recall.yaml +211 -0
  124. rem/schemas/evaluators/rem/search-correctness.yaml +192 -0
  125. rem/services/__init__.py +18 -0
  126. rem/services/audio/INTEGRATION.md +308 -0
  127. rem/services/audio/README.md +376 -0
  128. rem/services/audio/__init__.py +15 -0
  129. rem/services/audio/chunker.py +354 -0
  130. rem/services/audio/transcriber.py +259 -0
  131. rem/services/content/README.md +1269 -0
  132. rem/services/content/__init__.py +5 -0
  133. rem/services/content/providers.py +760 -0
  134. rem/services/content/service.py +762 -0
  135. rem/services/dreaming/README.md +230 -0
  136. rem/services/dreaming/__init__.py +53 -0
  137. rem/services/dreaming/affinity_service.py +322 -0
  138. rem/services/dreaming/moment_service.py +251 -0
  139. rem/services/dreaming/ontology_service.py +54 -0
  140. rem/services/dreaming/user_model_service.py +297 -0
  141. rem/services/dreaming/utils.py +39 -0
  142. rem/services/email/__init__.py +10 -0
  143. rem/services/email/service.py +522 -0
  144. rem/services/email/templates.py +360 -0
  145. rem/services/embeddings/__init__.py +11 -0
  146. rem/services/embeddings/api.py +127 -0
  147. rem/services/embeddings/worker.py +435 -0
  148. rem/services/fs/README.md +662 -0
  149. rem/services/fs/__init__.py +62 -0
  150. rem/services/fs/examples.py +206 -0
  151. rem/services/fs/examples_paths.py +204 -0
  152. rem/services/fs/git_provider.py +935 -0
  153. rem/services/fs/local_provider.py +760 -0
  154. rem/services/fs/parsing-hooks-examples.md +172 -0
  155. rem/services/fs/paths.py +276 -0
  156. rem/services/fs/provider.py +460 -0
  157. rem/services/fs/s3_provider.py +1042 -0
  158. rem/services/fs/service.py +186 -0
  159. rem/services/git/README.md +1075 -0
  160. rem/services/git/__init__.py +17 -0
  161. rem/services/git/service.py +469 -0
  162. rem/services/phoenix/EXPERIMENT_DESIGN.md +1146 -0
  163. rem/services/phoenix/README.md +453 -0
  164. rem/services/phoenix/__init__.py +46 -0
  165. rem/services/phoenix/client.py +960 -0
  166. rem/services/phoenix/config.py +88 -0
  167. rem/services/phoenix/prompt_labels.py +477 -0
  168. rem/services/postgres/README.md +757 -0
  169. rem/services/postgres/__init__.py +49 -0
  170. rem/services/postgres/diff_service.py +599 -0
  171. rem/services/postgres/migration_service.py +427 -0
  172. rem/services/postgres/programmable_diff_service.py +635 -0
  173. rem/services/postgres/pydantic_to_sqlalchemy.py +562 -0
  174. rem/services/postgres/register_type.py +353 -0
  175. rem/services/postgres/repository.py +481 -0
  176. rem/services/postgres/schema_generator.py +661 -0
  177. rem/services/postgres/service.py +802 -0
  178. rem/services/postgres/sql_builder.py +355 -0
  179. rem/services/rate_limit.py +113 -0
  180. rem/services/rem/README.md +318 -0
  181. rem/services/rem/__init__.py +23 -0
  182. rem/services/rem/exceptions.py +71 -0
  183. rem/services/rem/executor.py +293 -0
  184. rem/services/rem/parser.py +180 -0
  185. rem/services/rem/queries.py +196 -0
  186. rem/services/rem/query.py +371 -0
  187. rem/services/rem/service.py +608 -0
  188. rem/services/session/README.md +374 -0
  189. rem/services/session/__init__.py +13 -0
  190. rem/services/session/compression.py +488 -0
  191. rem/services/session/pydantic_messages.py +310 -0
  192. rem/services/session/reload.py +85 -0
  193. rem/services/user_service.py +130 -0
  194. rem/settings.py +1877 -0
  195. rem/sql/background_indexes.sql +52 -0
  196. rem/sql/migrations/001_install.sql +983 -0
  197. rem/sql/migrations/002_install_models.sql +3157 -0
  198. rem/sql/migrations/003_optional_extensions.sql +326 -0
  199. rem/sql/migrations/004_cache_system.sql +282 -0
  200. rem/sql/migrations/005_schema_update.sql +145 -0
  201. rem/sql/migrations/migrate_session_id_to_uuid.sql +45 -0
  202. rem/utils/AGENTIC_CHUNKING.md +597 -0
  203. rem/utils/README.md +628 -0
  204. rem/utils/__init__.py +61 -0
  205. rem/utils/agentic_chunking.py +622 -0
  206. rem/utils/batch_ops.py +343 -0
  207. rem/utils/chunking.py +108 -0
  208. rem/utils/clip_embeddings.py +276 -0
  209. rem/utils/constants.py +97 -0
  210. rem/utils/date_utils.py +228 -0
  211. rem/utils/dict_utils.py +98 -0
  212. rem/utils/embeddings.py +436 -0
  213. rem/utils/examples/embeddings_example.py +305 -0
  214. rem/utils/examples/sql_types_example.py +202 -0
  215. rem/utils/files.py +323 -0
  216. rem/utils/markdown.py +16 -0
  217. rem/utils/mime_types.py +158 -0
  218. rem/utils/model_helpers.py +492 -0
  219. rem/utils/schema_loader.py +649 -0
  220. rem/utils/sql_paths.py +146 -0
  221. rem/utils/sql_types.py +350 -0
  222. rem/utils/user_id.py +81 -0
  223. rem/utils/vision.py +325 -0
  224. rem/workers/README.md +506 -0
  225. rem/workers/__init__.py +7 -0
  226. rem/workers/db_listener.py +579 -0
  227. rem/workers/db_maintainer.py +74 -0
  228. rem/workers/dreaming.py +502 -0
  229. rem/workers/engram_processor.py +312 -0
  230. rem/workers/sqs_file_processor.py +193 -0
  231. rem/workers/unlogged_maintainer.py +463 -0
  232. remdb-0.3.242.dist-info/METADATA +1632 -0
  233. remdb-0.3.242.dist-info/RECORD +235 -0
  234. remdb-0.3.242.dist-info/WHEEL +4 -0
  235. remdb-0.3.242.dist-info/entry_points.txt +2 -0
rem/api/deps.py ADDED
@@ -0,0 +1,253 @@
1
+ """
2
+ Shared FastAPI dependencies for authentication and authorization.
3
+
4
+ Provides dependency injection utilities for:
5
+ - Extracting current user from session
6
+ - Requiring authentication
7
+ - Requiring specific roles (admin, user)
8
+ - User-scoped data filtering with admin override
9
+
10
+ Design Pattern:
11
+ - Use as FastAPI dependencies via Depends()
12
+ - Middleware sets request.state.user and request.state.is_anonymous
13
+ - Dependencies extract and validate from request.state
14
+ - Admin users can access any user's data via filters
15
+
16
+ Roles:
17
+ - "admin": Full access to all data across all users
18
+ - "user": Default role, access limited to own data
19
+ - Anonymous: Rate-limited access, no persistent data
20
+
21
+ Usage:
22
+ from rem.api.deps import require_auth, require_admin, get_user_filter
23
+
24
+ @router.get("/items")
25
+ async def list_items(user: dict = Depends(require_auth)):
26
+ # user is guaranteed to be authenticated
27
+ ...
28
+
29
+ @router.post("/admin/action")
30
+ async def admin_action(user: dict = Depends(require_admin)):
31
+ # user is guaranteed to have admin role
32
+ ...
33
+
34
+ @router.get("/sessions/{session_id}")
35
+ async def get_session(
36
+ session_id: str,
37
+ filters: dict = Depends(get_user_filter),
38
+ ):
39
+ # filters includes user_id constraint (unless admin)
40
+ ...
41
+ """
42
+
43
+ from typing import Any
44
+
45
+ from fastapi import Depends, HTTPException, Request
46
+ from loguru import logger
47
+
48
+
49
+ class AuthError(HTTPException):
50
+ """Authentication/Authorization error."""
51
+
52
+ def __init__(self, detail: str, status_code: int = 401):
53
+ super().__init__(status_code=status_code, detail=detail)
54
+
55
+
56
+ def get_current_user(request: Request) -> dict | None:
57
+ """
58
+ Get current user from request state (set by AuthMiddleware).
59
+
60
+ Returns None if no user authenticated.
61
+ Use require_auth() if authentication is mandatory.
62
+
63
+ Args:
64
+ request: FastAPI request
65
+
66
+ Returns:
67
+ User dict from session or None
68
+ """
69
+ return getattr(request.state, "user", None)
70
+
71
+
72
+ def get_is_anonymous(request: Request) -> bool:
73
+ """
74
+ Check if current request is anonymous.
75
+
76
+ Args:
77
+ request: FastAPI request
78
+
79
+ Returns:
80
+ True if anonymous, False if authenticated
81
+ """
82
+ return getattr(request.state, "is_anonymous", True)
83
+
84
+
85
+ def require_auth(request: Request) -> dict:
86
+ """
87
+ Require authenticated user.
88
+
89
+ Use as FastAPI dependency to enforce authentication.
90
+
91
+ Args:
92
+ request: FastAPI request
93
+
94
+ Returns:
95
+ User dict from session
96
+
97
+ Raises:
98
+ HTTPException 401 if not authenticated
99
+ """
100
+ user = get_current_user(request)
101
+ if not user:
102
+ raise AuthError("Authentication required", status_code=401)
103
+ return user
104
+
105
+
106
+ def require_admin(request: Request) -> dict:
107
+ """
108
+ Require authenticated user with admin role.
109
+
110
+ Use as FastAPI dependency to protect admin-only endpoints.
111
+
112
+ Args:
113
+ request: FastAPI request
114
+
115
+ Returns:
116
+ User dict from session
117
+
118
+ Raises:
119
+ HTTPException 401 if not authenticated
120
+ HTTPException 403 if not admin
121
+ """
122
+ user = require_auth(request)
123
+ roles = user.get("roles", [])
124
+
125
+ if "admin" not in roles:
126
+ logger.warning(f"Admin access denied for user {user.get('email')}")
127
+ raise AuthError("Admin access required", status_code=403)
128
+
129
+ return user
130
+
131
+
132
+ def is_admin(user: dict | None) -> bool:
133
+ """
134
+ Check if user has admin role.
135
+
136
+ Args:
137
+ user: User dict or None
138
+
139
+ Returns:
140
+ True if user is admin
141
+ """
142
+ if not user:
143
+ return False
144
+ return "admin" in user.get("roles", [])
145
+
146
+
147
+ async def get_user_filter(
148
+ request: Request,
149
+ x_user_id: str | None = None,
150
+ ) -> dict[str, Any]:
151
+ """
152
+ Get user-scoped filter dict for database queries.
153
+
154
+ For regular users: Always filters by their own user_id.
155
+ For admin users: Can filter by any user_id (or no filter for all users).
156
+
157
+ Args:
158
+ request: FastAPI request
159
+ x_user_id: Optional user_id filter (admin only for cross-user)
160
+
161
+ Returns:
162
+ Filter dict with appropriate user_id constraint
163
+
164
+ Usage:
165
+ @router.get("/items")
166
+ async def list_items(filters: dict = Depends(get_user_filter)):
167
+ return await repo.find(filters)
168
+ """
169
+ user = get_current_user(request)
170
+ filters: dict[str, Any] = {}
171
+
172
+ if is_admin(user):
173
+ # Admin can filter by any user or see all
174
+ if x_user_id:
175
+ filters["user_id"] = x_user_id
176
+ # If no user_id specified, admin sees all (no user_id filter)
177
+ logger.debug(f"Admin access: filters={filters}")
178
+ elif user:
179
+ # Regular authenticated user: always filter by own user_id
180
+ filters["user_id"] = user.get("id")
181
+ if x_user_id and x_user_id != user.get("id"):
182
+ logger.warning(
183
+ f"User {user.get('email')} attempted to filter by user_id={x_user_id}"
184
+ )
185
+ else:
186
+ # Anonymous: use anonymous tracking ID
187
+ # Note: user_id should come from JWT, not from parameters
188
+ anon_id = getattr(request.state, "anon_id", None)
189
+ if anon_id:
190
+ filters["user_id"] = f"anon:{anon_id}"
191
+ else:
192
+ filters["user_id"] = "anonymous"
193
+
194
+ return filters
195
+
196
+
197
+ async def require_owner_or_admin(
198
+ request: Request,
199
+ resource_user_id: str,
200
+ ) -> dict:
201
+ """
202
+ Require that current user owns the resource or is admin.
203
+
204
+ Use for parametric endpoints (GET /resource/{id}) where
205
+ only the owner or admin should access.
206
+
207
+ Args:
208
+ request: FastAPI request
209
+ resource_user_id: The user_id of the resource being accessed
210
+
211
+ Returns:
212
+ User dict from session
213
+
214
+ Raises:
215
+ HTTPException 401 if not authenticated
216
+ HTTPException 403 if not owner and not admin
217
+ """
218
+ user = require_auth(request)
219
+
220
+ if is_admin(user):
221
+ return user
222
+
223
+ if user.get("id") != resource_user_id:
224
+ logger.warning(
225
+ f"Access denied: user {user.get('email')} tried to access "
226
+ f"resource owned by {resource_user_id}"
227
+ )
228
+ raise AuthError("Access denied: not owner", status_code=403)
229
+
230
+ return user
231
+
232
+
233
+ def get_user_id_from_request(request: Request) -> str:
234
+ """
235
+ Get effective user_id for creating resources.
236
+
237
+ Returns authenticated user's ID or anonymous tracking ID.
238
+
239
+ Args:
240
+ request: FastAPI request
241
+
242
+ Returns:
243
+ User ID string
244
+ """
245
+ user = get_current_user(request)
246
+ if user:
247
+ return user.get("id", "unknown")
248
+
249
+ anon_id = getattr(request.state, "anon_id", None)
250
+ if anon_id:
251
+ return f"anon:{anon_id}"
252
+
253
+ return "anonymous"