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.
Files changed (68) hide show
  1. {utim_cli-1.44.9/utim_cli.egg-info → utim_cli-1.45.2}/PKG-INFO +10 -5
  2. {utim_cli-1.44.9 → utim_cli-1.45.2}/pyproject.toml +11 -5
  3. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/doctor.py +2 -1
  4. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/db.py +50 -49
  5. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/router.py +1 -1
  6. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/completion_routes.py +4 -0
  7. utim_cli-1.45.2/utim_cli/server/server.py +56 -0
  8. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/utim.py +3 -3
  9. {utim_cli-1.44.9 → utim_cli-1.45.2/utim_cli.egg-info}/PKG-INFO +10 -5
  10. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli.egg-info/requires.txt +10 -4
  11. utim_cli-1.44.9/utim_cli/server/server.py +0 -56
  12. {utim_cli-1.44.9 → utim_cli-1.45.2}/CHANGELOG.md +0 -0
  13. {utim_cli-1.44.9 → utim_cli-1.45.2}/LICENSE +0 -0
  14. {utim_cli-1.44.9 → utim_cli-1.45.2}/MANIFEST.in +0 -0
  15. {utim_cli-1.44.9 → utim_cli-1.45.2}/README.md +0 -0
  16. {utim_cli-1.44.9 → utim_cli-1.45.2}/setup.cfg +0 -0
  17. {utim_cli-1.44.9 → utim_cli-1.45.2}/setup.py +0 -0
  18. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/__init__.py +0 -0
  19. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/agent.py +0 -0
  20. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/auth.py +0 -0
  21. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/backup.py +0 -0
  22. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/blender_agent.py +0 -0
  23. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/bootstrap.py +0 -0
  24. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/client_utils.py +0 -0
  25. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/config.py +0 -0
  26. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/constants.py +0 -0
  27. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/context_pruner.py +0 -0
  28. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/knowledge_graph.py +0 -0
  29. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/logger.py +0 -0
  30. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/mcp_clean_wrapper.py +0 -0
  31. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/mcp_client.py +0 -0
  32. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/mcp_registry.json +0 -0
  33. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/orchestrator.py +0 -0
  34. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/reflection.py +0 -0
  35. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/report.py +0 -0
  36. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/scrapy_search.py +0 -0
  37. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/__init__.py +0 -0
  38. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/auth.py +0 -0
  39. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/email_utils.py +0 -0
  40. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/firebase.py +0 -0
  41. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/history.py +0 -0
  42. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/logging_config.py +0 -0
  43. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/models.py +0 -0
  44. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/rate_limit.py +0 -0
  45. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/__init__.py +0 -0
  46. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/auth_routes.py +0 -0
  47. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/credit_routes.py +0 -0
  48. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/quota_routes.py +0 -0
  49. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/session_routes.py +0 -0
  50. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/server/routes/share_routes.py +0 -0
  51. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/share.py +0 -0
  52. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/share_tui.py +0 -0
  53. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/situational_scoring.py +0 -0
  54. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/state.py +0 -0
  55. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tools.py +0 -0
  56. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/__init__.py +0 -0
  57. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/history_dialog.py +0 -0
  58. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/mcp_dialog.py +0 -0
  59. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/model_dialog.py +0 -0
  60. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/resume_dialog.py +0 -0
  61. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/tools_dialog.py +0 -0
  62. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/tui/update_dialog.py +0 -0
  63. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/vector_memory.py +0 -0
  64. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli/workspace.py +0 -0
  65. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli.egg-info/SOURCES.txt +0 -0
  66. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli.egg-info/dependency_links.txt +0 -0
  67. {utim_cli-1.44.9 → utim_cli-1.45.2}/utim_cli.egg-info/entry_points.txt +0 -0
  68. {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.44.9
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.44.9"
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", "tree_sitter", "mcp", "nest_asyncio"
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
- def _run_migration(sql: str, label: str):
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
- # "already exists" errors are expected and safe to ignore
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
- # PostgreSQL supports IF NOT EXISTS fully idempotent
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():
@@ -37,7 +37,7 @@ logger = logging.getLogger("utim.server")
37
37
 
38
38
  # ── Database init ─────────────────────────────────────────────────────────────
39
39
 
40
- init_db()
40
+ init_db(silent=False)
41
41
 
42
42
  # ── App ───────────────────────────────────────────────────────────────────────
43
43
 
@@ -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.44.9[/dim]")
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.44.9"
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.44.9")
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.44.9
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