-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Expand file tree
/
Copy pathcli.py
More file actions
176 lines (148 loc) · 5.81 KB
/
Copy pathcli.py
File metadata and controls
176 lines (148 loc) · 5.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import json
from urllib.request import Request, urlopen
import speech_recognition as sr
from . import state
from .actions import handle_user_text, rule_based_action
from .apps import build_application_index, search_apps
from .config import OPENAI_BASE_URL, OPENAI_MODEL
from .memory import clear_memory
from .speech import init_tts_engine, listen_once, say, set_tts_engine
from .text_utils import normalize_text
def should_exit(text):
return normalize_text(text) in {"exit", "quit", "bye", "cik", "çık", "stop jarvis", "kapat jarvis"}
def wants_type_mode(text):
return normalize_text(text) in {
"type",
"type mode",
"keyboard",
"keyboard mode",
"yaz",
"yazi",
"yazı",
"yazi modu",
"yazı modu",
}
def wants_developer_mode(text):
return normalize_text(text) in {"developer mode", "development mode", "dev mode", "change mode"}
def wants_normal_mode(text):
return normalize_text(text) in {"normal mode", "user mode", "exit developer mode"}
def choose_best_candidate(candidates):
if not candidates:
return ""
for candidate in candidates:
if rule_based_action(candidate):
return candidate
return candidates[0]
def help_text():
return (
"Commands: say an app/site to open it, say 'python ara' or 'search for python', "
"'chrome kapat' to close a visible window, 'remember that ...' to save a note, "
"'developer mode' to show prompts/raw AI/token usage, '/apps chrome' in type mode to list apps."
)
def check_lm_studio():
try:
request = Request(f"{OPENAI_BASE_URL}/models")
with urlopen(request, timeout=3) as response:
data = json.loads(response.read().decode("utf-8"))
models = [item.get("id", "") for item in data.get("data", [])]
if OPENAI_MODEL in models:
say(f"LM Studio connected: {OPENAI_MODEL}")
else:
say("LM Studio is running, but the selected model was not listed.")
except Exception as exc:
say(f"LM Studio not ready: {exc}")
def handle_command(user_input):
cleaned = normalize_text(user_input)
if wants_developer_mode(user_input):
state.set_developer_mode(True)
return "Developer mode enabled. I will print prompts, raw AI outputs, and token usage when available."
if wants_normal_mode(user_input):
state.set_developer_mode(False)
return "Developer mode disabled."
if cleaned in {"help", "/help", "yardim", "yardım"}:
return help_text()
if cleaned in {"clear memory", "memory clear", "hafizayi temizle", "hafızayı temizle"}:
clear_memory()
return "Memory cleared."
if cleaned.startswith("/apps"):
query = user_input[5:].strip()
matches = search_apps(query)
return "Matching apps: " + (", ".join(matches) if matches else "none found")
return handle_user_text(user_input)
def handle_and_say(user_input):
try:
say(handle_command(user_input))
except Exception as exc:
say(f"I could not complete that: {exc}")
def voice_loop():
say("Ready.")
print("Listening stays on. Speak when you want something, or say 'type mode' to write.")
check_lm_studio()
apps = build_application_index()
say(f"Safe app index ready: {len(apps)} apps found.")
recognizer = sr.Recognizer()
recognizer.pause_threshold = 2
recognizer.non_speaking_duration = 1
try:
with sr.Microphone() as source:
print("Calibrating microphone...")
recognizer.adjust_for_ambient_noise(source, duration=1)
while True:
user_input = listen_once(recognizer, source, choose_best_candidate)
if not user_input:
print("No clear speech detected. Continuing to listen...")
continue
if should_exit(user_input):
say("Goodbye.")
break
if wants_type_mode(user_input):
typed = input("Type to Jarvis: ").strip()
if typed:
print(f"You typed: {typed}")
if should_exit(typed):
say("Goodbye.")
break
handle_and_say(typed)
print("Listening again...")
continue
if normalize_text(user_input) in {"refresh apps", "uygulamalari yenile", "uygulamaları yenile"}:
apps = build_application_index()
say(f"Safe app index refreshed: {len(apps)} apps found.")
continue
handle_and_say(user_input)
except KeyboardInterrupt:
print()
say("Goodbye.")
except Exception as exc:
say(f"Microphone error: {exc}")
print("Falling back to type mode.")
typed_loop()
def typed_loop():
say("Type mode is active. Type /voice to return to listening.")
while True:
try:
user_input = input("You: ").strip()
except (EOFError, KeyboardInterrupt):
print()
say("Goodbye.")
break
if not user_input:
continue
if should_exit(user_input):
say("Goodbye.")
break
if normalize_text(user_input) in {"/voice", "voice", "listen", "listening"}:
voice_loop()
break
if normalize_text(user_input) in {"/refresh", "refresh apps"}:
apps = build_application_index()
say(f"Safe app index refreshed: {len(apps)} apps found.")
continue
handle_and_say(user_input)
def main(argv=None):
argv = argv or []
set_tts_engine(init_tts_engine())
if len(argv) > 1 and argv[1].lower() in {"--type", "--text"}:
typed_loop()
else:
voice_loop()