utim-cli 1.44.9__tar.gz → 1.45.2__tar.gz
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.
- {utim_cli-1.44.9/utim_cli.egg-info → utim_cli-1.45.2}/PKG-INFO +10 -5
- {utim_cli-1.44.9 → utim_cli-1.45.2}/pyproject.toml +11 -5
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/doctor.py +2 -1
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/db.py +50 -49
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/router.py +1 -1
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/completion_routes.py +4 -0
- utim_cli-1.45.2/utim_cli/server/server.py +56 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/utim.py +3 -3
- {utim_cli-1.44.9 → utim_cli-1.45.2/utim_cli.egg-info}/PKG-INFO +10 -5
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli.egg-info/requires.txt +10 -4
- utim_cli-1.44.9/utim_cli/server/server.py +0 -56
- {utim_cli-1.44.9 → utim_cli-1.45.2}/CHANGELOG.md +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/LICENSE +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/MANIFEST.in +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/README.md +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/setup.cfg +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/setup.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/__init__.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/agent.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/auth.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/backup.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/blender_agent.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/bootstrap.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/client_utils.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/config.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/constants.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/context_pruner.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/knowledge_graph.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/logger.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/mcp_clean_wrapper.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/mcp_client.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/mcp_registry.json +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/orchestrator.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/reflection.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/report.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/scrapy_search.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/__init__.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/auth.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/email_utils.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/firebase.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/history.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/logging_config.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/models.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/rate_limit.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/__init__.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/auth_routes.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/credit_routes.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/quota_routes.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/session_routes.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/share_routes.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/share.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/share_tui.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/situational_scoring.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/state.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tools.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/__init__.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/history_dialog.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/mcp_dialog.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/model_dialog.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/resume_dialog.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/tools_dialog.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/update_dialog.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/vector_memory.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/workspace.py +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli.egg-info/SOURCES.txt +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli.egg-info/dependency_links.txt +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli.egg-info/entry_points.txt +0 -0
- {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: utim-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.45.2
|
|
4
4
|
Summary: UTIM – Universal Terminal Intelligence Manager. A powerful agentic AI coding assistant for your terminal.
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Homepage, https://utim.dev
|
|
@@ -30,10 +30,6 @@ Requires-Dist: chardet==4.0.0
|
|
|
30
30
|
Requires-Dist: typer>=0.9.0
|
|
31
31
|
Requires-Dist: rich>=13.0.0
|
|
32
32
|
Requires-Dist: prompt_toolkit>=3.0.0
|
|
33
|
-
Requires-Dist: tree-sitter>=0.21.0
|
|
34
|
-
Requires-Dist: tree-sitter-python>=0.21.0
|
|
35
|
-
Requires-Dist: tree-sitter-javascript>=0.21.0
|
|
36
|
-
Requires-Dist: tree-sitter-typescript>=0.21.0
|
|
37
33
|
Requires-Dist: mcp>=0.1.0
|
|
38
34
|
Requires-Dist: nest-asyncio>=1.5.0
|
|
39
35
|
Requires-Dist: python-multipart>=0.0.7
|
|
@@ -45,11 +41,20 @@ Requires-Dist: scrapy-playwright>=0.0.34; extra == "search"
|
|
|
45
41
|
Requires-Dist: beautifulsoup4>=4.12.0; extra == "search"
|
|
46
42
|
Provides-Extra: images
|
|
47
43
|
Requires-Dist: pillow>=9.0.0; extra == "images"
|
|
44
|
+
Provides-Extra: parsers
|
|
45
|
+
Requires-Dist: tree-sitter>=0.21.0; extra == "parsers"
|
|
46
|
+
Requires-Dist: tree-sitter-python>=0.21.0; extra == "parsers"
|
|
47
|
+
Requires-Dist: tree-sitter-javascript>=0.21.0; extra == "parsers"
|
|
48
|
+
Requires-Dist: tree-sitter-typescript>=0.21.0; extra == "parsers"
|
|
48
49
|
Provides-Extra: full
|
|
49
50
|
Requires-Dist: scrapy>=2.11.0; extra == "full"
|
|
50
51
|
Requires-Dist: scrapy-playwright>=0.0.34; extra == "full"
|
|
51
52
|
Requires-Dist: beautifulsoup4>=4.12.0; extra == "full"
|
|
52
53
|
Requires-Dist: pillow>=9.0.0; extra == "full"
|
|
54
|
+
Requires-Dist: tree-sitter>=0.21.0; extra == "full"
|
|
55
|
+
Requires-Dist: tree-sitter-python>=0.21.0; extra == "full"
|
|
56
|
+
Requires-Dist: tree-sitter-javascript>=0.21.0; extra == "full"
|
|
57
|
+
Requires-Dist: tree-sitter-typescript>=0.21.0; extra == "full"
|
|
53
58
|
Dynamic: license-file
|
|
54
59
|
|
|
55
60
|
# UTIM CLI Agent: Enterprise Coder Assistant
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "utim-cli"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.45.2"
|
|
8
8
|
description = "UTIM – Universal Terminal Intelligence Manager. A powerful agentic AI coding assistant for your terminal."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -32,10 +32,6 @@ dependencies = [
|
|
|
32
32
|
"typer>=0.9.0",
|
|
33
33
|
"rich>=13.0.0",
|
|
34
34
|
"prompt_toolkit>=3.0.0",
|
|
35
|
-
"tree-sitter>=0.21.0",
|
|
36
|
-
"tree-sitter-python>=0.21.0",
|
|
37
|
-
"tree-sitter-javascript>=0.21.0",
|
|
38
|
-
"tree-sitter-typescript>=0.21.0",
|
|
39
35
|
"mcp>=0.1.0",
|
|
40
36
|
"nest-asyncio>=1.5.0",
|
|
41
37
|
"python-multipart>=0.0.7",
|
|
@@ -59,11 +55,21 @@ search = [
|
|
|
59
55
|
images = [
|
|
60
56
|
"pillow>=9.0.0",
|
|
61
57
|
]
|
|
58
|
+
parsers = [
|
|
59
|
+
"tree-sitter>=0.21.0",
|
|
60
|
+
"tree-sitter-python>=0.21.0",
|
|
61
|
+
"tree-sitter-javascript>=0.21.0",
|
|
62
|
+
"tree-sitter-typescript>=0.21.0",
|
|
63
|
+
]
|
|
62
64
|
full = [
|
|
63
65
|
"scrapy>=2.11.0",
|
|
64
66
|
"scrapy-playwright>=0.0.34",
|
|
65
67
|
"beautifulsoup4>=4.12.0",
|
|
66
68
|
"pillow>=9.0.0",
|
|
69
|
+
"tree-sitter>=0.21.0",
|
|
70
|
+
"tree-sitter-python>=0.21.0",
|
|
71
|
+
"tree-sitter-javascript>=0.21.0",
|
|
72
|
+
"tree-sitter-typescript>=0.21.0",
|
|
67
73
|
]
|
|
68
74
|
|
|
69
75
|
[project.scripts]
|
|
@@ -22,7 +22,7 @@ def run_diagnostics(console: Console = None):
|
|
|
22
22
|
console.print("\n [bold #42bcf5]Core Dependencies:[/bold #42bcf5]")
|
|
23
23
|
core_dependencies = [
|
|
24
24
|
"openai", "requests", "aiohttp", "typer", "rich",
|
|
25
|
-
"prompt_toolkit", "
|
|
25
|
+
"prompt_toolkit", "mcp", "nest_asyncio"
|
|
26
26
|
]
|
|
27
27
|
for dep in core_dependencies:
|
|
28
28
|
try:
|
|
@@ -34,6 +34,7 @@ def run_diagnostics(console: Console = None):
|
|
|
34
34
|
|
|
35
35
|
console.print("\n [bold #42bcf5]Optional Feature Dependencies:[/bold #42bcf5]")
|
|
36
36
|
optional_dependencies = {
|
|
37
|
+
"tree_sitter": "AST-based Knowledge Graph / dependency mapping",
|
|
37
38
|
"chromadb": "RAG Vector DB feature",
|
|
38
39
|
"sentence_transformers": "Dynamic embedding extraction",
|
|
39
40
|
"scrapy": "Scrapy search crawler",
|
|
@@ -396,14 +396,22 @@ class EmailTracking(Base):
|
|
|
396
396
|
|
|
397
397
|
# ── Bootstrap ─────────────────────────────────────────────────────────────────
|
|
398
398
|
|
|
399
|
-
def init_db() -> None:
|
|
399
|
+
def init_db(silent: bool = True) -> None:
|
|
400
400
|
"""Create all tables and ensure the schema is up to date."""
|
|
401
401
|
import logging as _logging
|
|
402
402
|
_mig_log = _logging.getLogger("utim.db.migration")
|
|
403
|
+
|
|
404
|
+
def _print(msg: str):
|
|
405
|
+
if not silent:
|
|
406
|
+
print(msg)
|
|
403
407
|
|
|
408
|
+
_print("[DB INIT] init_db() starting...")
|
|
404
409
|
try:
|
|
410
|
+
_print(f"[DB INIT] Connecting to DB: {engine.url.drivername} (host: {engine.url.host})")
|
|
405
411
|
Base.metadata.create_all(bind=engine)
|
|
412
|
+
_print("[DB INIT] create_all() completed.")
|
|
406
413
|
except Exception as exc:
|
|
414
|
+
_print(f"[DB INIT] create_all() failed: {exc}")
|
|
407
415
|
_mig_log.warning(f"Skipping table creation (database might be unavailable): {exc}")
|
|
408
416
|
return
|
|
409
417
|
|
|
@@ -412,70 +420,62 @@ def init_db() -> None:
|
|
|
412
420
|
from sqlalchemy import text, inspect as sa_inspect
|
|
413
421
|
is_postgres = DATABASE_URL.startswith("postgresql")
|
|
414
422
|
|
|
415
|
-
|
|
423
|
+
try:
|
|
424
|
+
inspector = sa_inspect(engine)
|
|
425
|
+
existing_tables = inspector.get_table_names()
|
|
426
|
+
except Exception as inspect_exc:
|
|
427
|
+
_print(f"[DB INIT] DB inspection failed (might be normal on new DB): {inspect_exc}")
|
|
428
|
+
existing_tables = []
|
|
429
|
+
|
|
430
|
+
def _col_exists(table_name: str, col_name: str) -> bool:
|
|
431
|
+
if table_name not in existing_tables:
|
|
432
|
+
return False
|
|
433
|
+
try:
|
|
434
|
+
columns = [c["name"] for c in inspector.get_columns(table_name)]
|
|
435
|
+
return col_name in columns
|
|
436
|
+
except Exception:
|
|
437
|
+
return False
|
|
438
|
+
|
|
439
|
+
def _run_migration(table_name: str, col_name: str, sql: str, label: str):
|
|
440
|
+
if _col_exists(table_name, col_name):
|
|
441
|
+
_print(f"[DB INIT] Column {table_name}.{col_name} already exists. Skipping.")
|
|
442
|
+
return
|
|
443
|
+
|
|
444
|
+
_print(f"[DB INIT] Running migration: {label}")
|
|
416
445
|
try:
|
|
417
446
|
with engine.begin() as _conn:
|
|
447
|
+
if is_postgres:
|
|
448
|
+
# Never hang startup for lock queues: fail fast if blocked for > 3s
|
|
449
|
+
_conn.execute(text("SET lock_timeout = 3000"))
|
|
418
450
|
_conn.execute(text(sql))
|
|
451
|
+
_print(f"[DB INIT] Migration OK: {label}")
|
|
419
452
|
_mig_log.info(f"Migration OK: {label}")
|
|
420
453
|
except Exception as _exc:
|
|
421
|
-
|
|
454
|
+
_print(f"[DB INIT] Migration skipped/failed ({label}): {_exc}")
|
|
422
455
|
_mig_log.debug(f"Migration skipped ({label}): {_exc}")
|
|
423
456
|
|
|
424
457
|
if is_postgres:
|
|
425
|
-
|
|
426
|
-
_run_migration(
|
|
427
|
-
"ALTER TABLE user_subscriptions ADD COLUMN IF NOT EXISTS refills_processed INTEGER DEFAULT 0 NOT NULL",
|
|
428
|
-
"add refills_processed"
|
|
429
|
-
)
|
|
430
|
-
_run_migration(
|
|
431
|
-
"ALTER TABLE user_subscriptions ADD COLUMN IF NOT EXISTS last_refill_at TIMESTAMP",
|
|
432
|
-
"add last_refill_at"
|
|
433
|
-
)
|
|
434
|
-
_run_migration(
|
|
435
|
-
"ALTER TABLE user_subscriptions ADD COLUMN IF NOT EXISTS current_cycle_used DOUBLE PRECISION DEFAULT 0.0 NOT NULL",
|
|
436
|
-
"add current_cycle_used"
|
|
437
|
-
)
|
|
438
|
-
_run_migration(
|
|
439
|
-
"ALTER TABLE credits ADD COLUMN IF NOT EXISTS bonus_balance DOUBLE PRECISION DEFAULT 0.0 NOT NULL",
|
|
440
|
-
"add bonus_balance"
|
|
441
|
-
)
|
|
442
|
-
_run_migration(
|
|
443
|
-
"ALTER TABLE credits ADD COLUMN IF NOT EXISTS bonus_limit DOUBLE PRECISION DEFAULT 0.0 NOT NULL",
|
|
444
|
-
"add bonus_limit"
|
|
445
|
-
)
|
|
446
|
-
_run_migration(
|
|
447
|
-
"ALTER TABLE email_tracking ADD COLUMN IF NOT EXISTS low_quota_email_sent_at TIMESTAMP",
|
|
448
|
-
"add low_quota_email_sent_at"
|
|
449
|
-
)
|
|
450
|
-
_run_migration(
|
|
451
|
-
"ALTER TABLE email_tracking ADD COLUMN IF NOT EXISTS exhausted_email_sent_at TIMESTAMP",
|
|
452
|
-
"add exhausted_email_sent_at"
|
|
453
|
-
)
|
|
454
|
-
_run_migration(
|
|
455
|
-
"ALTER TABLE email_tracking ADD COLUMN IF NOT EXISTS bonus_email_sent_at TIMESTAMP",
|
|
456
|
-
"add bonus_email_sent_at"
|
|
457
|
-
)
|
|
458
|
-
_run_migration(
|
|
459
|
-
"ALTER TABLE users ADD COLUMN IF NOT EXISTS last_project_folder TEXT",
|
|
460
|
-
"add last_project_folder"
|
|
461
|
-
)
|
|
458
|
+
_print("[DB INIT] Postgres detected. Bypassing ALTER TABLE migrations (already applied in production).")
|
|
462
459
|
else:
|
|
463
460
|
# SQLite: no IF NOT EXISTS on ADD COLUMN, swallow duplicate errors
|
|
464
|
-
_run_migration("ALTER TABLE user_subscriptions ADD COLUMN refills_processed INTEGER DEFAULT 0 NOT NULL", "sqlite add refills_processed")
|
|
465
|
-
_run_migration("ALTER TABLE user_subscriptions ADD COLUMN last_refill_at TIMESTAMP", "sqlite add last_refill_at")
|
|
466
|
-
_run_migration("ALTER TABLE user_subscriptions ADD COLUMN current_cycle_used FLOAT DEFAULT 0.0 NOT NULL", "sqlite add current_cycle_used")
|
|
467
|
-
_run_migration("ALTER TABLE credits ADD COLUMN bonus_balance FLOAT DEFAULT 0.0 NOT NULL", "sqlite add bonus_balance")
|
|
468
|
-
_run_migration("ALTER TABLE credits ADD COLUMN bonus_limit FLOAT DEFAULT 0.0 NOT NULL", "sqlite add bonus_limit")
|
|
469
|
-
_run_migration("ALTER TABLE email_tracking ADD COLUMN low_quota_email_sent_at TIMESTAMP", "sqlite add low_quota_email_sent_at")
|
|
470
|
-
_run_migration("ALTER TABLE email_tracking ADD COLUMN exhausted_email_sent_at TIMESTAMP", "sqlite add exhausted_email_sent_at")
|
|
471
|
-
_run_migration("ALTER TABLE email_tracking ADD COLUMN bonus_email_sent_at TIMESTAMP", "sqlite add bonus_email_sent_at")
|
|
472
|
-
_run_migration("ALTER TABLE users ADD COLUMN last_project_folder TEXT", "sqlite add last_project_folder")
|
|
461
|
+
_run_migration("user_subscriptions", "refills_processed", "ALTER TABLE user_subscriptions ADD COLUMN refills_processed INTEGER DEFAULT 0 NOT NULL", "sqlite add refills_processed")
|
|
462
|
+
_run_migration("user_subscriptions", "last_refill_at", "ALTER TABLE user_subscriptions ADD COLUMN last_refill_at TIMESTAMP", "sqlite add last_refill_at")
|
|
463
|
+
_run_migration("user_subscriptions", "current_cycle_used", "ALTER TABLE user_subscriptions ADD COLUMN current_cycle_used FLOAT DEFAULT 0.0 NOT NULL", "sqlite add current_cycle_used")
|
|
464
|
+
_run_migration("credits", "bonus_balance", "ALTER TABLE credits ADD COLUMN bonus_balance FLOAT DEFAULT 0.0 NOT NULL", "sqlite add bonus_balance")
|
|
465
|
+
_run_migration("credits", "bonus_limit", "ALTER TABLE credits ADD COLUMN bonus_limit FLOAT DEFAULT 0.0 NOT NULL", "sqlite add bonus_limit")
|
|
466
|
+
_run_migration("email_tracking", "low_quota_email_sent_at", "ALTER TABLE email_tracking ADD COLUMN low_quota_email_sent_at TIMESTAMP", "sqlite add low_quota_email_sent_at")
|
|
467
|
+
_run_migration("email_tracking", "exhausted_email_sent_at", "ALTER TABLE email_tracking ADD COLUMN exhausted_email_sent_at TIMESTAMP", "sqlite add exhausted_email_sent_at")
|
|
468
|
+
_run_migration("email_tracking", "bonus_email_sent_at", "ALTER TABLE email_tracking ADD COLUMN bonus_email_sent_at TIMESTAMP", "sqlite add bonus_email_sent_at")
|
|
469
|
+
_run_migration("users", "last_project_folder", "ALTER TABLE users ADD COLUMN last_project_folder TEXT", "sqlite add last_project_folder")
|
|
473
470
|
|
|
474
471
|
# Seed the plans if they don't exist
|
|
472
|
+
_print("[DB INIT] Seeding plans checking...")
|
|
475
473
|
db = SessionLocal()
|
|
476
474
|
try:
|
|
477
475
|
free_plan = db.query(Plan).filter(Plan.name == "free").first()
|
|
476
|
+
_print(f"[DB INIT] Free plan query done. Exists: {bool(free_plan)}")
|
|
478
477
|
if not free_plan:
|
|
478
|
+
_print("[DB INIT] Creating new plans...")
|
|
479
479
|
plans = [
|
|
480
480
|
Plan(
|
|
481
481
|
id="free",
|
|
@@ -594,6 +594,7 @@ def init_db() -> None:
|
|
|
594
594
|
pass
|
|
595
595
|
finally:
|
|
596
596
|
db.close()
|
|
597
|
+
_print("[DB INIT] init_db() completed successfully.")
|
|
597
598
|
|
|
598
599
|
|
|
599
600
|
def get_db():
|
|
@@ -178,6 +178,10 @@ async def completions(
|
|
|
178
178
|
|
|
179
179
|
client = _get_client()
|
|
180
180
|
|
|
181
|
+
# Commit transaction to release all with_for_update locks on UserSubscription
|
|
182
|
+
# before returning the StreamingResponse, preventing deadlocks in the generator's SessionLocal updates.
|
|
183
|
+
db.commit()
|
|
184
|
+
|
|
181
185
|
async def _stream() -> AsyncGenerator[str, None]:
|
|
182
186
|
content_buf = ""
|
|
183
187
|
tool_calls_map: Dict[int, Dict[str, Any]] = {}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
UTIM Production Server — Entry Point
|
|
3
|
+
Run locally: python -m utim_cli.server.server
|
|
4
|
+
Railway runs: uvicorn utim_cli.server.router:app --host 0.0.0.0 --port $PORT
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
# Ensure parent and grandparent directories are in sys.path to import 'utim_cli'
|
|
12
|
+
_dir = os.path.dirname(os.path.abspath(__file__))
|
|
13
|
+
for _pd in [os.path.dirname(os.path.dirname(_dir)), os.path.dirname(_dir)]:
|
|
14
|
+
if _pd and _pd not in sys.path:
|
|
15
|
+
sys.path.insert(0, _pd)
|
|
16
|
+
|
|
17
|
+
import uvicorn
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def main():
|
|
21
|
+
host = os.environ.get("HOST", "0.0.0.0")
|
|
22
|
+
port = int(os.environ.get("PORT", 8080))
|
|
23
|
+
|
|
24
|
+
# Warn about missing env vars but DO NOT exit — server must start
|
|
25
|
+
required = {
|
|
26
|
+
"DATABASE_URL": os.environ.get("DATABASE_URL"),
|
|
27
|
+
"OPENROUTER_API_KEY": os.environ.get("OPENROUTER_API_KEY"),
|
|
28
|
+
"UTIM_MASTER_KEY": os.environ.get("UTIM_MASTER_KEY"),
|
|
29
|
+
}
|
|
30
|
+
missing = [k for k, v in required.items() if not v]
|
|
31
|
+
if missing:
|
|
32
|
+
print(f"[WARNING] Missing env vars: {', '.join(missing)} — some features will be degraded.")
|
|
33
|
+
print(" Set these in Railway → Service → Variables")
|
|
34
|
+
|
|
35
|
+
print(f"🚀 UTIM Production Server")
|
|
36
|
+
print(f" http://{host}:{port}")
|
|
37
|
+
print(f" Docs: http://{host}:{port}/docs")
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
uvicorn.run(
|
|
41
|
+
"utim_cli.server.router:app",
|
|
42
|
+
host=host,
|
|
43
|
+
port=port,
|
|
44
|
+
reload=False,
|
|
45
|
+
workers=1,
|
|
46
|
+
# Do NOT pass log_config=None — keep default logging so errors are visible
|
|
47
|
+
)
|
|
48
|
+
except Exception as exc:
|
|
49
|
+
print(f"[FATAL] uvicorn failed to start: {exc}", file=sys.stderr)
|
|
50
|
+
import traceback
|
|
51
|
+
traceback.print_exc()
|
|
52
|
+
sys.exit(1)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
if __name__ == "__main__":
|
|
56
|
+
main()
|
|
@@ -585,7 +585,7 @@ def _print_animated_banner():
|
|
|
585
585
|
# Speed up for spaces to make it feel more like typing
|
|
586
586
|
time.sleep(0.002 if char == " " else 0.005)
|
|
587
587
|
|
|
588
|
-
console.print(f"\n [bold white]U Think I Make[/bold white] [dim]v1.
|
|
588
|
+
console.print(f"\n [bold white]U Think I Make[/bold white] [dim]v1.45.2[/dim]")
|
|
589
589
|
user_email = config.email
|
|
590
590
|
user_type = "UTIM Community"
|
|
591
591
|
api_key = config.get("api_key")
|
|
@@ -2691,7 +2691,7 @@ def check_and_update_background():
|
|
|
2691
2691
|
return
|
|
2692
2692
|
|
|
2693
2693
|
latest_ver = resp.json().get("version", "")
|
|
2694
|
-
current_ver = "1.
|
|
2694
|
+
current_ver = "1.45.2"
|
|
2695
2695
|
|
|
2696
2696
|
def parse_ver(v):
|
|
2697
2697
|
return [int(x) for x in v.split(".") if x.isdigit()]
|
|
@@ -2887,7 +2887,7 @@ app = typer.Typer()
|
|
|
2887
2887
|
def version_callback(value: bool):
|
|
2888
2888
|
if value:
|
|
2889
2889
|
import typer
|
|
2890
|
-
print("U Think I Make v1.
|
|
2890
|
+
print("U Think I Make v1.45.2")
|
|
2891
2891
|
raise typer.Exit()
|
|
2892
2892
|
|
|
2893
2893
|
@app.callback(invoke_without_command=True)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: utim-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.45.2
|
|
4
4
|
Summary: UTIM – Universal Terminal Intelligence Manager. A powerful agentic AI coding assistant for your terminal.
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Homepage, https://utim.dev
|
|
@@ -30,10 +30,6 @@ Requires-Dist: chardet==4.0.0
|
|
|
30
30
|
Requires-Dist: typer>=0.9.0
|
|
31
31
|
Requires-Dist: rich>=13.0.0
|
|
32
32
|
Requires-Dist: prompt_toolkit>=3.0.0
|
|
33
|
-
Requires-Dist: tree-sitter>=0.21.0
|
|
34
|
-
Requires-Dist: tree-sitter-python>=0.21.0
|
|
35
|
-
Requires-Dist: tree-sitter-javascript>=0.21.0
|
|
36
|
-
Requires-Dist: tree-sitter-typescript>=0.21.0
|
|
37
33
|
Requires-Dist: mcp>=0.1.0
|
|
38
34
|
Requires-Dist: nest-asyncio>=1.5.0
|
|
39
35
|
Requires-Dist: python-multipart>=0.0.7
|
|
@@ -45,11 +41,20 @@ Requires-Dist: scrapy-playwright>=0.0.34; extra == "search"
|
|
|
45
41
|
Requires-Dist: beautifulsoup4>=4.12.0; extra == "search"
|
|
46
42
|
Provides-Extra: images
|
|
47
43
|
Requires-Dist: pillow>=9.0.0; extra == "images"
|
|
44
|
+
Provides-Extra: parsers
|
|
45
|
+
Requires-Dist: tree-sitter>=0.21.0; extra == "parsers"
|
|
46
|
+
Requires-Dist: tree-sitter-python>=0.21.0; extra == "parsers"
|
|
47
|
+
Requires-Dist: tree-sitter-javascript>=0.21.0; extra == "parsers"
|
|
48
|
+
Requires-Dist: tree-sitter-typescript>=0.21.0; extra == "parsers"
|
|
48
49
|
Provides-Extra: full
|
|
49
50
|
Requires-Dist: scrapy>=2.11.0; extra == "full"
|
|
50
51
|
Requires-Dist: scrapy-playwright>=0.0.34; extra == "full"
|
|
51
52
|
Requires-Dist: beautifulsoup4>=4.12.0; extra == "full"
|
|
52
53
|
Requires-Dist: pillow>=9.0.0; extra == "full"
|
|
54
|
+
Requires-Dist: tree-sitter>=0.21.0; extra == "full"
|
|
55
|
+
Requires-Dist: tree-sitter-python>=0.21.0; extra == "full"
|
|
56
|
+
Requires-Dist: tree-sitter-javascript>=0.21.0; extra == "full"
|
|
57
|
+
Requires-Dist: tree-sitter-typescript>=0.21.0; extra == "full"
|
|
53
58
|
Dynamic: license-file
|
|
54
59
|
|
|
55
60
|
# UTIM CLI Agent: Enterprise Coder Assistant
|
|
@@ -8,10 +8,6 @@ chardet==4.0.0
|
|
|
8
8
|
typer>=0.9.0
|
|
9
9
|
rich>=13.0.0
|
|
10
10
|
prompt_toolkit>=3.0.0
|
|
11
|
-
tree-sitter>=0.21.0
|
|
12
|
-
tree-sitter-python>=0.21.0
|
|
13
|
-
tree-sitter-javascript>=0.21.0
|
|
14
|
-
tree-sitter-typescript>=0.21.0
|
|
15
11
|
mcp>=0.1.0
|
|
16
12
|
nest-asyncio>=1.5.0
|
|
17
13
|
python-multipart>=0.0.7
|
|
@@ -23,10 +19,20 @@ scrapy>=2.11.0
|
|
|
23
19
|
scrapy-playwright>=0.0.34
|
|
24
20
|
beautifulsoup4>=4.12.0
|
|
25
21
|
pillow>=9.0.0
|
|
22
|
+
tree-sitter>=0.21.0
|
|
23
|
+
tree-sitter-python>=0.21.0
|
|
24
|
+
tree-sitter-javascript>=0.21.0
|
|
25
|
+
tree-sitter-typescript>=0.21.0
|
|
26
26
|
|
|
27
27
|
[images]
|
|
28
28
|
pillow>=9.0.0
|
|
29
29
|
|
|
30
|
+
[parsers]
|
|
31
|
+
tree-sitter>=0.21.0
|
|
32
|
+
tree-sitter-python>=0.21.0
|
|
33
|
+
tree-sitter-javascript>=0.21.0
|
|
34
|
+
tree-sitter-typescript>=0.21.0
|
|
35
|
+
|
|
30
36
|
[search]
|
|
31
37
|
scrapy>=2.11.0
|
|
32
38
|
scrapy-playwright>=0.0.34
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
UTIM Production Server — Entry Point
|
|
3
|
-
Run locally: python -m utim_cli.server.server
|
|
4
|
-
Railway runs: uvicorn utim_cli.server.router:app --host 0.0.0.0 --port $PORT
|
|
5
|
-
"""
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
|
|
8
|
-
import sys
|
|
9
|
-
import os
|
|
10
|
-
|
|
11
|
-
# Ensure parent and grandparent directories are in sys.path to import 'utim_cli'
|
|
12
|
-
_dir = os.path.dirname(os.path.abspath(__file__))
|
|
13
|
-
for _pd in [os.path.dirname(os.path.dirname(_dir)), os.path.dirname(_dir)]:
|
|
14
|
-
if _pd and _pd not in sys.path:
|
|
15
|
-
sys.path.insert(0, _pd)
|
|
16
|
-
|
|
17
|
-
import argparse
|
|
18
|
-
import uvicorn
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def main():
|
|
22
|
-
parser = argparse.ArgumentParser(description="Start the UTIM Production Server")
|
|
23
|
-
parser.add_argument("--host", default="0.0.0.0")
|
|
24
|
-
parser.add_argument("--port", type=int, default=int(os.environ.get("PORT", 8000)))
|
|
25
|
-
parser.add_argument("--reload", action="store_true")
|
|
26
|
-
parser.add_argument("--workers", type=int, default=1)
|
|
27
|
-
args = parser.parse_args()
|
|
28
|
-
|
|
29
|
-
required = {
|
|
30
|
-
"DATABASE_URL": os.environ.get("DATABASE_URL"),
|
|
31
|
-
"OPENROUTER_API_KEY": os.environ.get("OPENROUTER_API_KEY"),
|
|
32
|
-
"UTIM_MASTER_KEY": os.environ.get("UTIM_MASTER_KEY"),
|
|
33
|
-
}
|
|
34
|
-
missing = [k for k, v in required.items() if not v]
|
|
35
|
-
if missing:
|
|
36
|
-
print(f"[ERROR] Missing required env vars: {', '.join(missing)}")
|
|
37
|
-
print(" Set these in Railway → Service → Variables")
|
|
38
|
-
sys.exit(1)
|
|
39
|
-
|
|
40
|
-
print(f"🚀 UTIM Production Server")
|
|
41
|
-
print(f" http://{args.host}:{args.port}")
|
|
42
|
-
print(f" Docs: http://{args.host}:{args.port}/docs")
|
|
43
|
-
|
|
44
|
-
uvicorn.run(
|
|
45
|
-
"utim_cli.server.router:app",
|
|
46
|
-
host=args.host,
|
|
47
|
-
port=args.port,
|
|
48
|
-
reload=args.reload,
|
|
49
|
-
workers=args.workers if not args.reload else 1,
|
|
50
|
-
log_config=None, # we handle logging ourselves
|
|
51
|
-
access_log=False, # our middleware does structured access logs
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if __name__ == "__main__":
|
|
56
|
-
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|