utim-cli 1.48.2__tar.gz → 1.48.3__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.48.2 → utim_cli-1.48.3}/CHANGELOG.md +7 -1
- {utim_cli-1.48.2/utim_cli.egg-info → utim_cli-1.48.3}/PKG-INFO +1 -1
- {utim_cli-1.48.2 → utim_cli-1.48.3}/pyproject.toml +1 -1
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/__init__.py +1 -1
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/_version.py +1 -1
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/blender_agent.py +1 -1
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/client_utils.py +5 -2
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/orchestrator.py +24 -4
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/auth.py +5 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/db.py +3 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/routes/completion_routes.py +404 -129
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/routes/quota_share_routes.py +2 -1
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tools.py +354 -3
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tui/quota_redeem_dialog.py +20 -3
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tui/quota_share_dialog.py +22 -4
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tui/tools_dialog.py +5 -26
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/utim.py +34 -3
- {utim_cli-1.48.2 → utim_cli-1.48.3/utim_cli.egg-info}/PKG-INFO +1 -1
- {utim_cli-1.48.2 → utim_cli-1.48.3}/LICENSE +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/MANIFEST.in +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/README.md +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/setup.cfg +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/setup.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/agent.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/auth.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/backup.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/bootstrap.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/config.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/constants.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/context_pruner.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/doctor.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/knowledge_graph.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/local_db.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/logger.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/mcp_clean_wrapper.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/mcp_client.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/mcp_registry.json +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/reflection.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/report.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/scrapy_search.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/__init__.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/docs_md/about.md +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/docs_md/changelog.md +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/docs_md/docs.md +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/docs_md/features.md +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/docs_md/license.md +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/docs_md/pricing.md +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/docs_md/privacy.md +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/docs_md/refund.md +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/docs_md/support.md +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/docs_md/terms.md +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/email_utils.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/exchange_rate.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/firebase.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/history.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/logging_config.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/models.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/pricing_updater.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/rate_limit.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/router.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/routes/__init__.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/routes/auth_routes.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/routes/credit_routes.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/routes/feedback_routes.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/routes/quota_routes.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/routes/referral_routes.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/routes/session_routes.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/routes/share_routes.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/server/server.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/share.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/share_tui.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/situational_scoring.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/state.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tui/__init__.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tui/feedback_dialog.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tui/history_dialog.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tui/mcp_dialog.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tui/model_dialog.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tui/quota_dialog.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tui/resume_dialog.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tui/skills_dialog.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/tui/update_dialog.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/utilities.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/vector_memory.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli/workspace.py +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli.egg-info/SOURCES.txt +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli.egg-info/dependency_links.txt +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli.egg-info/entry_points.txt +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli.egg-info/requires.txt +0 -0
- {utim_cli-1.48.2 → utim_cli-1.48.3}/utim_cli.egg-info/top_level.txt +0 -0
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [1.48.
|
|
3
|
+
## [1.48.3] - 2026-07-24
|
|
4
4
|
|
|
5
5
|
### Fixed
|
|
6
|
+
- **Blender 3D Tools**: Fully restored normal functionality and re-enabled the local Blender asset generation workflow and agent scripts.
|
|
7
|
+
- **Windows Shell Sanitization**: Resolved issues with Unix commands like `mkdir -p` and `rm -rf` failing on native Windows PowerShell by introducing automatic translation to `New-Item` and `Remove-Item`.
|
|
8
|
+
- **Command Redirection Safeguards**: Automatically blocks Bash-style here-docs (`<<`) on Windows with a helpful prompt to guide models to use proper file-write tools.
|
|
9
|
+
- **UI Abort and Confirmation Fixes**: Removed the 30-second background timeout on confirmation dialogs to prevent thread synchronization freeze states. Fixed signal-handling bugs so pressing Ctrl+C or Esc immediately cancels active HTTP streams and releases the CLI layout.
|
|
10
|
+
|
|
11
|
+
## [1.48.2] - 2026-07-23
|
|
6
12
|
- **Minor Bug Fixes**: Under-the-hood optimization and resolution of minor dependency issues.
|
|
7
13
|
|
|
8
14
|
## [1.48.1] - 2026-07-23
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "utim-cli"
|
|
7
|
-
version = "1.48.
|
|
7
|
+
version = "1.48.3"
|
|
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"
|
|
@@ -1110,7 +1110,7 @@ def blender_agent_create_from_image(
|
|
|
1110
1110
|
A human-readable progress log including the path to the exported
|
|
1111
1111
|
file, or an error description.
|
|
1112
1112
|
"""
|
|
1113
|
-
|
|
1113
|
+
|
|
1114
1114
|
|
|
1115
1115
|
output_dir = output_path or os.path.join(os.getcwd(), ".utim_tmp", "blender_assets")
|
|
1116
1116
|
assets_dir = pathlib.Path(output_dir).absolute()
|
|
@@ -258,7 +258,7 @@ def parse_xml_tool_calls(content: str) -> tuple[str | None, list[dict]]:
|
|
|
258
258
|
|
|
259
259
|
args = {}
|
|
260
260
|
# Pattern 1: <arg_key>key</arg_key>\s*<arg_value>value</arg_value>
|
|
261
|
-
arg_pattern = re.compile(r'<arg_key>([^<]+)</arg_key>\s*<arg_value>([
|
|
261
|
+
arg_pattern = re.compile(r'<arg_key>([^<]+)</arg_key>\s*<arg_value>([\s\S]*?)</arg_value>')
|
|
262
262
|
for arg_match in arg_pattern.finditer(block):
|
|
263
263
|
args[arg_match.group(1).strip()] = arg_match.group(2).strip()
|
|
264
264
|
|
|
@@ -269,9 +269,12 @@ def parse_xml_tool_calls(content: str) -> tuple[str | None, list[dict]]:
|
|
|
269
269
|
|
|
270
270
|
# Standardize argument name for run_command
|
|
271
271
|
if tool_name == "run_command":
|
|
272
|
-
for wrong_key in ["CommandLine", "cmd", "shell", "script"]:
|
|
272
|
+
for wrong_key in ["CommandLine", "commandLine", "command_line", "cmd_line", "cmd", "shell", "script"]:
|
|
273
273
|
if wrong_key in args and "command" not in args:
|
|
274
274
|
args["command"] = args.pop(wrong_key)
|
|
275
|
+
for path_key in ["cwd", "directory", "folder", "path"]:
|
|
276
|
+
if path_key in args and "dir_path" not in args:
|
|
277
|
+
args["dir_path"] = args.pop(path_key)
|
|
275
278
|
for bg_key in ["background", "is_background", "bg"]:
|
|
276
279
|
if bg_key in args:
|
|
277
280
|
val = args.pop(bg_key)
|
|
@@ -2040,6 +2040,15 @@ class Orchestrator:
|
|
|
2040
2040
|
finally:
|
|
2041
2041
|
self.active_response = None
|
|
2042
2042
|
|
|
2043
|
+
if self.cancel_event.is_set():
|
|
2044
|
+
return {
|
|
2045
|
+
"role": "assistant",
|
|
2046
|
+
"content": "[Aborted by user]",
|
|
2047
|
+
"tool_calls": None,
|
|
2048
|
+
"was_cut_off": True,
|
|
2049
|
+
"aborted": True,
|
|
2050
|
+
}, False
|
|
2051
|
+
|
|
2043
2052
|
# Flush any remaining text in _line_buf and table_buf
|
|
2044
2053
|
flush_table()
|
|
2045
2054
|
if _line_buf and not silent:
|
|
@@ -3084,10 +3093,21 @@ class Orchestrator:
|
|
|
3084
3093
|
("edit_file", "path"): "filepath",
|
|
3085
3094
|
("edit_file", "file"): "filepath",
|
|
3086
3095
|
("edit_file", "filename"): "filepath",
|
|
3087
|
-
# run_command: model sometimes uses 'cmd'
|
|
3088
|
-
("run_command", "cmd"):
|
|
3089
|
-
("run_command", "shell"):
|
|
3090
|
-
("run_command", "script"):
|
|
3096
|
+
# run_command: model sometimes uses 'cmd' or 'CommandLine'
|
|
3097
|
+
("run_command", "cmd"): "command",
|
|
3098
|
+
("run_command", "shell"): "command",
|
|
3099
|
+
("run_command", "script"): "command",
|
|
3100
|
+
("run_command", "CommandLine"): "command",
|
|
3101
|
+
("run_command", "commandLine"): "command",
|
|
3102
|
+
("run_command", "command_line"): "command",
|
|
3103
|
+
("run_command", "cmd_line"): "command",
|
|
3104
|
+
("run_command", "cwd"): "dir_path",
|
|
3105
|
+
("run_command", "directory"): "dir_path",
|
|
3106
|
+
("run_command", "folder"): "dir_path",
|
|
3107
|
+
("run_command", "path"): "dir_path",
|
|
3108
|
+
("run_command", "background"): "is_background",
|
|
3109
|
+
("run_command", "bg"): "is_background",
|
|
3110
|
+
("run_command", "run_in_background"):"is_background",
|
|
3091
3111
|
# web_search: model sometimes uses 'prompt'
|
|
3092
3112
|
("web_search", "prompt"): "query",
|
|
3093
3113
|
("web_search", "text"): "query",
|
|
@@ -163,6 +163,11 @@ def process_user_refills(db: Session, user_id: str) -> None:
|
|
|
163
163
|
unused_credits = max(0.0, cycle_allowance - current_cycle_used)
|
|
164
164
|
if due > 1:
|
|
165
165
|
unused_credits += cycle_allowance * (due - 1)
|
|
166
|
+
|
|
167
|
+
# Cap refills to remaining monthly plan credits after direct deductions
|
|
168
|
+
unallocated_deducted = getattr(sub, "unallocated_deducted", 0.0) or 0.0
|
|
169
|
+
remaining_pool = max(0.0, plan.credits_per_month - (sub.refills_processed * cycle_allowance) - unallocated_deducted)
|
|
170
|
+
unused_credits = min(unused_credits, remaining_pool)
|
|
166
171
|
|
|
167
172
|
credit = db.query(Credit).filter(Credit.user_id == user_id).first()
|
|
168
173
|
if not credit:
|
|
@@ -118,6 +118,7 @@ class UserSubscription(Base):
|
|
|
118
118
|
last_refill_at = Column(DateTime, nullable=True)
|
|
119
119
|
# Overrides the default per-cycle credit allocation after a quota-share deduction
|
|
120
120
|
refill_rate_override = Column(Float, nullable=True)
|
|
121
|
+
unallocated_deducted = Column(Float, default=0.0, nullable=False)
|
|
121
122
|
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
|
|
122
123
|
updated_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
|
|
123
124
|
|
|
@@ -630,12 +631,14 @@ def init_db(silent: bool = True) -> None:
|
|
|
630
631
|
_run_migration("users", "referral_code", "ALTER TABLE users ADD COLUMN IF NOT EXISTS referral_code VARCHAR(50)", "postgres add referral_code")
|
|
631
632
|
_run_migration("feedbacks", "chat_history", "ALTER TABLE feedbacks ADD COLUMN IF NOT EXISTS chat_history TEXT", "postgres add chat_history")
|
|
632
633
|
_run_migration("user_subscriptions", "refill_rate_override", "ALTER TABLE user_subscriptions ADD COLUMN IF NOT EXISTS refill_rate_override FLOAT", "postgres add refill_rate_override")
|
|
634
|
+
_run_migration("user_subscriptions", "unallocated_deducted", "ALTER TABLE user_subscriptions ADD COLUMN IF NOT EXISTS unallocated_deducted FLOAT DEFAULT 0.0 NOT NULL", "postgres add unallocated_deducted")
|
|
633
635
|
else:
|
|
634
636
|
# SQLite: no IF NOT EXISTS on ADD COLUMN, swallow duplicate errors
|
|
635
637
|
_run_migration("user_subscriptions", "refills_processed", "ALTER TABLE user_subscriptions ADD COLUMN refills_processed INTEGER DEFAULT 0 NOT NULL", "sqlite add refills_processed")
|
|
636
638
|
_run_migration("user_subscriptions", "last_refill_at", "ALTER TABLE user_subscriptions ADD COLUMN last_refill_at TIMESTAMP", "sqlite add last_refill_at")
|
|
637
639
|
_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")
|
|
638
640
|
_run_migration("user_subscriptions", "refill_rate_override", "ALTER TABLE user_subscriptions ADD COLUMN refill_rate_override FLOAT", "sqlite add refill_rate_override")
|
|
641
|
+
_run_migration("user_subscriptions", "unallocated_deducted", "ALTER TABLE user_subscriptions ADD COLUMN unallocated_deducted FLOAT DEFAULT 0.0 NOT NULL", "sqlite add unallocated_deducted")
|
|
639
642
|
_run_migration("credits", "bonus_balance", "ALTER TABLE credits ADD COLUMN bonus_balance FLOAT DEFAULT 0.0 NOT NULL", "sqlite add bonus_balance")
|
|
640
643
|
_run_migration("credits", "bonus_limit", "ALTER TABLE credits ADD COLUMN bonus_limit FLOAT DEFAULT 0.0 NOT NULL", "sqlite add bonus_limit")
|
|
641
644
|
_run_migration("credits", "free_monthly_used", "ALTER TABLE credits ADD COLUMN free_monthly_used FLOAT DEFAULT 0.0 NOT NULL", "sqlite add free_monthly_used")
|