utim-cli 1.46.30__tar.gz → 1.46.32__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.46.30 → utim_cli-1.46.32}/CHANGELOG.md +5 -1
- {utim_cli-1.46.30/utim_cli.egg-info → utim_cli-1.46.32}/PKG-INFO +1 -1
- {utim_cli-1.46.30 → utim_cli-1.46.32}/pyproject.toml +1 -1
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/__init__.py +1 -1
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/_version.py +1 -1
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/config.py +50 -10
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/orchestrator.py +14 -1
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/utim.py +13 -5
- {utim_cli-1.46.30 → utim_cli-1.46.32/utim_cli.egg-info}/PKG-INFO +1 -1
- {utim_cli-1.46.30 → utim_cli-1.46.32}/LICENSE +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/MANIFEST.in +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/README.md +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/setup.cfg +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/setup.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/agent.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/auth.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/backup.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/blender_agent.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/bootstrap.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/client_utils.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/constants.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/context_pruner.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/doctor.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/knowledge_graph.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/local_db.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/logger.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/mcp_clean_wrapper.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/mcp_client.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/mcp_registry.json +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/reflection.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/report.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/scrapy_search.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/__init__.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/auth.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/db.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/email_utils.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/exchange_rate.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/firebase.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/history.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/logging_config.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/models.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/pricing_updater.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/rate_limit.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/router.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/routes/__init__.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/routes/auth_routes.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/routes/completion_routes.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/routes/credit_routes.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/routes/feedback_routes.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/routes/quota_routes.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/routes/session_routes.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/routes/share_routes.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/server/server.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/share.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/share_tui.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/situational_scoring.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/state.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/tools.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/tui/__init__.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/tui/feedback_dialog.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/tui/history_dialog.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/tui/mcp_dialog.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/tui/model_dialog.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/tui/resume_dialog.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/tui/tools_dialog.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/tui/update_dialog.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/utilities.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/vector_memory.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli/workspace.py +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli.egg-info/SOURCES.txt +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli.egg-info/dependency_links.txt +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli.egg-info/entry_points.txt +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli.egg-info/requires.txt +0 -0
- {utim_cli-1.46.30 → utim_cli-1.46.32}/utim_cli.egg-info/top_level.txt +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the UTIM CLI Agent will be documented in this file.
|
|
4
4
|
|
|
5
|
-
## [1.46.
|
|
5
|
+
## [1.46.32] - 2026-07-11
|
|
6
6
|
|
|
7
7
|
### Added
|
|
8
8
|
- **Dynamic Console Glyph Fallbacks**: Detected legacy Windows terminals (where `WT_SESSION` is not set) and automatically fell back to standard ASCII symbols (`>` and `->`) instead of unicode characters (`❯`, `▶`, and `➔`) to prevent `⍰` or empty box rendering issues.
|
|
@@ -12,6 +12,10 @@ All notable changes to the UTIM CLI Agent will be documented in this file.
|
|
|
12
12
|
- **Model Selection Dialog Crash**: Fixed an `AttributeError` crash on the model list dialog screen (main agent or subagent picker) when the user's local `user_plan` config value is missing or explicitly `null`.
|
|
13
13
|
- **Global Config Null-Safety Improvements**: Fixed multiple potential crashes across the tools dialog, share manager, and usage dashboard when keys like `disabled_tools`, `mcpServers`, `role`, or `user_plan` are missing or set to `null` in config files.
|
|
14
14
|
- **Server Upload Limit & Connection Resets**: Increased the `/shares/upload` workspace file sharing size limit from 4MB to 25MB on the server. Added stream consumption middleware handlers to prevent connection termination resets and `SSLEOFError` crashes on the client during larger uploads.
|
|
15
|
+
- **Modern prompt_toolkit Style Crash**: Fixed a crash (`ValueError: Wrong color format 'dim'`) on lists with scrolling indicators (like the model dialog or history dialog) when run on newer versions of `prompt_toolkit` (3.0.40+) by correcting the shorthand styling `'dim fg:#f9e2af'` to `'class:dim fg:#f9e2af'`.
|
|
16
|
+
- **User-Agent Shielding & HTTP 429 Proxy Blocks**: Patched the global requests Session initializer to spoof a standard browser User-Agent, preventing corporate firewalls/proxies from blocking or rate-limiting requests. Added HTML-stripping parser helpers to the orchestrator to extract and display readable error details directly inside the offline connection panels if a proxy returns an HTTP 429.
|
|
17
|
+
- **Added /sslverify command**: Integrated a local slash command `/sslverify` to toggle SSL verification directly from the CLI input prompt without needing to edit config files manually.
|
|
18
|
+
- **Automated SSL Verification Fallback**: Implemented an automated, silent self-healing retry mechanism inside the requests wrapper. If UTIM encounters an SSL validation failure (commonly caused by decrypting proxies/firewalls in corporate or local networks), it automatically suppresses warnings, updates the config file to persist `"verify_ssl": false`, and retries the connection silently in the background with SSL verification disabled, preventing any service interruption without displaying warning messages to the user.
|
|
15
19
|
|
|
16
20
|
## [1.46.29] - 2026-07-11
|
|
17
21
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "utim-cli"
|
|
7
|
-
version = "1.46.
|
|
7
|
+
version = "1.46.32"
|
|
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"
|
|
@@ -22,22 +22,62 @@ class Config:
|
|
|
22
22
|
self._global_data: Dict[str, Any] = {}
|
|
23
23
|
self._local_data: Dict[str, Any] = {}
|
|
24
24
|
self._load()
|
|
25
|
-
#
|
|
25
|
+
# Always inject a browser User-Agent to prevent firewalls/proxies blocking default python-requests
|
|
26
|
+
try:
|
|
27
|
+
import requests
|
|
28
|
+
original_init = requests.Session.__init__
|
|
29
|
+
def patched_init(self_session, *args, **kwargs):
|
|
30
|
+
original_init(self_session, *args, **kwargs)
|
|
31
|
+
self_session.headers.update({
|
|
32
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
|
33
|
+
})
|
|
34
|
+
requests.Session.__init__ = patched_init
|
|
35
|
+
except Exception:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
# Patch requests Session to support automatic SSL verification bypass and fallback
|
|
39
|
+
try:
|
|
40
|
+
import requests
|
|
41
|
+
original_request = requests.Session.request
|
|
42
|
+
def new_request(self_session, method, url, *args, **kwargs):
|
|
43
|
+
# If verify_ssl is explicitly False, always disable verification
|
|
44
|
+
if not self.verify_ssl:
|
|
45
|
+
kwargs['verify'] = False
|
|
46
|
+
return original_request(self_session, method, url, *args, **kwargs)
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
return original_request(self_session, method, url, *args, **kwargs)
|
|
50
|
+
except Exception as exc:
|
|
51
|
+
is_ssl_err = False
|
|
52
|
+
err_str = str(exc).lower()
|
|
53
|
+
if "ssl" in err_str and ("cert" in err_str or "verify" in err_str or "untrusted" in err_str or "authority" in err_str):
|
|
54
|
+
is_ssl_err = True
|
|
55
|
+
|
|
56
|
+
if is_ssl_err:
|
|
57
|
+
try:
|
|
58
|
+
import urllib3
|
|
59
|
+
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
60
|
+
except Exception:
|
|
61
|
+
pass
|
|
62
|
+
try:
|
|
63
|
+
self.set("verify_ssl", False)
|
|
64
|
+
except Exception:
|
|
65
|
+
pass
|
|
66
|
+
kwargs['verify'] = False
|
|
67
|
+
return original_request(self_session, method, url, *args, **kwargs)
|
|
68
|
+
raise exc
|
|
69
|
+
|
|
70
|
+
requests.Session.request = new_request
|
|
71
|
+
except Exception:
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
# Suppress warnings if SSL verification is disabled
|
|
26
75
|
if not self.verify_ssl:
|
|
27
76
|
try:
|
|
28
77
|
import urllib3
|
|
29
78
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
30
79
|
except Exception:
|
|
31
80
|
pass
|
|
32
|
-
try:
|
|
33
|
-
import requests
|
|
34
|
-
original_request = requests.Session.request
|
|
35
|
-
def new_request(self, method, url, *args, **kwargs):
|
|
36
|
-
kwargs['verify'] = False
|
|
37
|
-
return original_request(self, method, url, *args, **kwargs)
|
|
38
|
-
requests.Session.request = new_request
|
|
39
|
-
except Exception:
|
|
40
|
-
pass
|
|
41
81
|
|
|
42
82
|
def _load(self):
|
|
43
83
|
# Load global config
|
|
@@ -1607,7 +1607,20 @@ class Orchestrator:
|
|
|
1607
1607
|
# If we exit the loop, all models failed
|
|
1608
1608
|
if isinstance(last_exc, requests.exceptions.HTTPError):
|
|
1609
1609
|
code = last_exc.response.status_code if last_exc.response is not None else "?"
|
|
1610
|
-
|
|
1610
|
+
err_msg = f"Model API returned an error after trying all fallbacks (HTTP {code})."
|
|
1611
|
+
if code == 429 and last_exc.response is not None:
|
|
1612
|
+
try:
|
|
1613
|
+
text_detail = last_exc.response.text.strip()
|
|
1614
|
+
if text_detail:
|
|
1615
|
+
import re
|
|
1616
|
+
text_detail = re.sub('<[^<]+?>', '', text_detail)
|
|
1617
|
+
text_detail = " ".join(text_detail.split())
|
|
1618
|
+
if len(text_detail) > 150:
|
|
1619
|
+
text_detail = text_detail[:147] + "..."
|
|
1620
|
+
err_msg += f"\nDetails: {text_detail}"
|
|
1621
|
+
except Exception:
|
|
1622
|
+
pass
|
|
1623
|
+
raise _ServerUnavailableError(err_msg) from last_exc
|
|
1611
1624
|
elif last_exc:
|
|
1612
1625
|
raise _ServerUnavailableError(f"Cannot reach model API after trying all fallback models. Last error: {last_exc}") from last_exc
|
|
1613
1626
|
else:
|
|
@@ -660,6 +660,7 @@ COMMANDS = {
|
|
|
660
660
|
"redo": "Redo the last undone action",
|
|
661
661
|
"report": "Generate a redacted support zip bundle under .utim_tmp/",
|
|
662
662
|
"chatrestore": "Toggle active session state auto-restoration on startup",
|
|
663
|
+
"sslverify": "Toggle SSL certificate validation (useful behind decrypting proxies)",
|
|
663
664
|
"resume": "Manage/Load previous conversations",
|
|
664
665
|
"rewind": "Undo last action and revert code",
|
|
665
666
|
"share": "Share chat and zip package of the workspace",
|
|
@@ -859,7 +860,7 @@ def _print_animated_banner(animated: bool = True):
|
|
|
859
860
|
else:
|
|
860
861
|
console.print(f"[bold {color}]{BANNER_BIG}[/bold {color}]")
|
|
861
862
|
|
|
862
|
-
console.print(f" [bold white]U Think I Make[/bold white] [dim]v1.46.
|
|
863
|
+
console.print(f" [bold white]U Think I Make[/bold white] [dim]v1.46.32[/dim]")
|
|
863
864
|
user_email = config.email
|
|
864
865
|
user_type = "UTIM Community"
|
|
865
866
|
api_key = config.get("api_key")
|
|
@@ -1014,7 +1015,7 @@ def _run_list_dialog(rows, render_row_fn, title="", legend="", extra_keys=None):
|
|
|
1014
1015
|
# Show indicator for items below the viewport
|
|
1015
1016
|
remaining = N - end_idx
|
|
1016
1017
|
if remaining > 0:
|
|
1017
|
-
out.append(('dim fg:#f9e2af', f' ▼ ... ({remaining} more item{"s" if remaining > 1 else ""} below) ... ▼\n'))
|
|
1018
|
+
out.append(('class:dim fg:#f9e2af', f' ▼ ... ({remaining} more item{"s" if remaining > 1 else ""} below) ... ▼\n'))
|
|
1018
1019
|
|
|
1019
1020
|
out.append(('', '\n'))
|
|
1020
1021
|
return out
|
|
@@ -1197,7 +1198,7 @@ def _run_mcp_search_list_dialog(rows, render_row_fn, title="", legend="", search
|
|
|
1197
1198
|
|
|
1198
1199
|
remaining = N_filtered[0] - end_idx
|
|
1199
1200
|
if remaining > 0:
|
|
1200
|
-
out.append(('dim fg:#f9e2af', f'\n ▼ ... ({remaining} more below) ... ▼\n'))
|
|
1201
|
+
out.append(('class:dim fg:#f9e2af', f'\n ▼ ... ({remaining} more below) ... ▼\n'))
|
|
1201
1202
|
|
|
1202
1203
|
return out
|
|
1203
1204
|
|
|
@@ -1637,6 +1638,13 @@ def _handle_command(cmd: str, orchestrator: Orchestrator, app_ref) -> None:
|
|
|
1637
1638
|
if not new_val:
|
|
1638
1639
|
console.print("[dim]Next time you boot UTIM, it will start with a fresh new chat session.[/dim]\n")
|
|
1639
1640
|
|
|
1641
|
+
elif c == "sslverify":
|
|
1642
|
+
current = config.get("verify_ssl", True)
|
|
1643
|
+
new_val = not current
|
|
1644
|
+
config.set("verify_ssl", new_val)
|
|
1645
|
+
console.print(f"\n[bold green]✓ SSL certificate verification has been {'enabled' if new_val else 'disabled'}.[/bold green]\n")
|
|
1646
|
+
console.print("[dim]Restart UTIM for changes to take full effect across all components.[/dim]\n")
|
|
1647
|
+
|
|
1640
1648
|
elif c == "rate":
|
|
1641
1649
|
from utim_cli.tui.feedback_dialog import _dialog_submit_feedback
|
|
1642
1650
|
_dialog_submit_feedback(orchestrator)
|
|
@@ -2820,7 +2828,7 @@ def _build_pt_app(orchestrator, last_sigint):
|
|
|
2820
2828
|
words[0] = cmd_word
|
|
2821
2829
|
text = " ".join(words)
|
|
2822
2830
|
cmd_name = cmd_word.lstrip('/')
|
|
2823
|
-
CONCURRENT_COMMANDS = {"usage", "hint", "tools", "help", "about", "doctor", "report", "chatrestore", "rate", "feedback", "feedbacks"}
|
|
2831
|
+
CONCURRENT_COMMANDS = {"usage", "hint", "tools", "help", "about", "doctor", "report", "chatrestore", "sslverify", "rate", "feedback", "feedbacks"}
|
|
2824
2832
|
if STATE["busy"] and cmd_name not in CONCURRENT_COMMANDS:
|
|
2825
2833
|
console.print(f"\n[dim yellow]⚠ Cannot execute command {text} while agent is busy.[/dim yellow]")
|
|
2826
2834
|
return
|
|
@@ -3109,7 +3117,7 @@ def check_and_update_background():
|
|
|
3109
3117
|
return
|
|
3110
3118
|
|
|
3111
3119
|
latest_ver = resp.json().get("version", "")
|
|
3112
|
-
current_ver = "1.46.
|
|
3120
|
+
current_ver = "1.46.32"
|
|
3113
3121
|
|
|
3114
3122
|
def parse_ver(v):
|
|
3115
3123
|
return [int(x) for x in v.split(".") if x.isdigit()]
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|