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.

Files changed (235) hide show
  1. rem/__init__.py +129 -0
  2. rem/agentic/README.md +760 -0
  3. rem/agentic/__init__.py +54 -0
  4. rem/agentic/agents/README.md +155 -0
  5. rem/agentic/agents/__init__.py +38 -0
  6. rem/agentic/agents/agent_manager.py +311 -0
  7. rem/agentic/agents/sse_simulator.py +502 -0
  8. rem/agentic/context.py +425 -0
  9. rem/agentic/context_builder.py +360 -0
  10. rem/agentic/llm_provider_models.py +301 -0
  11. rem/agentic/mcp/__init__.py +0 -0
  12. rem/agentic/mcp/tool_wrapper.py +273 -0
  13. rem/agentic/otel/__init__.py +5 -0
  14. rem/agentic/otel/setup.py +240 -0
  15. rem/agentic/providers/phoenix.py +926 -0
  16. rem/agentic/providers/pydantic_ai.py +854 -0
  17. rem/agentic/query.py +117 -0
  18. rem/agentic/query_helper.py +89 -0
  19. rem/agentic/schema.py +737 -0
  20. rem/agentic/serialization.py +245 -0
  21. rem/agentic/tools/__init__.py +5 -0
  22. rem/agentic/tools/rem_tools.py +242 -0
  23. rem/api/README.md +657 -0
  24. rem/api/deps.py +253 -0
  25. rem/api/main.py +460 -0
  26. rem/api/mcp_router/prompts.py +182 -0
  27. rem/api/mcp_router/resources.py +820 -0
  28. rem/api/mcp_router/server.py +243 -0
  29. rem/api/mcp_router/tools.py +1605 -0
  30. rem/api/middleware/tracking.py +172 -0
  31. rem/api/routers/admin.py +520 -0
  32. rem/api/routers/auth.py +898 -0
  33. rem/api/routers/chat/__init__.py +5 -0
  34. rem/api/routers/chat/child_streaming.py +394 -0
  35. rem/api/routers/chat/completions.py +702 -0
  36. rem/api/routers/chat/json_utils.py +76 -0
  37. rem/api/routers/chat/models.py +202 -0
  38. rem/api/routers/chat/otel_utils.py +33 -0
  39. rem/api/routers/chat/sse_events.py +546 -0
  40. rem/api/routers/chat/streaming.py +950 -0
  41. rem/api/routers/chat/streaming_utils.py +327 -0
  42. rem/api/routers/common.py +18 -0
  43. rem/api/routers/dev.py +87 -0
  44. rem/api/routers/feedback.py +276 -0
  45. rem/api/routers/messages.py +620 -0
  46. rem/api/routers/models.py +86 -0
  47. rem/api/routers/query.py +362 -0
  48. rem/api/routers/shared_sessions.py +422 -0
  49. rem/auth/README.md +258 -0
  50. rem/auth/__init__.py +36 -0
  51. rem/auth/jwt.py +367 -0
  52. rem/auth/middleware.py +318 -0
  53. rem/auth/providers/__init__.py +16 -0
  54. rem/auth/providers/base.py +376 -0
  55. rem/auth/providers/email.py +215 -0
  56. rem/auth/providers/google.py +163 -0
  57. rem/auth/providers/microsoft.py +237 -0
  58. rem/cli/README.md +517 -0
  59. rem/cli/__init__.py +8 -0
  60. rem/cli/commands/README.md +299 -0
  61. rem/cli/commands/__init__.py +3 -0
  62. rem/cli/commands/ask.py +549 -0
  63. rem/cli/commands/cluster.py +1808 -0
  64. rem/cli/commands/configure.py +495 -0
  65. rem/cli/commands/db.py +828 -0
  66. rem/cli/commands/dreaming.py +324 -0
  67. rem/cli/commands/experiments.py +1698 -0
  68. rem/cli/commands/mcp.py +66 -0
  69. rem/cli/commands/process.py +388 -0
  70. rem/cli/commands/query.py +109 -0
  71. rem/cli/commands/scaffold.py +47 -0
  72. rem/cli/commands/schema.py +230 -0
  73. rem/cli/commands/serve.py +106 -0
  74. rem/cli/commands/session.py +453 -0
  75. rem/cli/dreaming.py +363 -0
  76. rem/cli/main.py +123 -0
  77. rem/config.py +244 -0
  78. rem/mcp_server.py +41 -0
  79. rem/models/core/__init__.py +49 -0
  80. rem/models/core/core_model.py +70 -0
  81. rem/models/core/engram.py +333 -0
  82. rem/models/core/experiment.py +672 -0
  83. rem/models/core/inline_edge.py +132 -0
  84. rem/models/core/rem_query.py +246 -0
  85. rem/models/entities/__init__.py +68 -0
  86. rem/models/entities/domain_resource.py +38 -0
  87. rem/models/entities/feedback.py +123 -0
  88. rem/models/entities/file.py +57 -0
  89. rem/models/entities/image_resource.py +88 -0
  90. rem/models/entities/message.py +64 -0
  91. rem/models/entities/moment.py +123 -0
  92. rem/models/entities/ontology.py +181 -0
  93. rem/models/entities/ontology_config.py +131 -0
  94. rem/models/entities/resource.py +95 -0
  95. rem/models/entities/schema.py +87 -0
  96. rem/models/entities/session.py +84 -0
  97. rem/models/entities/shared_session.py +180 -0
  98. rem/models/entities/subscriber.py +175 -0
  99. rem/models/entities/user.py +93 -0
  100. rem/py.typed +0 -0
  101. rem/registry.py +373 -0
  102. rem/schemas/README.md +507 -0
  103. rem/schemas/__init__.py +6 -0
  104. rem/schemas/agents/README.md +92 -0
  105. rem/schemas/agents/core/agent-builder.yaml +235 -0
  106. rem/schemas/agents/core/moment-builder.yaml +178 -0
  107. rem/schemas/agents/core/rem-query-agent.yaml +226 -0
  108. rem/schemas/agents/core/resource-affinity-assessor.yaml +99 -0
  109. rem/schemas/agents/core/simple-assistant.yaml +19 -0
  110. rem/schemas/agents/core/user-profile-builder.yaml +163 -0
  111. rem/schemas/agents/examples/contract-analyzer.yaml +317 -0
  112. rem/schemas/agents/examples/contract-extractor.yaml +134 -0
  113. rem/schemas/agents/examples/cv-parser.yaml +263 -0
  114. rem/schemas/agents/examples/hello-world.yaml +37 -0
  115. rem/schemas/agents/examples/query.yaml +54 -0
  116. rem/schemas/agents/examples/simple.yaml +21 -0
  117. rem/schemas/agents/examples/test.yaml +29 -0
  118. rem/schemas/agents/rem.yaml +132 -0
  119. rem/schemas/evaluators/hello-world/default.yaml +77 -0
  120. rem/schemas/evaluators/rem/faithfulness.yaml +219 -0
  121. rem/schemas/evaluators/rem/lookup-correctness.yaml +182 -0
  122. rem/schemas/evaluators/rem/retrieval-precision.yaml +199 -0
  123. rem/schemas/evaluators/rem/retrieval-recall.yaml +211 -0
  124. rem/schemas/evaluators/rem/search-correctness.yaml +192 -0
  125. rem/services/__init__.py +18 -0
  126. rem/services/audio/INTEGRATION.md +308 -0
  127. rem/services/audio/README.md +376 -0
  128. rem/services/audio/__init__.py +15 -0
  129. rem/services/audio/chunker.py +354 -0
  130. rem/services/audio/transcriber.py +259 -0
  131. rem/services/content/README.md +1269 -0
  132. rem/services/content/__init__.py +5 -0
  133. rem/services/content/providers.py +760 -0
  134. rem/services/content/service.py +762 -0
  135. rem/services/dreaming/README.md +230 -0
  136. rem/services/dreaming/__init__.py +53 -0
  137. rem/services/dreaming/affinity_service.py +322 -0
  138. rem/services/dreaming/moment_service.py +251 -0
  139. rem/services/dreaming/ontology_service.py +54 -0
  140. rem/services/dreaming/user_model_service.py +297 -0
  141. rem/services/dreaming/utils.py +39 -0
  142. rem/services/email/__init__.py +10 -0
  143. rem/services/email/service.py +522 -0
  144. rem/services/email/templates.py +360 -0
  145. rem/services/embeddings/__init__.py +11 -0
  146. rem/services/embeddings/api.py +127 -0
  147. rem/services/embeddings/worker.py +435 -0
  148. rem/services/fs/README.md +662 -0
  149. rem/services/fs/__init__.py +62 -0
  150. rem/services/fs/examples.py +206 -0
  151. rem/services/fs/examples_paths.py +204 -0
  152. rem/services/fs/git_provider.py +935 -0
  153. rem/services/fs/local_provider.py +760 -0
  154. rem/services/fs/parsing-hooks-examples.md +172 -0
  155. rem/services/fs/paths.py +276 -0
  156. rem/services/fs/provider.py +460 -0
  157. rem/services/fs/s3_provider.py +1042 -0
  158. rem/services/fs/service.py +186 -0
  159. rem/services/git/README.md +1075 -0
  160. rem/services/git/__init__.py +17 -0
  161. rem/services/git/service.py +469 -0
  162. rem/services/phoenix/EXPERIMENT_DESIGN.md +1146 -0
  163. rem/services/phoenix/README.md +453 -0
  164. rem/services/phoenix/__init__.py +46 -0
  165. rem/services/phoenix/client.py +960 -0
  166. rem/services/phoenix/config.py +88 -0
  167. rem/services/phoenix/prompt_labels.py +477 -0
  168. rem/services/postgres/README.md +757 -0
  169. rem/services/postgres/__init__.py +49 -0
  170. rem/services/postgres/diff_service.py +599 -0
  171. rem/services/postgres/migration_service.py +427 -0
  172. rem/services/postgres/programmable_diff_service.py +635 -0
  173. rem/services/postgres/pydantic_to_sqlalchemy.py +562 -0
  174. rem/services/postgres/register_type.py +353 -0
  175. rem/services/postgres/repository.py +481 -0
  176. rem/services/postgres/schema_generator.py +661 -0
  177. rem/services/postgres/service.py +802 -0
  178. rem/services/postgres/sql_builder.py +355 -0
  179. rem/services/rate_limit.py +113 -0
  180. rem/services/rem/README.md +318 -0
  181. rem/services/rem/__init__.py +23 -0
  182. rem/services/rem/exceptions.py +71 -0
  183. rem/services/rem/executor.py +293 -0
  184. rem/services/rem/parser.py +180 -0
  185. rem/services/rem/queries.py +196 -0
  186. rem/services/rem/query.py +371 -0
  187. rem/services/rem/service.py +608 -0
  188. rem/services/session/README.md +374 -0
  189. rem/services/session/__init__.py +13 -0
  190. rem/services/session/compression.py +488 -0
  191. rem/services/session/pydantic_messages.py +310 -0
  192. rem/services/session/reload.py +85 -0
  193. rem/services/user_service.py +130 -0
  194. rem/settings.py +1877 -0
  195. rem/sql/background_indexes.sql +52 -0
  196. rem/sql/migrations/001_install.sql +983 -0
  197. rem/sql/migrations/002_install_models.sql +3157 -0
  198. rem/sql/migrations/003_optional_extensions.sql +326 -0
  199. rem/sql/migrations/004_cache_system.sql +282 -0
  200. rem/sql/migrations/005_schema_update.sql +145 -0
  201. rem/sql/migrations/migrate_session_id_to_uuid.sql +45 -0
  202. rem/utils/AGENTIC_CHUNKING.md +597 -0
  203. rem/utils/README.md +628 -0
  204. rem/utils/__init__.py +61 -0
  205. rem/utils/agentic_chunking.py +622 -0
  206. rem/utils/batch_ops.py +343 -0
  207. rem/utils/chunking.py +108 -0
  208. rem/utils/clip_embeddings.py +276 -0
  209. rem/utils/constants.py +97 -0
  210. rem/utils/date_utils.py +228 -0
  211. rem/utils/dict_utils.py +98 -0
  212. rem/utils/embeddings.py +436 -0
  213. rem/utils/examples/embeddings_example.py +305 -0
  214. rem/utils/examples/sql_types_example.py +202 -0
  215. rem/utils/files.py +323 -0
  216. rem/utils/markdown.py +16 -0
  217. rem/utils/mime_types.py +158 -0
  218. rem/utils/model_helpers.py +492 -0
  219. rem/utils/schema_loader.py +649 -0
  220. rem/utils/sql_paths.py +146 -0
  221. rem/utils/sql_types.py +350 -0
  222. rem/utils/user_id.py +81 -0
  223. rem/utils/vision.py +325 -0
  224. rem/workers/README.md +506 -0
  225. rem/workers/__init__.py +7 -0
  226. rem/workers/db_listener.py +579 -0
  227. rem/workers/db_maintainer.py +74 -0
  228. rem/workers/dreaming.py +502 -0
  229. rem/workers/engram_processor.py +312 -0
  230. rem/workers/sqs_file_processor.py +193 -0
  231. rem/workers/unlogged_maintainer.py +463 -0
  232. remdb-0.3.242.dist-info/METADATA +1632 -0
  233. remdb-0.3.242.dist-info/RECORD +235 -0
  234. remdb-0.3.242.dist-info/WHEEL +4 -0
  235. 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)