remdb 0.3.114__py3-none-any.whl → 0.3.172__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 (83) hide show
  1. rem/agentic/agents/__init__.py +16 -0
  2. rem/agentic/agents/agent_manager.py +311 -0
  3. rem/agentic/agents/sse_simulator.py +2 -0
  4. rem/agentic/context.py +103 -5
  5. rem/agentic/context_builder.py +36 -9
  6. rem/agentic/mcp/tool_wrapper.py +161 -18
  7. rem/agentic/otel/setup.py +1 -0
  8. rem/agentic/providers/phoenix.py +371 -108
  9. rem/agentic/providers/pydantic_ai.py +172 -30
  10. rem/agentic/schema.py +8 -4
  11. rem/api/deps.py +3 -5
  12. rem/api/main.py +26 -4
  13. rem/api/mcp_router/resources.py +15 -10
  14. rem/api/mcp_router/server.py +11 -3
  15. rem/api/mcp_router/tools.py +418 -4
  16. rem/api/middleware/tracking.py +5 -5
  17. rem/api/routers/admin.py +218 -1
  18. rem/api/routers/auth.py +349 -6
  19. rem/api/routers/chat/completions.py +255 -7
  20. rem/api/routers/chat/models.py +81 -7
  21. rem/api/routers/chat/otel_utils.py +33 -0
  22. rem/api/routers/chat/sse_events.py +17 -1
  23. rem/api/routers/chat/streaming.py +126 -19
  24. rem/api/routers/feedback.py +134 -14
  25. rem/api/routers/messages.py +24 -15
  26. rem/api/routers/query.py +6 -3
  27. rem/auth/__init__.py +13 -3
  28. rem/auth/jwt.py +352 -0
  29. rem/auth/middleware.py +115 -10
  30. rem/auth/providers/__init__.py +4 -1
  31. rem/auth/providers/email.py +215 -0
  32. rem/cli/commands/README.md +42 -0
  33. rem/cli/commands/cluster.py +617 -168
  34. rem/cli/commands/configure.py +4 -7
  35. rem/cli/commands/db.py +66 -22
  36. rem/cli/commands/experiments.py +468 -76
  37. rem/cli/commands/schema.py +6 -5
  38. rem/cli/commands/session.py +336 -0
  39. rem/cli/dreaming.py +2 -2
  40. rem/cli/main.py +2 -0
  41. rem/config.py +8 -1
  42. rem/models/core/experiment.py +58 -14
  43. rem/models/entities/__init__.py +4 -0
  44. rem/models/entities/ontology.py +1 -1
  45. rem/models/entities/ontology_config.py +1 -1
  46. rem/models/entities/subscriber.py +175 -0
  47. rem/models/entities/user.py +1 -0
  48. rem/schemas/agents/core/agent-builder.yaml +235 -0
  49. rem/schemas/agents/examples/contract-analyzer.yaml +1 -1
  50. rem/schemas/agents/examples/contract-extractor.yaml +1 -1
  51. rem/schemas/agents/examples/cv-parser.yaml +1 -1
  52. rem/services/__init__.py +3 -1
  53. rem/services/content/service.py +4 -3
  54. rem/services/email/__init__.py +10 -0
  55. rem/services/email/service.py +513 -0
  56. rem/services/email/templates.py +360 -0
  57. rem/services/phoenix/client.py +59 -18
  58. rem/services/postgres/README.md +38 -0
  59. rem/services/postgres/diff_service.py +127 -6
  60. rem/services/postgres/pydantic_to_sqlalchemy.py +45 -13
  61. rem/services/postgres/repository.py +5 -4
  62. rem/services/postgres/schema_generator.py +205 -4
  63. rem/services/session/compression.py +120 -50
  64. rem/services/session/reload.py +14 -7
  65. rem/services/user_service.py +41 -9
  66. rem/settings.py +442 -23
  67. rem/sql/migrations/001_install.sql +156 -0
  68. rem/sql/migrations/002_install_models.sql +1951 -88
  69. rem/sql/migrations/004_cache_system.sql +548 -0
  70. rem/sql/migrations/005_schema_update.sql +145 -0
  71. rem/utils/README.md +45 -0
  72. rem/utils/__init__.py +18 -0
  73. rem/utils/files.py +157 -1
  74. rem/utils/schema_loader.py +139 -10
  75. rem/utils/sql_paths.py +146 -0
  76. rem/utils/vision.py +1 -1
  77. rem/workers/__init__.py +3 -1
  78. rem/workers/db_listener.py +579 -0
  79. rem/workers/unlogged_maintainer.py +463 -0
  80. {remdb-0.3.114.dist-info → remdb-0.3.172.dist-info}/METADATA +218 -180
  81. {remdb-0.3.114.dist-info → remdb-0.3.172.dist-info}/RECORD +83 -68
  82. {remdb-0.3.114.dist-info → remdb-0.3.172.dist-info}/WHEEL +0 -0
  83. {remdb-0.3.114.dist-info → remdb-0.3.172.dist-info}/entry_points.txt +0 -0
@@ -110,7 +110,7 @@ def prompt_llm_config(use_defaults: bool = False) -> dict:
110
110
  config = {}
111
111
 
112
112
  # Default values
113
- default_model = "anthropic:claude-sonnet-4-5-20250929"
113
+ default_model = "openai:gpt-4.1"
114
114
  default_temperature = 0.5
115
115
 
116
116
  if use_defaults:
@@ -124,9 +124,9 @@ def prompt_llm_config(use_defaults: bool = False) -> dict:
124
124
  # Default model
125
125
  click.echo("\nDefault LLM model (format: provider:model-id)")
126
126
  click.echo("Examples:")
127
+ click.echo(" - openai:gpt-4.1")
127
128
  click.echo(" - anthropic:claude-sonnet-4-5-20250929")
128
- click.echo(" - openai:gpt-4o")
129
- click.echo(" - openai:gpt-4o-mini")
129
+ click.echo(" - openai:gpt-4.1-mini")
130
130
 
131
131
  config["default_model"] = click.prompt(
132
132
  "Default model", default=default_model
@@ -405,9 +405,7 @@ def configure_command(install: bool, claude_desktop: bool, show: bool, edit: boo
405
405
 
406
406
  # Create a context for the command and invoke it
407
407
  ctx = click.Context(migrate)
408
- ctx.invoke(migrate, install_only=False, models_only=False,
409
- background_indexes=False, connection=None,
410
- sql_dir=Path("rem/sql"))
408
+ ctx.invoke(migrate, background_indexes=False)
411
409
 
412
410
  click.echo("✅ Database installation complete")
413
411
 
@@ -424,7 +422,6 @@ def configure_command(install: bool, claude_desktop: bool, show: bool, edit: boo
424
422
 
425
423
  try:
426
424
  import shutil
427
- from pathlib import Path
428
425
  from fastmcp.mcp_config import update_config_file, StdioMCPServer
429
426
 
430
427
  # Find Claude Desktop config path
rem/cli/commands/db.py CHANGED
@@ -126,29 +126,51 @@ def migrate(background_indexes: bool):
126
126
  async def _migrate_async(background_indexes: bool):
127
127
  """Async implementation of migrate command."""
128
128
  from ...settings import settings
129
+ from ...utils.sql_paths import (
130
+ get_package_sql_dir,
131
+ get_user_sql_dir,
132
+ list_all_migrations,
133
+ )
129
134
 
130
135
  click.echo()
131
136
  click.echo("REM Database Migration")
132
137
  click.echo("=" * 60)
133
138
 
134
- # Find SQL directory
135
- sql_dir = Path(settings.sql_dir)
136
- migrations_dir = sql_dir / "migrations"
139
+ # Find package SQL directory
140
+ try:
141
+ package_sql_dir = get_package_sql_dir()
142
+ click.echo(f"Package SQL: {package_sql_dir}")
143
+ except FileNotFoundError as e:
144
+ click.secho(f"✗ {e}", fg="red")
145
+ raise click.Abort()
146
+
147
+ # Check for user migrations
148
+ user_sql_dir = get_user_sql_dir()
149
+ if user_sql_dir:
150
+ click.echo(f"User SQL: {user_sql_dir}")
151
+
152
+ # Get all migrations (package + user)
153
+ all_migrations = list_all_migrations()
154
+
155
+ if not all_migrations:
156
+ click.secho("✗ No migration files found", fg="red")
157
+ raise click.Abort()
137
158
 
138
- click.echo(f"SQL Directory: {sql_dir}")
159
+ click.echo(f"Found {len(all_migrations)} migration(s)")
139
160
  click.echo()
140
161
 
141
- # Standard migration files
142
- migrations = [
143
- (migrations_dir / "001_install.sql", "Core Infrastructure"),
144
- (migrations_dir / "002_install_models.sql", "Entity Tables"),
145
- ]
162
+ # Add background indexes if requested
163
+ migrations_to_apply = [(f, f.stem) for f in all_migrations]
146
164
 
147
165
  if background_indexes:
148
- migrations.append((sql_dir / "background_indexes.sql", "Background Indexes"))
149
-
150
- # Check files exist
151
- for file_path, description in migrations:
166
+ bg_indexes = package_sql_dir / "background_indexes.sql"
167
+ if bg_indexes.exists():
168
+ migrations_to_apply.append((bg_indexes, "Background Indexes"))
169
+ else:
170
+ click.secho("⚠ background_indexes.sql not found, skipping", fg="yellow")
171
+
172
+ # Check all files exist (they should, but verify)
173
+ for file_path, description in migrations_to_apply:
152
174
  if not file_path.exists():
153
175
  click.secho(f"✗ {file_path.name} not found", fg="red")
154
176
  if "002" in file_path.name:
@@ -162,8 +184,8 @@ async def _migrate_async(background_indexes: bool):
162
184
  conn_str = settings.postgres.connection_string
163
185
  total_time = 0.0
164
186
 
165
- for file_path, description in migrations:
166
- click.echo(f"Applying: {description} ({file_path.name})")
187
+ for file_path, description in migrations_to_apply:
188
+ click.echo(f"Applying: {file_path.name}")
167
189
 
168
190
  sql_content = file_path.read_text(encoding="utf-8")
169
191
  start_time = time.time()
@@ -469,6 +491,13 @@ async def _load_async(file_path: Path, user_id: str | None, dry_run: bool):
469
491
  is_flag=True,
470
492
  help="Generate incremental migration file from diff",
471
493
  )
494
+ @click.option(
495
+ "--strategy",
496
+ "-s",
497
+ type=click.Choice(["additive", "full", "safe"]),
498
+ default="additive",
499
+ help="Migration strategy: additive (no drops, default), full (all changes), safe (additive + type widenings)",
500
+ )
472
501
  @click.option(
473
502
  "--models",
474
503
  "-m",
@@ -491,6 +520,7 @@ async def _load_async(file_path: Path, user_id: str | None, dry_run: bool):
491
520
  def diff(
492
521
  check: bool,
493
522
  generate: bool,
523
+ strategy: str,
494
524
  models: Path | None,
495
525
  output_dir: Path | None,
496
526
  message: str,
@@ -502,23 +532,30 @@ def diff(
502
532
  - Your Pydantic models (the target schema)
503
533
  - The current database (what's actually deployed)
504
534
 
535
+ Strategies:
536
+ additive Only ADD columns/tables/indexes (safe, no data loss) [default]
537
+ full All changes including DROPs (use with caution)
538
+ safe Additive + safe column type changes (widenings only)
539
+
505
540
  Examples:
506
- rem db diff # Show what would change
507
- rem db diff --check # CI mode: exit 1 if drift detected
508
- rem db diff --generate # Create migration file from diff
541
+ rem db diff # Show additive changes only
542
+ rem db diff --strategy full # Show all changes including drops
543
+ rem db diff --generate # Create migration file
544
+ rem db diff --check # CI mode: exit 1 if drift
509
545
 
510
546
  Workflow:
511
547
  1. Develop locally, modify Pydantic models
512
548
  2. Run 'rem db diff' to see changes
513
549
  3. Run 'rem db diff --generate' to create migration
514
- 4. Review generated SQL, then 'rem db migrate'
550
+ 4. Review generated SQL, then 'rem db apply <file>'
515
551
  """
516
- asyncio.run(_diff_async(check, generate, models, output_dir, message))
552
+ asyncio.run(_diff_async(check, generate, strategy, models, output_dir, message))
517
553
 
518
554
 
519
555
  async def _diff_async(
520
556
  check: bool,
521
557
  generate: bool,
558
+ strategy: str,
522
559
  models: Path | None,
523
560
  output_dir: Path | None,
524
561
  message: str,
@@ -529,9 +566,10 @@ async def _diff_async(
529
566
  click.echo()
530
567
  click.echo("REM Schema Diff")
531
568
  click.echo("=" * 60)
569
+ click.echo(f"Strategy: {strategy}")
532
570
 
533
571
  # Initialize diff service
534
- diff_service = DiffService(models_dir=models)
572
+ diff_service = DiffService(models_dir=models, strategy=strategy)
535
573
 
536
574
  try:
537
575
  # Compute diff
@@ -543,10 +581,16 @@ async def _diff_async(
543
581
  if not result.has_changes:
544
582
  click.secho("✓ No schema drift detected", fg="green")
545
583
  click.echo(" Database matches Pydantic models")
584
+ if result.filtered_count > 0:
585
+ click.echo()
586
+ click.secho(f" ({result.filtered_count} destructive change(s) hidden by '{strategy}' strategy)", fg="yellow")
587
+ click.echo(" Use --strategy full to see all changes")
546
588
  return
547
589
 
548
590
  # Show changes
549
591
  click.secho(f"⚠ Schema drift detected: {result.change_count} change(s)", fg="yellow")
592
+ if result.filtered_count > 0:
593
+ click.secho(f" ({result.filtered_count} destructive change(s) hidden by '{strategy}' strategy)", fg="yellow")
550
594
  click.echo()
551
595
  click.echo("Changes:")
552
596
  for line in result.summary:
@@ -581,7 +625,7 @@ async def _diff_async(
581
625
  click.echo()
582
626
  click.echo("Next steps:")
583
627
  click.echo(" 1. Review the generated SQL file")
584
- click.echo(" 2. Run: rem db migrate")
628
+ click.echo(" 2. Run: rem db apply <file>")
585
629
  else:
586
630
  click.echo("No migration file generated (no changes)")
587
631