remdb 0.3.200__py3-none-any.whl → 0.3.202__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.

rem/api/routers/auth.py CHANGED
@@ -541,6 +541,9 @@ async def refresh_token(body: TokenRefreshRequest):
541
541
  """
542
542
  Refresh access token using refresh token.
543
543
 
544
+ Fetches the user's current role/tier from the database to ensure
545
+ the new access token reflects their actual permissions.
546
+
544
547
  Args:
545
548
  body: TokenRefreshRequest with refresh_token
546
549
 
@@ -548,7 +551,46 @@ async def refresh_token(body: TokenRefreshRequest):
548
551
  New access token or 401 if refresh token is invalid
549
552
  """
550
553
  jwt_service = get_jwt_service()
551
- result = jwt_service.refresh_access_token(body.refresh_token)
554
+
555
+ # First decode the refresh token to get user_id (without full verification yet)
556
+ payload = jwt_service.decode_without_verification(body.refresh_token)
557
+ if not payload:
558
+ raise HTTPException(
559
+ status_code=401,
560
+ detail="Invalid refresh token format"
561
+ )
562
+
563
+ user_id = payload.get("sub")
564
+ if not user_id:
565
+ raise HTTPException(
566
+ status_code=401,
567
+ detail="Invalid refresh token: missing user ID"
568
+ )
569
+
570
+ # Fetch user from database to get current role/tier
571
+ user_override = None
572
+ if settings.postgres.enabled:
573
+ db = PostgresService()
574
+ try:
575
+ await db.connect()
576
+ user_service = UserService(db)
577
+ user_entity = await user_service.get_user_by_id(user_id)
578
+ if user_entity:
579
+ user_override = {
580
+ "role": user_entity.role or "user",
581
+ "roles": [user_entity.role] if user_entity.role else ["user"],
582
+ "tier": user_entity.tier.value if user_entity.tier else "free",
583
+ "name": user_entity.name,
584
+ }
585
+ logger.debug(f"Refresh token: fetched user {user_id} with role={user_override['role']}, tier={user_override['tier']}")
586
+ except Exception as e:
587
+ logger.warning(f"Could not fetch user for token refresh: {e}")
588
+ # Continue without override - will use defaults
589
+ finally:
590
+ await db.disconnect()
591
+
592
+ # Now do the actual refresh with proper verification
593
+ result = jwt_service.refresh_access_token(body.refresh_token, user_override=user_override)
552
594
 
553
595
  if not result:
554
596
  raise HTTPException(
rem/auth/jwt.py CHANGED
@@ -260,12 +260,16 @@ class JWTService:
260
260
  "tenant_id": payload.get("tenant_id", "default"),
261
261
  }
262
262
 
263
- def refresh_access_token(self, refresh_token: str) -> dict | None:
263
+ def refresh_access_token(
264
+ self, refresh_token: str, user_override: dict | None = None
265
+ ) -> dict | None:
264
266
  """
265
267
  Create new access token using refresh token.
266
268
 
267
269
  Args:
268
270
  refresh_token: Valid refresh token
271
+ user_override: Optional dict with user fields to override defaults
272
+ (e.g., role, roles, tier, name from database lookup)
269
273
 
270
274
  Returns:
271
275
  New token dict or None if refresh token is invalid
@@ -285,8 +289,7 @@ class JWTService:
285
289
  logger.debug("Refresh token expired")
286
290
  return None
287
291
 
288
- # Create new access token with minimal info from refresh token
289
- # In production, you'd look up the full user from database
292
+ # Build user dict with defaults
290
293
  user = {
291
294
  "id": payload.get("sub"),
292
295
  "email": payload.get("email"),
@@ -294,16 +297,28 @@ class JWTService:
294
297
  "provider": "email",
295
298
  "tenant_id": "default",
296
299
  "tier": "free",
300
+ "role": "user",
297
301
  "roles": ["user"],
298
302
  }
299
303
 
304
+ # Apply overrides from database lookup if provided
305
+ if user_override:
306
+ if user_override.get("role"):
307
+ user["role"] = user_override["role"]
308
+ if user_override.get("roles"):
309
+ user["roles"] = user_override["roles"]
310
+ if user_override.get("tier"):
311
+ user["tier"] = user_override["tier"]
312
+ if user_override.get("name"):
313
+ user["name"] = user_override["name"]
314
+
300
315
  # Only return new access token, keep same refresh token
301
316
  now = int(time.time())
302
317
  access_payload = {
303
318
  "sub": user["id"],
304
319
  "email": user["email"],
305
320
  "name": user["name"],
306
- "role": user.get("role"),
321
+ "role": user["role"],
307
322
  "tier": user["tier"],
308
323
  "roles": user["roles"],
309
324
  "provider": user["provider"],
@@ -103,32 +103,30 @@ class Ontology(CoreModel):
103
103
  tags=["cv", "engineering"]
104
104
  )
105
105
 
106
- # Direct-loaded: Medical knowledge base from git
107
- disorder_ontology = Ontology(
108
- name="panic-disorder",
109
- uri="git://bwolfson-siggie/Siggy-MVP/ontology/disorders/anxiety/panic-disorder.md",
110
- content="# Panic Disorder\\n\\nPanic disorder is characterized by...",
106
+ # Direct-loaded: Knowledge base from git
107
+ api_docs = Ontology(
108
+ name="rest-api-guide",
109
+ uri="git://example-org/docs/api/rest-api-guide.md",
110
+ content="# REST API Guide\\n\\nThis guide covers RESTful API design...",
111
111
  extracted_data={
112
- "type": "disorder",
113
- "category": "anxiety",
114
- "icd10": "F41.0",
115
- "dsm5_criteria": ["A", "B", "C", "D"],
112
+ "type": "documentation",
113
+ "category": "api",
114
+ "version": "2.0",
116
115
  },
117
- tags=["disorder", "anxiety", "dsm5"]
116
+ tags=["api", "rest", "documentation"]
118
117
  )
119
118
 
120
- # Direct-loaded: Clinical procedure from git
121
- scid_node = Ontology(
122
- name="scid-5-f1",
123
- uri="git://bwolfson-siggie/Siggy-MVP/ontology/procedures/scid-5/module-f/scid-5-f1.md",
124
- content="# scid-5-f1: Panic Attack Screening\\n\\n...",
119
+ # Direct-loaded: Technical spec from git
120
+ config_spec = Ontology(
121
+ name="config-schema",
122
+ uri="git://example-org/docs/specs/config-schema.md",
123
+ content="# Configuration Schema\\n\\nThis document defines...",
125
124
  extracted_data={
126
- "type": "procedure",
127
- "module": "F",
128
- "section": "Panic Disorder",
129
- "dsm5_criterion": "Panic Attack Specifier",
125
+ "type": "specification",
126
+ "format": "yaml",
127
+ "version": "1.0",
130
128
  },
131
- tags=["scid-5", "procedure", "anxiety"]
129
+ tags=["config", "schema", "specification"]
132
130
  )
133
131
  """
134
132
 
@@ -65,7 +65,7 @@ def truncate_key(key: str, max_length: int = MAX_ENTITY_KEY_LENGTH) -> str:
65
65
  logger.warning(f"Truncated key from {len(key)} to {len(truncated)} chars: {key[:50]}...")
66
66
  return truncated
67
67
 
68
- from rem.models.entities import Message
68
+ from rem.models.entities import Message, Session
69
69
  from rem.services.postgres import PostgresService, Repository
70
70
  from rem.settings import settings
71
71
 
@@ -177,6 +177,41 @@ class SessionMessageStore:
177
177
  self.user_id = user_id
178
178
  self.compressor = compressor or MessageCompressor()
179
179
  self.repo = Repository(Message)
180
+ self._session_repo = Repository(Session, table_name="sessions")
181
+
182
+ async def _ensure_session_exists(
183
+ self,
184
+ session_id: str,
185
+ user_id: str | None = None,
186
+ ) -> None:
187
+ """
188
+ Ensure session exists, creating it if necessary.
189
+
190
+ Args:
191
+ session_id: Session identifier (maps to Session.name)
192
+ user_id: Optional user identifier
193
+ """
194
+ try:
195
+ # Check if session already exists by name
196
+ existing = await self._session_repo.find(
197
+ filters={"name": session_id},
198
+ limit=1,
199
+ )
200
+ if existing:
201
+ return # Session already exists
202
+
203
+ # Create new session
204
+ session = Session(
205
+ name=session_id,
206
+ user_id=user_id or self.user_id,
207
+ tenant_id=self.user_id, # tenant_id set to user_id for scoping
208
+ )
209
+ await self._session_repo.upsert(session)
210
+ logger.info(f"Created session {session_id} for user {user_id or self.user_id}")
211
+
212
+ except Exception as e:
213
+ # Log but don't fail - session creation is best-effort
214
+ logger.warning(f"Failed to ensure session exists: {e}")
180
215
 
181
216
  async def store_message(
182
217
  self,
@@ -283,8 +318,10 @@ class SessionMessageStore:
283
318
  """
284
319
  Store all session messages and return compressed versions.
285
320
 
321
+ Ensures session exists before storing messages.
322
+
286
323
  Args:
287
- session_id: Session identifier
324
+ session_id: Session identifier (maps to Session.name)
288
325
  messages: List of messages to store
289
326
  user_id: Optional user identifier
290
327
  compress: Whether to compress messages (default: True)
@@ -296,6 +333,9 @@ class SessionMessageStore:
296
333
  logger.debug("Postgres disabled, returning messages uncompressed")
297
334
  return messages
298
335
 
336
+ # Ensure session exists before storing messages
337
+ await self._ensure_session_exists(session_id, user_id)
338
+
299
339
  compressed_messages = []
300
340
 
301
341
  for idx, message in enumerate(messages):
@@ -822,6 +822,7 @@ COMMENT ON FUNCTION fn_get_shared_messages IS
822
822
  -- Function to list sessions with user details (name, email) for admin views
823
823
 
824
824
  -- List sessions with user info, CTE pagination
825
+ -- Note: messages.session_id stores the session name (not UUID), so we join on sessions.name
825
826
  CREATE OR REPLACE FUNCTION fn_list_sessions_with_user(
826
827
  p_user_id VARCHAR(256) DEFAULT NULL, -- Filter by user_id (NULL = all users, admin only)
827
828
  p_user_name VARCHAR(256) DEFAULT NULL, -- Filter by user name (partial match, admin only)
@@ -847,7 +848,15 @@ RETURNS TABLE(
847
848
  ) AS $$
848
849
  BEGIN
849
850
  RETURN QUERY
850
- WITH filtered_sessions AS (
851
+ WITH session_msg_counts AS (
852
+ -- Count messages per session (joining on session name since messages.session_id = sessions.name)
853
+ SELECT
854
+ m.session_id as session_name,
855
+ COUNT(*)::INTEGER as actual_message_count
856
+ FROM messages m
857
+ GROUP BY m.session_id
858
+ ),
859
+ filtered_sessions AS (
851
860
  SELECT
852
861
  s.id,
853
862
  s.name,
@@ -856,13 +865,14 @@ BEGIN
856
865
  s.user_id,
857
866
  COALESCE(u.name, s.user_id)::VARCHAR(256) AS user_name,
858
867
  u.email::VARCHAR(256) AS user_email,
859
- s.message_count,
868
+ COALESCE(mc.actual_message_count, 0) AS message_count,
860
869
  s.total_tokens,
861
870
  s.created_at,
862
871
  s.updated_at,
863
872
  s.metadata
864
873
  FROM sessions s
865
874
  LEFT JOIN users u ON u.id::text = s.user_id
875
+ LEFT JOIN session_msg_counts mc ON mc.session_name = s.name
866
876
  WHERE s.deleted_at IS NULL
867
877
  AND (p_user_id IS NULL OR s.user_id = p_user_id)
868
878
  AND (p_user_name IS NULL OR u.name ILIKE '%' || p_user_name || '%')
@@ -895,7 +905,7 @@ END;
895
905
  $$ LANGUAGE plpgsql STABLE;
896
906
 
897
907
  COMMENT ON FUNCTION fn_list_sessions_with_user IS
898
- 'List sessions with user details (name, email). Supports filtering by user_id, user_name, user_email, and mode.';
908
+ 'List sessions with user details and computed message counts. Joins messages on session name.';
899
909
 
900
910
  -- ============================================================================
901
911
  -- RECORD INSTALLATION
@@ -1,7 +1,7 @@
1
1
  -- REM Model Schema (install_models.sql)
2
2
  -- Generated from Pydantic models
3
3
  -- Source: model registry
4
- -- Generated at: 2025-12-15T09:58:08.880060
4
+ -- Generated at: 2025-12-22T17:34:54.187339
5
5
  --
6
6
  -- DO NOT EDIT MANUALLY - Regenerate with: rem db schema generate
7
7
  --
@@ -2088,32 +2088,30 @@ Domain-specific knowledge - either agent-extracted or direct-loaded.
2088
2088
  tags=["cv", "engineering"]
2089
2089
  )
2090
2090
 
2091
- # Direct-loaded: Medical knowledge base from git
2092
- disorder_ontology = Ontology(
2093
- name="panic-disorder",
2094
- uri="git://bwolfson-siggie/Siggy-MVP/ontology/disorders/anxiety/panic-disorder.md",
2095
- content="# Panic Disorder\n\nPanic disorder is characterized by...",
2091
+ # Direct-loaded: Knowledge base from git
2092
+ api_docs = Ontology(
2093
+ name="rest-api-guide",
2094
+ uri="git://example-org/docs/api/rest-api-guide.md",
2095
+ content="# REST API Guide\n\nThis guide covers RESTful API design...",
2096
2096
  extracted_data={
2097
- "type": "disorder",
2098
- "category": "anxiety",
2099
- "icd10": "F41.0",
2100
- "dsm5_criteria": ["A", "B", "C", "D"],
2097
+ "type": "documentation",
2098
+ "category": "api",
2099
+ "version": "2.0",
2101
2100
  },
2102
- tags=["disorder", "anxiety", "dsm5"]
2101
+ tags=["api", "rest", "documentation"]
2103
2102
  )
2104
2103
 
2105
- # Direct-loaded: Clinical procedure from git
2106
- scid_node = Ontology(
2107
- name="scid-5-f1",
2108
- uri="git://bwolfson-siggie/Siggy-MVP/ontology/procedures/scid-5/module-f/scid-5-f1.md",
2109
- content="# scid-5-f1: Panic Attack Screening\n\n...",
2104
+ # Direct-loaded: Technical spec from git
2105
+ config_spec = Ontology(
2106
+ name="config-schema",
2107
+ uri="git://example-org/docs/specs/config-schema.md",
2108
+ content="# Configuration Schema\n\nThis document defines...",
2110
2109
  extracted_data={
2111
- "type": "procedure",
2112
- "module": "F",
2113
- "section": "Panic Disorder",
2114
- "dsm5_criterion": "Panic Attack Specifier",
2110
+ "type": "specification",
2111
+ "format": "yaml",
2112
+ "version": "1.0",
2115
2113
  },
2116
- tags=["scid-5", "procedure", "anxiety"]
2114
+ tags=["config", "schema", "specification"]
2117
2115
  )
2118
2116
 
2119
2117
 
@@ -2227,7 +2225,7 @@ This schema includes the `search_rem` tool which supports:
2227
2225
  - **Optional**
2228
2226
 
2229
2227
  ',
2230
- '{"type": "object", "description": "Domain-specific knowledge - either agent-extracted or direct-loaded.\n\n Attributes:\n name: Human-readable label for this ontology instance\n uri: External source reference (git://, s3://, https://) for direct-loaded ontologies\n file_id: Foreign key to File entity (optional - only for agent-extracted)\n agent_schema_id: Schema that performed extraction (optional - only for agent-extracted)\n provider_name: LLM provider used for extraction (optional)\n model_name: Specific model used (optional)\n extracted_data: Structured data - either extracted by agent or parsed from source\n confidence_score: Optional confidence score from extraction (0.0-1.0)\n extraction_timestamp: When extraction was performed\n content: Text used for generating embedding\n\n Inherited from CoreModel:\n id: UUID or string identifier\n created_at: Entity creation timestamp\n updated_at: Last update timestamp\n deleted_at: Soft deletion timestamp\n tenant_id: Multi-tenancy isolation\n user_id: Ownership\n graph_edges: Relationships to other entities\n metadata: Flexible metadata storage\n tags: Classification tags\n\n Example Usage:\n # Agent-extracted: CV parsing\n cv_ontology = Ontology(\n name=\"john-doe-cv-2024\",\n file_id=\"file-uuid-123\",\n agent_schema_id=\"cv-parser-v1\",\n provider_name=\"anthropic\",\n model_name=\"claude-sonnet-4-5-20250929\",\n extracted_data={\n \"candidate_name\": \"John Doe\",\n \"skills\": [\"Python\", \"PostgreSQL\", \"Kubernetes\"],\n },\n confidence_score=0.95,\n tags=[\"cv\", \"engineering\"]\n )\n\n # Direct-loaded: Medical knowledge base from git\n disorder_ontology = Ontology(\n name=\"panic-disorder\",\n uri=\"git://bwolfson-siggie/Siggy-MVP/ontology/disorders/anxiety/panic-disorder.md\",\n content=\"# Panic Disorder\\n\\nPanic disorder is characterized by...\",\n extracted_data={\n \"type\": \"disorder\",\n \"category\": \"anxiety\",\n \"icd10\": \"F41.0\",\n \"dsm5_criteria\": [\"A\", \"B\", \"C\", \"D\"],\n },\n tags=[\"disorder\", \"anxiety\", \"dsm5\"]\n )\n\n # Direct-loaded: Clinical procedure from git\n scid_node = Ontology(\n name=\"scid-5-f1\",\n uri=\"git://bwolfson-siggie/Siggy-MVP/ontology/procedures/scid-5/module-f/scid-5-f1.md\",\n content=\"# scid-5-f1: Panic Attack Screening\\n\\n...\",\n extracted_data={\n \"type\": \"procedure\",\n \"module\": \"F\",\n \"section\": \"Panic Disorder\",\n \"dsm5_criterion\": \"Panic Attack Specifier\",\n },\n tags=[\"scid-5\", \"procedure\", \"anxiety\"]\n )\n \n\nThis agent can search the `ontologies` table using the `search_rem` tool. Use REM query syntax: LOOKUP for exact match, FUZZY for typo-tolerant search, SEARCH for semantic similarity, or SQL for complex queries.", "properties": {"id": {"anyOf": [{"format": "uuid", "type": "string"}, {"type": "string"}, {"type": "null"}], "default": null, "description": "Unique identifier (UUID or string, generated per model type). Generated automatically if not provided.", "title": "Id"}, "created_at": {"description": "Entity creation timestamp", "format": "date-time", "title": "Created At", "type": "string"}, "updated_at": {"description": "Last update timestamp", "format": "date-time", "title": "Updated At", "type": "string"}, "deleted_at": {"anyOf": [{"format": "date-time", "type": "string"}, {"type": "null"}], "default": null, "description": "Soft deletion timestamp", "title": "Deleted At"}, "tenant_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Tenant identifier for multi-tenancy isolation", "title": "Tenant Id"}, "user_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Owner user identifier (tenant-scoped). This is a VARCHAR(256), not a UUID, to allow flexibility for external identity providers. Typically generated as a hash of the user''s email address. In future, other strong unique claims (e.g., OAuth sub, verified phone) could also be used for generation.", "title": "User Id"}, "graph_edges": {"description": "Knowledge graph edges stored as InlineEdge dicts", "items": {"additionalProperties": true, "type": "object"}, "title": "Graph Edges", "type": "array"}, "metadata": {"additionalProperties": true, "description": "Flexible metadata storage", "title": "Metadata", "type": "object"}, "tags": {"description": "Entity tags", "items": {"type": "string"}, "title": "Tags", "type": "array"}, "name": {"title": "Name", "type": "string"}, "uri": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Uri"}, "file_id": {"anyOf": [{"format": "uuid", "type": "string"}, {"type": "string"}, {"type": "null"}], "default": null, "title": "File Id"}, "agent_schema_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Agent Schema Id"}, "provider_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Provider Name"}, "model_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Model Name"}, "extracted_data": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "default": null, "title": "Extracted Data"}, "confidence_score": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": null, "title": "Confidence Score"}, "extraction_timestamp": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Extraction Timestamp"}, "content": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Content"}}, "required": ["name"], "json_schema_extra": {"table_name": "ontologies", "entity_key_field": "name", "embedding_fields": ["content"], "fully_qualified_name": "rem.models.entities.ontology.Ontology", "tools": ["search_rem"], "default_search_table": "ontologies", "has_embeddings": true}}'::jsonb,
2228
+ '{"type": "object", "description": "Domain-specific knowledge - either agent-extracted or direct-loaded.\n\n Attributes:\n name: Human-readable label for this ontology instance\n uri: External source reference (git://, s3://, https://) for direct-loaded ontologies\n file_id: Foreign key to File entity (optional - only for agent-extracted)\n agent_schema_id: Schema that performed extraction (optional - only for agent-extracted)\n provider_name: LLM provider used for extraction (optional)\n model_name: Specific model used (optional)\n extracted_data: Structured data - either extracted by agent or parsed from source\n confidence_score: Optional confidence score from extraction (0.0-1.0)\n extraction_timestamp: When extraction was performed\n content: Text used for generating embedding\n\n Inherited from CoreModel:\n id: UUID or string identifier\n created_at: Entity creation timestamp\n updated_at: Last update timestamp\n deleted_at: Soft deletion timestamp\n tenant_id: Multi-tenancy isolation\n user_id: Ownership\n graph_edges: Relationships to other entities\n metadata: Flexible metadata storage\n tags: Classification tags\n\n Example Usage:\n # Agent-extracted: CV parsing\n cv_ontology = Ontology(\n name=\"john-doe-cv-2024\",\n file_id=\"file-uuid-123\",\n agent_schema_id=\"cv-parser-v1\",\n provider_name=\"anthropic\",\n model_name=\"claude-sonnet-4-5-20250929\",\n extracted_data={\n \"candidate_name\": \"John Doe\",\n \"skills\": [\"Python\", \"PostgreSQL\", \"Kubernetes\"],\n },\n confidence_score=0.95,\n tags=[\"cv\", \"engineering\"]\n )\n\n # Direct-loaded: Knowledge base from git\n api_docs = Ontology(\n name=\"rest-api-guide\",\n uri=\"git://example-org/docs/api/rest-api-guide.md\",\n content=\"# REST API Guide\\n\\nThis guide covers RESTful API design...\",\n extracted_data={\n \"type\": \"documentation\",\n \"category\": \"api\",\n \"version\": \"2.0\",\n },\n tags=[\"api\", \"rest\", \"documentation\"]\n )\n\n # Direct-loaded: Technical spec from git\n config_spec = Ontology(\n name=\"config-schema\",\n uri=\"git://example-org/docs/specs/config-schema.md\",\n content=\"# Configuration Schema\\n\\nThis document defines...\",\n extracted_data={\n \"type\": \"specification\",\n \"format\": \"yaml\",\n \"version\": \"1.0\",\n },\n tags=[\"config\", \"schema\", \"specification\"]\n )\n \n\nThis agent can search the `ontologies` table using the `search_rem` tool. Use REM query syntax: LOOKUP for exact match, FUZZY for typo-tolerant search, SEARCH for semantic similarity, or SQL for complex queries.", "properties": {"id": {"anyOf": [{"format": "uuid", "type": "string"}, {"type": "string"}, {"type": "null"}], "default": null, "description": "Unique identifier (UUID or string, generated per model type). Generated automatically if not provided.", "title": "Id"}, "created_at": {"description": "Entity creation timestamp", "format": "date-time", "title": "Created At", "type": "string"}, "updated_at": {"description": "Last update timestamp", "format": "date-time", "title": "Updated At", "type": "string"}, "deleted_at": {"anyOf": [{"format": "date-time", "type": "string"}, {"type": "null"}], "default": null, "description": "Soft deletion timestamp", "title": "Deleted At"}, "tenant_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Tenant identifier for multi-tenancy isolation", "title": "Tenant Id"}, "user_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "description": "Owner user identifier (tenant-scoped). This is a VARCHAR(256), not a UUID, to allow flexibility for external identity providers. Typically generated as a hash of the user''s email address. In future, other strong unique claims (e.g., OAuth sub, verified phone) could also be used for generation.", "title": "User Id"}, "graph_edges": {"description": "Knowledge graph edges stored as InlineEdge dicts", "items": {"additionalProperties": true, "type": "object"}, "title": "Graph Edges", "type": "array"}, "metadata": {"additionalProperties": true, "description": "Flexible metadata storage", "title": "Metadata", "type": "object"}, "tags": {"description": "Entity tags", "items": {"type": "string"}, "title": "Tags", "type": "array"}, "name": {"title": "Name", "type": "string"}, "uri": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Uri"}, "file_id": {"anyOf": [{"format": "uuid", "type": "string"}, {"type": "string"}, {"type": "null"}], "default": null, "title": "File Id"}, "agent_schema_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Agent Schema Id"}, "provider_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Provider Name"}, "model_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Model Name"}, "extracted_data": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "default": null, "title": "Extracted Data"}, "confidence_score": {"anyOf": [{"type": "number"}, {"type": "null"}], "default": null, "title": "Confidence Score"}, "extraction_timestamp": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Extraction Timestamp"}, "content": {"anyOf": [{"type": "string"}, {"type": "null"}], "default": null, "title": "Content"}}, "required": ["name"], "json_schema_extra": {"table_name": "ontologies", "entity_key_field": "name", "embedding_fields": ["content"], "fully_qualified_name": "rem.models.entities.ontology.Ontology", "tools": ["search_rem"], "default_search_table": "ontologies", "has_embeddings": true}}'::jsonb,
2231
2229
  'entity',
2232
2230
  '{"table_name": "ontologies", "entity_key_field": "name", "embedding_fields": ["content"], "fqn": "rem.models.entities.ontology.Ontology"}'::jsonb
2233
2231
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: remdb
3
- Version: 0.3.200
3
+ Version: 0.3.202
4
4
  Summary: Resources Entities Moments - Bio-inspired memory system for agentic AI workloads
5
5
  Project-URL: Homepage, https://github.com/Percolation-Labs/reminiscent
6
6
  Project-URL: Documentation, https://github.com/Percolation-Labs/reminiscent/blob/main/README.md
@@ -34,7 +34,7 @@ rem/api/mcp_router/server.py,sha256=06yqR7CBAcmMqHJyUpndQXXYCnu42M5Uen3Oh4mnMVI,
34
34
  rem/api/mcp_router/tools.py,sha256=PaDDPRHKg8TYTFHnQi1a74pKlijEmW63gx367hgo2Bk,51337
35
35
  rem/api/middleware/tracking.py,sha256=ZlFkCVsmIfGuiRX1PPWN0vEIPZoOFIKqMZ3P-CjwfHc,6453
36
36
  rem/api/routers/admin.py,sha256=AEvfi5QyfTG_3a8LZ5FPgbOXPajKeIu_5P6oqmLYa1E,14696
37
- rem/api/routers/auth.py,sha256=U42HaghPwyT--yTWHplAFmZbwkwXHpkaTo9Y4LQ0DDE,23168
37
+ rem/api/routers/auth.py,sha256=onNJngduQm3KxezjtVpDoSqhic46lajk8jBYf17tOUc,24868
38
38
  rem/api/routers/dev.py,sha256=rLySeGas9USZxMxJiHU4ziaA8EK9aoc8dg7TpJagV-I,2229
39
39
  rem/api/routers/feedback.py,sha256=UfDQlqeRwB1b4Q0agJOBahiAHL_aAHMb_l7TEjwZuGs,11378
40
40
  rem/api/routers/messages.py,sha256=t9OsCMZs0RCrGySXiG_0gjhpOWiPy7z5lh6oi0vQw6M,18728
@@ -50,7 +50,7 @@ rem/api/routers/chat/sse_events.py,sha256=yiwhuG2Fx0-iJwNIFbVDDNj6UpF_MjBMuX_16V
50
50
  rem/api/routers/chat/streaming.py,sha256=ExGS94-GAJwF58jbUKOUgt9l97nKmtd9d1L5tcfU9RQ,47871
51
51
  rem/auth/README.md,sha256=BpZUqEVYMUpQG4guykyuvmtzlH3_LsGzspuRZS20i8k,8631
52
52
  rem/auth/__init__.py,sha256=ebS-_x21TZsgq7QVgziUpXagSVQU5y0kIxqc_ZywzCE,1027
53
- rem/auth/jwt.py,sha256=hKO8DeNZohqBiS8F7ZVOnlg-IF0SrGZ7cWMdC0a9jTE,10997
53
+ rem/auth/jwt.py,sha256=VT77nTYqCt4tkbd_ZmXQy9wU3LcjQ8WLqm9sEcYLYLs,11600
54
54
  rem/auth/middleware.py,sha256=LuEVtl2umRqeh2gp3vPrrDHtiELghkgho9hflXRaOkc,11740
55
55
  rem/auth/providers/__init__.py,sha256=yWurO-3o0fT_XIVcIyDX-ECx37jVn5g0pvOxcsU4Q3k,429
56
56
  rem/auth/providers/base.py,sha256=wa7lrgM0AetZnITc45QFyiNHXgVVoWmZgW9tBpInDLw,11831
@@ -88,7 +88,7 @@ rem/models/entities/file.py,sha256=plUm0Caww_yNrpgnOkGp3RBv4l9I6szGOe-NuAuWCcg,1
88
88
  rem/models/entities/image_resource.py,sha256=FIZbGVgsroHY47ESbFIjy0sOtgM8w6vHPUk9lJSVJz4,3254
89
89
  rem/models/entities/message.py,sha256=KHHDBKs_UsWQ-0LURRQlDTV_iiUozmERMBWLPlHPbgg,1966
90
90
  rem/models/entities/moment.py,sha256=sTRFShQwgJMez9OcU7-Vs6k-Whof2TuZCVjdUSyVjVY,4434
91
- rem/models/entities/ontology.py,sha256=bvUBTlg4fQ0mWtiSEggeri3he5BqwYXF_TpuYmzCKxI,7584
91
+ rem/models/entities/ontology.py,sha256=1K9rNZ32BjS24tmjYN89zW81kFVw2vAfcY24ldJqY-I,7398
92
92
  rem/models/entities/ontology_config.py,sha256=fe-LLM-AaKznVoQ02ou2GvPSAp_Bwez0rk3H0RIUYTw,5055
93
93
  rem/models/entities/resource.py,sha256=FW7R_AylZilb-1iYfZA5MMQw2zA42CUVweKgO-4cwqM,3407
94
94
  rem/models/entities/schema.py,sha256=CEcd49kR_6YgaLLKsWaIb2J0KdbVsgYoi_srPgzr9Aw,2945
@@ -185,12 +185,12 @@ rem/services/rem/query.py,sha256=z4Qcaed1mPG2p-4pazEUlnUFqOEYxrKGYLffwD2-V-c,121
185
185
  rem/services/rem/service.py,sha256=cYPPCZ90S9QRWi_4JxEe9oybdDM8Is7wgYt8EpLoiVY,21093
186
186
  rem/services/session/README.md,sha256=WDoVWMRXrSh6wRSlUQ0oIHUItOol65INl86VCNPUOYQ,10446
187
187
  rem/services/session/__init__.py,sha256=htT9QvxtfeSJ5ExTPheQhTlrB77e4XSJ3e_PUhYU250,365
188
- rem/services/session/compression.py,sha256=8PTGqJ9G4AJaMHzJL5BbVMz_okFSqWbRI3TSHCRYriU,17079
188
+ rem/services/session/compression.py,sha256=uxXOA5pwN1fg49C8aaQmJI41JayfpNqvXopnFgldqC8,18530
189
189
  rem/services/session/pydantic_messages.py,sha256=KaU8Tgp7qzBNrq98Dr65poZW_IEaD6223ZYMVTmxPJs,8412
190
190
  rem/services/session/reload.py,sha256=qbs9yYYBaEH0n_XN_A4BqHcB0RIX_JMkZjHNzUR6zY4,2805
191
191
  rem/sql/background_indexes.sql,sha256=wbQMtgap247K29w24aPPHhhF0tdcFuZ2nCWyALh51DM,1985
192
- rem/sql/migrations/001_install.sql,sha256=IgER5B4AlCFwSp-PKNLSlE0UAILq2jMunGCPpOqu-ME,35080
193
- rem/sql/migrations/002_install_models.sql,sha256=Z9XrAm3t4yoeySLDeFt8H9Xnz2gEhTse27gAZhArJSg,154154
192
+ rem/sql/migrations/001_install.sql,sha256=FfJjt7HqC9BPQSdyVOWT51Cv9OuybFPCGlmpoTCaG7k,35567
193
+ rem/sql/migrations/002_install_models.sql,sha256=bxb35SX4KZ9qLAlQrKf35R82F3jWiqmVyeuvDRlXUeA,153766
194
194
  rem/sql/migrations/003_optional_extensions.sql,sha256=QACy3J50ZgV_4BHNkkT3iswkE1ijc0oCAOgavv6KC5g,12443
195
195
  rem/sql/migrations/004_cache_system.sql,sha256=iUMRj4r45EhI2kKABp9PS9i_Bs16715HG2ovbYMOsgc,10571
196
196
  rem/sql/migrations/005_schema_update.sql,sha256=fVcuUt0I24UXMEWA25TM-kN29GC19IAqxlxFP-3Z2ys,5055
@@ -224,7 +224,7 @@ rem/workers/dreaming.py,sha256=UqCf-iBUhzBVBRFj7_DtR6q27oRo7EUoal9qqHLzlo4,17823
224
224
  rem/workers/engram_processor.py,sha256=Ws92kAILMLK_np3F1HRmhKKXiruLIvFn3o9MY3V2W8g,10779
225
225
  rem/workers/sqs_file_processor.py,sha256=tX8S0yo2n1XGvaZ7JUqeGmtTwxybQqz3wkHT2j6Ak7Y,6597
226
226
  rem/workers/unlogged_maintainer.py,sha256=KhebhXl3s6DwvHnXXEJ45r5tLK9PNj-0KclNIQVQ68s,15817
227
- remdb-0.3.200.dist-info/METADATA,sha256=zy9cTdFoqAF1NthL6VS0XcgaRtpoSpXOqHXxdqvxeVw,53341
228
- remdb-0.3.200.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
229
- remdb-0.3.200.dist-info/entry_points.txt,sha256=gmmrz7tRC1WGUrCMJMg6p5pEP5h5mPYRvWIxp1FYdr0,42
230
- remdb-0.3.200.dist-info/RECORD,,
227
+ remdb-0.3.202.dist-info/METADATA,sha256=_r_Mo484kcAAZW2uqAgbV5LyE7YoskzzAOEiIed6ZWM,53341
228
+ remdb-0.3.202.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
229
+ remdb-0.3.202.dist-info/entry_points.txt,sha256=gmmrz7tRC1WGUrCMJMg6p5pEP5h5mPYRvWIxp1FYdr0,42
230
+ remdb-0.3.202.dist-info/RECORD,,