npcsh 0.3.27.1__tar.gz → 0.3.27.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.
Files changed (71) hide show
  1. {npcsh-0.3.27.1/npcsh.egg-info → npcsh-0.3.27.3}/PKG-INFO +44 -29
  2. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/search.py +5 -1
  3. {npcsh-0.3.27.1 → npcsh-0.3.27.3/npcsh.egg-info}/PKG-INFO +44 -29
  4. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh.egg-info/SOURCES.txt +1 -0
  5. npcsh-0.3.27.3/npcsh.egg-info/requires.txt +56 -0
  6. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/setup.py +27 -52
  7. npcsh-0.3.27.3/tests/test_tars.py +178 -0
  8. npcsh-0.3.27.1/npcsh.egg-info/requires.txt +0 -38
  9. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/LICENSE +0 -0
  10. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/MANIFEST.in +0 -0
  11. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/README.md +0 -0
  12. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/__init__.py +0 -0
  13. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/audio.py +0 -0
  14. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/cli.py +0 -0
  15. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/command_history.py +0 -0
  16. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/conversation.py +0 -0
  17. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/data_models.py +0 -0
  18. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/dataframes.py +0 -0
  19. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/embeddings.py +0 -0
  20. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/helpers.py +0 -0
  21. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/image.py +0 -0
  22. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/image_gen.py +0 -0
  23. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/knowledge_graph.py +0 -0
  24. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/llm_funcs.py +0 -0
  25. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/load_data.py +0 -0
  26. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/main.py +0 -0
  27. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/model_runner.py +0 -0
  28. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_compiler.py +0 -0
  29. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_sysenv.py +0 -0
  30. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/assembly_lines/test_pipeline.py +0 -0
  31. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/corca.npc +0 -0
  32. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/foreman.npc +0 -0
  33. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/npcsh.ctx +0 -0
  34. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/sibiji.npc +0 -0
  35. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/analytics/celona.npc +0 -0
  36. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/hr_support/raone.npc +0 -0
  37. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/humanities/eriane.npc +0 -0
  38. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/it_support/lineru.npc +0 -0
  39. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/marketing/slean.npc +0 -0
  40. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/philosophy/maurawa.npc +0 -0
  41. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/sales/turnic.npc +0 -0
  42. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/software/welxor.npc +0 -0
  43. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/tools/calculator.tool +0 -0
  44. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/tools/generic_search.tool +0 -0
  45. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/tools/image_generation.tool +0 -0
  46. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/tools/local_search.tool +0 -0
  47. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/tools/screen_cap.tool +0 -0
  48. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/tools/sql_executor.tool +0 -0
  49. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/plonk.py +0 -0
  50. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/response.py +0 -0
  51. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/serve.py +0 -0
  52. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/shell.py +0 -0
  53. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/shell_helpers.py +0 -0
  54. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/stream.py +0 -0
  55. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/video.py +0 -0
  56. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh.egg-info/dependency_links.txt +0 -0
  57. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh.egg-info/entry_points.txt +0 -0
  58. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh.egg-info/top_level.txt +0 -0
  59. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/setup.cfg +0 -0
  60. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_chromadb.py +0 -0
  61. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_embedding_check.py +0 -0
  62. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_embedding_methods.py +0 -0
  63. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_helpers.py +0 -0
  64. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_knowledge_graph_rag.py +0 -0
  65. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_llm_funcs.py +0 -0
  66. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_networkx_vis.py +0 -0
  67. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_npc_compiler.py +0 -0
  68. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_npcsh.py +0 -0
  69. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_npcteam.py +0 -0
  70. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_shell_helpers.py +0 -0
  71. {npcsh-0.3.27.1 → npcsh-0.3.27.3}/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.1
3
+ Version: 0.3.27.3
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
@@ -10,44 +10,58 @@ Classifier: License :: OSI Approved :: MIT License
10
10
  Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: redis
14
- Requires-Dist: flask_sse
15
- Requires-Dist: anthropic
16
- Requires-Dist: beautifulsoup4
17
- Requires-Dist: google-generativeai
18
- Requires-Dist: google-genai
19
- Requires-Dist: duckduckgo-search
20
- Requires-Dist: openai
21
13
  Requires-Dist: jinja2
14
+ Requires-Dist: scipy
15
+ Requires-Dist: numpy
22
16
  Requires-Dist: requests
23
17
  Requires-Dist: markdown
24
18
  Requires-Dist: PyYAML
25
- Requires-Dist: langchain
26
- Requires-Dist: langchain_community
27
19
  Requires-Dist: pygments
28
20
  Requires-Dist: termcolor
29
21
  Requires-Dist: colorama
22
+ Requires-Dist: Pillow
30
23
  Requires-Dist: python-dotenv
31
- Requires-Dist: pytest
32
- Requires-Dist: googlesearch-python
24
+ Requires-Dist: pandas
25
+ Requires-Dist: beautifulsoup4
26
+ Requires-Dist: duckduckgo-search
33
27
  Requires-Dist: flask
34
28
  Requires-Dist: flask_cors
35
- Requires-Dist: librosa
36
- Requires-Dist: pandas
37
- Requires-Dist: matplotlib
38
- Requires-Dist: IPython
39
- Requires-Dist: pyautogui
40
- Requires-Dist: nltk
41
- Requires-Dist: thefuzz
42
- Requires-Dist: pypdf
43
- Requires-Dist: PyMuPDF
44
- Requires-Dist: screeninfo
45
- Requires-Dist: sentence_transformers
46
- Requires-Dist: opencv-python
47
- Requires-Dist: ollama
48
- Requires-Dist: kuzu
49
- Requires-Dist: chromadb
50
- Requires-Dist: diffusers
29
+ Requires-Dist: redis
30
+ Requires-Dist: flask_sse
31
+ Provides-Extra: lite
32
+ Requires-Dist: anthropic; extra == "lite"
33
+ Requires-Dist: openai; extra == "lite"
34
+ Requires-Dist: google-generativeai; extra == "lite"
35
+ Requires-Dist: google-genai; extra == "lite"
36
+ Provides-Extra: local
37
+ Requires-Dist: sentence_transformers; extra == "local"
38
+ Requires-Dist: opencv-python; extra == "local"
39
+ Requires-Dist: ollama; extra == "local"
40
+ Requires-Dist: kuzu; extra == "local"
41
+ Requires-Dist: chromadb; extra == "local"
42
+ Requires-Dist: diffusers; extra == "local"
43
+ Provides-Extra: whisper
44
+ Requires-Dist: openai-whisper; extra == "whisper"
45
+ Requires-Dist: pyaudio; extra == "whisper"
46
+ Requires-Dist: gtts; extra == "whisper"
47
+ Requires-Dist: playsound==1.2.2; extra == "whisper"
48
+ Requires-Dist: pyttsx3; extra == "whisper"
49
+ Provides-Extra: all
50
+ Requires-Dist: anthropic; extra == "all"
51
+ Requires-Dist: openai; extra == "all"
52
+ Requires-Dist: google-generativeai; extra == "all"
53
+ Requires-Dist: google-genai; extra == "all"
54
+ Requires-Dist: sentence_transformers; extra == "all"
55
+ Requires-Dist: opencv-python; extra == "all"
56
+ Requires-Dist: ollama; extra == "all"
57
+ Requires-Dist: kuzu; extra == "all"
58
+ Requires-Dist: chromadb; extra == "all"
59
+ Requires-Dist: diffusers; extra == "all"
60
+ Requires-Dist: openai-whisper; extra == "all"
61
+ Requires-Dist: pyaudio; extra == "all"
62
+ Requires-Dist: gtts; extra == "all"
63
+ Requires-Dist: playsound==1.2.2; extra == "all"
64
+ Requires-Dist: pyttsx3; extra == "all"
51
65
  Dynamic: author
52
66
  Dynamic: author-email
53
67
  Dynamic: classifier
@@ -55,6 +69,7 @@ Dynamic: description
55
69
  Dynamic: description-content-type
56
70
  Dynamic: home-page
57
71
  Dynamic: license-file
72
+ Dynamic: provides-extra
58
73
  Dynamic: requires-dist
59
74
  Dynamic: requires-python
60
75
  Dynamic: summary
@@ -5,7 +5,11 @@ import os
5
5
 
6
6
  from bs4 import BeautifulSoup
7
7
  from duckduckgo_search import DDGS
8
- from googlesearch import search
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.1
3
+ Version: 0.3.27.3
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
@@ -10,44 +10,58 @@ Classifier: License :: OSI Approved :: MIT License
10
10
  Requires-Python: >=3.10
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: redis
14
- Requires-Dist: flask_sse
15
- Requires-Dist: anthropic
16
- Requires-Dist: beautifulsoup4
17
- Requires-Dist: google-generativeai
18
- Requires-Dist: google-genai
19
- Requires-Dist: duckduckgo-search
20
- Requires-Dist: openai
21
13
  Requires-Dist: jinja2
14
+ Requires-Dist: scipy
15
+ Requires-Dist: numpy
22
16
  Requires-Dist: requests
23
17
  Requires-Dist: markdown
24
18
  Requires-Dist: PyYAML
25
- Requires-Dist: langchain
26
- Requires-Dist: langchain_community
27
19
  Requires-Dist: pygments
28
20
  Requires-Dist: termcolor
29
21
  Requires-Dist: colorama
22
+ Requires-Dist: Pillow
30
23
  Requires-Dist: python-dotenv
31
- Requires-Dist: pytest
32
- Requires-Dist: googlesearch-python
24
+ Requires-Dist: pandas
25
+ Requires-Dist: beautifulsoup4
26
+ Requires-Dist: duckduckgo-search
33
27
  Requires-Dist: flask
34
28
  Requires-Dist: flask_cors
35
- Requires-Dist: librosa
36
- Requires-Dist: pandas
37
- Requires-Dist: matplotlib
38
- Requires-Dist: IPython
39
- Requires-Dist: pyautogui
40
- Requires-Dist: nltk
41
- Requires-Dist: thefuzz
42
- Requires-Dist: pypdf
43
- Requires-Dist: PyMuPDF
44
- Requires-Dist: screeninfo
45
- Requires-Dist: sentence_transformers
46
- Requires-Dist: opencv-python
47
- Requires-Dist: ollama
48
- Requires-Dist: kuzu
49
- Requires-Dist: chromadb
50
- Requires-Dist: diffusers
29
+ Requires-Dist: redis
30
+ Requires-Dist: flask_sse
31
+ Provides-Extra: lite
32
+ Requires-Dist: anthropic; extra == "lite"
33
+ Requires-Dist: openai; extra == "lite"
34
+ Requires-Dist: google-generativeai; extra == "lite"
35
+ Requires-Dist: google-genai; extra == "lite"
36
+ Provides-Extra: local
37
+ Requires-Dist: sentence_transformers; extra == "local"
38
+ Requires-Dist: opencv-python; extra == "local"
39
+ Requires-Dist: ollama; extra == "local"
40
+ Requires-Dist: kuzu; extra == "local"
41
+ Requires-Dist: chromadb; extra == "local"
42
+ Requires-Dist: diffusers; extra == "local"
43
+ Provides-Extra: whisper
44
+ Requires-Dist: openai-whisper; extra == "whisper"
45
+ Requires-Dist: pyaudio; extra == "whisper"
46
+ Requires-Dist: gtts; extra == "whisper"
47
+ Requires-Dist: playsound==1.2.2; extra == "whisper"
48
+ Requires-Dist: pyttsx3; extra == "whisper"
49
+ Provides-Extra: all
50
+ Requires-Dist: anthropic; extra == "all"
51
+ Requires-Dist: openai; extra == "all"
52
+ Requires-Dist: google-generativeai; extra == "all"
53
+ Requires-Dist: google-genai; extra == "all"
54
+ Requires-Dist: sentence_transformers; extra == "all"
55
+ Requires-Dist: opencv-python; extra == "all"
56
+ Requires-Dist: ollama; extra == "all"
57
+ Requires-Dist: kuzu; extra == "all"
58
+ Requires-Dist: chromadb; extra == "all"
59
+ Requires-Dist: diffusers; extra == "all"
60
+ Requires-Dist: openai-whisper; extra == "all"
61
+ Requires-Dist: pyaudio; extra == "all"
62
+ Requires-Dist: gtts; extra == "all"
63
+ Requires-Dist: playsound==1.2.2; extra == "all"
64
+ Requires-Dist: pyttsx3; extra == "all"
51
65
  Dynamic: author
52
66
  Dynamic: author-email
53
67
  Dynamic: classifier
@@ -55,6 +69,7 @@ Dynamic: description
55
69
  Dynamic: description-content-type
56
70
  Dynamic: home-page
57
71
  Dynamic: license-file
72
+ Dynamic: provides-extra
58
73
  Dynamic: requires-dist
59
74
  Dynamic: requires-python
60
75
  Dynamic: summary
@@ -64,4 +64,5 @@ tests/test_npc_compiler.py
64
64
  tests/test_npcsh.py
65
65
  tests/test_npcteam.py
66
66
  tests/test_shell_helpers.py
67
+ tests/test_tars.py
67
68
  tests/test_tool_use.py
@@ -0,0 +1,56 @@
1
+ jinja2
2
+ scipy
3
+ numpy
4
+ requests
5
+ markdown
6
+ PyYAML
7
+ pygments
8
+ termcolor
9
+ colorama
10
+ Pillow
11
+ python-dotenv
12
+ pandas
13
+ beautifulsoup4
14
+ duckduckgo-search
15
+ flask
16
+ flask_cors
17
+ redis
18
+ flask_sse
19
+
20
+ [all]
21
+ anthropic
22
+ openai
23
+ google-generativeai
24
+ google-genai
25
+ sentence_transformers
26
+ opencv-python
27
+ ollama
28
+ kuzu
29
+ chromadb
30
+ diffusers
31
+ openai-whisper
32
+ pyaudio
33
+ gtts
34
+ playsound==1.2.2
35
+ pyttsx3
36
+
37
+ [lite]
38
+ anthropic
39
+ openai
40
+ google-generativeai
41
+ google-genai
42
+
43
+ [local]
44
+ sentence_transformers
45
+ opencv-python
46
+ ollama
47
+ kuzu
48
+ chromadb
49
+ diffusers
50
+
51
+ [whisper]
52
+ openai-whisper
53
+ pyaudio
54
+ gtts
55
+ playsound==1.2.2
56
+ pyttsx3
@@ -1,17 +1,8 @@
1
- # Force lite installation if environment variable is set
2
- import os
3
-
4
- import sys
5
-
6
- if os.environ.get("NPCSH_LITE_INSTALL", "").lower() == "true":
7
-
8
- sys.argv.append("--config-settings")
9
- sys.argv.append("install.lite=true")
10
-
11
1
  from setuptools import setup, find_packages
12
2
  import site
13
3
  import platform
14
4
  from pathlib import Path
5
+ import os
15
6
 
16
7
 
17
8
  def package_files(directory):
@@ -58,47 +49,36 @@ npcsh-setup
58
49
  To configure your API keys and preferences.
59
50
  ==============================================
60
51
  """
61
- return "" # Return empty string for non-Windows platforms
52
+ return ""
62
53
 
63
54
 
64
- # Define core (lite) requirements
65
- core_requirements = [
66
- "redis",
67
- "flask_sse",
68
- "anthropic",
69
- "beautifulsoup4",
70
- "google-generativeai",
71
- "google-genai",
72
- "duckduckgo-search",
73
- "openai",
55
+ # Base requirements (no LLM packages)
56
+ base_requirements = [
74
57
  "jinja2",
58
+ "scipy",
59
+ "numpy",
75
60
  "requests",
76
61
  "markdown",
77
62
  "PyYAML",
78
- "langchain",
79
- "langchain_community",
80
63
  "pygments",
81
64
  "termcolor",
82
65
  "colorama",
66
+ "Pillow",
83
67
  "python-dotenv",
84
- "pytest",
85
- "googlesearch-python",
68
+ "pandas",
69
+ "beautifulsoup4",
70
+ "duckduckgo-search",
86
71
  "flask",
87
72
  "flask_cors",
88
- "librosa",
89
- "pandas",
90
- "matplotlib",
91
- "IPython",
92
- "pyautogui",
93
- "nltk",
94
- "thefuzz",
95
- "pypdf",
96
- "PyMuPDF",
97
- "screeninfo",
73
+ "redis",
74
+ "flask_sse",
98
75
  ]
99
76
 
100
- # Define additional requirements for full installation
101
- extra_requirements = [
77
+ # API integration requirements
78
+ api_requirements = ["anthropic", "openai", "google-generativeai", "google-genai"]
79
+
80
+ # Local ML/AI requirements
81
+ local_requirements = [
102
82
  "sentence_transformers",
103
83
  "opencv-python",
104
84
  "ollama",
@@ -107,8 +87,8 @@ extra_requirements = [
107
87
  "diffusers",
108
88
  ]
109
89
 
110
- # Define audio requirements
111
- audio_requirements = [
90
+ # Voice/Audio requirements
91
+ voice_requirements = [
112
92
  "openai-whisper",
113
93
  "pyaudio",
114
94
  "gtts",
@@ -118,21 +98,17 @@ audio_requirements = [
118
98
 
119
99
  extra_files = package_files("npcsh/npc_team/")
120
100
 
121
-
122
- def get_requirements():
123
- # Check if lite installation was requested via sys.argv
124
- if any("install.lite=true" in arg for arg in sys.argv):
125
- return core_requirements
126
- elif os.environ.get("NPCSH_AUDIO_INSTALL", "").lower() == "true":
127
- return core_requirements + extra_requirements + audio_requirements
128
- return core_requirements + extra_requirements
129
-
130
-
131
101
  setup(
132
102
  name="npcsh",
133
- version="0.3.27.1",
103
+ version="0.3.27.3",
134
104
  packages=find_packages(exclude=["tests*"]),
135
- install_requires=get_requirements(),
105
+ install_requires=base_requirements, # Only install base requirements by default
106
+ extras_require={
107
+ "lite": api_requirements, # Just API integrations
108
+ "local": local_requirements, # Local AI/ML features
109
+ "whisper": voice_requirements, # Voice/Audio features
110
+ "all": api_requirements + local_requirements + voice_requirements, # Everything
111
+ },
136
112
  entry_points={
137
113
  "console_scripts": [
138
114
  "npcsh=npcsh.shell:main",
@@ -154,6 +130,5 @@ setup(
154
130
  python_requires=">=3.10",
155
131
  )
156
132
 
157
- # Print setup message only on Windows
158
133
  if platform.system() == "Windows":
159
134
  print(get_setup_message())
@@ -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)
@@ -1,38 +0,0 @@
1
- redis
2
- flask_sse
3
- anthropic
4
- beautifulsoup4
5
- google-generativeai
6
- google-genai
7
- duckduckgo-search
8
- openai
9
- jinja2
10
- requests
11
- markdown
12
- PyYAML
13
- langchain
14
- langchain_community
15
- pygments
16
- termcolor
17
- colorama
18
- python-dotenv
19
- pytest
20
- googlesearch-python
21
- flask
22
- flask_cors
23
- librosa
24
- pandas
25
- matplotlib
26
- IPython
27
- pyautogui
28
- nltk
29
- thefuzz
30
- pypdf
31
- PyMuPDF
32
- screeninfo
33
- sentence_transformers
34
- opencv-python
35
- ollama
36
- kuzu
37
- chromadb
38
- diffusers
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