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.
- {npcsh-0.3.27.1/npcsh.egg-info → npcsh-0.3.27.3}/PKG-INFO +44 -29
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/search.py +5 -1
- {npcsh-0.3.27.1 → npcsh-0.3.27.3/npcsh.egg-info}/PKG-INFO +44 -29
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh.egg-info/SOURCES.txt +1 -0
- npcsh-0.3.27.3/npcsh.egg-info/requires.txt +56 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/setup.py +27 -52
- npcsh-0.3.27.3/tests/test_tars.py +178 -0
- npcsh-0.3.27.1/npcsh.egg-info/requires.txt +0 -38
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/LICENSE +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/MANIFEST.in +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/README.md +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/__init__.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/audio.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/cli.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/command_history.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/conversation.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/data_models.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/dataframes.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/embeddings.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/helpers.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/image.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/image_gen.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/knowledge_graph.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/llm_funcs.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/load_data.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/main.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/model_runner.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_compiler.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_sysenv.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/assembly_lines/test_pipeline.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/corca.npc +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/foreman.npc +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/npcsh.ctx +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/sibiji.npc +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/analytics/celona.npc +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/hr_support/raone.npc +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/humanities/eriane.npc +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/it_support/lineru.npc +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/marketing/slean.npc +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/philosophy/maurawa.npc +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/sales/turnic.npc +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/templates/software/welxor.npc +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/tools/calculator.tool +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/tools/generic_search.tool +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/tools/image_generation.tool +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/tools/local_search.tool +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/tools/screen_cap.tool +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/npc_team/tools/sql_executor.tool +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/plonk.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/response.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/serve.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/shell.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/shell_helpers.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/stream.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh/video.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh.egg-info/dependency_links.txt +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh.egg-info/entry_points.txt +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/npcsh.egg-info/top_level.txt +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/setup.cfg +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_chromadb.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_embedding_check.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_embedding_methods.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_helpers.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_knowledge_graph_rag.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_llm_funcs.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_networkx_vis.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_npc_compiler.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_npcsh.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_npcteam.py +0 -0
- {npcsh-0.3.27.1 → npcsh-0.3.27.3}/tests/test_shell_helpers.py +0 -0
- {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.
|
|
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:
|
|
32
|
-
Requires-Dist:
|
|
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:
|
|
36
|
-
Requires-Dist:
|
|
37
|
-
|
|
38
|
-
Requires-Dist:
|
|
39
|
-
Requires-Dist:
|
|
40
|
-
Requires-Dist:
|
|
41
|
-
Requires-Dist:
|
|
42
|
-
|
|
43
|
-
Requires-Dist:
|
|
44
|
-
Requires-Dist:
|
|
45
|
-
Requires-Dist:
|
|
46
|
-
Requires-Dist:
|
|
47
|
-
Requires-Dist:
|
|
48
|
-
Requires-Dist:
|
|
49
|
-
|
|
50
|
-
Requires-Dist:
|
|
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
|
-
|
|
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.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:
|
|
32
|
-
Requires-Dist:
|
|
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:
|
|
36
|
-
Requires-Dist:
|
|
37
|
-
|
|
38
|
-
Requires-Dist:
|
|
39
|
-
Requires-Dist:
|
|
40
|
-
Requires-Dist:
|
|
41
|
-
Requires-Dist:
|
|
42
|
-
|
|
43
|
-
Requires-Dist:
|
|
44
|
-
Requires-Dist:
|
|
45
|
-
Requires-Dist:
|
|
46
|
-
Requires-Dist:
|
|
47
|
-
Requires-Dist:
|
|
48
|
-
Requires-Dist:
|
|
49
|
-
|
|
50
|
-
Requires-Dist:
|
|
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
|
|
@@ -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 ""
|
|
52
|
+
return ""
|
|
62
53
|
|
|
63
54
|
|
|
64
|
-
#
|
|
65
|
-
|
|
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
|
-
"
|
|
85
|
-
"
|
|
68
|
+
"pandas",
|
|
69
|
+
"beautifulsoup4",
|
|
70
|
+
"duckduckgo-search",
|
|
86
71
|
"flask",
|
|
87
72
|
"flask_cors",
|
|
88
|
-
"
|
|
89
|
-
"
|
|
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
|
-
#
|
|
101
|
-
|
|
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
|
-
#
|
|
111
|
-
|
|
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.
|
|
103
|
+
version="0.3.27.3",
|
|
134
104
|
packages=find_packages(exclude=["tests*"]),
|
|
135
|
-
install_requires=
|
|
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
|
|
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
|