codegpt-ai 1.27.0 → 1.28.1
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 +212 -2
- package/package.json +1 -1
package/chat.py
CHANGED
|
@@ -422,6 +422,8 @@ COMMANDS = {
|
|
|
422
422
|
"/vote": "All agents vote on a question",
|
|
423
423
|
"/swarm": "Agents collaborate on a task step by step",
|
|
424
424
|
"/team": "Start a team chat with 2 AIs (/team coder reviewer)",
|
|
425
|
+
"/room": "AI chat room — multiple AIs talk (/room coder reviewer architect)",
|
|
426
|
+
"/spectate": "Watch AIs chat without you (/spectate claude codex topic)",
|
|
425
427
|
"/github": "GitHub tools (/github repos, issues, prs)",
|
|
426
428
|
"/weather": "Get weather (/weather London)",
|
|
427
429
|
"/open": "Open URL in browser (/open google.com)",
|
|
@@ -2412,10 +2414,35 @@ def get_weather(city):
|
|
|
2412
2414
|
|
|
2413
2415
|
|
|
2414
2416
|
def open_url(url):
|
|
2415
|
-
"""Open a URL in the default browser."""
|
|
2417
|
+
"""Open a URL or search query in the default browser."""
|
|
2416
2418
|
import webbrowser
|
|
2417
|
-
|
|
2419
|
+
|
|
2420
|
+
# Shortcuts
|
|
2421
|
+
shortcuts = {
|
|
2422
|
+
"google": "https://google.com",
|
|
2423
|
+
"youtube": "https://youtube.com",
|
|
2424
|
+
"github": "https://github.com",
|
|
2425
|
+
"reddit": "https://reddit.com",
|
|
2426
|
+
"twitter": "https://x.com",
|
|
2427
|
+
"x": "https://x.com",
|
|
2428
|
+
"stackoverflow": "https://stackoverflow.com",
|
|
2429
|
+
"npm": "https://npmjs.com",
|
|
2430
|
+
"pypi": "https://pypi.org",
|
|
2431
|
+
"ollama": "https://ollama.com",
|
|
2432
|
+
"claude": "https://claude.ai",
|
|
2433
|
+
"chatgpt": "https://chat.openai.com",
|
|
2434
|
+
"gemini": "https://gemini.google.com",
|
|
2435
|
+
}
|
|
2436
|
+
|
|
2437
|
+
if url.lower() in shortcuts:
|
|
2438
|
+
url = shortcuts[url.lower()]
|
|
2439
|
+
elif "." not in url and ":" not in url:
|
|
2440
|
+
# No dots = search query, not a URL
|
|
2441
|
+
query = url.replace(" ", "+")
|
|
2442
|
+
url = f"https://google.com/search?q={query}"
|
|
2443
|
+
elif not url.startswith("http"):
|
|
2418
2444
|
url = "https://" + url
|
|
2445
|
+
|
|
2419
2446
|
webbrowser.open(url)
|
|
2420
2447
|
print_sys(f"Opened: {url}")
|
|
2421
2448
|
audit_log("OPEN_URL", url)
|
|
@@ -3884,6 +3911,149 @@ def team_chat(name1, name2, default_model, system):
|
|
|
3884
3911
|
return history
|
|
3885
3912
|
|
|
3886
3913
|
|
|
3914
|
+
# --- Chat Room ---
|
|
3915
|
+
|
|
3916
|
+
def chat_room(member_names, default_model, system, user_joins=True):
|
|
3917
|
+
"""Multi-AI chat room. User can join or spectate."""
|
|
3918
|
+
members = [resolve_team_member(n) for n in member_names]
|
|
3919
|
+
|
|
3920
|
+
names_display = ", ".join(f"[{m['color']}]{m['name']}[/]" for m in members)
|
|
3921
|
+
mode = "Join" if user_joins else "Spectate"
|
|
3922
|
+
|
|
3923
|
+
console.print(Rule(style="bright_green", characters="─"))
|
|
3924
|
+
console.print(Text.from_markup(
|
|
3925
|
+
f" [bold]Chat Room[/] — {mode} mode\n"
|
|
3926
|
+
f" Members: {names_display}\n"
|
|
3927
|
+
))
|
|
3928
|
+
if user_joins:
|
|
3929
|
+
console.print(Text(" Type to talk. @name to address one AI. 'exit' to leave.", style="dim"))
|
|
3930
|
+
else:
|
|
3931
|
+
console.print(Text(" Watching AIs chat. Ctrl+C to stop.", style="dim"))
|
|
3932
|
+
console.print(Rule(style="bright_green", characters="─"))
|
|
3933
|
+
console.print()
|
|
3934
|
+
|
|
3935
|
+
history = []
|
|
3936
|
+
|
|
3937
|
+
if user_joins:
|
|
3938
|
+
# Interactive room — user + multiple AIs
|
|
3939
|
+
while True:
|
|
3940
|
+
try:
|
|
3941
|
+
user_input = prompt(
|
|
3942
|
+
[("class:prompt", " You ❯ ")],
|
|
3943
|
+
style=input_style,
|
|
3944
|
+
history=input_history,
|
|
3945
|
+
).strip()
|
|
3946
|
+
except (KeyboardInterrupt, EOFError):
|
|
3947
|
+
break
|
|
3948
|
+
|
|
3949
|
+
if not user_input or user_input.lower() in ("exit", "/exit", "quit"):
|
|
3950
|
+
break
|
|
3951
|
+
|
|
3952
|
+
console.print(Text(f" {user_input}", style="bold white"))
|
|
3953
|
+
console.print()
|
|
3954
|
+
history.append({"speaker": "user", "content": user_input})
|
|
3955
|
+
|
|
3956
|
+
# Check for @mentions
|
|
3957
|
+
mentioned = []
|
|
3958
|
+
for m in members:
|
|
3959
|
+
if f"@{m['name']}" in user_input.lower():
|
|
3960
|
+
mentioned.append(m)
|
|
3961
|
+
|
|
3962
|
+
# If no mentions, all respond
|
|
3963
|
+
responders = mentioned if mentioned else members
|
|
3964
|
+
|
|
3965
|
+
for member in responders:
|
|
3966
|
+
others = [m['name'] for m in members if m != member] + ["user"]
|
|
3967
|
+
conv = "\n".join(
|
|
3968
|
+
f"{h['speaker']}: {h['content'][:200]}"
|
|
3969
|
+
for h in history[-10:]
|
|
3970
|
+
)
|
|
3971
|
+
|
|
3972
|
+
room_prompt = (
|
|
3973
|
+
f"You are {member['name']} in a group chat with {', '.join(others)}.\n"
|
|
3974
|
+
f"Chat so far:\n{conv}\n\n"
|
|
3975
|
+
f"Respond as {member['name']}. Keep it short (2-4 sentences). "
|
|
3976
|
+
f"React to what was said. Agree, disagree, or add something new. "
|
|
3977
|
+
f"Don't repeat what others said."
|
|
3978
|
+
)
|
|
3979
|
+
|
|
3980
|
+
try:
|
|
3981
|
+
resp = requests.post(OLLAMA_URL, json={
|
|
3982
|
+
"model": member["model"] or default_model,
|
|
3983
|
+
"messages": [
|
|
3984
|
+
{"role": "system", "content": member["system"]},
|
|
3985
|
+
{"role": "user", "content": room_prompt},
|
|
3986
|
+
],
|
|
3987
|
+
"stream": False,
|
|
3988
|
+
}, timeout=60)
|
|
3989
|
+
response = resp.json().get("message", {}).get("content", "")
|
|
3990
|
+
except Exception as e:
|
|
3991
|
+
response = f"(offline)"
|
|
3992
|
+
|
|
3993
|
+
console.print(Text.from_markup(f" [{member['color']}]{member['name']}[/] {response}"))
|
|
3994
|
+
console.print()
|
|
3995
|
+
history.append({"speaker": member["name"], "content": response})
|
|
3996
|
+
bus_send(member["name"], "codegpt", response[:200], "response")
|
|
3997
|
+
|
|
3998
|
+
else:
|
|
3999
|
+
# Spectate mode — AIs chat with each other, user watches
|
|
4000
|
+
try:
|
|
4001
|
+
# Get initial topic from last arg or default
|
|
4002
|
+
topic = "Introduce yourselves and start a technical discussion."
|
|
4003
|
+
if history:
|
|
4004
|
+
topic = history[-1]["content"]
|
|
4005
|
+
|
|
4006
|
+
current_input = topic
|
|
4007
|
+
rounds = 0
|
|
4008
|
+
max_rounds = 12
|
|
4009
|
+
|
|
4010
|
+
while rounds < max_rounds:
|
|
4011
|
+
for member in members:
|
|
4012
|
+
rounds += 1
|
|
4013
|
+
if rounds > max_rounds:
|
|
4014
|
+
break
|
|
4015
|
+
|
|
4016
|
+
others = [m['name'] for m in members if m != member]
|
|
4017
|
+
conv = "\n".join(
|
|
4018
|
+
f"{h['speaker']}: {h['content'][:200]}"
|
|
4019
|
+
for h in history[-8:]
|
|
4020
|
+
)
|
|
4021
|
+
|
|
4022
|
+
room_prompt = (
|
|
4023
|
+
f"You are {member['name']} in a group chat with {', '.join(others)}.\n"
|
|
4024
|
+
f"{'Topic: ' + current_input if not history else 'Chat so far:'}\n"
|
|
4025
|
+
f"{conv}\n\n"
|
|
4026
|
+
f"Respond as {member['name']}. Keep it short (2-3 sentences). "
|
|
4027
|
+
f"Build on the conversation. Be opinionated."
|
|
4028
|
+
)
|
|
4029
|
+
|
|
4030
|
+
try:
|
|
4031
|
+
resp = requests.post(OLLAMA_URL, json={
|
|
4032
|
+
"model": member["model"] or default_model,
|
|
4033
|
+
"messages": [
|
|
4034
|
+
{"role": "system", "content": member["system"]},
|
|
4035
|
+
{"role": "user", "content": room_prompt},
|
|
4036
|
+
],
|
|
4037
|
+
"stream": False,
|
|
4038
|
+
}, timeout=60)
|
|
4039
|
+
response = resp.json().get("message", {}).get("content", "")
|
|
4040
|
+
except Exception as e:
|
|
4041
|
+
response = "(offline)"
|
|
4042
|
+
|
|
4043
|
+
console.print(Text.from_markup(f" [{member['color']}]{member['name']}[/] {response}"))
|
|
4044
|
+
console.print()
|
|
4045
|
+
history.append({"speaker": member["name"], "content": response})
|
|
4046
|
+
time.sleep(0.5)
|
|
4047
|
+
|
|
4048
|
+
except KeyboardInterrupt:
|
|
4049
|
+
pass
|
|
4050
|
+
|
|
4051
|
+
console.print(Rule(style="dim", characters="─"))
|
|
4052
|
+
console.print(Text(f" Room closed. {len(history)} messages.", style="dim"))
|
|
4053
|
+
console.print()
|
|
4054
|
+
return history
|
|
4055
|
+
|
|
4056
|
+
|
|
3887
4057
|
# --- Split Screen ---
|
|
3888
4058
|
|
|
3889
4059
|
def get_tool_cmd(name):
|
|
@@ -5656,6 +5826,46 @@ def main():
|
|
|
5656
5826
|
print_sys("Terminal too narrow for sidebar. Widen to 80+ chars.")
|
|
5657
5827
|
continue
|
|
5658
5828
|
|
|
5829
|
+
elif cmd == "/room":
|
|
5830
|
+
parts = user_input[len("/room "):].strip().split()
|
|
5831
|
+
if len(parts) >= 2:
|
|
5832
|
+
history = chat_room(parts, model, system, user_joins=True)
|
|
5833
|
+
for h in history:
|
|
5834
|
+
if h["speaker"] == "user":
|
|
5835
|
+
messages.append({"role": "user", "content": h["content"]})
|
|
5836
|
+
else:
|
|
5837
|
+
messages.append({"role": "assistant", "content": f"[{h['speaker']}] {h['content']}"})
|
|
5838
|
+
session_stats["messages"] += len(history)
|
|
5839
|
+
else:
|
|
5840
|
+
print_sys("Usage: /room coder reviewer architect")
|
|
5841
|
+
print_sys(" /room claude codex gemini deepseek")
|
|
5842
|
+
print_sys(f"\nAvailable: {', '.join(list(AI_AGENTS.keys()) + list(TOOL_PERSONAS.keys()))}")
|
|
5843
|
+
continue
|
|
5844
|
+
|
|
5845
|
+
elif cmd == "/spectate":
|
|
5846
|
+
args = user_input[len("/spectate "):].strip().split()
|
|
5847
|
+
if len(args) >= 2:
|
|
5848
|
+
# Last arg could be a topic
|
|
5849
|
+
names = args
|
|
5850
|
+
topic = ""
|
|
5851
|
+
# Check if last args aren't AI names — treat as topic
|
|
5852
|
+
all_names = set(AI_AGENTS.keys()) | set(TOOL_PERSONAS.keys())
|
|
5853
|
+
topic_words = []
|
|
5854
|
+
while names and names[-1] not in all_names:
|
|
5855
|
+
topic_words.insert(0, names.pop())
|
|
5856
|
+
topic = " ".join(topic_words) if topic_words else "Discuss the best programming practices"
|
|
5857
|
+
|
|
5858
|
+
if len(names) >= 2:
|
|
5859
|
+
# Inject topic
|
|
5860
|
+
history_init = [{"speaker": "moderator", "content": topic}]
|
|
5861
|
+
h = chat_room(names, model, system, user_joins=False)
|
|
5862
|
+
else:
|
|
5863
|
+
print_sys("Need at least 2 AIs. Example: /spectate coder reviewer discuss Python")
|
|
5864
|
+
else:
|
|
5865
|
+
print_sys("Usage: /spectate coder reviewer discuss error handling")
|
|
5866
|
+
print_sys(" /spectate claude codex gemini debate which is best")
|
|
5867
|
+
continue
|
|
5868
|
+
|
|
5659
5869
|
elif cmd == "/monitor":
|
|
5660
5870
|
# Live updating dashboard — press Ctrl+C to exit
|
|
5661
5871
|
console.print(Text(" Live monitor — Ctrl+C to stop\n", style="dim"))
|