remdb 0.2.6__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 +2 -0
- rem/agentic/README.md +650 -0
- rem/agentic/__init__.py +39 -0
- rem/agentic/agents/README.md +155 -0
- rem/agentic/agents/__init__.py +8 -0
- rem/agentic/context.py +148 -0
- rem/agentic/context_builder.py +329 -0
- rem/agentic/mcp/__init__.py +0 -0
- rem/agentic/mcp/tool_wrapper.py +107 -0
- rem/agentic/otel/__init__.py +5 -0
- rem/agentic/otel/setup.py +151 -0
- rem/agentic/providers/phoenix.py +674 -0
- rem/agentic/providers/pydantic_ai.py +572 -0
- rem/agentic/query.py +117 -0
- rem/agentic/query_helper.py +89 -0
- rem/agentic/schema.py +396 -0
- rem/agentic/serialization.py +245 -0
- rem/agentic/tools/__init__.py +5 -0
- rem/agentic/tools/rem_tools.py +231 -0
- rem/api/README.md +420 -0
- rem/api/main.py +324 -0
- rem/api/mcp_router/prompts.py +182 -0
- rem/api/mcp_router/resources.py +536 -0
- rem/api/mcp_router/server.py +213 -0
- rem/api/mcp_router/tools.py +584 -0
- rem/api/routers/auth.py +229 -0
- rem/api/routers/chat/__init__.py +5 -0
- rem/api/routers/chat/completions.py +281 -0
- rem/api/routers/chat/json_utils.py +76 -0
- rem/api/routers/chat/models.py +124 -0
- rem/api/routers/chat/streaming.py +185 -0
- rem/auth/README.md +258 -0
- rem/auth/__init__.py +26 -0
- rem/auth/middleware.py +100 -0
- rem/auth/providers/__init__.py +13 -0
- rem/auth/providers/base.py +376 -0
- rem/auth/providers/google.py +163 -0
- rem/auth/providers/microsoft.py +237 -0
- rem/cli/README.md +455 -0
- rem/cli/__init__.py +8 -0
- rem/cli/commands/README.md +126 -0
- rem/cli/commands/__init__.py +3 -0
- rem/cli/commands/ask.py +565 -0
- rem/cli/commands/configure.py +423 -0
- rem/cli/commands/db.py +493 -0
- rem/cli/commands/dreaming.py +324 -0
- rem/cli/commands/experiments.py +1124 -0
- rem/cli/commands/mcp.py +66 -0
- rem/cli/commands/process.py +245 -0
- rem/cli/commands/schema.py +183 -0
- rem/cli/commands/serve.py +106 -0
- rem/cli/dreaming.py +363 -0
- rem/cli/main.py +88 -0
- rem/config.py +237 -0
- rem/mcp_server.py +41 -0
- rem/models/core/__init__.py +49 -0
- rem/models/core/core_model.py +64 -0
- rem/models/core/engram.py +333 -0
- rem/models/core/experiment.py +628 -0
- rem/models/core/inline_edge.py +132 -0
- rem/models/core/rem_query.py +243 -0
- rem/models/entities/__init__.py +43 -0
- rem/models/entities/file.py +57 -0
- rem/models/entities/image_resource.py +88 -0
- rem/models/entities/message.py +35 -0
- rem/models/entities/moment.py +123 -0
- rem/models/entities/ontology.py +191 -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/user.py +85 -0
- rem/py.typed +0 -0
- rem/schemas/README.md +507 -0
- rem/schemas/__init__.py +6 -0
- rem/schemas/agents/README.md +92 -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 +128 -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 +16 -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 +806 -0
- rem/services/content/service.py +657 -0
- rem/services/dreaming/README.md +230 -0
- rem/services/dreaming/__init__.py +53 -0
- rem/services/dreaming/affinity_service.py +336 -0
- rem/services/dreaming/moment_service.py +264 -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/embeddings/__init__.py +11 -0
- rem/services/embeddings/api.py +120 -0
- rem/services/embeddings/worker.py +421 -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 +686 -0
- rem/services/phoenix/config.py +88 -0
- rem/services/phoenix/prompt_labels.py +477 -0
- rem/services/postgres/README.md +575 -0
- rem/services/postgres/__init__.py +23 -0
- rem/services/postgres/migration_service.py +427 -0
- rem/services/postgres/pydantic_to_sqlalchemy.py +232 -0
- rem/services/postgres/register_type.py +352 -0
- rem/services/postgres/repository.py +337 -0
- rem/services/postgres/schema_generator.py +379 -0
- rem/services/postgres/service.py +802 -0
- rem/services/postgres/sql_builder.py +354 -0
- rem/services/rem/README.md +304 -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 +145 -0
- rem/services/rem/queries.py +196 -0
- rem/services/rem/query.py +371 -0
- rem/services/rem/service.py +527 -0
- rem/services/session/README.md +374 -0
- rem/services/session/__init__.py +6 -0
- rem/services/session/compression.py +360 -0
- rem/services/session/reload.py +77 -0
- rem/settings.py +1235 -0
- rem/sql/002_install_models.sql +1068 -0
- rem/sql/background_indexes.sql +42 -0
- rem/sql/install_models.sql +1038 -0
- rem/sql/migrations/001_install.sql +503 -0
- rem/sql/migrations/002_install_models.sql +1202 -0
- rem/utils/AGENTIC_CHUNKING.md +597 -0
- rem/utils/README.md +583 -0
- rem/utils/__init__.py +43 -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/dict_utils.py +98 -0
- rem/utils/embeddings.py +423 -0
- rem/utils/examples/embeddings_example.py +305 -0
- rem/utils/examples/sql_types_example.py +202 -0
- rem/utils/markdown.py +16 -0
- rem/utils/model_helpers.py +236 -0
- rem/utils/schema_loader.py +229 -0
- rem/utils/sql_types.py +348 -0
- rem/utils/user_id.py +81 -0
- rem/utils/vision.py +330 -0
- rem/workers/README.md +506 -0
- rem/workers/__init__.py +5 -0
- rem/workers/dreaming.py +502 -0
- rem/workers/engram_processor.py +312 -0
- rem/workers/sqs_file_processor.py +193 -0
- remdb-0.2.6.dist-info/METADATA +1191 -0
- remdb-0.2.6.dist-info/RECORD +187 -0
- remdb-0.2.6.dist-info/WHEEL +4 -0
- remdb-0.2.6.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
"""
|
|
2
|
+
REM configuration wizard.
|
|
3
|
+
|
|
4
|
+
Interactive setup wizard for configuring REM on a new installation.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
rem configure # Interactive wizard
|
|
8
|
+
rem configure --install # Run wizard + install database tables
|
|
9
|
+
rem configure --show # Show current configuration
|
|
10
|
+
rem configure --edit # Open config file in editor
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import subprocess
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
import click
|
|
18
|
+
from loguru import logger
|
|
19
|
+
|
|
20
|
+
from rem.config import (
|
|
21
|
+
config_exists,
|
|
22
|
+
ensure_config_dir,
|
|
23
|
+
get_config_path,
|
|
24
|
+
get_default_config,
|
|
25
|
+
load_config,
|
|
26
|
+
save_config,
|
|
27
|
+
validate_config,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def prompt_postgres_config() -> dict:
|
|
32
|
+
"""
|
|
33
|
+
Prompt user for PostgreSQL configuration.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
PostgreSQL configuration dictionary
|
|
37
|
+
"""
|
|
38
|
+
click.echo("\n" + "=" * 60)
|
|
39
|
+
click.echo("PostgreSQL Configuration")
|
|
40
|
+
click.echo("=" * 60)
|
|
41
|
+
|
|
42
|
+
# Parse existing config if available
|
|
43
|
+
existing_conn = os.environ.get(
|
|
44
|
+
"POSTGRES__CONNECTION_STRING", "postgresql://rem:rem@localhost:5051/rem"
|
|
45
|
+
)
|
|
46
|
+
|
|
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")
|
|
54
|
+
|
|
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)
|
|
60
|
+
|
|
61
|
+
# Build connection string
|
|
62
|
+
connection_string = f"postgresql://{username}:{password}@{host}:{port}/{database}"
|
|
63
|
+
|
|
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
|
+
return {
|
|
70
|
+
"connection_string": connection_string,
|
|
71
|
+
"pool_min_size": pool_min_size,
|
|
72
|
+
"pool_max_size": pool_max_size,
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def prompt_llm_config() -> dict:
|
|
77
|
+
"""
|
|
78
|
+
Prompt user for LLM provider configuration.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
LLM configuration dictionary
|
|
82
|
+
"""
|
|
83
|
+
click.echo("\n" + "=" * 60)
|
|
84
|
+
click.echo("LLM Provider Configuration")
|
|
85
|
+
click.echo("=" * 60)
|
|
86
|
+
|
|
87
|
+
config = {}
|
|
88
|
+
|
|
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
|
+
)
|
|
99
|
+
|
|
100
|
+
# Temperature
|
|
101
|
+
config["default_temperature"] = click.prompt(
|
|
102
|
+
"Default temperature (0.0-1.0)", default=0.5, type=float
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# API keys
|
|
106
|
+
click.echo("\nAPI Keys (optional - leave empty to skip):")
|
|
107
|
+
|
|
108
|
+
openai_key = click.prompt("OpenAI API key", default="", show_default=False)
|
|
109
|
+
if openai_key:
|
|
110
|
+
config["openai_api_key"] = openai_key
|
|
111
|
+
|
|
112
|
+
anthropic_key = click.prompt("Anthropic API key", default="", show_default=False)
|
|
113
|
+
if anthropic_key:
|
|
114
|
+
config["anthropic_api_key"] = anthropic_key
|
|
115
|
+
|
|
116
|
+
return config
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def prompt_s3_config() -> dict:
|
|
120
|
+
"""
|
|
121
|
+
Prompt user for S3 storage configuration.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
S3 configuration dictionary
|
|
125
|
+
"""
|
|
126
|
+
click.echo("\n" + "=" * 60)
|
|
127
|
+
click.echo("S3 Storage Configuration")
|
|
128
|
+
click.echo("=" * 60)
|
|
129
|
+
|
|
130
|
+
config = {}
|
|
131
|
+
|
|
132
|
+
click.echo("\nS3 storage is used for file uploads and processed content.")
|
|
133
|
+
use_s3 = click.confirm("Configure S3 storage?", default=True)
|
|
134
|
+
|
|
135
|
+
if not use_s3:
|
|
136
|
+
return {}
|
|
137
|
+
|
|
138
|
+
config["bucket_name"] = click.prompt("S3 bucket name", default="rem-storage")
|
|
139
|
+
config["region"] = click.prompt("AWS region", default="us-east-1")
|
|
140
|
+
|
|
141
|
+
# Optional: MinIO or LocalStack endpoint
|
|
142
|
+
use_custom_endpoint = click.confirm(
|
|
143
|
+
"Use custom S3 endpoint (MinIO, LocalStack)?", default=False
|
|
144
|
+
)
|
|
145
|
+
if use_custom_endpoint:
|
|
146
|
+
config["endpoint_url"] = click.prompt(
|
|
147
|
+
"Endpoint URL", default="http://localhost:9000"
|
|
148
|
+
)
|
|
149
|
+
config["access_key_id"] = click.prompt("Access key ID", default="minioadmin")
|
|
150
|
+
config["secret_access_key"] = click.prompt(
|
|
151
|
+
"Secret access key", default="minioadmin", hide_input=True
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
return config
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def prompt_additional_env_vars() -> dict:
|
|
158
|
+
"""
|
|
159
|
+
Prompt user for additional environment variables.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
Dictionary of custom environment variables
|
|
163
|
+
"""
|
|
164
|
+
click.echo("\n" + "=" * 60)
|
|
165
|
+
click.echo("Additional Environment Variables")
|
|
166
|
+
click.echo("=" * 60)
|
|
167
|
+
|
|
168
|
+
env_vars: dict[str, str] = {}
|
|
169
|
+
|
|
170
|
+
add_env = click.confirm(
|
|
171
|
+
"Add custom environment variables?", default=False
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
if not add_env:
|
|
175
|
+
return env_vars
|
|
176
|
+
|
|
177
|
+
click.echo("\nEnter environment variables (empty name to finish):")
|
|
178
|
+
while True:
|
|
179
|
+
name = click.prompt("Variable name", default="", show_default=False)
|
|
180
|
+
if not name:
|
|
181
|
+
break
|
|
182
|
+
|
|
183
|
+
value = click.prompt(f"Value for {name}")
|
|
184
|
+
env_vars[name] = value
|
|
185
|
+
|
|
186
|
+
return env_vars
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
@click.command("configure")
|
|
190
|
+
@click.option(
|
|
191
|
+
"--install",
|
|
192
|
+
is_flag=True,
|
|
193
|
+
help="Install database tables after configuration",
|
|
194
|
+
)
|
|
195
|
+
@click.option(
|
|
196
|
+
"--claude-desktop",
|
|
197
|
+
is_flag=True,
|
|
198
|
+
help="Register REM MCP server with Claude Desktop",
|
|
199
|
+
)
|
|
200
|
+
@click.option(
|
|
201
|
+
"--show",
|
|
202
|
+
is_flag=True,
|
|
203
|
+
help="Show current configuration",
|
|
204
|
+
)
|
|
205
|
+
@click.option(
|
|
206
|
+
"--edit",
|
|
207
|
+
is_flag=True,
|
|
208
|
+
help="Open configuration file in editor",
|
|
209
|
+
)
|
|
210
|
+
def configure_command(install: bool, claude_desktop: bool, show: bool, edit: bool):
|
|
211
|
+
"""
|
|
212
|
+
Configure REM installation.
|
|
213
|
+
|
|
214
|
+
Interactive wizard for setting up PostgreSQL, LLM providers, S3, and more.
|
|
215
|
+
Configuration is saved to ~/.rem/config.yaml and merged with environment variables.
|
|
216
|
+
|
|
217
|
+
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
|
|
222
|
+
"""
|
|
223
|
+
config_path = get_config_path()
|
|
224
|
+
|
|
225
|
+
# Show current configuration
|
|
226
|
+
if show:
|
|
227
|
+
if not config_exists():
|
|
228
|
+
click.echo(f"No configuration file found at {config_path}")
|
|
229
|
+
click.echo("Run 'rem configure' to create one.")
|
|
230
|
+
return
|
|
231
|
+
|
|
232
|
+
config = load_config()
|
|
233
|
+
click.echo(f"\nConfiguration file: {config_path}")
|
|
234
|
+
click.echo("=" * 60)
|
|
235
|
+
|
|
236
|
+
import yaml
|
|
237
|
+
|
|
238
|
+
click.echo(yaml.dump(config, default_flow_style=False, sort_keys=False))
|
|
239
|
+
return
|
|
240
|
+
|
|
241
|
+
# Edit configuration file
|
|
242
|
+
if edit:
|
|
243
|
+
if not config_exists():
|
|
244
|
+
click.echo(f"No configuration file found at {config_path}")
|
|
245
|
+
click.echo("Run 'rem configure' to create one first.")
|
|
246
|
+
return
|
|
247
|
+
|
|
248
|
+
editor = os.environ.get("EDITOR", "vim")
|
|
249
|
+
try:
|
|
250
|
+
subprocess.run([editor, str(config_path)], check=True)
|
|
251
|
+
click.echo(f"\nConfiguration saved to {config_path}")
|
|
252
|
+
except Exception as e:
|
|
253
|
+
click.echo(f"Error opening editor: {e}", err=True)
|
|
254
|
+
click.echo(f"Manually edit: {config_path}")
|
|
255
|
+
return
|
|
256
|
+
|
|
257
|
+
# Run interactive wizard
|
|
258
|
+
click.echo("\n" + "=" * 60)
|
|
259
|
+
click.echo("REM Configuration Wizard")
|
|
260
|
+
click.echo("=" * 60)
|
|
261
|
+
click.echo("\nThis wizard will help you configure REM for first-time use.")
|
|
262
|
+
click.echo(f"Configuration will be saved to: {config_path}")
|
|
263
|
+
|
|
264
|
+
# Check if config already exists
|
|
265
|
+
if config_exists():
|
|
266
|
+
click.echo(f"\nConfiguration file already exists at {config_path}")
|
|
267
|
+
if not click.confirm("Overwrite existing configuration?", default=False):
|
|
268
|
+
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)
|
|
294
|
+
|
|
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
|
|
302
|
+
|
|
303
|
+
click.echo("✅ Configuration is valid")
|
|
304
|
+
|
|
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
|
|
312
|
+
|
|
313
|
+
# Install database tables if requested
|
|
314
|
+
if install:
|
|
315
|
+
click.echo("\n" + "=" * 60)
|
|
316
|
+
click.echo("Database Installation")
|
|
317
|
+
click.echo("=" * 60)
|
|
318
|
+
|
|
319
|
+
if click.confirm("\nInstall database tables?", default=True):
|
|
320
|
+
try:
|
|
321
|
+
# Import here to ensure config is loaded first
|
|
322
|
+
from rem.config import merge_config_to_env
|
|
323
|
+
|
|
324
|
+
# Merge config into environment before running migrations
|
|
325
|
+
merge_config_to_env(config)
|
|
326
|
+
|
|
327
|
+
click.echo("\nRunning database migrations...")
|
|
328
|
+
|
|
329
|
+
# Import and run migrations
|
|
330
|
+
from rem.cli.commands.db import migrate
|
|
331
|
+
|
|
332
|
+
# Create a context for the command and invoke it
|
|
333
|
+
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"))
|
|
337
|
+
|
|
338
|
+
click.echo("✅ Database installation complete")
|
|
339
|
+
|
|
340
|
+
except Exception as e:
|
|
341
|
+
click.echo(f"\n❌ Database installation failed: {e}", err=True)
|
|
342
|
+
click.echo("\nYou can manually install tables later with:")
|
|
343
|
+
click.echo(" rem db migrate")
|
|
344
|
+
|
|
345
|
+
# Register with Claude Desktop if requested
|
|
346
|
+
if claude_desktop:
|
|
347
|
+
click.echo("\n" + "=" * 60)
|
|
348
|
+
click.echo("Claude Desktop Integration")
|
|
349
|
+
click.echo("=" * 60)
|
|
350
|
+
|
|
351
|
+
try:
|
|
352
|
+
import shutil
|
|
353
|
+
from pathlib import Path
|
|
354
|
+
from fastmcp.mcp_config import update_config_file, StdioMCPServer
|
|
355
|
+
|
|
356
|
+
# Find Claude Desktop config path
|
|
357
|
+
if os.name == "nt": # Windows
|
|
358
|
+
config_dir = Path.home() / "AppData/Roaming/Claude"
|
|
359
|
+
elif os.name == "posix":
|
|
360
|
+
if Path.home() / "Library/Application Support/Claude":
|
|
361
|
+
config_dir = Path.home() / "Library/Application Support/Claude"
|
|
362
|
+
else:
|
|
363
|
+
config_dir = Path.home() / ".config/Claude"
|
|
364
|
+
else:
|
|
365
|
+
config_dir = Path.home() / ".config/Claude"
|
|
366
|
+
|
|
367
|
+
config_path = config_dir / "claude_desktop_config.json"
|
|
368
|
+
|
|
369
|
+
# Find rem executable
|
|
370
|
+
rem_executable = shutil.which("rem")
|
|
371
|
+
if not rem_executable:
|
|
372
|
+
click.echo("❌ 'rem' command not found in PATH", err=True)
|
|
373
|
+
return
|
|
374
|
+
|
|
375
|
+
# Create server config with all necessary env vars
|
|
376
|
+
env_vars = {
|
|
377
|
+
"POSTGRES__CONNECTION_STRING": config.get("postgres", {}).get("connection_string", "")
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
# Add LLM API keys if present
|
|
381
|
+
llm_config = config.get("llm", {})
|
|
382
|
+
if llm_config.get("openai_api_key"):
|
|
383
|
+
env_vars["LLM__OPENAI_API_KEY"] = llm_config["openai_api_key"]
|
|
384
|
+
if llm_config.get("anthropic_api_key"):
|
|
385
|
+
env_vars["LLM__ANTHROPIC_API_KEY"] = llm_config["anthropic_api_key"]
|
|
386
|
+
|
|
387
|
+
server_config = StdioMCPServer(
|
|
388
|
+
command=rem_executable,
|
|
389
|
+
args=["mcp"],
|
|
390
|
+
env=env_vars
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
# Update config file using FastMCP utility
|
|
394
|
+
update_config_file(config_path, "rem", server_config)
|
|
395
|
+
|
|
396
|
+
click.echo(f"✅ Registered REM MCP server with Claude Desktop")
|
|
397
|
+
click.echo(f"Config: {config_path}")
|
|
398
|
+
click.echo("\nRestart Claude Desktop to use the REM server.")
|
|
399
|
+
|
|
400
|
+
except Exception as e:
|
|
401
|
+
click.echo(f"❌ Failed: {e}", err=True)
|
|
402
|
+
|
|
403
|
+
# Next steps
|
|
404
|
+
click.echo("\n" + "=" * 60)
|
|
405
|
+
click.echo("Next Steps")
|
|
406
|
+
click.echo("=" * 60)
|
|
407
|
+
click.echo("\n1. Verify configuration:")
|
|
408
|
+
click.echo(" rem configure --show")
|
|
409
|
+
click.echo("\n2. Edit configuration (if needed):")
|
|
410
|
+
click.echo(" rem configure --edit")
|
|
411
|
+
if not install:
|
|
412
|
+
click.echo("\n3. Install database tables:")
|
|
413
|
+
click.echo(" rem db migrate")
|
|
414
|
+
click.echo("\n4. Start the API server:")
|
|
415
|
+
click.echo(" rem dev run-server")
|
|
416
|
+
click.echo("\n5. Test the installation:")
|
|
417
|
+
click.echo(" rem ask 'Hello, REM!'")
|
|
418
|
+
click.echo()
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def register_command(cli_group):
|
|
422
|
+
"""Register the configure command."""
|
|
423
|
+
cli_group.add_command(configure_command)
|