utim-cli 1.45.8__tar.gz → 1.46.0__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 (67) hide show
  1. {utim_cli-1.45.8/utim_cli.egg-info → utim_cli-1.46.0}/PKG-INFO +1 -1
  2. {utim_cli-1.45.8 → utim_cli-1.46.0}/pyproject.toml +1 -1
  3. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/auth.py +47 -60
  4. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/utim.py +5 -8
  5. {utim_cli-1.45.8 → utim_cli-1.46.0/utim_cli.egg-info}/PKG-INFO +1 -1
  6. {utim_cli-1.45.8 → utim_cli-1.46.0}/CHANGELOG.md +0 -0
  7. {utim_cli-1.45.8 → utim_cli-1.46.0}/LICENSE +0 -0
  8. {utim_cli-1.45.8 → utim_cli-1.46.0}/MANIFEST.in +0 -0
  9. {utim_cli-1.45.8 → utim_cli-1.46.0}/README.md +0 -0
  10. {utim_cli-1.45.8 → utim_cli-1.46.0}/setup.cfg +0 -0
  11. {utim_cli-1.45.8 → utim_cli-1.46.0}/setup.py +0 -0
  12. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/__init__.py +0 -0
  13. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/agent.py +0 -0
  14. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/backup.py +0 -0
  15. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/blender_agent.py +0 -0
  16. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/bootstrap.py +0 -0
  17. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/client_utils.py +0 -0
  18. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/config.py +0 -0
  19. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/constants.py +0 -0
  20. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/context_pruner.py +0 -0
  21. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/doctor.py +0 -0
  22. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/knowledge_graph.py +0 -0
  23. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/logger.py +0 -0
  24. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/mcp_clean_wrapper.py +0 -0
  25. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/mcp_client.py +0 -0
  26. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/mcp_registry.json +0 -0
  27. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/orchestrator.py +0 -0
  28. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/reflection.py +0 -0
  29. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/report.py +0 -0
  30. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/scrapy_search.py +0 -0
  31. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/__init__.py +0 -0
  32. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/auth.py +0 -0
  33. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/db.py +0 -0
  34. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/email_utils.py +0 -0
  35. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/firebase.py +0 -0
  36. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/history.py +0 -0
  37. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/logging_config.py +0 -0
  38. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/models.py +0 -0
  39. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/rate_limit.py +0 -0
  40. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/router.py +0 -0
  41. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/routes/__init__.py +0 -0
  42. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/routes/auth_routes.py +0 -0
  43. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/routes/completion_routes.py +0 -0
  44. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/routes/credit_routes.py +0 -0
  45. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/routes/quota_routes.py +0 -0
  46. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/routes/session_routes.py +0 -0
  47. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/routes/share_routes.py +0 -0
  48. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/server/server.py +0 -0
  49. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/share.py +0 -0
  50. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/share_tui.py +0 -0
  51. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/situational_scoring.py +0 -0
  52. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/state.py +0 -0
  53. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/tools.py +0 -0
  54. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/tui/__init__.py +0 -0
  55. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/tui/history_dialog.py +0 -0
  56. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/tui/mcp_dialog.py +0 -0
  57. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/tui/model_dialog.py +0 -0
  58. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/tui/resume_dialog.py +0 -0
  59. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/tui/tools_dialog.py +0 -0
  60. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/tui/update_dialog.py +0 -0
  61. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/vector_memory.py +0 -0
  62. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli/workspace.py +0 -0
  63. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli.egg-info/SOURCES.txt +0 -0
  64. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli.egg-info/dependency_links.txt +0 -0
  65. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli.egg-info/entry_points.txt +0 -0
  66. {utim_cli-1.45.8 → utim_cli-1.46.0}/utim_cli.egg-info/requires.txt +0 -0
  67. {utim_cli-1.45.8 → utim_cli-1.46.0}/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.45.8
3
+ Version: 1.46.0
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "utim-cli"
7
- version = "1.45.8"
7
+ version = "1.46.0"
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"
@@ -90,82 +90,69 @@ class _AuthCallbackHandler(http.server.BaseHTTPRequestHandler):
90
90
 
91
91
  def login() -> None:
92
92
  """
93
- Open the browser for Firebase authentication and exchange the resulting
94
- ID token for a UTIM API key from the production server.
93
+ Sign in by prompting the user to copy their UTIM API key from the web dashboard.
95
94
  """
96
- _AuthCallbackHandler.received = {}
97
- socketserver.TCPServer.allow_reuse_address = True
98
- try:
99
- httpd = socketserver.TCPServer(("", 31415), _AuthCallbackHandler)
100
- port = 31415
101
- except OSError:
102
- # Fallback: bind to a random free port allocated by the OS if 31415 is in use
103
- httpd = socketserver.TCPServer(("", 0), _AuthCallbackHandler)
104
- port = httpd.server_address[1]
105
-
106
- callback_url = f"http://localhost:{port}/auth/callback"
107
-
108
- # Build the auth redirect URL pointing to our website auth page.
109
- auth_url = (
110
- f"{WEB_URL}/auth"
111
- f"?callback={urllib.parse.quote(callback_url)}"
112
- )
113
-
114
- console.print(f"\n [bold {PURPLE}]Opening browser for sign-in…[/bold {PURPLE}]")
115
- console.print(f" [dim]If the browser doesn't open, visit:[/dim]")
116
- console.print(f" [bold {BLUE}]{auth_url}[/bold {BLUE}]\n")
117
-
95
+ # ANSI escape codes for formatting
96
+ PURPLE = "\033[1;35m"
97
+ BLUE = "\033[1;34m"
98
+ YELLOW = "\033[1;33m"
99
+ WHITE = "\033[1;37m"
100
+ RESET = "\033[0m"
101
+ DIM = "\033[2m"
102
+
103
+ print(f"\n {PURPLE}UTIM CLI Sign-In{RESET}")
104
+ print(" 1. Visit the UTIM Profile page in your browser:")
105
+ print(f" {BLUE}{WEB_URL}/profile{RESET}")
106
+ print(f" 2. Copy your {WHITE}UTIM API Key{RESET}.")
107
+ print(" 3. Paste the key below to log in.\n")
108
+
118
109
  import sys
119
110
  sys.stdout.flush()
120
111
 
121
- # Run webbrowser.open in a daemon thread so it never hangs the CLI on Termux/mobile
122
- threading.Thread(target=webbrowser.open, args=(auth_url,), daemon=True).start()
123
-
124
- # Block until the callback arrives with a 5-minute timeout
125
- import time
126
- httpd.timeout = 1.0
127
- start_time = time.time()
128
- while not _AuthCallbackHandler.received:
129
- if time.time() - start_time > 300:
130
- console.print(f" [bold red]✗ Authentication timed out (5 minutes).[/bold red]\n")
131
- httpd.server_close()
132
- return
133
- httpd.handle_request()
134
-
135
- httpd.server_close()
112
+ # Try to open the profile page in a background thread for convenience
113
+ threading.Thread(target=webbrowser.open, args=(f"{WEB_URL}/profile",), daemon=True).start()
114
+
115
+ try:
116
+ api_key = input(" Enter UTIM API Key (or press Enter to cancel): ").strip()
117
+ except (EOFError, KeyboardInterrupt):
118
+ print("\n \033[1;33mCancelled.\033[0m\n")
119
+ sys.stdout.flush()
120
+ return
136
121
 
137
- data = _AuthCallbackHandler.received
138
- if not data.get("token"):
139
- console.print(f" [bold red]✗ Authentication cancelled or failed.[/bold red]\n")
122
+ if not api_key:
123
+ print("\n \033[1;33mCancelled.\033[0m\n")
124
+ sys.stdout.flush()
140
125
  return
141
126
 
142
- # Exchange Firebase ID token → UTIM API key
143
- console.print(f" [dim]Verifying with UTIM server…[/dim]")
127
+ print(f" {DIM}Verifying with UTIM server…{RESET}")
128
+ sys.stdout.flush()
144
129
  try:
145
- resp = requests.post(
146
- f"{SERVER_URL}/auth/firebase-login",
147
- json={"id_token": data["token"]},
130
+ resp = requests.get(
131
+ f"{SERVER_URL}/auth/me",
132
+ headers={"X-API-Key": api_key},
148
133
  timeout=15,
149
134
  )
150
- resp.raise_for_status()
135
+ if resp.status_code != 200:
136
+ print(f" \033[1;31m✗ Invalid API Key or server error (HTTP {resp.status_code}).\033[0m\n")
137
+ sys.stdout.flush()
138
+ return
151
139
  payload = resp.json()
152
140
  except Exception as exc:
153
- console.print(f" [bold red]Server error: {exc}[/bold red]\n")
141
+ print(f" \033[1;31mVerification failed: {exc}\033[0m\n")
142
+ sys.stdout.flush()
154
143
  return
155
144
 
156
145
  # Persist credentials
157
- config.set("token", data["token"])
146
+ config.set("token", "direct_key") # sentinel
158
147
  config.set("email", payload["email"])
159
- config.set("uid", data["uid"])
160
- config.set("name", payload.get("display_name", data["name"]))
161
- config.set("api_key", payload["api_key"])
162
-
163
- greeting = "Welcome! Your account has been created." if payload.get("is_new_user") else "Welcome back!"
164
- console.print(
165
- f" [bold {YELLOW}]✓ {greeting}[/bold {YELLOW}]\n"
166
- f" [dim]Signed in as[/dim] [bold {BLUE}]{payload['email']}[/bold {BLUE}]\n"
167
- f" [dim]Credits:[/dim] [bold]{payload['credits']:,.0f} UTIM[/bold]\n"
168
- )
148
+ config.set("uid", payload["user_id"])
149
+ config.set("name", payload.get("display_name") or payload["email"].split("@")[0])
150
+ config.set("api_key", api_key)
151
+
152
+ print(f" {YELLOW}✓ Welcome back!{RESET}\n")
153
+ print(f" Signed in as {BLUE}{payload['email']}{RESET}\n")
154
+ print(f" Credits: {payload['credits']:,.0f} UTIM\n")
155
+ sys.stdout.flush()
169
156
 
170
157
 
171
158
  # ── HTML templates ────────────────────────────────────────────────────────────
@@ -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.45.8[/dim]")
588
+ console.print(f"\n [bold white]U Think I Make[/bold white] [dim]v1.46.0[/dim]")
589
589
  user_email = config.email
590
590
  user_type = "UTIM Community"
591
591
  api_key = config.get("api_key")
@@ -2420,10 +2420,7 @@ def _build_pt_app(orchestrator, last_sigint):
2420
2420
  if STATE["busy"]:
2421
2421
  console.print(f"\n[dim yellow]⚠ Cannot execute command {text} while agent is busy.[/dim yellow]")
2422
2422
  return
2423
- if cmd_word == "/login":
2424
- run_in_terminal(lambda: _handle_command(cmd_word, orchestrator, event.app), in_executor=True)
2425
- else:
2426
- run_in_terminal(lambda: _handle_command(cmd_word, orchestrator, event.app))
2423
+ run_in_terminal(lambda: _handle_command(cmd_word, orchestrator, event.app))
2427
2424
  return
2428
2425
 
2429
2426
  # Check if the user pasted a UTIM share URL/ID
@@ -2439,7 +2436,7 @@ def _build_pt_app(orchestrator, last_sigint):
2439
2436
  auth.login()
2440
2437
  except Exception as exc:
2441
2438
  console.print(f"\n [bold red]✗ Login failed: {exc}[/bold red]\n")
2442
- run_in_terminal(run_auth_login, in_executor=True)
2439
+ run_in_terminal(run_auth_login)
2443
2440
  # Restore their prompt text so they don't have to retype it
2444
2441
  input_field.text = text
2445
2442
  return
@@ -2694,7 +2691,7 @@ def check_and_update_background():
2694
2691
  return
2695
2692
 
2696
2693
  latest_ver = resp.json().get("version", "")
2697
- current_ver = "1.45.8"
2694
+ current_ver = "1.46.0"
2698
2695
 
2699
2696
  def parse_ver(v):
2700
2697
  return [int(x) for x in v.split(".") if x.isdigit()]
@@ -2890,7 +2887,7 @@ app = typer.Typer()
2890
2887
  def version_callback(value: bool):
2891
2888
  if value:
2892
2889
  import typer
2893
- print("U Think I Make v1.45.8")
2890
+ print("U Think I Make v1.46.0")
2894
2891
  raise typer.Exit()
2895
2892
 
2896
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.45.8
3
+ Version: 1.46.0
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
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