utim-cli 1.0.0__py3-none-any.whl
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/__init__.py +40 -0
- utim_cli/agent.py +359 -0
- utim_cli/auth.py +208 -0
- utim_cli/backup.py +101 -0
- utim_cli/billing.py +40 -0
- utim_cli/blender_agent.py +1018 -0
- utim_cli/bootstrap.py +324 -0
- utim_cli/client_utils.py +135 -0
- utim_cli/config.py +194 -0
- utim_cli/context_pruner.py +504 -0
- utim_cli/doctor.py +118 -0
- utim_cli/knowledge_graph.py +462 -0
- utim_cli/logger.py +121 -0
- utim_cli/mcp_clean_wrapper.py +55 -0
- utim_cli/mcp_client.py +198 -0
- utim_cli/mcp_registry.json +1102 -0
- utim_cli/orchestrator.py +3209 -0
- utim_cli/reflection.py +200 -0
- utim_cli/report.py +100 -0
- utim_cli/scrapy_search.py +229 -0
- utim_cli/share.py +320 -0
- utim_cli/share_tui.py +554 -0
- utim_cli/situational_scoring.py +269 -0
- utim_cli/state.py +15 -0
- utim_cli/tools.py +3381 -0
- utim_cli/utim.py +4051 -0
- utim_cli/vector_memory.py +629 -0
- utim_cli/workspace.py +33 -0
- utim_cli-1.0.0.dist-info/METADATA +134 -0
- utim_cli-1.0.0.dist-info/RECORD +34 -0
- utim_cli-1.0.0.dist-info/WHEEL +5 -0
- utim_cli-1.0.0.dist-info/entry_points.txt +2 -0
- utim_cli-1.0.0.dist-info/licenses/LICENSE +21 -0
- utim_cli-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Situational Scoring & Context Experience Feedback System.
|
|
3
|
+
|
|
4
|
+
Calculates situational scores for RAG context items (rules, memories, experiences)
|
|
5
|
+
based on the active task type, workspace parameters, and past success/efficiency feedback.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import sqlite3
|
|
10
|
+
import hashlib
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
from typing import Dict, List, Optional, Tuple
|
|
13
|
+
|
|
14
|
+
RAG_DB_PATH = os.path.expanduser("~/.utim/rag_intelligence.db")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
TASK_ANCHORS = {
|
|
18
|
+
"testing": [
|
|
19
|
+
"run pytest tests suite",
|
|
20
|
+
"check the test coverage",
|
|
21
|
+
"verify assertions and test cases",
|
|
22
|
+
"debug failing test assertions"
|
|
23
|
+
],
|
|
24
|
+
"ui_design": [
|
|
25
|
+
"style landing page css html",
|
|
26
|
+
"aesthetic design slides logo ui",
|
|
27
|
+
"create slide layout visual colors",
|
|
28
|
+
"presentation design slide styling"
|
|
29
|
+
],
|
|
30
|
+
"setup": [
|
|
31
|
+
"npm install tailwindcss packages",
|
|
32
|
+
"pip install requirements setup",
|
|
33
|
+
"build environment configurations dependency",
|
|
34
|
+
"initialize workspace project structure setup"
|
|
35
|
+
],
|
|
36
|
+
"refactoring": [
|
|
37
|
+
"refactor helper method cleanly",
|
|
38
|
+
"simplify codebase layout modular structure",
|
|
39
|
+
"optimize functions and clean structure",
|
|
40
|
+
"restructure code components cleanup"
|
|
41
|
+
],
|
|
42
|
+
"file_edit": [
|
|
43
|
+
"edit target file code write",
|
|
44
|
+
"modify python file update replace",
|
|
45
|
+
"write code block content edit",
|
|
46
|
+
"create code file replace lines"
|
|
47
|
+
],
|
|
48
|
+
"search": [
|
|
49
|
+
"grep search codebase query find",
|
|
50
|
+
"locate symbols functions search files",
|
|
51
|
+
"find class usage search directory",
|
|
52
|
+
"query codebase locate definition"
|
|
53
|
+
],
|
|
54
|
+
"general": [
|
|
55
|
+
"hello general chat prompt conversation",
|
|
56
|
+
"explain conceptual question general help",
|
|
57
|
+
"discuss ideas general answer"
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
_emb_fn = None
|
|
62
|
+
_anchor_embeddings = {}
|
|
63
|
+
|
|
64
|
+
def get_embedding_fn():
|
|
65
|
+
global _emb_fn
|
|
66
|
+
if _emb_fn is None:
|
|
67
|
+
try:
|
|
68
|
+
import chromadb.utils.embedding_functions as ef
|
|
69
|
+
_emb_fn = ef.DefaultEmbeddingFunction()
|
|
70
|
+
except Exception:
|
|
71
|
+
try:
|
|
72
|
+
import chromadb.utils.embedding_functions as ef
|
|
73
|
+
_emb_fn = ef.SentenceTransformerEmbeddingFunction(model_name="all-MiniLM-L6-v2")
|
|
74
|
+
except Exception:
|
|
75
|
+
_emb_fn = None
|
|
76
|
+
return _emb_fn
|
|
77
|
+
|
|
78
|
+
def cosine_similarity(v1, v2) -> float:
|
|
79
|
+
import math
|
|
80
|
+
dot = sum(a * b for a, b in zip(v1, v2))
|
|
81
|
+
norm1 = math.sqrt(sum(a * a for a in v1))
|
|
82
|
+
norm2 = math.sqrt(sum(a * a for a in v2))
|
|
83
|
+
if norm1 == 0 or norm2 == 0:
|
|
84
|
+
return 0.0
|
|
85
|
+
return dot / (norm1 * norm2)
|
|
86
|
+
|
|
87
|
+
def classify_task_type(user_prompt: str) -> str:
|
|
88
|
+
"""Classify the user's task prompt into a conceptual technical pattern using Hugging Face embeddings."""
|
|
89
|
+
if not user_prompt:
|
|
90
|
+
return "general"
|
|
91
|
+
|
|
92
|
+
def fallback_heuristics(p: str) -> str:
|
|
93
|
+
if any(k in p for k in ["test", "pytest", "unittest", "assert", "coverage", "check test"]):
|
|
94
|
+
return "testing"
|
|
95
|
+
elif any(k in p for k in ["install", "setup", "init", "npm", "pip", "build", "dependency", "package"]):
|
|
96
|
+
return "setup"
|
|
97
|
+
elif any(k in p for k in ["ui", "design", "aesthetic", "style", "css", "html", "color", "slide"]):
|
|
98
|
+
return "ui_design"
|
|
99
|
+
elif any(k in p for k in ["refactor", "clean", "simplify", "restructure"]):
|
|
100
|
+
return "refactoring"
|
|
101
|
+
elif any(k in p for k in ["edit", "modify", "update", "write", "replace", "create"]):
|
|
102
|
+
return "file_edit"
|
|
103
|
+
elif any(k in p for k in ["search", "find", "grep", "locate", "query"]):
|
|
104
|
+
return "search"
|
|
105
|
+
return "general"
|
|
106
|
+
|
|
107
|
+
p_lower = user_prompt.lower()
|
|
108
|
+
emb_fn = get_embedding_fn()
|
|
109
|
+
if not emb_fn:
|
|
110
|
+
return fallback_heuristics(p_lower)
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
global _anchor_embeddings
|
|
114
|
+
user_emb = emb_fn([user_prompt])[0]
|
|
115
|
+
|
|
116
|
+
if not _anchor_embeddings:
|
|
117
|
+
for task_type, anchors in TASK_ANCHORS.items():
|
|
118
|
+
_anchor_embeddings[task_type] = emb_fn(anchors)
|
|
119
|
+
|
|
120
|
+
best_type = "general"
|
|
121
|
+
best_sim = -1.0
|
|
122
|
+
|
|
123
|
+
for task_type, embs in _anchor_embeddings.items():
|
|
124
|
+
for emb in embs:
|
|
125
|
+
sim = cosine_similarity(user_emb, emb)
|
|
126
|
+
if sim > best_sim:
|
|
127
|
+
best_sim = sim
|
|
128
|
+
best_type = task_type
|
|
129
|
+
|
|
130
|
+
if best_sim > 0.30:
|
|
131
|
+
return best_type
|
|
132
|
+
return fallback_heuristics(p_lower)
|
|
133
|
+
except Exception:
|
|
134
|
+
return fallback_heuristics(p_lower)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def get_situational_multiplier(content: str, task_type: str, user_prompt: str = "") -> float:
|
|
138
|
+
"""
|
|
139
|
+
Calculate dynamic situational multiplier using neural conceptual pattern recognition.
|
|
140
|
+
Measures abstract semantic pattern similarity between user prompt and experience rules.
|
|
141
|
+
"""
|
|
142
|
+
if not content:
|
|
143
|
+
return 1.0
|
|
144
|
+
|
|
145
|
+
multiplier = 1.0
|
|
146
|
+
c_lower = content.lower()
|
|
147
|
+
emb_fn = get_embedding_fn()
|
|
148
|
+
|
|
149
|
+
# 1. Neural Semantic Conceptual Pattern Matching (Dense Vector Cosine Distance)
|
|
150
|
+
if emb_fn and user_prompt:
|
|
151
|
+
try:
|
|
152
|
+
vecs = emb_fn([user_prompt, content])
|
|
153
|
+
sim = cosine_similarity(vecs[0], vecs[1])
|
|
154
|
+
if sim > 0.35:
|
|
155
|
+
# Dynamic neural pattern boost up to 2.5x based on conceptual similarity
|
|
156
|
+
multiplier *= (1.0 + (sim * 1.6))
|
|
157
|
+
except Exception:
|
|
158
|
+
pass
|
|
159
|
+
|
|
160
|
+
# 2. Command Chaining & Operator Pattern Boosting (e.g., && vs ; separation)
|
|
161
|
+
if any(k in c_lower for k in ["&&", "command", "shell", "powershell", "cmd", "operator", "separate", ";"]):
|
|
162
|
+
if task_type in ["setup", "testing", "file_edit", "general"]:
|
|
163
|
+
multiplier *= 2.2
|
|
164
|
+
|
|
165
|
+
# 3. Operating System and Platform Pattern Boosting
|
|
166
|
+
if os.name == "nt": # Windows
|
|
167
|
+
if any(w in c_lower for w in ["win32", "windows", "powershell", "cmd", "chcp", "nt"]):
|
|
168
|
+
multiplier *= 1.25
|
|
169
|
+
if any(w in c_lower for w in ["sudo apt", "brew install", "darwin", "termux"]):
|
|
170
|
+
multiplier *= 0.5
|
|
171
|
+
else: # Linux / Unix / macOS
|
|
172
|
+
if any(w in c_lower for w in ["linux", "unix", "bash", "darwin", "macos", "sudo", "apt", "brew"]):
|
|
173
|
+
multiplier *= 1.25
|
|
174
|
+
if any(w in c_lower for w in ["powershell", "winget", "chocolatey"]):
|
|
175
|
+
multiplier *= 0.5
|
|
176
|
+
|
|
177
|
+
# 4. Dynamic Success & Efficiency Feedback Experience Loop
|
|
178
|
+
content_hash = hashlib.sha256(content.encode("utf-8")).hexdigest()
|
|
179
|
+
if os.path.exists(RAG_DB_PATH):
|
|
180
|
+
try:
|
|
181
|
+
conn = sqlite3.connect(RAG_DB_PATH)
|
|
182
|
+
c = conn.cursor()
|
|
183
|
+
c.execute("""
|
|
184
|
+
SELECT status, steps, duration
|
|
185
|
+
FROM context_item_feedback
|
|
186
|
+
WHERE content_hash = ? AND task_type = ?
|
|
187
|
+
""", (content_hash, task_type))
|
|
188
|
+
rows = c.fetchall()
|
|
189
|
+
conn.close()
|
|
190
|
+
|
|
191
|
+
if rows:
|
|
192
|
+
total_runs = len(rows)
|
|
193
|
+
successes = sum(1 for r in rows if r[0] == "success")
|
|
194
|
+
success_ratio = successes / total_runs
|
|
195
|
+
|
|
196
|
+
if success_ratio >= 0.8:
|
|
197
|
+
multiplier *= 1.25
|
|
198
|
+
elif success_ratio <= 0.4:
|
|
199
|
+
multiplier *= 0.6
|
|
200
|
+
except Exception:
|
|
201
|
+
pass
|
|
202
|
+
|
|
203
|
+
return multiplier
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def score_and_filter_context(items: List[Dict], user_prompt: str, limit: int = 5) -> List[Dict]:
|
|
207
|
+
"""Scores a list of retrieved context items based on neural conceptual pattern matching."""
|
|
208
|
+
if not items:
|
|
209
|
+
return []
|
|
210
|
+
|
|
211
|
+
task_type = classify_task_type(user_prompt)
|
|
212
|
+
scored_items = []
|
|
213
|
+
|
|
214
|
+
for item in items:
|
|
215
|
+
content = item.get("content", "")
|
|
216
|
+
base_score = item.get("base_score", 1.0)
|
|
217
|
+
|
|
218
|
+
# Calculate neural pattern multiplier
|
|
219
|
+
multiplier = get_situational_multiplier(content, task_type, user_prompt=user_prompt)
|
|
220
|
+
situational_score = base_score * multiplier
|
|
221
|
+
|
|
222
|
+
scored_item = item.copy()
|
|
223
|
+
scored_item["situational_score"] = situational_score
|
|
224
|
+
scored_item["task_type"] = task_type
|
|
225
|
+
scored_items.append(scored_item)
|
|
226
|
+
|
|
227
|
+
scored_items.sort(key=lambda x: x["situational_score"], reverse=True)
|
|
228
|
+
return scored_items[:limit]
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def record_context_feedback(injected_contents: List[str], user_prompt: str, status: str, steps: int, duration: int):
|
|
232
|
+
"""Save feedback experience for all context contents injected in the prompt."""
|
|
233
|
+
parent_dir = os.path.dirname(RAG_DB_PATH)
|
|
234
|
+
if not injected_contents or (parent_dir and not os.path.exists(parent_dir)):
|
|
235
|
+
return
|
|
236
|
+
|
|
237
|
+
task_type = classify_task_type(user_prompt)
|
|
238
|
+
timestamp = datetime.now().isoformat()
|
|
239
|
+
|
|
240
|
+
try:
|
|
241
|
+
conn = sqlite3.connect(RAG_DB_PATH)
|
|
242
|
+
c = conn.cursor()
|
|
243
|
+
|
|
244
|
+
# Make sure feedback table exists
|
|
245
|
+
c.execute('''
|
|
246
|
+
CREATE TABLE IF NOT EXISTS context_item_feedback (
|
|
247
|
+
id TEXT PRIMARY KEY DEFAULT (hex(randomblob(16))),
|
|
248
|
+
content_hash TEXT,
|
|
249
|
+
task_type TEXT,
|
|
250
|
+
status TEXT,
|
|
251
|
+
steps INTEGER,
|
|
252
|
+
duration INTEGER,
|
|
253
|
+
timestamp TEXT
|
|
254
|
+
)
|
|
255
|
+
''')
|
|
256
|
+
|
|
257
|
+
for content in injected_contents:
|
|
258
|
+
if not content:
|
|
259
|
+
continue
|
|
260
|
+
content_hash = hashlib.sha256(content.encode("utf-8")).hexdigest()
|
|
261
|
+
c.execute("""
|
|
262
|
+
INSERT INTO context_item_feedback (content_hash, task_type, status, steps, duration, timestamp)
|
|
263
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
264
|
+
""", (content_hash, task_type, status, steps, duration, timestamp))
|
|
265
|
+
|
|
266
|
+
conn.commit()
|
|
267
|
+
conn.close()
|
|
268
|
+
except Exception:
|
|
269
|
+
pass
|
utim_cli/state.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Global App State
|
|
2
|
+
STATE = {
|
|
3
|
+
"mode": "auto-accept edits",
|
|
4
|
+
"busy": False,
|
|
5
|
+
"busy_start": None,
|
|
6
|
+
"session_id": None,
|
|
7
|
+
"last_ctrl_c": 0.0, # timestamp of the last Ctrl+C press
|
|
8
|
+
"focused_process": None, # process_id when user is focused on a background process
|
|
9
|
+
"focus_mode": False, # True when user is in terminal focus mode
|
|
10
|
+
"queue": [], # queue for prompts
|
|
11
|
+
"planning_mode": True, # True = wait for approval, False = Autonomous
|
|
12
|
+
"tool_view": {"active": False, "index": -1}, # Inspector mode
|
|
13
|
+
"thinking_topic": "", # Dynamic topic for the spinner
|
|
14
|
+
"is_verified": False, # True if user has entered the secret code in this session
|
|
15
|
+
}
|