remdb 0.2.6__py3-none-any.whl → 0.3.118__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/__init__.py +129 -2
- rem/agentic/README.md +76 -0
- rem/agentic/__init__.py +15 -0
- rem/agentic/agents/__init__.py +16 -2
- rem/agentic/agents/sse_simulator.py +500 -0
- rem/agentic/context.py +28 -22
- rem/agentic/llm_provider_models.py +301 -0
- rem/agentic/mcp/tool_wrapper.py +29 -3
- rem/agentic/otel/setup.py +92 -4
- rem/agentic/providers/phoenix.py +32 -43
- rem/agentic/providers/pydantic_ai.py +168 -24
- rem/agentic/schema.py +358 -21
- rem/agentic/tools/rem_tools.py +3 -3
- rem/api/README.md +238 -1
- rem/api/deps.py +255 -0
- rem/api/main.py +154 -37
- rem/api/mcp_router/resources.py +1 -1
- rem/api/mcp_router/server.py +26 -5
- rem/api/mcp_router/tools.py +454 -7
- rem/api/middleware/tracking.py +172 -0
- rem/api/routers/admin.py +494 -0
- rem/api/routers/auth.py +124 -0
- rem/api/routers/chat/completions.py +152 -16
- rem/api/routers/chat/models.py +7 -3
- rem/api/routers/chat/sse_events.py +526 -0
- rem/api/routers/chat/streaming.py +608 -45
- rem/api/routers/dev.py +81 -0
- rem/api/routers/feedback.py +148 -0
- rem/api/routers/messages.py +473 -0
- rem/api/routers/models.py +78 -0
- rem/api/routers/query.py +360 -0
- rem/api/routers/shared_sessions.py +406 -0
- rem/auth/middleware.py +126 -27
- rem/cli/commands/README.md +237 -64
- rem/cli/commands/ask.py +15 -11
- rem/cli/commands/cluster.py +1300 -0
- rem/cli/commands/configure.py +170 -97
- rem/cli/commands/db.py +396 -139
- rem/cli/commands/experiments.py +278 -96
- rem/cli/commands/process.py +22 -15
- rem/cli/commands/scaffold.py +47 -0
- rem/cli/commands/schema.py +97 -50
- rem/cli/main.py +37 -6
- rem/config.py +2 -2
- rem/models/core/core_model.py +7 -1
- rem/models/core/rem_query.py +5 -2
- rem/models/entities/__init__.py +21 -0
- rem/models/entities/domain_resource.py +38 -0
- rem/models/entities/feedback.py +123 -0
- rem/models/entities/message.py +30 -1
- rem/models/entities/session.py +83 -0
- rem/models/entities/shared_session.py +180 -0
- rem/models/entities/user.py +10 -3
- rem/registry.py +373 -0
- rem/schemas/agents/rem.yaml +7 -3
- rem/services/content/providers.py +94 -140
- rem/services/content/service.py +115 -24
- rem/services/dreaming/affinity_service.py +2 -16
- rem/services/dreaming/moment_service.py +2 -15
- rem/services/embeddings/api.py +24 -17
- rem/services/embeddings/worker.py +16 -16
- rem/services/phoenix/EXPERIMENT_DESIGN.md +3 -3
- rem/services/phoenix/client.py +252 -19
- rem/services/postgres/README.md +159 -15
- rem/services/postgres/__init__.py +2 -1
- rem/services/postgres/diff_service.py +531 -0
- rem/services/postgres/pydantic_to_sqlalchemy.py +427 -129
- rem/services/postgres/repository.py +132 -0
- rem/services/postgres/schema_generator.py +291 -9
- rem/services/postgres/service.py +6 -6
- rem/services/rate_limit.py +113 -0
- rem/services/rem/README.md +14 -0
- rem/services/rem/parser.py +44 -9
- rem/services/rem/service.py +36 -2
- rem/services/session/compression.py +17 -1
- rem/services/session/reload.py +1 -1
- rem/services/user_service.py +98 -0
- rem/settings.py +169 -22
- rem/sql/background_indexes.sql +21 -16
- rem/sql/migrations/001_install.sql +387 -54
- rem/sql/migrations/002_install_models.sql +2320 -393
- rem/sql/migrations/003_optional_extensions.sql +326 -0
- rem/sql/migrations/004_cache_system.sql +548 -0
- rem/utils/__init__.py +18 -0
- rem/utils/constants.py +97 -0
- rem/utils/date_utils.py +228 -0
- rem/utils/embeddings.py +17 -4
- rem/utils/files.py +167 -0
- rem/utils/mime_types.py +158 -0
- rem/utils/model_helpers.py +156 -1
- rem/utils/schema_loader.py +284 -21
- rem/utils/sql_paths.py +146 -0
- rem/utils/sql_types.py +3 -1
- rem/utils/vision.py +9 -14
- rem/workers/README.md +14 -14
- rem/workers/__init__.py +2 -1
- rem/workers/db_maintainer.py +74 -0
- rem/workers/unlogged_maintainer.py +463 -0
- {remdb-0.2.6.dist-info → remdb-0.3.118.dist-info}/METADATA +598 -171
- {remdb-0.2.6.dist-info → remdb-0.3.118.dist-info}/RECORD +102 -73
- {remdb-0.2.6.dist-info → remdb-0.3.118.dist-info}/WHEEL +1 -1
- rem/sql/002_install_models.sql +0 -1068
- rem/sql/install_models.sql +0 -1038
- {remdb-0.2.6.dist-info → remdb-0.3.118.dist-info}/entry_points.txt +0 -0
rem/cli/commands/configure.py
CHANGED
|
@@ -28,10 +28,13 @@ from rem.config import (
|
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def prompt_postgres_config() -> dict:
|
|
31
|
+
def prompt_postgres_config(use_defaults: bool = False) -> dict:
|
|
32
32
|
"""
|
|
33
33
|
Prompt user for PostgreSQL configuration.
|
|
34
34
|
|
|
35
|
+
Args:
|
|
36
|
+
use_defaults: If True, use all default values without prompting
|
|
37
|
+
|
|
35
38
|
Returns:
|
|
36
39
|
PostgreSQL configuration dictionary
|
|
37
40
|
"""
|
|
@@ -44,28 +47,45 @@ def prompt_postgres_config() -> dict:
|
|
|
44
47
|
"POSTGRES__CONNECTION_STRING", "postgresql://rem:rem@localhost:5051/rem"
|
|
45
48
|
)
|
|
46
49
|
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
# Default values
|
|
51
|
+
host = "localhost"
|
|
52
|
+
port = 5051
|
|
53
|
+
database = "rem"
|
|
54
|
+
username = "rem"
|
|
55
|
+
password = "rem"
|
|
56
|
+
pool_min_size = 5
|
|
57
|
+
pool_max_size = 20
|
|
58
|
+
|
|
59
|
+
if use_defaults:
|
|
60
|
+
click.echo("\nUsing default PostgreSQL configuration:")
|
|
61
|
+
click.echo(f" Host: {host}")
|
|
62
|
+
click.echo(f" Port: {port}")
|
|
63
|
+
click.echo(f" Database: {database}")
|
|
64
|
+
click.echo(f" Username: {username}")
|
|
65
|
+
click.echo(f" Pool: {pool_min_size}-{pool_max_size} connections")
|
|
66
|
+
else:
|
|
67
|
+
# Prompt for components
|
|
68
|
+
click.echo(
|
|
69
|
+
"\nEnter PostgreSQL connection details (press Enter to use default):"
|
|
70
|
+
)
|
|
71
|
+
click.echo("Default: Package users on port 5051 (docker compose -f docker-compose.prebuilt.yml up -d)")
|
|
72
|
+
click.echo("Developers: Change port to 5050 if using docker-compose.yml (local build)")
|
|
73
|
+
click.echo("Custom DB: Enter your own host/port below")
|
|
54
74
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
75
|
+
host = click.prompt("Host", default=host)
|
|
76
|
+
port = click.prompt("Port", default=port, type=int)
|
|
77
|
+
database = click.prompt("Database name", default=database)
|
|
78
|
+
username = click.prompt("Username", default=username)
|
|
79
|
+
password = click.prompt("Password", default=password, hide_input=True)
|
|
80
|
+
|
|
81
|
+
# Additional pool settings
|
|
82
|
+
click.echo("\nConnection pool settings:")
|
|
83
|
+
pool_min_size = click.prompt("Pool minimum size", default=pool_min_size, type=int)
|
|
84
|
+
pool_max_size = click.prompt("Pool maximum size", default=pool_max_size, type=int)
|
|
60
85
|
|
|
61
86
|
# Build connection string
|
|
62
87
|
connection_string = f"postgresql://{username}:{password}@{host}:{port}/{database}"
|
|
63
88
|
|
|
64
|
-
# Additional pool settings
|
|
65
|
-
click.echo("\nConnection pool settings:")
|
|
66
|
-
pool_min_size = click.prompt("Pool minimum size", default=5, type=int)
|
|
67
|
-
pool_max_size = click.prompt("Pool maximum size", default=20, type=int)
|
|
68
|
-
|
|
69
89
|
return {
|
|
70
90
|
"connection_string": connection_string,
|
|
71
91
|
"pool_min_size": pool_min_size,
|
|
@@ -73,10 +93,13 @@ def prompt_postgres_config() -> dict:
|
|
|
73
93
|
}
|
|
74
94
|
|
|
75
95
|
|
|
76
|
-
def prompt_llm_config() -> dict:
|
|
96
|
+
def prompt_llm_config(use_defaults: bool = False) -> dict:
|
|
77
97
|
"""
|
|
78
98
|
Prompt user for LLM provider configuration.
|
|
79
99
|
|
|
100
|
+
Args:
|
|
101
|
+
use_defaults: If True, use all default values without prompting
|
|
102
|
+
|
|
80
103
|
Returns:
|
|
81
104
|
LLM configuration dictionary
|
|
82
105
|
"""
|
|
@@ -86,40 +109,55 @@ def prompt_llm_config() -> dict:
|
|
|
86
109
|
|
|
87
110
|
config = {}
|
|
88
111
|
|
|
89
|
-
# Default
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
"
|
|
98
|
-
|
|
112
|
+
# Default values
|
|
113
|
+
default_model = "anthropic:claude-sonnet-4-5-20250929"
|
|
114
|
+
default_temperature = 0.5
|
|
115
|
+
|
|
116
|
+
if use_defaults:
|
|
117
|
+
click.echo("\nUsing default LLM configuration:")
|
|
118
|
+
click.echo(f" Model: {default_model}")
|
|
119
|
+
click.echo(f" Temperature: {default_temperature}")
|
|
120
|
+
click.echo(" API Keys: Not configured (set via environment variables)")
|
|
121
|
+
config["default_model"] = default_model
|
|
122
|
+
config["default_temperature"] = default_temperature
|
|
123
|
+
else:
|
|
124
|
+
# Default model
|
|
125
|
+
click.echo("\nDefault LLM model (format: provider:model-id)")
|
|
126
|
+
click.echo("Examples:")
|
|
127
|
+
click.echo(" - anthropic:claude-sonnet-4-5-20250929")
|
|
128
|
+
click.echo(" - openai:gpt-4o")
|
|
129
|
+
click.echo(" - openai:gpt-4o-mini")
|
|
130
|
+
|
|
131
|
+
config["default_model"] = click.prompt(
|
|
132
|
+
"Default model", default=default_model
|
|
133
|
+
)
|
|
99
134
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
135
|
+
# Temperature
|
|
136
|
+
config["default_temperature"] = click.prompt(
|
|
137
|
+
"Default temperature (0.0-1.0)", default=default_temperature, type=float
|
|
138
|
+
)
|
|
104
139
|
|
|
105
|
-
|
|
106
|
-
|
|
140
|
+
# API keys
|
|
141
|
+
click.echo("\nAPI Keys (optional - leave empty to skip):")
|
|
107
142
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
143
|
+
openai_key = click.prompt("OpenAI API key", default="", show_default=False)
|
|
144
|
+
if openai_key:
|
|
145
|
+
config["openai_api_key"] = openai_key
|
|
111
146
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
147
|
+
anthropic_key = click.prompt("Anthropic API key", default="", show_default=False)
|
|
148
|
+
if anthropic_key:
|
|
149
|
+
config["anthropic_api_key"] = anthropic_key
|
|
115
150
|
|
|
116
151
|
return config
|
|
117
152
|
|
|
118
153
|
|
|
119
|
-
def prompt_s3_config() -> dict:
|
|
154
|
+
def prompt_s3_config(use_defaults: bool = False) -> dict:
|
|
120
155
|
"""
|
|
121
156
|
Prompt user for S3 storage configuration.
|
|
122
157
|
|
|
158
|
+
Args:
|
|
159
|
+
use_defaults: If True, skip S3 configuration (optional feature)
|
|
160
|
+
|
|
123
161
|
Returns:
|
|
124
162
|
S3 configuration dictionary
|
|
125
163
|
"""
|
|
@@ -129,8 +167,12 @@ def prompt_s3_config() -> dict:
|
|
|
129
167
|
|
|
130
168
|
config = {}
|
|
131
169
|
|
|
170
|
+
if use_defaults:
|
|
171
|
+
click.echo("\nSkipping S3 configuration (optional - configure later if needed)")
|
|
172
|
+
return {}
|
|
173
|
+
|
|
132
174
|
click.echo("\nS3 storage is used for file uploads and processed content.")
|
|
133
|
-
use_s3 = click.confirm("Configure S3 storage?", default=
|
|
175
|
+
use_s3 = click.confirm("Configure S3 storage?", default=False)
|
|
134
176
|
|
|
135
177
|
if not use_s3:
|
|
136
178
|
return {}
|
|
@@ -154,10 +196,13 @@ def prompt_s3_config() -> dict:
|
|
|
154
196
|
return config
|
|
155
197
|
|
|
156
198
|
|
|
157
|
-
def prompt_additional_env_vars() -> dict:
|
|
199
|
+
def prompt_additional_env_vars(use_defaults: bool = False) -> dict:
|
|
158
200
|
"""
|
|
159
201
|
Prompt user for additional environment variables.
|
|
160
202
|
|
|
203
|
+
Args:
|
|
204
|
+
use_defaults: If True, skip additional env vars (optional feature)
|
|
205
|
+
|
|
161
206
|
Returns:
|
|
162
207
|
Dictionary of custom environment variables
|
|
163
208
|
"""
|
|
@@ -167,6 +212,10 @@ def prompt_additional_env_vars() -> dict:
|
|
|
167
212
|
|
|
168
213
|
env_vars: dict[str, str] = {}
|
|
169
214
|
|
|
215
|
+
if use_defaults:
|
|
216
|
+
click.echo("\nSkipping additional environment variables (configure later if needed)")
|
|
217
|
+
return env_vars
|
|
218
|
+
|
|
170
219
|
add_env = click.confirm(
|
|
171
220
|
"Add custom environment variables?", default=False
|
|
172
221
|
)
|
|
@@ -207,7 +256,13 @@ def prompt_additional_env_vars() -> dict:
|
|
|
207
256
|
is_flag=True,
|
|
208
257
|
help="Open configuration file in editor",
|
|
209
258
|
)
|
|
210
|
-
|
|
259
|
+
@click.option(
|
|
260
|
+
"--yes",
|
|
261
|
+
"-y",
|
|
262
|
+
is_flag=True,
|
|
263
|
+
help="Accept all defaults without prompting (non-interactive mode)",
|
|
264
|
+
)
|
|
265
|
+
def configure_command(install: bool, claude_desktop: bool, show: bool, edit: bool, yes: bool):
|
|
211
266
|
"""
|
|
212
267
|
Configure REM installation.
|
|
213
268
|
|
|
@@ -215,10 +270,12 @@ def configure_command(install: bool, claude_desktop: bool, show: bool, edit: boo
|
|
|
215
270
|
Configuration is saved to ~/.rem/config.yaml and merged with environment variables.
|
|
216
271
|
|
|
217
272
|
Examples:
|
|
218
|
-
rem configure
|
|
219
|
-
rem configure --
|
|
220
|
-
rem configure --
|
|
221
|
-
rem configure --
|
|
273
|
+
rem configure # Run interactive wizard
|
|
274
|
+
rem configure --yes # Accept all defaults (non-interactive)
|
|
275
|
+
rem configure --yes --install # Quick setup with defaults + install tables
|
|
276
|
+
rem configure --install # Run wizard + install database tables
|
|
277
|
+
rem configure --show # Show current configuration
|
|
278
|
+
rem configure --edit # Open config in $EDITOR
|
|
222
279
|
"""
|
|
223
280
|
config_path = get_config_path()
|
|
224
281
|
|
|
@@ -258,57 +315,74 @@ def configure_command(install: bool, claude_desktop: bool, show: bool, edit: boo
|
|
|
258
315
|
click.echo("\n" + "=" * 60)
|
|
259
316
|
click.echo("REM Configuration Wizard")
|
|
260
317
|
click.echo("=" * 60)
|
|
261
|
-
|
|
318
|
+
|
|
319
|
+
if yes:
|
|
320
|
+
click.echo("\nRunning in non-interactive mode (--yes flag)")
|
|
321
|
+
click.echo("Using default configuration values...")
|
|
322
|
+
else:
|
|
323
|
+
click.echo("\nThis wizard will help you configure REM for first-time use.")
|
|
324
|
+
|
|
262
325
|
click.echo(f"Configuration will be saved to: {config_path}")
|
|
263
326
|
|
|
264
327
|
# Check if config already exists
|
|
265
328
|
if config_exists():
|
|
266
329
|
click.echo(f"\nConfiguration file already exists at {config_path}")
|
|
267
|
-
if
|
|
330
|
+
if yes:
|
|
331
|
+
# In non-interactive mode, skip configuration creation
|
|
332
|
+
click.echo("Skipping configuration creation (file already exists)")
|
|
333
|
+
config = None # Will not save/validate
|
|
334
|
+
elif not click.confirm("Overwrite existing configuration?", default=False):
|
|
268
335
|
click.echo("Configuration unchanged.")
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
config
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
336
|
+
config = None # Will not save/validate
|
|
337
|
+
else:
|
|
338
|
+
# User confirmed overwrite - create new config
|
|
339
|
+
config = {}
|
|
340
|
+
config["postgres"] = prompt_postgres_config(use_defaults=yes)
|
|
341
|
+
config["llm"] = prompt_llm_config(use_defaults=yes)
|
|
342
|
+
s3_config = prompt_s3_config(use_defaults=yes)
|
|
343
|
+
if s3_config:
|
|
344
|
+
config["s3"] = s3_config
|
|
345
|
+
env_vars = prompt_additional_env_vars(use_defaults=yes)
|
|
346
|
+
if env_vars:
|
|
347
|
+
config["env"] = env_vars
|
|
348
|
+
else:
|
|
349
|
+
# No existing config - create new one
|
|
350
|
+
config = {}
|
|
351
|
+
config["postgres"] = prompt_postgres_config(use_defaults=yes)
|
|
352
|
+
config["llm"] = prompt_llm_config(use_defaults=yes)
|
|
353
|
+
s3_config = prompt_s3_config(use_defaults=yes)
|
|
354
|
+
if s3_config:
|
|
355
|
+
config["s3"] = s3_config
|
|
356
|
+
env_vars = prompt_additional_env_vars(use_defaults=yes)
|
|
357
|
+
if env_vars:
|
|
358
|
+
config["env"] = env_vars
|
|
359
|
+
|
|
360
|
+
# Validate and save configuration (only if we created one)
|
|
361
|
+
if config is not None:
|
|
362
|
+
click.echo("\n" + "=" * 60)
|
|
363
|
+
click.echo("Validating Configuration")
|
|
364
|
+
click.echo("=" * 60)
|
|
294
365
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
366
|
+
errors = validate_config(config)
|
|
367
|
+
if errors:
|
|
368
|
+
click.echo("\nConfiguration validation failed:")
|
|
369
|
+
for error in errors:
|
|
370
|
+
click.echo(f" ❌ {error}", err=True)
|
|
371
|
+
click.echo("\nPlease fix these errors and try again.")
|
|
372
|
+
return
|
|
302
373
|
|
|
303
|
-
|
|
374
|
+
click.echo("✅ Configuration is valid")
|
|
304
375
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
376
|
+
# Save configuration
|
|
377
|
+
try:
|
|
378
|
+
save_config(config)
|
|
379
|
+
click.echo(f"\n✅ Configuration saved to {config_path}")
|
|
380
|
+
except Exception as e:
|
|
381
|
+
click.echo(f"\n❌ Failed to save configuration: {e}", err=True)
|
|
382
|
+
return
|
|
383
|
+
else:
|
|
384
|
+
# Load existing config for use in install step
|
|
385
|
+
config = load_config() if config_exists() else {}
|
|
312
386
|
|
|
313
387
|
# Install database tables if requested
|
|
314
388
|
if install:
|
|
@@ -316,7 +390,7 @@ def configure_command(install: bool, claude_desktop: bool, show: bool, edit: boo
|
|
|
316
390
|
click.echo("Database Installation")
|
|
317
391
|
click.echo("=" * 60)
|
|
318
392
|
|
|
319
|
-
if click.confirm("\nInstall database tables?", default=True):
|
|
393
|
+
if yes or click.confirm("\nInstall database tables?", default=True):
|
|
320
394
|
try:
|
|
321
395
|
# Import here to ensure config is loaded first
|
|
322
396
|
from rem.config import merge_config_to_env
|
|
@@ -331,9 +405,7 @@ def configure_command(install: bool, claude_desktop: bool, show: bool, edit: boo
|
|
|
331
405
|
|
|
332
406
|
# Create a context for the command and invoke it
|
|
333
407
|
ctx = click.Context(migrate)
|
|
334
|
-
ctx.invoke(migrate,
|
|
335
|
-
background_indexes=False, connection=None,
|
|
336
|
-
sql_dir=Path("rem/sql"))
|
|
408
|
+
ctx.invoke(migrate, background_indexes=False)
|
|
337
409
|
|
|
338
410
|
click.echo("✅ Database installation complete")
|
|
339
411
|
|
|
@@ -357,8 +429,9 @@ def configure_command(install: bool, claude_desktop: bool, show: bool, edit: boo
|
|
|
357
429
|
if os.name == "nt": # Windows
|
|
358
430
|
config_dir = Path.home() / "AppData/Roaming/Claude"
|
|
359
431
|
elif os.name == "posix":
|
|
360
|
-
|
|
361
|
-
|
|
432
|
+
macos_path = Path.home() / "Library/Application Support/Claude"
|
|
433
|
+
if macos_path.exists():
|
|
434
|
+
config_dir = macos_path
|
|
362
435
|
else:
|
|
363
436
|
config_dir = Path.home() / ".config/Claude"
|
|
364
437
|
else:
|