utim-cli 2.0.0__tar.gz → 2.0.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 (107) hide show
  1. {utim_cli-2.0.0 → utim_cli-2.0.2}/CHANGELOG.md +21 -0
  2. {utim_cli-2.0.0/utim_cli.egg-info → utim_cli-2.0.2}/PKG-INFO +1 -1
  3. {utim_cli-2.0.0 → utim_cli-2.0.2}/pyproject.toml +1 -1
  4. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/__init__.py +1 -1
  5. utim_cli-2.0.2/utim_cli/_check_obj.py +9 -0
  6. utim_cli-2.0.2/utim_cli/_find_mcp.py +9 -0
  7. utim_cli-2.0.2/utim_cli/_find_plan.py +12 -0
  8. utim_cli-2.0.2/utim_cli/_find_tool.py +10 -0
  9. utim_cli-2.0.2/utim_cli/_patch_multimodal.py +125 -0
  10. utim_cli-2.0.2/utim_cli/_test_regex.py +22 -0
  11. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/_version.py +1 -1
  12. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/orchestrator.py +164 -128
  13. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/reflection.py +1873 -1873
  14. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tools.py +278 -28
  15. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/model_dialog.py +40 -36
  16. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/utim.py +3 -3
  17. {utim_cli-2.0.0 → utim_cli-2.0.2/utim_cli.egg-info}/PKG-INFO +1 -1
  18. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli.egg-info/SOURCES.txt +6 -0
  19. {utim_cli-2.0.0 → utim_cli-2.0.2}/LICENSE +0 -0
  20. {utim_cli-2.0.0 → utim_cli-2.0.2}/MANIFEST.in +0 -0
  21. {utim_cli-2.0.0 → utim_cli-2.0.2}/README.md +0 -0
  22. {utim_cli-2.0.0 → utim_cli-2.0.2}/setup.cfg +0 -0
  23. {utim_cli-2.0.0 → utim_cli-2.0.2}/setup.py +0 -0
  24. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/agent.py +0 -0
  25. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/auth.py +0 -0
  26. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/backup.py +0 -0
  27. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/billing.py +0 -0
  28. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/blender_agent.py +0 -0
  29. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/bootstrap.py +0 -0
  30. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/client_utils.py +0 -0
  31. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/config.py +0 -0
  32. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/constants.py +0 -0
  33. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/context_pruner.py +0 -0
  34. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/doctor.py +0 -0
  35. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/harbor.py +0 -0
  36. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/knowledge_graph.py +0 -0
  37. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/local_db.py +0 -0
  38. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/logger.py +0 -0
  39. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/mcp_clean_wrapper.py +0 -0
  40. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/mcp_client.py +0 -0
  41. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/mcp_registry.json +0 -0
  42. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/report.py +0 -0
  43. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/scrapy_search.py +0 -0
  44. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/__init__.py +0 -0
  45. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/auth.py +0 -0
  46. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/db.py +0 -0
  47. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/docs_md/about.md +0 -0
  48. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/docs_md/changelog.md +0 -0
  49. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/docs_md/docs.md +0 -0
  50. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/docs_md/features.md +0 -0
  51. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/docs_md/license.md +0 -0
  52. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/docs_md/pricing.md +0 -0
  53. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/docs_md/privacy.md +0 -0
  54. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/docs_md/refund.md +0 -0
  55. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/docs_md/support.md +0 -0
  56. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/docs_md/terms.md +0 -0
  57. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/email_utils.py +0 -0
  58. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/exchange_rate.py +0 -0
  59. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/firebase.py +0 -0
  60. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/history.py +0 -0
  61. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/logging_config.py +0 -0
  62. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/models.py +0 -0
  63. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/pricing_updater.py +0 -0
  64. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/rate_limit.py +0 -0
  65. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/router.py +0 -0
  66. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/routes/__init__.py +0 -0
  67. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/routes/auth_routes.py +0 -0
  68. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/routes/completion_routes.py +0 -0
  69. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/routes/credit_routes.py +0 -0
  70. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/routes/feedback_routes.py +0 -0
  71. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/routes/marketplace_routes.py +0 -0
  72. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/routes/quota_routes.py +0 -0
  73. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/routes/quota_share_routes.py +0 -0
  74. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/routes/referral_routes.py +0 -0
  75. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/routes/security_routes.py +0 -0
  76. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/routes/session_routes.py +0 -0
  77. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/routes/share_routes.py +0 -0
  78. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/server.py +0 -0
  79. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/server/storage_nodes.py +0 -0
  80. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/share.py +0 -0
  81. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/share_tui.py +0 -0
  82. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/situational_scoring.py +0 -0
  83. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/state.py +0 -0
  84. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/__init__.py +0 -0
  85. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/feedback_dialog.py +0 -0
  86. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/history_dialog.py +0 -0
  87. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/marketplace_app_state.py +0 -0
  88. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/marketplace_dialog.py +0 -0
  89. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/marketplace_layout_engine.py +0 -0
  90. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/mcp_dialog.py +0 -0
  91. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/miniagents_dialog.py +0 -0
  92. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/publish_dialog.py +0 -0
  93. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/quota_dialog.py +0 -0
  94. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/quota_redeem_dialog.py +0 -0
  95. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/quota_share_dialog.py +0 -0
  96. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/resume_dialog.py +0 -0
  97. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/skills_dialog.py +0 -0
  98. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/subagents_dialog.py +0 -0
  99. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/tools_dialog.py +0 -0
  100. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/tui/update_dialog.py +0 -0
  101. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/utilities.py +0 -0
  102. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/vector_memory.py +0 -0
  103. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli/workspace.py +0 -0
  104. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli.egg-info/dependency_links.txt +0 -0
  105. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli.egg-info/entry_points.txt +0 -0
  106. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli.egg-info/requires.txt +0 -0
  107. {utim_cli-2.0.0 → utim_cli-2.0.2}/utim_cli.egg-info/top_level.txt +0 -0
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.0.2] - 2026-08-04
4
+
5
+ ### 🛠️ Fixes
6
+ - Minor bug fixes.
7
+
8
+ ## [2.0.1] - 2026-08-04 - Bugfix & Adaptive Iteration Budget
9
+
10
+ ### 🛠️ Fixes
11
+ - **Fixed `unhashable type: 'slice'` crash in `_get_display_arg`**: `run_command` args are now defensively coerced to strings (handles malformed LLM args that arrive as list/dict instead of str).
12
+ - **Fixed thinking spinner persisting after response ends**: `STATE["thinking_topic"]` is cleared immediately after the response completes, so the spinner stops instead of animating through the entire response-end compression.
13
+ - **Response-end compression now runs in a background thread**: The elapsed-time rule prints instantly; context compression happens silently behind the scenes without blocking the UI.
14
+
15
+ ### 🧠 Adaptive Iteration Budget (Window-Aware)
16
+ - **Removed hardcoded "45 iterations max" from system directives**: The iteration budget is now computed at runtime from the model's context window.
17
+ - **Budget scales with context window** using the same buckets as compression intervals:
18
+ - `< 200k` context: budget `25`
19
+ - `200k – 500k` context: budget `35`
20
+ - `500k – 1M` context: budget `40`
21
+ - `1M+` context: budget `45`
22
+ - **One-shot milestone warnings**: Mid-task warning, "5 iterations left" urgent warning, and "+5 granted" notice each fire exactly once per model/iteration (tracked via `_milestones_fired` set) instead of repeating on every request.
23
+
3
24
  ## [2.0.0] - 2026-08-04 - UTIM V2.0 RELEASE
4
25
 
5
26
  ### 🚀 Major Release: UTIM V2.0 — Creators Ecosystem & Adaptive Intelligence
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: utim-cli
3
- Version: 2.0.0
3
+ Version: 2.0.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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "utim-cli"
7
- version = "2.0.0"
7
+ version = "2.0.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"
@@ -5,7 +5,7 @@ try:
5
5
  from utim_cli._version import VERSION as __version__
6
6
  except ImportError:
7
7
  # Fallback during first-install / editable-install edge cases
8
- __version__ = "2.0.0"
8
+ __version__ = "2.0.2"
9
9
 
10
10
  import builtins, os, pathlib, urllib.parse, re
11
11
 
@@ -0,0 +1,9 @@
1
+ f = open('orchestrator.py', encoding='utf-8').read()
2
+ idx = f.find('Active Objective')
3
+ snippet = f[idx:idx+150]
4
+ print('Found:', 'Active Objective' in snippet)
5
+ print('Has 600:', '[:600]' in snippet)
6
+ print('Has 200:', '[:200]' in snippet)
7
+ # Write to file to avoid encoding issues
8
+ open('_check.txt', 'w', encoding='utf-8').write(snippet)
9
+ print('Written to _check.txt')
@@ -0,0 +1,9 @@
1
+ f = open('orchestrator.py', encoding='utf-8').read()
2
+ idx = f.find('class Orchestrator')
3
+ idx2 = f.find('def __init__', idx)
4
+ # Find mcp_tool_names references
5
+ import re
6
+ for m in re.finditer(r'mcp_tool_names', f):
7
+ line = f[:m.start()].count('\n') + 1
8
+ context = f[max(0,m.start()-80):m.end()+80]
9
+ print(f"Line {line}: ...{repr(context)}...")
@@ -0,0 +1,12 @@
1
+ f = open('tools.py', encoding='utf-8').read()
2
+ idx = f.find('def plan_project')
3
+ # Find the next def or the end of the function
4
+ rest = f[idx:]
5
+ # Find the save-to-file part
6
+ save_idx = rest.find('.utim_tmp/plans/')
7
+ print(f"plan_project starts at: {idx}")
8
+ print(f"save file reference at: {idx + save_idx}")
9
+ print()
10
+ # Show the save block
11
+ block = rest[save_idx-100:save_idx+500]
12
+ print(block)
@@ -0,0 +1,10 @@
1
+ f = open('orchestrator.py', encoding='utf-8').read()
2
+ # Find all "role": "tool" append blocks
3
+ import re
4
+ for m in re.finditer(r'role":\s*"tool"', f):
5
+ start = max(0, m.start() - 100)
6
+ end = min(len(f), m.end() + 300)
7
+ snippet = f[start:end]
8
+ print(f"--- Match at {m.start()} ---")
9
+ print(snippet)
10
+ print()
@@ -0,0 +1,125 @@
1
+ f = open('orchestrator.py', encoding='utf-8').read()
2
+
3
+ # Find the single tool append (second occurrence of _cap_tool_result)
4
+ idx1 = f.find('result = _cap_tool_result(func_name, result)')
5
+ idx2 = f.find('result = _cap_tool_result(func_name, result)', idx1 + 50)
6
+
7
+ # The single append starts at idx2 and ends at the "# --- Repeated Tool" line
8
+ end_marker = '\n # --- Repeated Tool '
9
+ end_idx = f.find(end_marker, idx2)
10
+
11
+ old_block = f[idx2:end_idx]
12
+ print("=== OLD BLOCK ===")
13
+ print(repr(old_block))
14
+ print()
15
+
16
+ # Build new block
17
+ new_block = '''result = _cap_tool_result(func_name, result)
18
+
19
+ # If result is an [Image: path] marker and model is vision-capable,
20
+ # inject the actual image as multimodal content
21
+ _img_match = __import__("re").match(r"^\\[Image:\\s+(.+)\\]$", result.strip())
22
+ if _img_match and func_name in ("read_file",):
23
+ try:
24
+ from utim_cli.tools import is_model_vision_capable
25
+ if is_model_vision_capable():
26
+ _img_path = _img_match.group(1)
27
+ _multimodal = _tool_result_to_multimodal(result, _img_path)
28
+ self.messages.append(
29
+ {
30
+ "role": "tool",
31
+ "tool_call_id": tc_id,
32
+ "name": func_name,
33
+ "content": _multimodal,
34
+ }
35
+ )
36
+ else:
37
+ self.messages.append(
38
+ {
39
+ "role": "tool",
40
+ "tool_call_id": tc_id,
41
+ "name": func_name,
42
+ "content": result,
43
+ }
44
+ )
45
+ except Exception:
46
+ self.messages.append(
47
+ {
48
+ "role": "tool",
49
+ "tool_call_id": tc_id,
50
+ "name": func_name,
51
+ "content": result,
52
+ }
53
+ )
54
+ else:
55
+ self.messages.append(
56
+ {
57
+ "role": "tool",
58
+ "tool_call_id": tc_id,
59
+ "name": func_name,
60
+ "content": result,
61
+ }
62
+ )'''
63
+
64
+ f = f.replace(old_block, new_block)
65
+
66
+ # Now do the parallel one (first occurrence)
67
+ idx1_end = f.find(end_marker, f.find('result = _cap_tool_result(func_name, result)'))
68
+ # Actually the parallel one ends differently - find its actual end
69
+ # It's followed by " else:" not "# --- Repeated Tool"
70
+ old_para_end_marker = '\n else:\n # Single tool'
71
+ old_para_start = f.find('result = _cap_tool_result(func_name, result)')
72
+ old_para_end = f.find(old_para_end_marker, old_para_start)
73
+ old_para_block = f[old_para_start:old_para_end]
74
+
75
+ new_para_block = '''result = _cap_tool_result(func_name, result)
76
+
77
+ # If result is an [Image: path] marker and model is vision-capable,
78
+ # inject the actual image as multimodal content
79
+ _img_match = __import__("re").match(r"^\\[Image:\\s+(.+)\\]$", result.strip())
80
+ if _img_match and func_name in ("read_file",):
81
+ try:
82
+ from utim_cli.tools import is_model_vision_capable
83
+ if is_model_vision_capable():
84
+ _img_path = _img_match.group(1)
85
+ _multimodal = _tool_result_to_multimodal(result, _img_path)
86
+ self.messages.append(
87
+ {
88
+ "role": "tool",
89
+ "tool_call_id": tc_id,
90
+ "name": func_name,
91
+ "content": _multimodal,
92
+ }
93
+ )
94
+ else:
95
+ self.messages.append(
96
+ {
97
+ "role": "tool",
98
+ "tool_call_id": tc_id,
99
+ "name": func_name,
100
+ "content": result,
101
+ }
102
+ )
103
+ except Exception:
104
+ self.messages.append(
105
+ {
106
+ "role": "tool",
107
+ "tool_call_id": tc_id,
108
+ "name": func_name,
109
+ "content": result,
110
+ }
111
+ )
112
+ else:
113
+ self.messages.append(
114
+ {
115
+ "role": "tool",
116
+ "tool_call_id": tc_id,
117
+ "name": func_name,
118
+ "content": result,
119
+ }
120
+ )'''
121
+
122
+ f = f.replace(old_para_block, new_para_block)
123
+
124
+ open('orchestrator.py', 'w', encoding='utf-8').write(f)
125
+ print("OK: both tool append blocks replaced")
@@ -0,0 +1,22 @@
1
+ import re
2
+
3
+ # Test the full noise string
4
+ text = "System.Management.Automation.PSCustomObjectSystem.Object1Preparing modules for first use.0-1-1Completed-1"
5
+
6
+ # Broader pattern: match the whole PowerShell startup noise line
7
+ _PS_NOISE_RE = re.compile(
8
+ r'System\.Management\.Automation\..*?(?:Completed-\d+|$)|'
9
+ r'Preparing modules for first use\..*?(?:Completed-\d+|$)|'
10
+ r'out-file\s*:\s*FileStream was asked to open a device.*?(?:$|\n)|'
11
+ r'For support for devices like.*?(?:$|\n)|'
12
+ r'call CreateFile, then use the FileStream.*?(?:$|\n)|'
13
+ r'CategoryInfo\s*:\s*OpenError.*?(?:$|\n)|'
14
+ r'FullyQualifiedErrorId\s*:\s*FileOpenFailure.*?(?:$|\n)|'
15
+ r'At line:\d+ char:\d+.*?(?:$|\n)',
16
+ re.IGNORECASE | re.DOTALL
17
+ )
18
+
19
+ result = _PS_NOISE_RE.sub("", text).strip()
20
+ print(f"Input: {repr(text)}")
21
+ print(f"Output: {repr(result)}")
22
+ print(f"Empty: {result == ''}")
@@ -11,4 +11,4 @@
11
11
  # from here so every surface stays in sync automatically.
12
12
  # ─────────────────────────────────────────────────────────────────────────────
13
13
 
14
- VERSION = "2.0.0"
14
+ VERSION = "2.0.2"