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.

Files changed (104) 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 +500 -0
  6. rem/agentic/context.py +28 -22
  7. rem/agentic/llm_provider_models.py +301 -0
  8. rem/agentic/mcp/tool_wrapper.py +29 -3
  9. rem/agentic/otel/setup.py +92 -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 +454 -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 +152 -16
  24. rem/api/routers/chat/models.py +7 -3
  25. rem/api/routers/chat/sse_events.py +526 -0
  26. rem/api/routers/chat/streaming.py +608 -45
  27. rem/api/routers/dev.py +81 -0
  28. rem/api/routers/feedback.py +148 -0
  29. rem/api/routers/messages.py +473 -0
  30. rem/api/routers/models.py +78 -0
  31. rem/api/routers/query.py +360 -0
  32. rem/api/routers/shared_sessions.py +406 -0
  33. rem/auth/middleware.py +126 -27
  34. rem/cli/commands/README.md +237 -64
  35. rem/cli/commands/ask.py +15 -11
  36. rem/cli/commands/cluster.py +1300 -0
  37. rem/cli/commands/configure.py +170 -97
  38. rem/cli/commands/db.py +396 -139
  39. rem/cli/commands/experiments.py +278 -96
  40. rem/cli/commands/process.py +22 -15
  41. rem/cli/commands/scaffold.py +47 -0
  42. rem/cli/commands/schema.py +97 -50
  43. rem/cli/main.py +37 -6
  44. rem/config.py +2 -2
  45. rem/models/core/core_model.py +7 -1
  46. rem/models/core/rem_query.py +5 -2
  47. rem/models/entities/__init__.py +21 -0
  48. rem/models/entities/domain_resource.py +38 -0
  49. rem/models/entities/feedback.py +123 -0
  50. rem/models/entities/message.py +30 -1
  51. rem/models/entities/session.py +83 -0
  52. rem/models/entities/shared_session.py +180 -0
  53. rem/models/entities/user.py +10 -3
  54. rem/registry.py +373 -0
  55. rem/schemas/agents/rem.yaml +7 -3
  56. rem/services/content/providers.py +94 -140
  57. rem/services/content/service.py +115 -24
  58. rem/services/dreaming/affinity_service.py +2 -16
  59. rem/services/dreaming/moment_service.py +2 -15
  60. rem/services/embeddings/api.py +24 -17
  61. rem/services/embeddings/worker.py +16 -16
  62. rem/services/phoenix/EXPERIMENT_DESIGN.md +3 -3
  63. rem/services/phoenix/client.py +252 -19
  64. rem/services/postgres/README.md +159 -15
  65. rem/services/postgres/__init__.py +2 -1
  66. rem/services/postgres/diff_service.py +531 -0
  67. rem/services/postgres/pydantic_to_sqlalchemy.py +427 -129
  68. rem/services/postgres/repository.py +132 -0
  69. rem/services/postgres/schema_generator.py +291 -9
  70. rem/services/postgres/service.py +6 -6
  71. rem/services/rate_limit.py +113 -0
  72. rem/services/rem/README.md +14 -0
  73. rem/services/rem/parser.py +44 -9
  74. rem/services/rem/service.py +36 -2
  75. rem/services/session/compression.py +17 -1
  76. rem/services/session/reload.py +1 -1
  77. rem/services/user_service.py +98 -0
  78. rem/settings.py +169 -22
  79. rem/sql/background_indexes.sql +21 -16
  80. rem/sql/migrations/001_install.sql +387 -54
  81. rem/sql/migrations/002_install_models.sql +2320 -393
  82. rem/sql/migrations/003_optional_extensions.sql +326 -0
  83. rem/sql/migrations/004_cache_system.sql +548 -0
  84. rem/utils/__init__.py +18 -0
  85. rem/utils/constants.py +97 -0
  86. rem/utils/date_utils.py +228 -0
  87. rem/utils/embeddings.py +17 -4
  88. rem/utils/files.py +167 -0
  89. rem/utils/mime_types.py +158 -0
  90. rem/utils/model_helpers.py +156 -1
  91. rem/utils/schema_loader.py +284 -21
  92. rem/utils/sql_paths.py +146 -0
  93. rem/utils/sql_types.py +3 -1
  94. rem/utils/vision.py +9 -14
  95. rem/workers/README.md +14 -14
  96. rem/workers/__init__.py +2 -1
  97. rem/workers/db_maintainer.py +74 -0
  98. rem/workers/unlogged_maintainer.py +463 -0
  99. {remdb-0.2.6.dist-info → remdb-0.3.118.dist-info}/METADATA +598 -171
  100. {remdb-0.2.6.dist-info → remdb-0.3.118.dist-info}/RECORD +102 -73
  101. {remdb-0.2.6.dist-info → remdb-0.3.118.dist-info}/WHEEL +1 -1
  102. rem/sql/002_install_models.sql +0 -1068
  103. rem/sql/install_models.sql +0 -1038
  104. {remdb-0.2.6.dist-info → remdb-0.3.118.dist-info}/entry_points.txt +0 -0
@@ -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
- # Prompt for components
48
- click.echo(
49
- "\nEnter PostgreSQL connection details (press Enter to use default):"
50
- )
51
- click.echo("Default: Package users on port 5051 (docker compose -f docker-compose.prebuilt.yml up -d)")
52
- click.echo("Developers: Change port to 5050 if using docker-compose.yml (local build)")
53
- click.echo("Custom DB: Enter your own host/port below")
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
- host = click.prompt("Host", default="localhost")
56
- port = click.prompt("Port", default=5051, type=int)
57
- database = click.prompt("Database name", default="rem")
58
- username = click.prompt("Username", default="rem")
59
- password = click.prompt("Password", default="rem", hide_input=True)
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 model
90
- click.echo("\nDefault LLM model (format: provider:model-id)")
91
- click.echo("Examples:")
92
- click.echo(" - anthropic:claude-sonnet-4-5-20250929")
93
- click.echo(" - openai:gpt-4o")
94
- click.echo(" - openai:gpt-4o-mini")
95
-
96
- config["default_model"] = click.prompt(
97
- "Default model", default="anthropic:claude-sonnet-4-5-20250929"
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
- # Temperature
101
- config["default_temperature"] = click.prompt(
102
- "Default temperature (0.0-1.0)", default=0.5, type=float
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
- # API keys
106
- click.echo("\nAPI Keys (optional - leave empty to skip):")
140
+ # API keys
141
+ click.echo("\nAPI Keys (optional - leave empty to skip):")
107
142
 
108
- openai_key = click.prompt("OpenAI API key", default="", show_default=False)
109
- if openai_key:
110
- config["openai_api_key"] = openai_key
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
- anthropic_key = click.prompt("Anthropic API key", default="", show_default=False)
113
- if anthropic_key:
114
- config["anthropic_api_key"] = anthropic_key
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=True)
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
- def configure_command(install: bool, claude_desktop: bool, show: bool, edit: bool):
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 # Run interactive wizard
219
- rem configure --install # Run wizard + install database tables
220
- rem configure --show # Show current configuration
221
- rem configure --edit # Open config in $EDITOR
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
- click.echo("\nThis wizard will help you configure REM for first-time use.")
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 not click.confirm("Overwrite existing configuration?", default=False):
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
- return
270
-
271
- # Build configuration
272
- config = {}
273
-
274
- # PostgreSQL (required)
275
- config["postgres"] = prompt_postgres_config()
276
-
277
- # LLM providers
278
- config["llm"] = prompt_llm_config()
279
-
280
- # S3 storage (optional)
281
- s3_config = prompt_s3_config()
282
- if s3_config:
283
- config["s3"] = s3_config
284
-
285
- # Additional environment variables
286
- env_vars = prompt_additional_env_vars()
287
- if env_vars:
288
- config["env"] = env_vars
289
-
290
- # Validate configuration
291
- click.echo("\n" + "=" * 60)
292
- click.echo("Validating Configuration")
293
- click.echo("=" * 60)
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
- errors = validate_config(config)
296
- if errors:
297
- click.echo("\nConfiguration validation failed:")
298
- for error in errors:
299
- click.echo(f" ❌ {error}", err=True)
300
- click.echo("\nPlease fix these errors and try again.")
301
- return
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
- click.echo("✅ Configuration is valid")
374
+ click.echo("✅ Configuration is valid")
304
375
 
305
- # Save configuration
306
- try:
307
- save_config(config)
308
- click.echo(f"\n✅ Configuration saved to {config_path}")
309
- except Exception as e:
310
- click.echo(f"\n❌ Failed to save configuration: {e}", err=True)
311
- return
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, install_only=False, models_only=False,
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
- if Path.home() / "Library/Application Support/Claude":
361
- config_dir = Path.home() / "Library/Application Support/Claude"
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: