npcsh 0.3.27.2__tar.gz → 0.3.27.4__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.
- {npcsh-0.3.27.2/npcsh.egg-info → npcsh-0.3.27.4}/PKG-INFO +4 -1
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/helpers.py +5 -1
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/search.py +5 -1
- {npcsh-0.3.27.2 → npcsh-0.3.27.4/npcsh.egg-info}/PKG-INFO +4 -1
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh.egg-info/SOURCES.txt +1 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh.egg-info/requires.txt +3 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/setup.py +3 -1
- npcsh-0.3.27.4/tests/test_tars.py +178 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/LICENSE +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/MANIFEST.in +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/README.md +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/__init__.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/audio.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/cli.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/command_history.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/conversation.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/data_models.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/dataframes.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/embeddings.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/image.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/image_gen.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/knowledge_graph.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/llm_funcs.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/load_data.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/main.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/model_runner.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_compiler.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_sysenv.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/assembly_lines/test_pipeline.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/corca.npc +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/foreman.npc +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/npcsh.ctx +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/sibiji.npc +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/templates/analytics/celona.npc +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/templates/hr_support/raone.npc +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/templates/humanities/eriane.npc +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/templates/it_support/lineru.npc +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/templates/marketing/slean.npc +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/templates/philosophy/maurawa.npc +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/templates/sales/turnic.npc +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/templates/software/welxor.npc +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/tools/calculator.tool +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/tools/generic_search.tool +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/tools/image_generation.tool +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/tools/local_search.tool +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/tools/screen_cap.tool +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/npc_team/tools/sql_executor.tool +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/plonk.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/response.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/serve.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/shell.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/shell_helpers.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/stream.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh/video.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh.egg-info/dependency_links.txt +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh.egg-info/entry_points.txt +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/npcsh.egg-info/top_level.txt +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/setup.cfg +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/tests/test_chromadb.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/tests/test_embedding_check.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/tests/test_embedding_methods.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/tests/test_helpers.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/tests/test_knowledge_graph_rag.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/tests/test_llm_funcs.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/tests/test_networkx_vis.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/tests/test_npc_compiler.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/tests/test_npcsh.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/tests/test_npcteam.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/tests/test_shell_helpers.py +0 -0
- {npcsh-0.3.27.2 → npcsh-0.3.27.4}/tests/test_tool_use.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: npcsh
|
|
3
|
-
Version: 0.3.27.
|
|
3
|
+
Version: 0.3.27.4
|
|
4
4
|
Summary: npcsh is a command line tool for integrating LLMs into everyday workflows and for orchestrating teams of NPCs.
|
|
5
5
|
Home-page: https://github.com/cagostino/npcsh
|
|
6
6
|
Author: Christopher Agostino
|
|
@@ -19,6 +19,7 @@ Requires-Dist: PyYAML
|
|
|
19
19
|
Requires-Dist: pygments
|
|
20
20
|
Requires-Dist: termcolor
|
|
21
21
|
Requires-Dist: colorama
|
|
22
|
+
Requires-Dist: Pillow
|
|
22
23
|
Requires-Dist: python-dotenv
|
|
23
24
|
Requires-Dist: pandas
|
|
24
25
|
Requires-Dist: beautifulsoup4
|
|
@@ -39,6 +40,7 @@ Requires-Dist: ollama; extra == "local"
|
|
|
39
40
|
Requires-Dist: kuzu; extra == "local"
|
|
40
41
|
Requires-Dist: chromadb; extra == "local"
|
|
41
42
|
Requires-Dist: diffusers; extra == "local"
|
|
43
|
+
Requires-Dist: nltk; extra == "local"
|
|
42
44
|
Provides-Extra: whisper
|
|
43
45
|
Requires-Dist: openai-whisper; extra == "whisper"
|
|
44
46
|
Requires-Dist: pyaudio; extra == "whisper"
|
|
@@ -56,6 +58,7 @@ Requires-Dist: ollama; extra == "all"
|
|
|
56
58
|
Requires-Dist: kuzu; extra == "all"
|
|
57
59
|
Requires-Dist: chromadb; extra == "all"
|
|
58
60
|
Requires-Dist: diffusers; extra == "all"
|
|
61
|
+
Requires-Dist: nltk; extra == "all"
|
|
59
62
|
Requires-Dist: openai-whisper; extra == "all"
|
|
60
63
|
Requires-Dist: pyaudio; extra == "all"
|
|
61
64
|
Requires-Dist: gtts; extra == "all"
|
|
@@ -5,7 +5,11 @@ import os
|
|
|
5
5
|
|
|
6
6
|
from bs4 import BeautifulSoup
|
|
7
7
|
from duckduckgo_search import DDGS
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from googlesearch import search
|
|
11
|
+
except:
|
|
12
|
+
pass
|
|
9
13
|
from typing import List, Dict, Any, Optional, Union
|
|
10
14
|
import numpy as np
|
|
11
15
|
import json
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: npcsh
|
|
3
|
-
Version: 0.3.27.
|
|
3
|
+
Version: 0.3.27.4
|
|
4
4
|
Summary: npcsh is a command line tool for integrating LLMs into everyday workflows and for orchestrating teams of NPCs.
|
|
5
5
|
Home-page: https://github.com/cagostino/npcsh
|
|
6
6
|
Author: Christopher Agostino
|
|
@@ -19,6 +19,7 @@ Requires-Dist: PyYAML
|
|
|
19
19
|
Requires-Dist: pygments
|
|
20
20
|
Requires-Dist: termcolor
|
|
21
21
|
Requires-Dist: colorama
|
|
22
|
+
Requires-Dist: Pillow
|
|
22
23
|
Requires-Dist: python-dotenv
|
|
23
24
|
Requires-Dist: pandas
|
|
24
25
|
Requires-Dist: beautifulsoup4
|
|
@@ -39,6 +40,7 @@ Requires-Dist: ollama; extra == "local"
|
|
|
39
40
|
Requires-Dist: kuzu; extra == "local"
|
|
40
41
|
Requires-Dist: chromadb; extra == "local"
|
|
41
42
|
Requires-Dist: diffusers; extra == "local"
|
|
43
|
+
Requires-Dist: nltk; extra == "local"
|
|
42
44
|
Provides-Extra: whisper
|
|
43
45
|
Requires-Dist: openai-whisper; extra == "whisper"
|
|
44
46
|
Requires-Dist: pyaudio; extra == "whisper"
|
|
@@ -56,6 +58,7 @@ Requires-Dist: ollama; extra == "all"
|
|
|
56
58
|
Requires-Dist: kuzu; extra == "all"
|
|
57
59
|
Requires-Dist: chromadb; extra == "all"
|
|
58
60
|
Requires-Dist: diffusers; extra == "all"
|
|
61
|
+
Requires-Dist: nltk; extra == "all"
|
|
59
62
|
Requires-Dist: openai-whisper; extra == "all"
|
|
60
63
|
Requires-Dist: pyaudio; extra == "all"
|
|
61
64
|
Requires-Dist: gtts; extra == "all"
|
|
@@ -7,6 +7,7 @@ PyYAML
|
|
|
7
7
|
pygments
|
|
8
8
|
termcolor
|
|
9
9
|
colorama
|
|
10
|
+
Pillow
|
|
10
11
|
python-dotenv
|
|
11
12
|
pandas
|
|
12
13
|
beautifulsoup4
|
|
@@ -27,6 +28,7 @@ ollama
|
|
|
27
28
|
kuzu
|
|
28
29
|
chromadb
|
|
29
30
|
diffusers
|
|
31
|
+
nltk
|
|
30
32
|
openai-whisper
|
|
31
33
|
pyaudio
|
|
32
34
|
gtts
|
|
@@ -46,6 +48,7 @@ ollama
|
|
|
46
48
|
kuzu
|
|
47
49
|
chromadb
|
|
48
50
|
diffusers
|
|
51
|
+
nltk
|
|
49
52
|
|
|
50
53
|
[whisper]
|
|
51
54
|
openai-whisper
|
|
@@ -63,6 +63,7 @@ base_requirements = [
|
|
|
63
63
|
"pygments",
|
|
64
64
|
"termcolor",
|
|
65
65
|
"colorama",
|
|
66
|
+
"Pillow",
|
|
66
67
|
"python-dotenv",
|
|
67
68
|
"pandas",
|
|
68
69
|
"beautifulsoup4",
|
|
@@ -84,6 +85,7 @@ local_requirements = [
|
|
|
84
85
|
"kuzu",
|
|
85
86
|
"chromadb",
|
|
86
87
|
"diffusers",
|
|
88
|
+
"nltk",
|
|
87
89
|
]
|
|
88
90
|
|
|
89
91
|
# Voice/Audio requirements
|
|
@@ -99,7 +101,7 @@ extra_files = package_files("npcsh/npc_team/")
|
|
|
99
101
|
|
|
100
102
|
setup(
|
|
101
103
|
name="npcsh",
|
|
102
|
-
version="0.3.27.
|
|
104
|
+
version="0.3.27.4",
|
|
103
105
|
packages=find_packages(exclude=["tests*"]),
|
|
104
106
|
install_requires=base_requirements, # Only install base requirements by default
|
|
105
107
|
extras_require={
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import base64
|
|
3
|
+
import requests
|
|
4
|
+
import json
|
|
5
|
+
import torch
|
|
6
|
+
import pyautogui # For taking screenshots
|
|
7
|
+
import time
|
|
8
|
+
from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
|
|
9
|
+
from screeninfo import get_monitors
|
|
10
|
+
from npcsh.llm_funcs import get_openai_response
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_screen_resolution():
|
|
14
|
+
monitor = get_monitors()[0] # Get primary monitor
|
|
15
|
+
return monitor.width, monitor.height
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
from PIL import Image
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def capture_screenshot() -> str:
|
|
22
|
+
"""Captures a screenshot and saves it to a specified path."""
|
|
23
|
+
screenshot_path = "screenshot.png"
|
|
24
|
+
screenshot = pyautogui.screenshot()
|
|
25
|
+
|
|
26
|
+
# Resize screenshot to fit model's pixel range
|
|
27
|
+
desired_width = 1280 # Adjust as needed based on max_pixels range
|
|
28
|
+
desired_height = int(
|
|
29
|
+
(desired_width * screenshot.height) / screenshot.width
|
|
30
|
+
) # Maintain aspect ratio
|
|
31
|
+
screenshot = screenshot.resize((desired_width, desired_height))
|
|
32
|
+
|
|
33
|
+
screenshot.save(screenshot_path)
|
|
34
|
+
return screenshot_path
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Adjust processor for specific pixel range
|
|
38
|
+
min_pixels = 256 * 28 * 28
|
|
39
|
+
max_pixels = 1280 * 28 * 28
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def encode_image_to_base64(image_path: str) -> str:
|
|
43
|
+
"""Encodes an image file to a base64 string."""
|
|
44
|
+
with open(image_path, "rb") as image_file:
|
|
45
|
+
encoded_string = base64.b64encode(image_file.read()).decode("utf-8")
|
|
46
|
+
return f"data:image/png;base64,{encoded_string}"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get_tars_response(command: str, model_name: str) -> str:
|
|
50
|
+
"""Generates a response from the UI-TARS model based on the command and screenshot image."""
|
|
51
|
+
# model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
|
|
52
|
+
# model_name, torch_dtype="auto", device_map="auto"
|
|
53
|
+
# )
|
|
54
|
+
# processor = AutoProcessor.from_pretrained(model_name)
|
|
55
|
+
|
|
56
|
+
# capture the current screen
|
|
57
|
+
im = capture_screenshot()
|
|
58
|
+
image_data = encode_image_to_base64(im)
|
|
59
|
+
prompt = (
|
|
60
|
+
f"""You are a GUI agent. You are given a task and your action history,
|
|
61
|
+
with screenshots. You need to perform the next action or set of actions to complete the task.
|
|
62
|
+
here is the task you must complete: {command}
|
|
63
|
+
"""
|
|
64
|
+
+ r"""
|
|
65
|
+
click(start_box='<|box_start|>(x1,y1)<|box_end|>')
|
|
66
|
+
left_double(start_box='<|box_start|>(x1,y1)<|box_end|>')
|
|
67
|
+
right_single(start_box='<|box_start|>(x1,y1)<|box_end|>')
|
|
68
|
+
drag(start_box='<|box_start|>(x1,y1)<|box_end|>', end_box='<|box_start|>(x3,y3)<|box_end|>')
|
|
69
|
+
hotkey(key='')
|
|
70
|
+
type(content='') #If you want to submit your input, use "\
|
|
71
|
+
" at the end of `content`.
|
|
72
|
+
scroll(start_box='<|box_start|>(x1,y1)<|box_end|>', direction='down or up or right or left')
|
|
73
|
+
wait() #Sleep for 5s and take a screenshot to check for any changes.
|
|
74
|
+
finished()
|
|
75
|
+
call_user() # Submit the task and call the user when the task is unsolvable, or when you need the user's help.
|
|
76
|
+
|
|
77
|
+
your response should be a list of actions to perform in the order they should be performed.
|
|
78
|
+
Provide a single json object with the following format:
|
|
79
|
+
{ "actions": ['action1', 'action2', 'action3'] }
|
|
80
|
+
Do not provide any additional text or markdown formatting.
|
|
81
|
+
"""
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
messages = [
|
|
85
|
+
{
|
|
86
|
+
"role": "user",
|
|
87
|
+
"content": [
|
|
88
|
+
{
|
|
89
|
+
"type": "image_url",
|
|
90
|
+
"image_url": {"url": image_data},
|
|
91
|
+
},
|
|
92
|
+
{"type": "text", "text": command},
|
|
93
|
+
],
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
# tars:
|
|
98
|
+
"""text = processor.apply_chat_template(
|
|
99
|
+
messages, tokenize=False, add_generation_prompt=True
|
|
100
|
+
)
|
|
101
|
+
inputs = processor(text=text, padding=True, return_tensors="pt").to(model.device)
|
|
102
|
+
generated_ids = model.generate(**inputs, max_new_tokens=128)
|
|
103
|
+
output_text = processor.batch_decode(generated_ids, skip_special_tokens=True)
|
|
104
|
+
return output_text[0]
|
|
105
|
+
"""
|
|
106
|
+
gpt4o_response = get_openai_response(
|
|
107
|
+
prompt, model="gpt-4o-mini", messages=messages, format="json"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
return gpt4o_response
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def execute_actions(actions: list):
|
|
114
|
+
"""Executes the actions received from the model using pyautogui."""
|
|
115
|
+
for action in actions:
|
|
116
|
+
if action.startswith("click"):
|
|
117
|
+
x, y = map(int, action[action.find("(") + 1 : action.find(")")].split(","))
|
|
118
|
+
pyautogui.click(x, y)
|
|
119
|
+
elif action.startswith("left_double"):
|
|
120
|
+
x, y = map(int, action[action.find("(") + 1 : action.find(")")].split(","))
|
|
121
|
+
pyautogui.doubleClick(x, y)
|
|
122
|
+
elif action.startswith("right_single"):
|
|
123
|
+
x, y = map(int, action[action.find("(") + 1 : action.find(")")].split(","))
|
|
124
|
+
pyautogui.rightClick(x, y)
|
|
125
|
+
elif action.startswith("drag"):
|
|
126
|
+
coords = list(
|
|
127
|
+
map(
|
|
128
|
+
int,
|
|
129
|
+
action[action.find("(") + 1 : action.find(")")]
|
|
130
|
+
.replace("(", "")
|
|
131
|
+
.replace(")", "")
|
|
132
|
+
.split(","),
|
|
133
|
+
)
|
|
134
|
+
)
|
|
135
|
+
pyautogui.moveTo(coords[0], coords[1])
|
|
136
|
+
pyautogui.dragTo(coords[2], coords[3], duration=0.5)
|
|
137
|
+
elif action.startswith("type"):
|
|
138
|
+
text = action.split("('")[1].split("')")[0]
|
|
139
|
+
pyautogui.write(text, interval=0.05)
|
|
140
|
+
elif action.startswith("hotkey"):
|
|
141
|
+
key = action.split("('")[1].split("')")[0]
|
|
142
|
+
pyautogui.hotkey(key)
|
|
143
|
+
elif action.startswith("scroll"):
|
|
144
|
+
direction = action.split("('")[1].split("')")[0]
|
|
145
|
+
amount = -100 if direction == "down" else 100
|
|
146
|
+
pyautogui.scroll(amount)
|
|
147
|
+
elif action.startswith("wait"):
|
|
148
|
+
time.sleep(5)
|
|
149
|
+
elif action.startswith("finished"):
|
|
150
|
+
print("Task completed.")
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def ui_tars_control_loop(model_name: str):
|
|
154
|
+
"""Main loop for interacting with the user and executing commands via UI-TARS."""
|
|
155
|
+
print("UI-TARS Control Loop Started.")
|
|
156
|
+
screen_width, screen_height = get_screen_resolution()
|
|
157
|
+
print(f"Screen resolution: {screen_width}x{screen_height}")
|
|
158
|
+
|
|
159
|
+
while True:
|
|
160
|
+
command = input("Enter your command (or type 'exit' to quit): ")
|
|
161
|
+
if command.lower() == "exit":
|
|
162
|
+
print("Exiting UI-TARS Control Loop.")
|
|
163
|
+
break
|
|
164
|
+
|
|
165
|
+
screenshot_path = capture_screenshot()
|
|
166
|
+
tars_result = get_tars_response(command, screenshot_path, model_name)
|
|
167
|
+
print(f"UI-TARS Response: {tars_result}")
|
|
168
|
+
|
|
169
|
+
try:
|
|
170
|
+
actions = json.loads(tars_result).get("actions", [])
|
|
171
|
+
execute_actions(actions)
|
|
172
|
+
except json.JSONDecodeError:
|
|
173
|
+
print("Error parsing actions from UI-TARS response.")
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
if __name__ == "__main__":
|
|
177
|
+
MODEL_NAME = "ui-tars-7B" # Replace with your actual UI-TARS model name
|
|
178
|
+
ui_tars_control_loop(MODEL_NAME)
|
|
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
|