remdb 0.3.0__py3-none-any.whl → 0.3.127__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 (106) hide show
  1. rem/__init__.py +129 -2
  2. rem/agentic/README.md +76 -0
  3. rem/agentic/__init__.py +15 -0
  4. rem/agentic/agents/__init__.py +16 -2
  5. rem/agentic/agents/sse_simulator.py +502 -0
  6. rem/agentic/context.py +51 -25
  7. rem/agentic/llm_provider_models.py +301 -0
  8. rem/agentic/mcp/tool_wrapper.py +29 -3
  9. rem/agentic/otel/setup.py +93 -4
  10. rem/agentic/providers/phoenix.py +32 -43
  11. rem/agentic/providers/pydantic_ai.py +168 -24
  12. rem/agentic/schema.py +358 -21
  13. rem/agentic/tools/rem_tools.py +3 -3
  14. rem/api/README.md +238 -1
  15. rem/api/deps.py +255 -0
  16. rem/api/main.py +154 -37
  17. rem/api/mcp_router/resources.py +1 -1
  18. rem/api/mcp_router/server.py +26 -5
  19. rem/api/mcp_router/tools.py +465 -7
  20. rem/api/middleware/tracking.py +172 -0
  21. rem/api/routers/admin.py +494 -0
  22. rem/api/routers/auth.py +124 -0
  23. rem/api/routers/chat/completions.py +402 -20
  24. rem/api/routers/chat/models.py +88 -10
  25. rem/api/routers/chat/otel_utils.py +33 -0
  26. rem/api/routers/chat/sse_events.py +542 -0
  27. rem/api/routers/chat/streaming.py +642 -45
  28. rem/api/routers/dev.py +81 -0
  29. rem/api/routers/feedback.py +268 -0
  30. rem/api/routers/messages.py +473 -0
  31. rem/api/routers/models.py +78 -0
  32. rem/api/routers/query.py +360 -0
  33. rem/api/routers/shared_sessions.py +406 -0
  34. rem/auth/middleware.py +126 -27
  35. rem/cli/commands/README.md +237 -64
  36. rem/cli/commands/ask.py +13 -10
  37. rem/cli/commands/cluster.py +1808 -0
  38. rem/cli/commands/configure.py +5 -6
  39. rem/cli/commands/db.py +396 -139
  40. rem/cli/commands/experiments.py +293 -73
  41. rem/cli/commands/process.py +22 -15
  42. rem/cli/commands/scaffold.py +47 -0
  43. rem/cli/commands/schema.py +97 -50
  44. rem/cli/main.py +29 -6
  45. rem/config.py +10 -3
  46. rem/models/core/core_model.py +7 -1
  47. rem/models/core/rem_query.py +5 -2
  48. rem/models/entities/__init__.py +21 -0
  49. rem/models/entities/domain_resource.py +38 -0
  50. rem/models/entities/feedback.py +123 -0
  51. rem/models/entities/message.py +30 -1
  52. rem/models/entities/session.py +83 -0
  53. rem/models/entities/shared_session.py +180 -0
  54. rem/models/entities/user.py +10 -3
  55. rem/registry.py +373 -0
  56. rem/schemas/agents/rem.yaml +7 -3
  57. rem/services/content/providers.py +94 -140
  58. rem/services/content/service.py +92 -20
  59. rem/services/dreaming/affinity_service.py +2 -16
  60. rem/services/dreaming/moment_service.py +2 -15
  61. rem/services/embeddings/api.py +24 -17
  62. rem/services/embeddings/worker.py +16 -16
  63. rem/services/phoenix/EXPERIMENT_DESIGN.md +3 -3
  64. rem/services/phoenix/client.py +302 -28
  65. rem/services/postgres/README.md +159 -15
  66. rem/services/postgres/__init__.py +2 -1
  67. rem/services/postgres/diff_service.py +531 -0
  68. rem/services/postgres/pydantic_to_sqlalchemy.py +427 -129
  69. rem/services/postgres/repository.py +132 -0
  70. rem/services/postgres/schema_generator.py +291 -9
  71. rem/services/postgres/service.py +6 -6
  72. rem/services/rate_limit.py +113 -0
  73. rem/services/rem/README.md +14 -0
  74. rem/services/rem/parser.py +44 -9
  75. rem/services/rem/service.py +36 -2
  76. rem/services/session/compression.py +24 -1
  77. rem/services/session/reload.py +1 -1
  78. rem/services/user_service.py +98 -0
  79. rem/settings.py +313 -29
  80. rem/sql/background_indexes.sql +21 -16
  81. rem/sql/migrations/001_install.sql +387 -54
  82. rem/sql/migrations/002_install_models.sql +2320 -393
  83. rem/sql/migrations/003_optional_extensions.sql +326 -0
  84. rem/sql/migrations/004_cache_system.sql +548 -0
  85. rem/utils/__init__.py +18 -0
  86. rem/utils/constants.py +97 -0
  87. rem/utils/date_utils.py +228 -0
  88. rem/utils/embeddings.py +17 -4
  89. rem/utils/files.py +167 -0
  90. rem/utils/mime_types.py +158 -0
  91. rem/utils/model_helpers.py +156 -1
  92. rem/utils/schema_loader.py +282 -35
  93. rem/utils/sql_paths.py +146 -0
  94. rem/utils/sql_types.py +3 -1
  95. rem/utils/vision.py +9 -14
  96. rem/workers/README.md +14 -14
  97. rem/workers/__init__.py +3 -1
  98. rem/workers/db_listener.py +579 -0
  99. rem/workers/db_maintainer.py +74 -0
  100. rem/workers/unlogged_maintainer.py +463 -0
  101. {remdb-0.3.0.dist-info → remdb-0.3.127.dist-info}/METADATA +464 -289
  102. {remdb-0.3.0.dist-info → remdb-0.3.127.dist-info}/RECORD +104 -73
  103. {remdb-0.3.0.dist-info → remdb-0.3.127.dist-info}/WHEEL +1 -1
  104. rem/sql/002_install_models.sql +0 -1068
  105. rem/sql/install_models.sql +0 -1038
  106. {remdb-0.3.0.dist-info → remdb-0.3.127.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,191 @@
1
1
  # REM CLI Commands
2
2
 
3
+ ## Database Management (`rem db`)
4
+
5
+ REM uses a **code-as-source-of-truth** approach to database schema management. Pydantic models define the schema, and the database is kept in sync via diff-based migrations.
6
+
7
+ ### Quick Reference
8
+
9
+ ```bash
10
+ rem db schema generate # Regenerate schema SQL from registered models
11
+ rem db diff # Compare models vs database (detect drift)
12
+ rem db diff --check # CI mode: exit 1 if drift detected
13
+ rem db apply <file> # Apply SQL file to database
14
+ ```
15
+
16
+ ### Schema Management Workflow
17
+
18
+ ```
19
+ ┌─────────────────────────────────────────────────────────────┐
20
+ │ Source of Truth │
21
+ │ │
22
+ │ Pydantic Models (CoreModel subclasses) │
23
+ │ └── src/rem/models/entities/*.py │
24
+ │ │
25
+ │ Model Registry │
26
+ │ └── Core models auto-registered │
27
+ │ └── Custom models via @rem.register_model │
28
+ └─────────────────────────────────────────────────────────────┘
29
+
30
+
31
+ ┌─────────────────────────────────────────────────────────────┐
32
+ │ rem db schema generate │
33
+ │ │
34
+ │ Generates SQL from registry → 002_install_models.sql │
35
+ └─────────────────────────────────────────────────────────────┘
36
+
37
+
38
+ ┌─────────────────────────────────────────────────────────────┐
39
+ │ rem db diff │
40
+ │ │
41
+ │ Compares models ↔ database using Alembic autogenerate │
42
+ │ Shows: + additions, - removals, ~ modifications │
43
+ └─────────────────────────────────────────────────────────────┘
44
+
45
+
46
+ ┌─────────────────────────────────────────────────────────────┐
47
+ │ rem db apply │
48
+ │ │
49
+ │ Executes SQL directly against database │
50
+ │ Optionally logs to rem_migrations (audit only) │
51
+ └─────────────────────────────────────────────────────────────┘
52
+ ```
53
+
54
+ ### File Structure
55
+
56
+ ```
57
+ src/rem/sql/
58
+ ├── migrations/
59
+ │ ├── 001_install.sql # Core infrastructure (manual)
60
+ │ └── 002_install_models.sql # Entity tables (auto-generated)
61
+ └── background_indexes.sql # HNSW vector indexes (optional)
62
+ ```
63
+
64
+ **Key principle**: Only two migration files. No incremental `003_`, `004_` files. The models file is always regenerated to match code.
65
+
66
+ ### Commands
67
+
68
+ #### `rem db schema generate`
69
+
70
+ Regenerate `002_install_models.sql` from the model registry:
71
+
72
+ ```bash
73
+ rem db schema generate
74
+ ```
75
+
76
+ This reads all registered models (core + custom) and generates:
77
+ - CREATE TABLE statements for each entity
78
+ - Embeddings tables (`embeddings_<table>`)
79
+ - KV_STORE triggers for cache maintenance
80
+ - Foreground indexes (GIN for JSONB, B-tree for lookups)
81
+
82
+ #### `rem db diff`
83
+
84
+ Compare Pydantic models against the live database:
85
+
86
+ ```bash
87
+ # Show differences
88
+ rem db diff
89
+
90
+ # CI mode: exit 1 if drift detected
91
+ rem db diff --check
92
+ ```
93
+
94
+ Output shows:
95
+ - `+ ADD COLUMN` - Column exists in model but not in DB
96
+ - `- DROP COLUMN` - Column exists in DB but not in model
97
+ - `~ ALTER COLUMN` - Column type or constraints differ
98
+ - `+ CREATE TABLE` - Table exists in model but not in DB
99
+ - `- DROP TABLE` - Table exists in DB but not in model
100
+
101
+ #### `rem db apply`
102
+
103
+ Apply a SQL file directly to the database:
104
+
105
+ ```bash
106
+ # Apply with audit logging (default)
107
+ rem db apply src/rem/sql/migrations/002_install_models.sql
108
+
109
+ # Preview without executing
110
+ rem db apply --dry-run src/rem/sql/migrations/002_install_models.sql
111
+
112
+ # Apply without logging to rem_migrations
113
+ rem db apply --no-log src/rem/sql/migrations/002_install_models.sql
114
+ ```
115
+
116
+ ### Typical Workflows
117
+
118
+ #### Initial Setup
119
+
120
+ ```bash
121
+ # 1. Generate schema from models
122
+ rem db schema generate
123
+
124
+ # 2. Apply infrastructure (extensions, kv_store)
125
+ rem db apply src/rem/sql/migrations/001_install.sql
126
+
127
+ # 3. Apply entity tables
128
+ rem db apply src/rem/sql/migrations/002_install_models.sql
129
+
130
+ # 4. Verify no drift
131
+ rem db diff
132
+ ```
133
+
134
+ #### Adding a New Entity
135
+
136
+ ```bash
137
+ # 1. Create model in src/rem/models/entities/
138
+ # 2. Register in src/rem/registry.py (add to core_models list)
139
+ # 3. Regenerate schema
140
+ rem db schema generate
141
+
142
+ # 4. Check what changed
143
+ rem db diff
144
+
145
+ # 5. Apply changes
146
+ rem db apply src/rem/sql/migrations/002_install_models.sql
147
+ ```
148
+
149
+ #### Modifying an Existing Entity
150
+
151
+ ```bash
152
+ # 1. Modify model in src/rem/models/entities/
153
+ # 2. Regenerate schema
154
+ rem db schema generate
155
+
156
+ # 3. Check what changed
157
+ rem db diff
158
+
159
+ # 4. Apply changes (idempotent - uses IF NOT EXISTS)
160
+ rem db apply src/rem/sql/migrations/002_install_models.sql
161
+ ```
162
+
163
+ #### CI/CD Pipeline
164
+
165
+ ```bash
166
+ # Fail build if schema drift detected
167
+ rem db diff --check
168
+ ```
169
+
170
+ ### Registering Custom Models
171
+
172
+ ```python
173
+ import rem
174
+ from rem.models.core import CoreModel
175
+
176
+ @rem.register_model
177
+ class MyEntity(CoreModel):
178
+ name: str
179
+ description: str # Auto-embeds (content field)
180
+
181
+ # Or with options:
182
+ @rem.register_model(table_name="custom_table")
183
+ class AnotherEntity(CoreModel):
184
+ title: str
185
+ ```
186
+
187
+ ---
188
+
3
189
  ## Configuration (`rem configure`)
4
190
 
5
191
  Interactive configuration wizard for REM setup.
@@ -13,114 +199,101 @@ rem configure
13
199
  # Configure + install database tables
14
200
  rem configure --install
15
201
 
16
- # Configure + install + register with Claude Desktop
17
- rem configure --install --claude-desktop
18
- ```
19
-
20
- ### Managing Configuration
21
-
22
- ```bash
23
202
  # View current configuration
24
203
  rem configure --show
25
204
 
26
205
  # Edit configuration file
27
- rem configure --edit # Opens in $EDITOR (defaults to vim)
28
-
29
- # Or edit manually
30
- vim ~/.rem/config.yaml
206
+ rem configure --edit
31
207
  ```
32
208
 
33
- ### Configuration File Structure
209
+ ### Configuration File
34
210
 
35
211
  `~/.rem/config.yaml`:
36
212
 
37
213
  ```yaml
38
214
  postgres:
39
215
  connection_string: postgresql://user:pass@localhost:5432/rem
40
- pool_min_size: 5
41
- pool_max_size: 20
42
216
 
43
217
  llm:
44
218
  default_model: anthropic:claude-sonnet-4-5-20250929
45
- default_temperature: 0.5
46
219
  openai_api_key: sk-...
47
220
  anthropic_api_key: sk-ant-...
48
221
 
49
222
  s3:
50
223
  bucket_name: rem-storage
51
224
  region: us-east-1
52
- # Optional: for MinIO/LocalStack
53
- endpoint_url: http://localhost:9000
54
- access_key_id: minioadmin
55
- secret_access_key: minioadmin
56
225
  ```
57
226
 
58
227
  ### Environment Variables
59
228
 
60
- All configuration can be overridden via environment variables using double underscore delimiter:
229
+ All configuration can be overridden via environment variables:
61
230
 
62
231
  ```bash
63
- # Postgres
64
232
  export POSTGRES__CONNECTION_STRING=postgresql://user:pass@host:5432/db
65
- export POSTGRES__POOL_MIN_SIZE=5
66
- export POSTGRES__POOL_MAX_SIZE=20
67
-
68
- # LLM
69
233
  export LLM__DEFAULT_MODEL=anthropic:claude-sonnet-4-5-20250929
70
234
  export LLM__OPENAI_API_KEY=sk-...
71
- export LLM__ANTHROPIC_API_KEY=sk-ant-...
72
-
73
- # S3
74
- export S3__BUCKET_NAME=rem-storage
75
- export S3__REGION=us-east-1
76
235
  ```
77
236
 
78
- ### Configuration Precedence
237
+ **Precedence**: Environment variables > Config file > Defaults
79
238
 
80
- 1. **Environment variables** (highest priority)
81
- 2. **Configuration file** (`~/.rem/config.yaml`)
82
- 3. **Default values** (from `rem/settings.py`)
239
+ ---
83
240
 
84
- ### Docker/Kubernetes
241
+ ## Cluster Management (`rem cluster`)
85
242
 
86
- In containerized environments, use environment variables exclusively:
243
+ Commands for deploying REM to Kubernetes.
87
244
 
88
- ```yaml
89
- # docker-compose.yml
90
- services:
91
- rem-api:
92
- image: rem:latest
93
- environment:
94
- POSTGRES__CONNECTION_STRING: postgresql://rem:rem@postgres:5432/rem
95
- LLM__OPENAI_API_KEY: ${OPENAI_API_KEY}
245
+ ### Quick Reference
246
+
247
+ ```bash
248
+ rem cluster init # Initialize cluster config
249
+ rem cluster generate # Generate all manifests (ArgoCD, ConfigMaps, etc.)
250
+ rem cluster setup-ssm # Create required SSM parameters in AWS
251
+ rem cluster validate # Validate deployment prerequisites
252
+ rem cluster env check # Validate .env for cluster deployment
96
253
  ```
97
254
 
98
- ```yaml
99
- # Kubernetes ConfigMap/Secret
100
- apiVersion: v1
101
- kind: Secret
102
- metadata:
103
- name: rem-secrets
104
- stringData:
105
- POSTGRES__CONNECTION_STRING: postgresql://rem:rem@postgres:5432/rem
106
- LLM__OPENAI_API_KEY: sk-...
255
+ ### `rem cluster generate`
256
+
257
+ Generates all Kubernetes manifests from cluster config:
258
+
259
+ ```bash
260
+ rem cluster generate
107
261
  ```
108
262
 
263
+ This generates/updates:
264
+ - ArgoCD Application manifests
265
+ - ClusterSecretStore configurations
266
+ - SQL init ConfigMap (from `rem/sql/migrations/*.sql`)
267
+
268
+ The SQL ConfigMap is used by CloudNativePG for database initialization on first cluster bootstrap.
269
+
270
+ ### `rem cluster env`
271
+
272
+ Environment configuration management:
273
+
274
+ ```bash
275
+ rem cluster env check # Validate .env for staging
276
+ rem cluster env check --env prod # Validate for production
277
+ rem cluster env generate # Generate ConfigMap from .env
278
+ rem cluster env diff # Compare .env with cluster ConfigMap
279
+ ```
280
+
281
+ ---
282
+
109
283
  ## Other Commands
110
284
 
111
- - **`rem ask`** - Interactive chat with REM memory
112
- - **`rem serve`** - Start FastAPI server
113
- - **`rem db`** - Database management (migrate, seed, etc.)
114
- - **`rem schema`** - Schema generation and validation
115
- - **`rem mcp`** - MCP server commands
116
- - **`rem dreaming`** - Background knowledge processing
117
- - **`rem process`** - File processing utilities
118
- - **`rem experiments`** - Experiment management (datasets, prompts, traces, runs)
285
+ | Command | Description |
286
+ |---------|-------------|
287
+ | `rem ask` | Interactive chat with REM agents |
288
+ | `rem serve` | Start FastAPI server |
289
+ | `rem mcp` | MCP server commands |
290
+ | `rem dreaming` | Background knowledge processing |
291
+ | `rem process` | File processing utilities |
119
292
 
120
- Run `rem COMMAND --help` for detailed usage of each command.
293
+ Run `rem COMMAND --help` for detailed usage.
121
294
 
122
295
  ## See Also
123
296
 
124
- - [README.md](../../../../../README.md) - Main documentation
297
+ - [rem/README.md](../../../../../README.md) - Main documentation
125
298
  - [CLAUDE.md](../../../../../CLAUDE.md) - Architecture overview
126
- - [settings.py](../../settings.py) - All available settings
299
+ - [postgres/README.md](../../services/postgres/README.md) - Database service details
rem/cli/commands/ask.py CHANGED
@@ -89,8 +89,8 @@ async def run_agent_streaming(
89
89
  context: Optional AgentContext for session persistence
90
90
  max_iterations: Maximum iterations/requests (from agent schema or settings)
91
91
  """
92
- from datetime import datetime, timezone
93
92
  from pydantic_ai import UsageLimits
93
+ from rem.utils.date_utils import to_iso_with_z, utc_now
94
94
 
95
95
  logger.info("Running agent in streaming mode...")
96
96
 
@@ -151,13 +151,13 @@ async def run_agent_streaming(
151
151
  user_message = {
152
152
  "role": "user",
153
153
  "content": user_message_content,
154
- "timestamp": datetime.now(timezone.utc).isoformat(),
154
+ "timestamp": to_iso_with_z(utc_now()),
155
155
  }
156
156
 
157
157
  assistant_message = {
158
158
  "role": "assistant",
159
159
  "content": "".join(assistant_response_parts),
160
- "timestamp": datetime.now(timezone.utc).isoformat(),
160
+ "timestamp": to_iso_with_z(utc_now()),
161
161
  }
162
162
 
163
163
  # Store messages with compression
@@ -200,8 +200,8 @@ async def run_agent_non_streaming(
200
200
  Returns:
201
201
  Output data if successful, None otherwise
202
202
  """
203
- from datetime import datetime, timezone
204
203
  from pydantic_ai import UsageLimits
204
+ from rem.utils.date_utils import to_iso_with_z, utc_now
205
205
 
206
206
  logger.info("Running agent in non-streaming mode...")
207
207
 
@@ -248,13 +248,13 @@ async def run_agent_non_streaming(
248
248
  user_message = {
249
249
  "role": "user",
250
250
  "content": user_message_content,
251
- "timestamp": datetime.now(timezone.utc).isoformat(),
251
+ "timestamp": to_iso_with_z(utc_now()),
252
252
  }
253
253
 
254
254
  assistant_message = {
255
255
  "role": "assistant",
256
256
  "content": assistant_content,
257
- "timestamp": datetime.now(timezone.utc).isoformat(),
257
+ "timestamp": to_iso_with_z(utc_now()),
258
258
  }
259
259
 
260
260
  # Store messages with compression
@@ -357,8 +357,8 @@ async def _save_output_file(file_path: Path, data: dict[str, Any]) -> None:
357
357
  )
358
358
  @click.option(
359
359
  "--user-id",
360
- default="test-user",
361
- help="User ID for context (default: test-user)",
360
+ default=None,
361
+ help="User ID for context (default: from settings.test.effective_user_id)",
362
362
  )
363
363
  @click.option(
364
364
  "--session-id",
@@ -393,7 +393,7 @@ def ask(
393
393
  max_turns: int,
394
394
  version: str | None,
395
395
  stream: bool,
396
- user_id: str,
396
+ user_id: str | None,
397
397
  session_id: str | None,
398
398
  input_file: Path | None,
399
399
  output_file: Path | None,
@@ -434,6 +434,9 @@ def ask(
434
434
  # Two arguments provided
435
435
  name = name_or_query
436
436
 
437
+ # Resolve user_id from settings if not provided
438
+ effective_user_id = user_id or settings.test.effective_user_id
439
+
437
440
  asyncio.run(
438
441
  _ask_async(
439
442
  name=name,
@@ -443,7 +446,7 @@ def ask(
443
446
  max_turns=max_turns,
444
447
  version=version,
445
448
  stream=stream,
446
- user_id=user_id,
449
+ user_id=effective_user_id,
447
450
  session_id=session_id,
448
451
  input_file=input_file,
449
452
  output_file=output_file,