codegpt-ai 1.20.0 → 1.22.0
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.
- package/chat.py +96 -25
- package/package.json +1 -1
package/chat.py
CHANGED
|
@@ -28,6 +28,21 @@ from prompt_toolkit.styles import Style as PtStyle
|
|
|
28
28
|
|
|
29
29
|
# --- Config ---
|
|
30
30
|
|
|
31
|
+
# Fix PATH for Termux and pip --user installs
|
|
32
|
+
_extra_paths = [
|
|
33
|
+
os.path.expanduser("~/.local/bin"),
|
|
34
|
+
os.path.expanduser("~/bin"),
|
|
35
|
+
]
|
|
36
|
+
if os.path.exists("/data/data/com.termux"):
|
|
37
|
+
_extra_paths.extend([
|
|
38
|
+
"/data/data/com.termux/files/usr/bin",
|
|
39
|
+
"/data/data/com.termux/files/home/.local/bin",
|
|
40
|
+
os.path.expanduser("~/.npm-global/bin"),
|
|
41
|
+
])
|
|
42
|
+
for _p in _extra_paths:
|
|
43
|
+
if _p not in os.environ.get("PATH", "") and os.path.isdir(_p):
|
|
44
|
+
os.environ["PATH"] = _p + os.pathsep + os.environ.get("PATH", "")
|
|
45
|
+
|
|
31
46
|
OLLAMA_URL = os.environ.get("OLLAMA_URL", "http://localhost:11434/api/chat")
|
|
32
47
|
MODEL = "llama3.2"
|
|
33
48
|
CHATS_DIR = Path.home() / ".codegpt" / "conversations"
|
|
@@ -223,7 +238,7 @@ AI_TOOLS = {
|
|
|
223
238
|
"install": ["npm", "i", "-g", "@openai/codex"],
|
|
224
239
|
"default_args": [],
|
|
225
240
|
"needs_key": "OPENAI_API_KEY",
|
|
226
|
-
"termux":
|
|
241
|
+
"termux": False, # ARM64 build fails on Termux
|
|
227
242
|
},
|
|
228
243
|
"gemini": {
|
|
229
244
|
"name": "Gemini CLI",
|
|
@@ -456,9 +471,15 @@ class SlashCompleter(Completer):
|
|
|
456
471
|
text = document.text_before_cursor.lstrip()
|
|
457
472
|
if text.startswith("/"):
|
|
458
473
|
typed = text.lower()
|
|
459
|
-
|
|
474
|
+
on_termux = os.path.exists("/data/data/com.termux")
|
|
475
|
+
|
|
476
|
+
# Main commands — hide unsupported tool commands on Termux
|
|
460
477
|
for cmd, desc in COMMANDS.items():
|
|
461
478
|
if cmd.startswith(typed):
|
|
479
|
+
# Skip tool commands that don't work on Termux
|
|
480
|
+
tool_name = cmd[1:]
|
|
481
|
+
if on_termux and tool_name in AI_TOOLS and not AI_TOOLS[tool_name].get("termux", True):
|
|
482
|
+
continue
|
|
462
483
|
yield Completion(
|
|
463
484
|
cmd,
|
|
464
485
|
start_position=-len(text),
|
|
@@ -5721,6 +5742,12 @@ def main():
|
|
|
5721
5742
|
tool_key = cmd[1:] # strip /
|
|
5722
5743
|
tool = AI_TOOLS[tool_key]
|
|
5723
5744
|
tool_bin = tool["bin"]
|
|
5745
|
+
|
|
5746
|
+
# Block unsupported tools on Termux
|
|
5747
|
+
is_termux = os.path.exists("/data/data/com.termux")
|
|
5748
|
+
if is_termux and not tool.get("termux", True):
|
|
5749
|
+
print_err(f"{tool['name']} doesn't work on Termux.")
|
|
5750
|
+
continue
|
|
5724
5751
|
tool_args = user_input[len(cmd):].strip()
|
|
5725
5752
|
|
|
5726
5753
|
if shutil.which(tool_bin):
|
|
@@ -5804,10 +5831,6 @@ def main():
|
|
|
5804
5831
|
print_sys("Use a desktop/PC for this tool.")
|
|
5805
5832
|
continue
|
|
5806
5833
|
|
|
5807
|
-
if not ask_permission("tool_install", f"Install {tool['name']} via {' '.join(install_cmd[:3])}"):
|
|
5808
|
-
continue
|
|
5809
|
-
print_sys(f"Installing {tool['name']}...")
|
|
5810
|
-
|
|
5811
5834
|
# Pick platform-specific install command
|
|
5812
5835
|
if is_termux and "install_termux" in tool:
|
|
5813
5836
|
install_cmd = list(tool["install_termux"])
|
|
@@ -5816,6 +5839,10 @@ def main():
|
|
|
5816
5839
|
else:
|
|
5817
5840
|
install_cmd = list(tool["install"])
|
|
5818
5841
|
|
|
5842
|
+
if not ask_permission("tool_install", f"Install {tool['name']} via {' '.join(install_cmd[:3])}"):
|
|
5843
|
+
continue
|
|
5844
|
+
print_sys(f"Installing {tool['name']}...")
|
|
5845
|
+
|
|
5819
5846
|
is_npm = install_cmd[0] in ("npm", "npm.cmd")
|
|
5820
5847
|
|
|
5821
5848
|
if is_npm and os.name == "nt":
|
|
@@ -5833,11 +5860,14 @@ def main():
|
|
|
5833
5860
|
)
|
|
5834
5861
|
install_ok[0] = r.returncode == 0
|
|
5835
5862
|
if not install_ok[0]:
|
|
5836
|
-
|
|
5863
|
+
# Show both stderr and stdout for better debugging
|
|
5864
|
+
err = r.stderr.strip() if r.stderr else ""
|
|
5865
|
+
out = r.stdout.strip() if r.stdout else ""
|
|
5866
|
+
install_err[0] = err[:300] or out[:300] or f"Exit code {r.returncode}"
|
|
5837
5867
|
except subprocess.TimeoutExpired:
|
|
5838
5868
|
install_err[0] = "Timed out (5min)"
|
|
5839
5869
|
except Exception as e:
|
|
5840
|
-
install_err[0] = str(e)
|
|
5870
|
+
install_err[0] = str(e)[:300]
|
|
5841
5871
|
install_done[0] = True
|
|
5842
5872
|
|
|
5843
5873
|
thr = threading.Thread(target=do_tool_install, daemon=True)
|
|
@@ -5867,25 +5897,66 @@ def main():
|
|
|
5867
5897
|
))
|
|
5868
5898
|
time.sleep(0.1)
|
|
5869
5899
|
|
|
5870
|
-
if install_ok[0]
|
|
5900
|
+
if install_ok[0]:
|
|
5871
5901
|
elapsed = time.time() - start_t
|
|
5872
|
-
print_sys(f"Installed in {elapsed:.1f}s. Launching...")
|
|
5873
|
-
audit_log(f"TOOL_INSTALL", tool_key)
|
|
5874
5902
|
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5903
|
+
# Rehash PATH — find newly installed binaries
|
|
5904
|
+
for _p in [
|
|
5905
|
+
os.path.expanduser("~/.local/bin"),
|
|
5906
|
+
os.path.expanduser("~/.npm-global/bin"),
|
|
5907
|
+
"/data/data/com.termux/files/usr/bin",
|
|
5908
|
+
os.path.expanduser("~/bin"),
|
|
5909
|
+
]:
|
|
5910
|
+
if os.path.isdir(_p) and _p not in os.environ.get("PATH", ""):
|
|
5911
|
+
os.environ["PATH"] = _p + os.pathsep + os.environ["PATH"]
|
|
5912
|
+
|
|
5913
|
+
# Try to find the binary
|
|
5914
|
+
found_bin = shutil.which(tool_bin)
|
|
5915
|
+
|
|
5916
|
+
# Fallback: search common install locations
|
|
5917
|
+
if not found_bin:
|
|
5918
|
+
search_dirs = [
|
|
5919
|
+
os.path.expanduser("~/.local/bin"),
|
|
5920
|
+
os.path.expanduser("~/.npm-global/bin"),
|
|
5921
|
+
"/data/data/com.termux/files/usr/bin",
|
|
5922
|
+
]
|
|
5923
|
+
for sd in search_dirs:
|
|
5924
|
+
candidate = os.path.join(sd, tool_bin)
|
|
5925
|
+
if os.path.isfile(candidate):
|
|
5926
|
+
found_bin = candidate
|
|
5927
|
+
break
|
|
5928
|
+
|
|
5929
|
+
# Fallback: try python -m for pip packages
|
|
5930
|
+
pip_module_map = {
|
|
5931
|
+
"sgpt": "sgpt",
|
|
5932
|
+
"llm": "llm",
|
|
5933
|
+
"litellm": "litellm",
|
|
5934
|
+
"gorilla": "gorilla_cli",
|
|
5935
|
+
"chatgpt": "chatgpt",
|
|
5936
|
+
"aider": "aider",
|
|
5937
|
+
"interpreter": "interpreter",
|
|
5938
|
+
"gpte": "gpt_engineer",
|
|
5939
|
+
"mentat": "mentat",
|
|
5940
|
+
}
|
|
5941
|
+
|
|
5942
|
+
if found_bin:
|
|
5943
|
+
print_sys(f"Installed in {elapsed:.1f}s. Launching...")
|
|
5944
|
+
audit_log(f"TOOL_INSTALL", tool_key)
|
|
5945
|
+
launch_cmd = [found_bin] + tool.get("default_args", [])
|
|
5946
|
+
subprocess.run(launch_cmd, shell=True)
|
|
5947
|
+
print_sys("Back to CodeGPT.")
|
|
5948
|
+
elif tool_bin in pip_module_map:
|
|
5949
|
+
# Try python -m fallback
|
|
5950
|
+
mod = pip_module_map[tool_bin]
|
|
5951
|
+
print_sys(f"Installed in {elapsed:.1f}s. Launching via python -m {mod}...")
|
|
5952
|
+
audit_log(f"TOOL_INSTALL", tool_key)
|
|
5953
|
+
launch_cmd = [sys.executable, "-m", mod] + tool.get("default_args", [])
|
|
5954
|
+
subprocess.run(launch_cmd)
|
|
5955
|
+
print_sys("Back to CodeGPT.")
|
|
5956
|
+
else:
|
|
5957
|
+
print_err(f"Installed but '{tool_bin}' not found in PATH.")
|
|
5958
|
+
print_sys(f"Try: which {tool_bin}")
|
|
5959
|
+
print_sys("Or restart your terminal and try again.")
|
|
5889
5960
|
else:
|
|
5890
5961
|
print_err(f"Install failed: {install_err[0]}")
|
|
5891
5962
|
manual = " ".join(tool["install"])
|