remdb 0.3.242__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 -0
- rem/agentic/README.md +760 -0
- rem/agentic/__init__.py +54 -0
- rem/agentic/agents/README.md +155 -0
- rem/agentic/agents/__init__.py +38 -0
- rem/agentic/agents/agent_manager.py +311 -0
- rem/agentic/agents/sse_simulator.py +502 -0
- rem/agentic/context.py +425 -0
- rem/agentic/context_builder.py +360 -0
- rem/agentic/llm_provider_models.py +301 -0
- rem/agentic/mcp/__init__.py +0 -0
- rem/agentic/mcp/tool_wrapper.py +273 -0
- rem/agentic/otel/__init__.py +5 -0
- rem/agentic/otel/setup.py +240 -0
- rem/agentic/providers/phoenix.py +926 -0
- rem/agentic/providers/pydantic_ai.py +854 -0
- rem/agentic/query.py +117 -0
- rem/agentic/query_helper.py +89 -0
- rem/agentic/schema.py +737 -0
- rem/agentic/serialization.py +245 -0
- rem/agentic/tools/__init__.py +5 -0
- rem/agentic/tools/rem_tools.py +242 -0
- rem/api/README.md +657 -0
- rem/api/deps.py +253 -0
- rem/api/main.py +460 -0
- rem/api/mcp_router/prompts.py +182 -0
- rem/api/mcp_router/resources.py +820 -0
- rem/api/mcp_router/server.py +243 -0
- rem/api/mcp_router/tools.py +1605 -0
- rem/api/middleware/tracking.py +172 -0
- rem/api/routers/admin.py +520 -0
- rem/api/routers/auth.py +898 -0
- rem/api/routers/chat/__init__.py +5 -0
- rem/api/routers/chat/child_streaming.py +394 -0
- rem/api/routers/chat/completions.py +702 -0
- rem/api/routers/chat/json_utils.py +76 -0
- rem/api/routers/chat/models.py +202 -0
- rem/api/routers/chat/otel_utils.py +33 -0
- rem/api/routers/chat/sse_events.py +546 -0
- rem/api/routers/chat/streaming.py +950 -0
- rem/api/routers/chat/streaming_utils.py +327 -0
- rem/api/routers/common.py +18 -0
- rem/api/routers/dev.py +87 -0
- rem/api/routers/feedback.py +276 -0
- rem/api/routers/messages.py +620 -0
- rem/api/routers/models.py +86 -0
- rem/api/routers/query.py +362 -0
- rem/api/routers/shared_sessions.py +422 -0
- rem/auth/README.md +258 -0
- rem/auth/__init__.py +36 -0
- rem/auth/jwt.py +367 -0
- rem/auth/middleware.py +318 -0
- rem/auth/providers/__init__.py +16 -0
- rem/auth/providers/base.py +376 -0
- rem/auth/providers/email.py +215 -0
- rem/auth/providers/google.py +163 -0
- rem/auth/providers/microsoft.py +237 -0
- rem/cli/README.md +517 -0
- rem/cli/__init__.py +8 -0
- rem/cli/commands/README.md +299 -0
- rem/cli/commands/__init__.py +3 -0
- rem/cli/commands/ask.py +549 -0
- rem/cli/commands/cluster.py +1808 -0
- rem/cli/commands/configure.py +495 -0
- rem/cli/commands/db.py +828 -0
- rem/cli/commands/dreaming.py +324 -0
- rem/cli/commands/experiments.py +1698 -0
- rem/cli/commands/mcp.py +66 -0
- rem/cli/commands/process.py +388 -0
- rem/cli/commands/query.py +109 -0
- rem/cli/commands/scaffold.py +47 -0
- rem/cli/commands/schema.py +230 -0
- rem/cli/commands/serve.py +106 -0
- rem/cli/commands/session.py +453 -0
- rem/cli/dreaming.py +363 -0
- rem/cli/main.py +123 -0
- rem/config.py +244 -0
- rem/mcp_server.py +41 -0
- rem/models/core/__init__.py +49 -0
- rem/models/core/core_model.py +70 -0
- rem/models/core/engram.py +333 -0
- rem/models/core/experiment.py +672 -0
- rem/models/core/inline_edge.py +132 -0
- rem/models/core/rem_query.py +246 -0
- rem/models/entities/__init__.py +68 -0
- rem/models/entities/domain_resource.py +38 -0
- rem/models/entities/feedback.py +123 -0
- rem/models/entities/file.py +57 -0
- rem/models/entities/image_resource.py +88 -0
- rem/models/entities/message.py +64 -0
- rem/models/entities/moment.py +123 -0
- rem/models/entities/ontology.py +181 -0
- rem/models/entities/ontology_config.py +131 -0
- rem/models/entities/resource.py +95 -0
- rem/models/entities/schema.py +87 -0
- rem/models/entities/session.py +84 -0
- rem/models/entities/shared_session.py +180 -0
- rem/models/entities/subscriber.py +175 -0
- rem/models/entities/user.py +93 -0
- rem/py.typed +0 -0
- rem/registry.py +373 -0
- rem/schemas/README.md +507 -0
- rem/schemas/__init__.py +6 -0
- rem/schemas/agents/README.md +92 -0
- rem/schemas/agents/core/agent-builder.yaml +235 -0
- rem/schemas/agents/core/moment-builder.yaml +178 -0
- rem/schemas/agents/core/rem-query-agent.yaml +226 -0
- rem/schemas/agents/core/resource-affinity-assessor.yaml +99 -0
- rem/schemas/agents/core/simple-assistant.yaml +19 -0
- rem/schemas/agents/core/user-profile-builder.yaml +163 -0
- rem/schemas/agents/examples/contract-analyzer.yaml +317 -0
- rem/schemas/agents/examples/contract-extractor.yaml +134 -0
- rem/schemas/agents/examples/cv-parser.yaml +263 -0
- rem/schemas/agents/examples/hello-world.yaml +37 -0
- rem/schemas/agents/examples/query.yaml +54 -0
- rem/schemas/agents/examples/simple.yaml +21 -0
- rem/schemas/agents/examples/test.yaml +29 -0
- rem/schemas/agents/rem.yaml +132 -0
- rem/schemas/evaluators/hello-world/default.yaml +77 -0
- rem/schemas/evaluators/rem/faithfulness.yaml +219 -0
- rem/schemas/evaluators/rem/lookup-correctness.yaml +182 -0
- rem/schemas/evaluators/rem/retrieval-precision.yaml +199 -0
- rem/schemas/evaluators/rem/retrieval-recall.yaml +211 -0
- rem/schemas/evaluators/rem/search-correctness.yaml +192 -0
- rem/services/__init__.py +18 -0
- rem/services/audio/INTEGRATION.md +308 -0
- rem/services/audio/README.md +376 -0
- rem/services/audio/__init__.py +15 -0
- rem/services/audio/chunker.py +354 -0
- rem/services/audio/transcriber.py +259 -0
- rem/services/content/README.md +1269 -0
- rem/services/content/__init__.py +5 -0
- rem/services/content/providers.py +760 -0
- rem/services/content/service.py +762 -0
- rem/services/dreaming/README.md +230 -0
- rem/services/dreaming/__init__.py +53 -0
- rem/services/dreaming/affinity_service.py +322 -0
- rem/services/dreaming/moment_service.py +251 -0
- rem/services/dreaming/ontology_service.py +54 -0
- rem/services/dreaming/user_model_service.py +297 -0
- rem/services/dreaming/utils.py +39 -0
- rem/services/email/__init__.py +10 -0
- rem/services/email/service.py +522 -0
- rem/services/email/templates.py +360 -0
- rem/services/embeddings/__init__.py +11 -0
- rem/services/embeddings/api.py +127 -0
- rem/services/embeddings/worker.py +435 -0
- rem/services/fs/README.md +662 -0
- rem/services/fs/__init__.py +62 -0
- rem/services/fs/examples.py +206 -0
- rem/services/fs/examples_paths.py +204 -0
- rem/services/fs/git_provider.py +935 -0
- rem/services/fs/local_provider.py +760 -0
- rem/services/fs/parsing-hooks-examples.md +172 -0
- rem/services/fs/paths.py +276 -0
- rem/services/fs/provider.py +460 -0
- rem/services/fs/s3_provider.py +1042 -0
- rem/services/fs/service.py +186 -0
- rem/services/git/README.md +1075 -0
- rem/services/git/__init__.py +17 -0
- rem/services/git/service.py +469 -0
- rem/services/phoenix/EXPERIMENT_DESIGN.md +1146 -0
- rem/services/phoenix/README.md +453 -0
- rem/services/phoenix/__init__.py +46 -0
- rem/services/phoenix/client.py +960 -0
- rem/services/phoenix/config.py +88 -0
- rem/services/phoenix/prompt_labels.py +477 -0
- rem/services/postgres/README.md +757 -0
- rem/services/postgres/__init__.py +49 -0
- rem/services/postgres/diff_service.py +599 -0
- rem/services/postgres/migration_service.py +427 -0
- rem/services/postgres/programmable_diff_service.py +635 -0
- rem/services/postgres/pydantic_to_sqlalchemy.py +562 -0
- rem/services/postgres/register_type.py +353 -0
- rem/services/postgres/repository.py +481 -0
- rem/services/postgres/schema_generator.py +661 -0
- rem/services/postgres/service.py +802 -0
- rem/services/postgres/sql_builder.py +355 -0
- rem/services/rate_limit.py +113 -0
- rem/services/rem/README.md +318 -0
- rem/services/rem/__init__.py +23 -0
- rem/services/rem/exceptions.py +71 -0
- rem/services/rem/executor.py +293 -0
- rem/services/rem/parser.py +180 -0
- rem/services/rem/queries.py +196 -0
- rem/services/rem/query.py +371 -0
- rem/services/rem/service.py +608 -0
- rem/services/session/README.md +374 -0
- rem/services/session/__init__.py +13 -0
- rem/services/session/compression.py +488 -0
- rem/services/session/pydantic_messages.py +310 -0
- rem/services/session/reload.py +85 -0
- rem/services/user_service.py +130 -0
- rem/settings.py +1877 -0
- rem/sql/background_indexes.sql +52 -0
- rem/sql/migrations/001_install.sql +983 -0
- rem/sql/migrations/002_install_models.sql +3157 -0
- rem/sql/migrations/003_optional_extensions.sql +326 -0
- rem/sql/migrations/004_cache_system.sql +282 -0
- rem/sql/migrations/005_schema_update.sql +145 -0
- rem/sql/migrations/migrate_session_id_to_uuid.sql +45 -0
- rem/utils/AGENTIC_CHUNKING.md +597 -0
- rem/utils/README.md +628 -0
- rem/utils/__init__.py +61 -0
- rem/utils/agentic_chunking.py +622 -0
- rem/utils/batch_ops.py +343 -0
- rem/utils/chunking.py +108 -0
- rem/utils/clip_embeddings.py +276 -0
- rem/utils/constants.py +97 -0
- rem/utils/date_utils.py +228 -0
- rem/utils/dict_utils.py +98 -0
- rem/utils/embeddings.py +436 -0
- rem/utils/examples/embeddings_example.py +305 -0
- rem/utils/examples/sql_types_example.py +202 -0
- rem/utils/files.py +323 -0
- rem/utils/markdown.py +16 -0
- rem/utils/mime_types.py +158 -0
- rem/utils/model_helpers.py +492 -0
- rem/utils/schema_loader.py +649 -0
- rem/utils/sql_paths.py +146 -0
- rem/utils/sql_types.py +350 -0
- rem/utils/user_id.py +81 -0
- rem/utils/vision.py +325 -0
- rem/workers/README.md +506 -0
- rem/workers/__init__.py +7 -0
- rem/workers/db_listener.py +579 -0
- rem/workers/db_maintainer.py +74 -0
- rem/workers/dreaming.py +502 -0
- rem/workers/engram_processor.py +312 -0
- rem/workers/sqs_file_processor.py +193 -0
- rem/workers/unlogged_maintainer.py +463 -0
- remdb-0.3.242.dist-info/METADATA +1632 -0
- remdb-0.3.242.dist-info/RECORD +235 -0
- remdb-0.3.242.dist-info/WHEEL +4 -0
- remdb-0.3.242.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Schema generation commands.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
rem db schema generate --models src/rem/models/entities
|
|
6
|
+
rem db schema validate
|
|
7
|
+
rem db schema indexes --background
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import asyncio
|
|
11
|
+
import importlib
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
import click
|
|
15
|
+
from loguru import logger
|
|
16
|
+
|
|
17
|
+
from ...settings import settings
|
|
18
|
+
from ...services.postgres.schema_generator import SchemaGenerator
|
|
19
|
+
from ...utils.sql_paths import get_package_sql_dir, get_package_migrations_dir
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _import_model_modules() -> list[str]:
|
|
23
|
+
"""
|
|
24
|
+
Import modules specified in MODELS__IMPORT_MODULES setting.
|
|
25
|
+
|
|
26
|
+
This ensures downstream models decorated with @rem.register_model
|
|
27
|
+
are registered before schema generation.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
List of successfully imported module names
|
|
31
|
+
"""
|
|
32
|
+
imported = []
|
|
33
|
+
for module_name in settings.models.module_list:
|
|
34
|
+
try:
|
|
35
|
+
importlib.import_module(module_name)
|
|
36
|
+
imported.append(module_name)
|
|
37
|
+
logger.debug(f"Imported model module: {module_name}")
|
|
38
|
+
except ImportError as e:
|
|
39
|
+
logger.warning(f"Failed to import model module '{module_name}': {e}")
|
|
40
|
+
click.echo(
|
|
41
|
+
click.style(f" ⚠ Could not import '{module_name}': {e}", fg="yellow"),
|
|
42
|
+
err=True,
|
|
43
|
+
)
|
|
44
|
+
return imported
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@click.command()
|
|
48
|
+
@click.option(
|
|
49
|
+
"--output",
|
|
50
|
+
"-o",
|
|
51
|
+
type=click.Path(path_type=Path),
|
|
52
|
+
default="002_install_models.sql",
|
|
53
|
+
help="Output SQL file (default: 002_install_models.sql)",
|
|
54
|
+
)
|
|
55
|
+
@click.option(
|
|
56
|
+
"--output-dir",
|
|
57
|
+
type=click.Path(path_type=Path),
|
|
58
|
+
default=None,
|
|
59
|
+
help="Base output directory (default: package sql/migrations)",
|
|
60
|
+
)
|
|
61
|
+
def generate(output: Path, output_dir: Path | None):
|
|
62
|
+
"""
|
|
63
|
+
Generate database schema from registered Pydantic models.
|
|
64
|
+
|
|
65
|
+
Uses the model registry (core models + user-registered models) to generate:
|
|
66
|
+
- CREATE TABLE statements
|
|
67
|
+
- Embeddings tables (embeddings_<table>)
|
|
68
|
+
- KV_STORE triggers for cache maintenance
|
|
69
|
+
- Indexes (foreground only)
|
|
70
|
+
|
|
71
|
+
Output is written to src/rem/sql/migrations/002_install_models.sql by default.
|
|
72
|
+
|
|
73
|
+
Example:
|
|
74
|
+
rem db schema generate
|
|
75
|
+
|
|
76
|
+
To register custom models in downstream apps:
|
|
77
|
+
|
|
78
|
+
1. Create models with @rem.register_model decorator:
|
|
79
|
+
|
|
80
|
+
# models/__init__.py
|
|
81
|
+
import rem
|
|
82
|
+
from rem.models.core import CoreModel
|
|
83
|
+
|
|
84
|
+
@rem.register_model
|
|
85
|
+
class MyEntity(CoreModel):
|
|
86
|
+
name: str
|
|
87
|
+
|
|
88
|
+
2. Set MODELS__IMPORT_MODULES in your .env:
|
|
89
|
+
|
|
90
|
+
MODELS__IMPORT_MODULES=models
|
|
91
|
+
|
|
92
|
+
3. Run schema generation:
|
|
93
|
+
|
|
94
|
+
rem db schema generate
|
|
95
|
+
|
|
96
|
+
This creates:
|
|
97
|
+
- src/rem/sql/migrations/002_install_models.sql - Entity tables and triggers
|
|
98
|
+
- src/rem/sql/background_indexes.sql - HNSW indexes (apply after data load)
|
|
99
|
+
|
|
100
|
+
After generation, verify with:
|
|
101
|
+
rem db diff
|
|
102
|
+
"""
|
|
103
|
+
from ...registry import get_model_registry
|
|
104
|
+
|
|
105
|
+
# Import downstream model modules to trigger @rem.register_model decorators
|
|
106
|
+
imported_modules = _import_model_modules()
|
|
107
|
+
if imported_modules:
|
|
108
|
+
click.echo(f"Imported model modules: {', '.join(imported_modules)}")
|
|
109
|
+
|
|
110
|
+
registry = get_model_registry()
|
|
111
|
+
models = registry.get_models(include_core=True)
|
|
112
|
+
click.echo(f"Generating schema from {len(models)} registered models")
|
|
113
|
+
|
|
114
|
+
# Default to package migrations directory
|
|
115
|
+
actual_output_dir = output_dir or get_package_migrations_dir()
|
|
116
|
+
generator = SchemaGenerator(output_dir=actual_output_dir)
|
|
117
|
+
|
|
118
|
+
# Generate schema from registry
|
|
119
|
+
try:
|
|
120
|
+
schema_sql = asyncio.run(generator.generate_from_registry(output_file=output.name))
|
|
121
|
+
|
|
122
|
+
click.echo(f"✓ Schema generated: {len(generator.schemas)} tables")
|
|
123
|
+
click.echo(f"✓ Written to: {actual_output_dir / output.name}")
|
|
124
|
+
|
|
125
|
+
# Generate background indexes in parent sql dir
|
|
126
|
+
background_indexes = generator.generate_background_indexes()
|
|
127
|
+
if background_indexes:
|
|
128
|
+
bg_file = get_package_sql_dir() / "background_indexes.sql"
|
|
129
|
+
bg_file.write_text(background_indexes)
|
|
130
|
+
click.echo(f"✓ Background indexes: {bg_file}")
|
|
131
|
+
|
|
132
|
+
# Summary
|
|
133
|
+
click.echo("\nGenerated tables:")
|
|
134
|
+
for table_name, schema in generator.schemas.items():
|
|
135
|
+
embeddable = len(schema.get("embeddable_fields", []))
|
|
136
|
+
embed_status = f"({embeddable} embeddable fields)" if embeddable else "(no embeddings)"
|
|
137
|
+
click.echo(f" - {table_name} {embed_status}")
|
|
138
|
+
|
|
139
|
+
except Exception as e:
|
|
140
|
+
logger.exception("Schema generation failed")
|
|
141
|
+
click.echo(f"✗ Error: {e}", err=True)
|
|
142
|
+
raise click.Abort()
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@click.command()
|
|
146
|
+
def validate():
|
|
147
|
+
"""
|
|
148
|
+
Validate registered Pydantic models for schema generation.
|
|
149
|
+
|
|
150
|
+
Checks:
|
|
151
|
+
- Models can be loaded from registry
|
|
152
|
+
- Models have suitable entity_key fields
|
|
153
|
+
- Fields with embeddings are properly configured
|
|
154
|
+
|
|
155
|
+
Set MODELS__IMPORT_MODULES to include custom models from downstream apps.
|
|
156
|
+
"""
|
|
157
|
+
from ...registry import get_model_registry
|
|
158
|
+
|
|
159
|
+
# Import downstream model modules to trigger @rem.register_model decorators
|
|
160
|
+
imported_modules = _import_model_modules()
|
|
161
|
+
if imported_modules:
|
|
162
|
+
click.echo(f"Imported model modules: {', '.join(imported_modules)}")
|
|
163
|
+
|
|
164
|
+
registry = get_model_registry()
|
|
165
|
+
models = registry.get_models(include_core=True)
|
|
166
|
+
|
|
167
|
+
click.echo(f"Validating {len(models)} registered models")
|
|
168
|
+
|
|
169
|
+
if not models:
|
|
170
|
+
click.echo("✗ No models found in registry", err=True)
|
|
171
|
+
raise click.Abort()
|
|
172
|
+
|
|
173
|
+
generator = SchemaGenerator()
|
|
174
|
+
errors: list[str] = []
|
|
175
|
+
warnings: list[str] = []
|
|
176
|
+
|
|
177
|
+
for model_name, ext in models.items():
|
|
178
|
+
model = ext.model
|
|
179
|
+
table_name = ext.table_name or generator.infer_table_name(model)
|
|
180
|
+
entity_key = ext.entity_key_field or generator.infer_entity_key_field(model)
|
|
181
|
+
|
|
182
|
+
# Check for entity_key
|
|
183
|
+
if entity_key == "id":
|
|
184
|
+
warnings.append(f"{model_name}: No natural key field, using 'id'")
|
|
185
|
+
|
|
186
|
+
click.echo(f" {model_name} -> {table_name} (key: {entity_key})")
|
|
187
|
+
|
|
188
|
+
if warnings:
|
|
189
|
+
click.echo("\nWarnings:")
|
|
190
|
+
for warning in warnings:
|
|
191
|
+
click.echo(click.style(f" ⚠ {warning}", fg="yellow"))
|
|
192
|
+
|
|
193
|
+
if errors:
|
|
194
|
+
click.echo("\nErrors:")
|
|
195
|
+
for error in errors:
|
|
196
|
+
click.echo(click.style(f" ✗ {error}", fg="red"))
|
|
197
|
+
raise click.Abort()
|
|
198
|
+
|
|
199
|
+
click.echo("\n✓ All models valid")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@click.command()
|
|
203
|
+
@click.option(
|
|
204
|
+
"--output",
|
|
205
|
+
"-o",
|
|
206
|
+
type=click.Path(path_type=Path),
|
|
207
|
+
default=None,
|
|
208
|
+
help="Output file for background indexes (default: package sql/background_indexes.sql)",
|
|
209
|
+
)
|
|
210
|
+
def indexes(output: Path):
|
|
211
|
+
"""
|
|
212
|
+
Generate SQL for background index creation.
|
|
213
|
+
|
|
214
|
+
Creates HNSW vector indexes that should be run CONCURRENTLY
|
|
215
|
+
after initial data load to avoid blocking writes.
|
|
216
|
+
"""
|
|
217
|
+
click.echo("Generating background index SQL")
|
|
218
|
+
|
|
219
|
+
generator = SchemaGenerator()
|
|
220
|
+
|
|
221
|
+
# Load existing schemas (would need to be persisted or regenerated)
|
|
222
|
+
click.echo(click.style("⚠ Note: This requires schemas to be generated first", fg="yellow"))
|
|
223
|
+
click.echo(click.style("⚠ Run 'rem db schema generate' before 'rem db schema indexes'", fg="yellow"))
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def register_commands(schema_group):
|
|
227
|
+
"""Register all schema commands."""
|
|
228
|
+
schema_group.add_command(generate)
|
|
229
|
+
schema_group.add_command(validate)
|
|
230
|
+
schema_group.add_command(indexes)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""
|
|
2
|
+
REM API server command.
|
|
3
|
+
|
|
4
|
+
Start the FastAPI server with uvicorn.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
rem serve # Start API server with default settings
|
|
8
|
+
rem serve --host 0.0.0.0 # Bind to all interfaces
|
|
9
|
+
rem serve --port 8080 # Use custom port
|
|
10
|
+
rem serve --reload # Enable auto-reload (development)
|
|
11
|
+
rem serve --workers 4 # Production mode with workers
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import click
|
|
15
|
+
from loguru import logger
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@click.command("serve")
|
|
19
|
+
@click.option(
|
|
20
|
+
"--host",
|
|
21
|
+
default=None,
|
|
22
|
+
help="Host to bind to (overrides config/env)",
|
|
23
|
+
)
|
|
24
|
+
@click.option(
|
|
25
|
+
"--port",
|
|
26
|
+
default=None,
|
|
27
|
+
type=int,
|
|
28
|
+
help="Port to listen on (overrides config/env)",
|
|
29
|
+
)
|
|
30
|
+
@click.option(
|
|
31
|
+
"--reload",
|
|
32
|
+
is_flag=True,
|
|
33
|
+
default=None,
|
|
34
|
+
help="Enable auto-reload for development",
|
|
35
|
+
)
|
|
36
|
+
@click.option(
|
|
37
|
+
"--workers",
|
|
38
|
+
default=None,
|
|
39
|
+
type=int,
|
|
40
|
+
help="Number of worker processes (production mode)",
|
|
41
|
+
)
|
|
42
|
+
@click.option(
|
|
43
|
+
"--log-level",
|
|
44
|
+
default=None,
|
|
45
|
+
type=click.Choice(["critical", "error", "warning", "info", "debug", "trace"]),
|
|
46
|
+
help="Logging level",
|
|
47
|
+
)
|
|
48
|
+
def serve_command(
|
|
49
|
+
host: str | None,
|
|
50
|
+
port: int | None,
|
|
51
|
+
reload: bool | None,
|
|
52
|
+
workers: int | None,
|
|
53
|
+
log_level: str | None,
|
|
54
|
+
):
|
|
55
|
+
"""
|
|
56
|
+
Start the REM API server.
|
|
57
|
+
|
|
58
|
+
The server will load configuration from:
|
|
59
|
+
1. Environment variables (highest priority)
|
|
60
|
+
2. ~/.rem/config.yaml (user configuration)
|
|
61
|
+
3. Default values (lowest priority)
|
|
62
|
+
|
|
63
|
+
Examples:
|
|
64
|
+
rem serve # Use settings from config
|
|
65
|
+
rem serve --host 0.0.0.0 # Bind to all interfaces
|
|
66
|
+
rem serve --reload # Development mode
|
|
67
|
+
rem serve --workers 4 # Production mode (4 workers)
|
|
68
|
+
"""
|
|
69
|
+
import uvicorn
|
|
70
|
+
|
|
71
|
+
# Import settings to trigger config loading
|
|
72
|
+
from rem.settings import settings
|
|
73
|
+
|
|
74
|
+
# Determine reload/workers (mutually exclusive)
|
|
75
|
+
use_reload = reload if reload is not None else (settings.api.reload if workers is None else False)
|
|
76
|
+
use_workers = workers if workers is not None else (settings.api.workers if not use_reload else None)
|
|
77
|
+
|
|
78
|
+
# Start server
|
|
79
|
+
final_host = host or settings.api.host
|
|
80
|
+
final_port = port or settings.api.port
|
|
81
|
+
final_log_level = log_level or settings.api.log_level
|
|
82
|
+
|
|
83
|
+
logger.info(f"Starting REM API server at http://{final_host}:{final_port}")
|
|
84
|
+
|
|
85
|
+
# Call uvicorn.run with explicit parameters to satisfy type checker
|
|
86
|
+
if use_reload:
|
|
87
|
+
uvicorn.run(
|
|
88
|
+
"rem.api.main:app",
|
|
89
|
+
host=final_host,
|
|
90
|
+
port=final_port,
|
|
91
|
+
log_level=final_log_level,
|
|
92
|
+
reload=True,
|
|
93
|
+
)
|
|
94
|
+
else:
|
|
95
|
+
uvicorn.run(
|
|
96
|
+
"rem.api.main:app",
|
|
97
|
+
host=final_host,
|
|
98
|
+
port=final_port,
|
|
99
|
+
log_level=final_log_level,
|
|
100
|
+
workers=use_workers,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def register_command(cli_group):
|
|
105
|
+
"""Register the serve command."""
|
|
106
|
+
cli_group.add_command(serve_command)
|