krims-code-cli 1.5.7__tar.gz → 1.5.8__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.
- {krims_code_cli-1.5.7 → krims_code_cli-1.5.8}/PKG-INFO +1 -1
- {krims_code_cli-1.5.7 → krims_code_cli-1.5.8}/krims_code_cli.egg-info/PKG-INFO +1 -1
- {krims_code_cli-1.5.7 → krims_code_cli-1.5.8}/krims_code_cli.egg-info/entry_points.txt +1 -0
- krims_code_cli-1.5.8/krims_pip/cli.py +392 -0
- {krims_code_cli-1.5.7 → krims_code_cli-1.5.8}/setup.py +2 -1
- krims_code_cli-1.5.7/krims_pip/cli.py +0 -215
- {krims_code_cli-1.5.7 → krims_code_cli-1.5.8}/LICENSE +0 -0
- {krims_code_cli-1.5.7 → krims_code_cli-1.5.8}/README.md +0 -0
- {krims_code_cli-1.5.7 → krims_code_cli-1.5.8}/krims_code_cli.egg-info/SOURCES.txt +0 -0
- {krims_code_cli-1.5.7 → krims_code_cli-1.5.8}/krims_code_cli.egg-info/dependency_links.txt +0 -0
- {krims_code_cli-1.5.7 → krims_code_cli-1.5.8}/krims_code_cli.egg-info/requires.txt +0 -0
- {krims_code_cli-1.5.7 → krims_code_cli-1.5.8}/krims_code_cli.egg-info/top_level.txt +0 -0
- {krims_code_cli-1.5.7 → krims_code_cli-1.5.8}/krims_pip/__init__.py +0 -0
- {krims_code_cli-1.5.7 → krims_code_cli-1.5.8}/setup.cfg +0 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
import json
|
|
4
|
+
import getpass
|
|
5
|
+
import urllib.request
|
|
6
|
+
import urllib.error
|
|
7
|
+
from krims_code_sdk import KrimsClient, PROVIDERS
|
|
8
|
+
|
|
9
|
+
if hasattr(sys.stdout, 'reconfigure'):
|
|
10
|
+
try:
|
|
11
|
+
sys.stdout.reconfigure(encoding='utf-8')
|
|
12
|
+
except Exception:
|
|
13
|
+
pass
|
|
14
|
+
if hasattr(sys.stderr, 'reconfigure'):
|
|
15
|
+
try:
|
|
16
|
+
sys.stderr.reconfigure(encoding='utf-8')
|
|
17
|
+
except Exception:
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
API_BASE = "https://krims-discord-bot-d57m.onrender.com"
|
|
21
|
+
|
|
22
|
+
# ANSI color helper matching chalk
|
|
23
|
+
class Colors:
|
|
24
|
+
RED = "\033[31m"
|
|
25
|
+
CYAN = "\033[36m"
|
|
26
|
+
GREEN = "\033[32m"
|
|
27
|
+
YELLOW = "\033[33m"
|
|
28
|
+
BLUE = "\033[34m"
|
|
29
|
+
MAGENTA = "\033[35m"
|
|
30
|
+
WHITE = "\033[37m"
|
|
31
|
+
RESET = "\033[0m"
|
|
32
|
+
BOLD = "\033[1m"
|
|
33
|
+
DIM = "\033[2m"
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def hex(code):
|
|
37
|
+
h = code.lstrip('#')
|
|
38
|
+
r, g, b = tuple(int(h[i:i+2], 16) for i in (0, 2, 4))
|
|
39
|
+
return f"\033[38;2;{r};{g};{b}m"
|
|
40
|
+
|
|
41
|
+
# Config Path Resolver
|
|
42
|
+
def get_config_path():
|
|
43
|
+
home = os.path.expanduser("~")
|
|
44
|
+
# Check ~/.krims/config.json first for parity with Node CLI
|
|
45
|
+
node_config = os.path.join(home, ".krims", "config.json")
|
|
46
|
+
if os.path.exists(node_config):
|
|
47
|
+
return node_config
|
|
48
|
+
return os.path.join(home, ".aether", "config.json")
|
|
49
|
+
|
|
50
|
+
def load_config():
|
|
51
|
+
config_path = get_config_path()
|
|
52
|
+
if os.path.exists(config_path):
|
|
53
|
+
try:
|
|
54
|
+
with open(config_path, "r", encoding="utf-8") as f:
|
|
55
|
+
return json.load(f)
|
|
56
|
+
except Exception:
|
|
57
|
+
pass
|
|
58
|
+
return {}
|
|
59
|
+
|
|
60
|
+
def save_config(config):
|
|
61
|
+
config_path = get_config_path()
|
|
62
|
+
os.makedirs(os.path.dirname(config_path), exist_ok=True)
|
|
63
|
+
with open(config_path, "w", encoding="utf-8") as f:
|
|
64
|
+
json.dump(config, f, indent=2)
|
|
65
|
+
|
|
66
|
+
def handle_discord(args, config):
|
|
67
|
+
action = args[0].lower() if len(args) > 0 else "status"
|
|
68
|
+
subarg = args[1] if len(args) > 1 else ""
|
|
69
|
+
|
|
70
|
+
if action in ["link", "connect"]:
|
|
71
|
+
target_id = subarg or (args[0] if len(args) == 1 and args[0].isdigit() else "")
|
|
72
|
+
if not target_id:
|
|
73
|
+
print(f"\n{Colors.YELLOW}Usage: krims-pip discord connect <your_discord_id>{Colors.RESET}")
|
|
74
|
+
print(f"{Colors.DIM}Enable Developer Mode in Discord, right-click your profile, and select 'Copy User ID'.{Colors.RESET}\n")
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
print(f"\n{Colors.CYAN}Connecting Discord identity [{target_id}] to Krims Fleet...{Colors.RESET}")
|
|
78
|
+
try:
|
|
79
|
+
req_data = json.dumps({"discordId": target_id, "username": getpass.getuser()}).encode("utf-8")
|
|
80
|
+
req = urllib.request.Request(
|
|
81
|
+
f"{API_BASE}/api/cli/connect",
|
|
82
|
+
data=req_data,
|
|
83
|
+
headers={"Content-Type": "application/json", "User-Agent": "KrimsCodeCLI-Python/1.5.8"}
|
|
84
|
+
)
|
|
85
|
+
with urllib.request.urlopen(req, timeout=15) as resp:
|
|
86
|
+
data = json.loads(resp.read().decode("utf-8"))
|
|
87
|
+
|
|
88
|
+
if not data.get("ok"):
|
|
89
|
+
print(f"{Colors.RED}Connection failed: {data.get('error', 'Unknown error')}{Colors.RESET}")
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
config["discord_id"] = data.get("discordId")
|
|
93
|
+
config["discord_user"] = data.get("username")
|
|
94
|
+
config["discord_linked_at"] = os.times().elapsed
|
|
95
|
+
save_config(config)
|
|
96
|
+
|
|
97
|
+
bonus_msg = f"{Colors.GREEN} (+1,000 KC Link Bonus Awarded!){Colors.RESET}" if data.get("bonusAwarded") else ""
|
|
98
|
+
print(f"\n{Colors.CYAN}⚡ DISCORD IDENTITY LINKED SUCCESSFULLY!{Colors.RESET}")
|
|
99
|
+
print("─" * 60)
|
|
100
|
+
print(f" Account : {Colors.CYAN}@{data.get('username')}{Colors.RESET}")
|
|
101
|
+
print(f" Discord ID : {data.get('discordId')}")
|
|
102
|
+
print(f" KC Vault : {Colors.YELLOW}{data.get('balance', 0):,} KC{Colors.RESET}{bonus_msg}")
|
|
103
|
+
print("─" * 60)
|
|
104
|
+
print(f"{Colors.DIM}Use /claim for daily rewards directly in your terminal.{Colors.RESET}\n")
|
|
105
|
+
except Exception as e:
|
|
106
|
+
print(f"{Colors.RED}Failed to reach Krims rewards server: {e}{Colors.RESET}\n")
|
|
107
|
+
|
|
108
|
+
elif action == "unlink":
|
|
109
|
+
if "discord_id" not in config:
|
|
110
|
+
print(f"\n{Colors.YELLOW}No Discord account currently linked.{Colors.RESET}\n")
|
|
111
|
+
return
|
|
112
|
+
old_id = config.pop("discord_id", None)
|
|
113
|
+
config.pop("discord_user", None)
|
|
114
|
+
save_config(config)
|
|
115
|
+
print(f"\n{Colors.GREEN}✓ Disconnected Discord identity ({old_id}).{Colors.RESET}\n")
|
|
116
|
+
|
|
117
|
+
else:
|
|
118
|
+
# Status
|
|
119
|
+
disc_id = config.get("discord_id")
|
|
120
|
+
if not disc_id:
|
|
121
|
+
print(f"\n{Colors.YELLOW}⚡ KRIMS CODE • DISCORD IDENTITY{Colors.RESET}")
|
|
122
|
+
print("─" * 60)
|
|
123
|
+
print(f" Status: {Colors.RED}✗ Not Linked{Colors.RESET}")
|
|
124
|
+
print("─" * 60)
|
|
125
|
+
print(" Link your account to earn +1,000 KC and claim daily terminal drops:")
|
|
126
|
+
print(f" {Colors.CYAN}krims-pip discord connect <discord_id>{Colors.RESET}\n")
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
try:
|
|
130
|
+
req = urllib.request.Request(
|
|
131
|
+
f"{API_BASE}/api/cli/balance?discordId={disc_id}",
|
|
132
|
+
headers={"User-Agent": "KrimsCodeCLI-Python/1.5.8"}
|
|
133
|
+
)
|
|
134
|
+
with urllib.request.urlopen(req, timeout=10) as resp:
|
|
135
|
+
data = json.loads(resp.read().decode("utf-8"))
|
|
136
|
+
bal = data.get("balance", 0)
|
|
137
|
+
except Exception:
|
|
138
|
+
bal = "Unavailable"
|
|
139
|
+
|
|
140
|
+
print(f"\n{Colors.CYAN}⚡ KRIMS CODE • DISCORD IDENTITY{Colors.RESET}")
|
|
141
|
+
print("─" * 60)
|
|
142
|
+
print(f" Status : {Colors.GREEN}✓ Connected{Colors.RESET}")
|
|
143
|
+
print(f" Account : {Colors.CYAN}@{config.get('discord_user', disc_id)}{Colors.RESET}")
|
|
144
|
+
print(f" Discord ID : {disc_id}")
|
|
145
|
+
print(f" KC Vault : {Colors.YELLOW}{bal:,} KC{Colors.RESET}" if isinstance(bal, int) else f" KC Vault : {bal}")
|
|
146
|
+
print("─" * 60)
|
|
147
|
+
print(f"{Colors.DIM}Type /claim for daily rewards, or krims-pip discord unlink to disconnect.{Colors.RESET}\n")
|
|
148
|
+
|
|
149
|
+
def handle_claim(config):
|
|
150
|
+
disc_id = config.get("discord_id")
|
|
151
|
+
if not disc_id:
|
|
152
|
+
print(f"\n{Colors.YELLOW}⚠️ No Discord Account Linked!{Colors.RESET}")
|
|
153
|
+
print("─" * 60)
|
|
154
|
+
print("Link your Discord ID first to claim KC drops directly into your vault:")
|
|
155
|
+
print(f" {Colors.CYAN}krims-pip discord connect <your_discord_id>{Colors.RESET}")
|
|
156
|
+
print("─" * 60)
|
|
157
|
+
print(f"{Colors.DIM}First-time linking grants an instant +1,000 KC bonus!{Colors.RESET}\n")
|
|
158
|
+
return
|
|
159
|
+
|
|
160
|
+
print(f"\n{Colors.CYAN}🔄 Contacting the Krims Fleet Rewards Server...{Colors.RESET}")
|
|
161
|
+
try:
|
|
162
|
+
req_data = json.dumps({"discordId": disc_id}).encode("utf-8")
|
|
163
|
+
req = urllib.request.Request(
|
|
164
|
+
f"{API_BASE}/api/cli/claim",
|
|
165
|
+
data=req_data,
|
|
166
|
+
headers={"Content-Type": "application/json", "User-Agent": "KrimsCodeCLI-Python/1.5.8"}
|
|
167
|
+
)
|
|
168
|
+
with urllib.request.urlopen(req, timeout=15) as resp:
|
|
169
|
+
data = json.loads(resp.read().decode("utf-8"))
|
|
170
|
+
|
|
171
|
+
if not data.get("ok"):
|
|
172
|
+
print(f"{Colors.RED}Claim failed: {data.get('error', 'Unknown error')}{Colors.RESET}")
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
if data.get("claimed"):
|
|
176
|
+
reward = data.get("reward", 250)
|
|
177
|
+
streak = data.get("streak", 1)
|
|
178
|
+
bal = data.get("balance", 0)
|
|
179
|
+
print(f"\n{Colors.GREEN}═════════════════════════════════════════════════════════════════{Colors.RESET}")
|
|
180
|
+
print(f"{Colors.GREEN}🎉 DAILY KC REWARD CLAIMED SUCCESSFULLY! 🚀{Colors.RESET}")
|
|
181
|
+
print("─" * 60)
|
|
182
|
+
print(f" Account : {Colors.CYAN}@{config.get('discord_user', disc_id)}{Colors.RESET}")
|
|
183
|
+
print(f" Reward Earned : {Colors.YELLOW}+{reward:,} KC{Colors.RESET}")
|
|
184
|
+
print(f" Daily Streak : {Colors.CYAN}{streak} Day(s) Multiplier{Colors.RESET}")
|
|
185
|
+
print(f" Total Vault : {Colors.YELLOW}{bal:,} KC{Colors.RESET}")
|
|
186
|
+
print("─" * 60)
|
|
187
|
+
print(f"{Colors.DIM}Next claim available in 24 hours. View rewards: https://krims-bot-dashboard.vercel.app/rewards{Colors.RESET}")
|
|
188
|
+
print(f"{Colors.GREEN}═════════════════════════════════════════════════════════════════{Colors.RESET}\n")
|
|
189
|
+
else:
|
|
190
|
+
time_rem = data.get("timeRemaining", 0)
|
|
191
|
+
hrs = time_rem // (1000 * 60 * 60)
|
|
192
|
+
mins = (time_rem % (1000 * 60 * 60)) // (1000 * 60)
|
|
193
|
+
bal = data.get("balance", 0)
|
|
194
|
+
streak = data.get("streak", 1)
|
|
195
|
+
print(f"\n{Colors.YELLOW}⏳ DAILY COOLDOWN ACTIVE{Colors.RESET}")
|
|
196
|
+
print("─" * 60)
|
|
197
|
+
print(f" Account : {Colors.CYAN}@{config.get('discord_user', disc_id)}{Colors.RESET}")
|
|
198
|
+
print(f" Cooldown : {Colors.YELLOW}{hrs}h {mins}m remaining{Colors.RESET}")
|
|
199
|
+
print(f" Current KC : {Colors.YELLOW}{bal:,} KC{Colors.RESET}")
|
|
200
|
+
print(f" Saved Streak: {streak} Day(s)")
|
|
201
|
+
print("─" * 60)
|
|
202
|
+
print(f"{Colors.DIM}Chat in the Discord server or use Krims Code to level up and earn passive KC!{Colors.RESET}\n")
|
|
203
|
+
|
|
204
|
+
except Exception as e:
|
|
205
|
+
print(f"{Colors.RED}Could not reach rewards server: {e}{Colors.RESET}\n")
|
|
206
|
+
|
|
207
|
+
def print_banner(config, current_mode="titan"):
|
|
208
|
+
c1 = Colors.hex('#FF3E3E') # Red-Orange
|
|
209
|
+
c2 = Colors.hex('#FF8500') # Orange
|
|
210
|
+
c3 = Colors.hex('#FFD000') # Yellow
|
|
211
|
+
c4 = Colors.hex('#00F2FF') # Cyan
|
|
212
|
+
c5 = Colors.hex('#0085FF') # Blue
|
|
213
|
+
c6 = Colors.hex('#7000FF') # Violet
|
|
214
|
+
c7 = Colors.hex('#B000FF') # Purple
|
|
215
|
+
dim = Colors.DIM
|
|
216
|
+
reset = Colors.RESET
|
|
217
|
+
|
|
218
|
+
username = getpass.getuser() or "Explorer"
|
|
219
|
+
cwd = os.getcwd()
|
|
220
|
+
home = os.path.expanduser("~")
|
|
221
|
+
display_cwd = cwd
|
|
222
|
+
if cwd.startswith(home):
|
|
223
|
+
display_cwd = "~" + cwd[len(home):]
|
|
224
|
+
|
|
225
|
+
# Resolve active providers
|
|
226
|
+
active_providers = []
|
|
227
|
+
for k, p in PROVIDERS.items():
|
|
228
|
+
env_key = p.get('envKey')
|
|
229
|
+
if env_key and os.environ.get(env_key):
|
|
230
|
+
active_providers.append(k)
|
|
231
|
+
elif env_key and config.get(env_key):
|
|
232
|
+
active_providers.append(k)
|
|
233
|
+
|
|
234
|
+
if active_providers:
|
|
235
|
+
active_names = ", ".join(set(active_providers))
|
|
236
|
+
mesh_status = f"{Colors.GREEN}● Online ({len(active_providers)} active node(s)){reset}"
|
|
237
|
+
else:
|
|
238
|
+
active_names = "Local math & offline logic only"
|
|
239
|
+
mesh_status = f"{Colors.YELLOW}○ Offline (Local fallbacks active){reset}"
|
|
240
|
+
|
|
241
|
+
# Truncate values to fit screen
|
|
242
|
+
max_val_width = 46
|
|
243
|
+
if len(display_cwd) > max_val_width:
|
|
244
|
+
display_cwd = "..." + display_cwd[-(max_val_width - 3):]
|
|
245
|
+
if len(active_names) > max_val_width:
|
|
246
|
+
active_names = active_names[:max_val_width - 3] + "..."
|
|
247
|
+
|
|
248
|
+
logo = [
|
|
249
|
+
c1(" █▄ ▄█"),
|
|
250
|
+
c2(" ██ ██ "),
|
|
251
|
+
c3(" ██ ▄█ "),
|
|
252
|
+
c4(" ███▀ "),
|
|
253
|
+
c5(" ██ ▀█ "),
|
|
254
|
+
c6(" ██ ██ "),
|
|
255
|
+
c7(" █▀ ▀█")
|
|
256
|
+
]
|
|
257
|
+
|
|
258
|
+
info = [
|
|
259
|
+
f" ⚡ {c4}KRIMS CODE COMMAND STATION v1.5.8{reset} • Welcome back, {c4}{username}{reset}",
|
|
260
|
+
dim(" " + "─" * 58),
|
|
261
|
+
f" {dim}Workspace{reset} : {display_cwd}",
|
|
262
|
+
f" {dim}Mode{reset} : {c4}{current_mode.upper()}{reset} {dim}— Ultimate reasoning fusion of Codex & Claude Code.{reset}",
|
|
263
|
+
f" {dim}Network{reset} : {mesh_status}",
|
|
264
|
+
f" {dim}Engine{reset} : {active_names}",
|
|
265
|
+
f" {dim}Packager{reset} : pip (krims-code-cli)"
|
|
266
|
+
]
|
|
267
|
+
|
|
268
|
+
print("")
|
|
269
|
+
for i in range(7):
|
|
270
|
+
print(logo[i] + info[i] + reset)
|
|
271
|
+
print("")
|
|
272
|
+
|
|
273
|
+
def run_chat(config, model=None, provider=None):
|
|
274
|
+
# Resolve default provider
|
|
275
|
+
prov_key = provider or config.get("DEFAULT_PROVIDER") or "google"
|
|
276
|
+
model_name = model or config.get("DEFAULT_MODEL") or ""
|
|
277
|
+
|
|
278
|
+
# Resolve key
|
|
279
|
+
prov_config = PROVIDERS.get(prov_key.lower(), {})
|
|
280
|
+
env_key = prov_config.get("envKey", "")
|
|
281
|
+
api_key = config.get(env_key) or os.environ.get(env_key) or ""
|
|
282
|
+
|
|
283
|
+
client = KrimsClient(provider=prov_key, model=model_name, api_key=api_key)
|
|
284
|
+
session = client.create_session()
|
|
285
|
+
|
|
286
|
+
print_banner(config)
|
|
287
|
+
print(f"{Colors.DIM}Type 'exit' or 'quit' to terminate session. /claim for daily KC, /discord connect <id> to link.{Colors.RESET}\n")
|
|
288
|
+
|
|
289
|
+
while True:
|
|
290
|
+
try:
|
|
291
|
+
prompt = input(f"{Colors.hex('#00F2FF')}you > {Colors.RESET}").strip()
|
|
292
|
+
if not prompt:
|
|
293
|
+
continue
|
|
294
|
+
if prompt.lower() in ['exit', 'quit']:
|
|
295
|
+
break
|
|
296
|
+
|
|
297
|
+
# Slash commands in chat
|
|
298
|
+
if prompt.startswith("/discord"):
|
|
299
|
+
parts = prompt.split()
|
|
300
|
+
handle_discord(parts[1:], config)
|
|
301
|
+
continue
|
|
302
|
+
if prompt.lower() in ["/claim", "/daily", "/kc", "/balance"]:
|
|
303
|
+
handle_claim(config)
|
|
304
|
+
continue
|
|
305
|
+
|
|
306
|
+
print(f"{Colors.DIM}krims is composing response...{Colors.RESET}")
|
|
307
|
+
res = session.ask(prompt)
|
|
308
|
+
print(f"\n{Colors.hex('#7000FF')}krims > {Colors.RESET}{res['text']}\n")
|
|
309
|
+
except KeyboardInterrupt:
|
|
310
|
+
print("\nSession terminated.")
|
|
311
|
+
break
|
|
312
|
+
except Exception as e:
|
|
313
|
+
print(f"\n{Colors.RED}Error: {e}{Colors.RESET}\n")
|
|
314
|
+
|
|
315
|
+
def run_ask(prompt, config):
|
|
316
|
+
prov_key = config.get("DEFAULT_PROVIDER") or "google"
|
|
317
|
+
model_name = config.get("DEFAULT_MODEL") or ""
|
|
318
|
+
prov_config = PROVIDERS.get(prov_key.lower(), {})
|
|
319
|
+
env_key = prov_config.get("envKey", "")
|
|
320
|
+
api_key = config.get(env_key) or os.environ.get(env_key) or ""
|
|
321
|
+
|
|
322
|
+
client = KrimsClient(provider=prov_key, model=model_name, api_key=api_key)
|
|
323
|
+
try:
|
|
324
|
+
res = client.ask(prompt)
|
|
325
|
+
print(res['text'])
|
|
326
|
+
except Exception as e:
|
|
327
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
328
|
+
sys.exit(1)
|
|
329
|
+
|
|
330
|
+
def handle_config(args, config):
|
|
331
|
+
if len(args) == 0:
|
|
332
|
+
print("Usage: krims-pip config <get/set/list/delete> [key] [value]")
|
|
333
|
+
return
|
|
334
|
+
|
|
335
|
+
action = args[0].lower()
|
|
336
|
+
if action == "list":
|
|
337
|
+
for k, v in config.items():
|
|
338
|
+
print(f"{k}={v}")
|
|
339
|
+
elif action == "get" and len(args) >= 2:
|
|
340
|
+
print(config.get(args[1], ""))
|
|
341
|
+
elif action == "set" and len(args) >= 3:
|
|
342
|
+
config[args[1]] = args[2]
|
|
343
|
+
save_config(config)
|
|
344
|
+
print(f"Set {args[1]}={args[2]}")
|
|
345
|
+
elif action == "delete" and len(args) >= 2:
|
|
346
|
+
if args[1] in config:
|
|
347
|
+
del config[args[1]]
|
|
348
|
+
save_config(config)
|
|
349
|
+
print(f"Deleted {args[1]}")
|
|
350
|
+
else:
|
|
351
|
+
print(f"Key {args[1]} not found")
|
|
352
|
+
else:
|
|
353
|
+
print("Invalid config arguments.")
|
|
354
|
+
|
|
355
|
+
def main():
|
|
356
|
+
config = load_config()
|
|
357
|
+
args = sys.argv[1:]
|
|
358
|
+
|
|
359
|
+
if not args:
|
|
360
|
+
run_chat(config)
|
|
361
|
+
return
|
|
362
|
+
|
|
363
|
+
cmd = args[0].lower()
|
|
364
|
+
if cmd == "chat":
|
|
365
|
+
run_chat(config)
|
|
366
|
+
elif cmd in ["claim", "daily", "balance", "kc"]:
|
|
367
|
+
handle_claim(config)
|
|
368
|
+
elif cmd in ["discord", "link"]:
|
|
369
|
+
handle_discord(args[1:], config)
|
|
370
|
+
elif cmd == "ask" and len(args) >= 2:
|
|
371
|
+
run_ask(args[1], config)
|
|
372
|
+
elif cmd == "config":
|
|
373
|
+
handle_config(args[1:], config)
|
|
374
|
+
elif cmd in ["version", "-v", "--version"]:
|
|
375
|
+
print("Krims Code CLI v1.5.8 (Native Python Edition)")
|
|
376
|
+
elif cmd in ["help", "-h", "--help"]:
|
|
377
|
+
print("Krims Code CLI — Native Python Edition")
|
|
378
|
+
print("\nCommands:")
|
|
379
|
+
print(" chat Start stateful chat loop (default)")
|
|
380
|
+
print(" claim | daily Claim daily KC rewards (+250 KC)")
|
|
381
|
+
print(" discord connect <id> Link Discord account to Krims Fleet (+1,000 KC bonus)")
|
|
382
|
+
print(" discord View linked Discord account and KC vault")
|
|
383
|
+
print(" ask <prompt> Get single answer for prompt")
|
|
384
|
+
print(" config <get/set/list> Get or set keys")
|
|
385
|
+
print(" version Display version info")
|
|
386
|
+
else:
|
|
387
|
+
# Fallback to ask if they just write a prompt directly
|
|
388
|
+
run_ask(" ".join(args), config)
|
|
389
|
+
run_ask(" ".join(args), config)
|
|
390
|
+
|
|
391
|
+
if __name__ == "__main__":
|
|
392
|
+
main()
|
|
@@ -3,7 +3,7 @@ import os
|
|
|
3
3
|
|
|
4
4
|
setup(
|
|
5
5
|
name="krims-code-cli",
|
|
6
|
-
version="1.5.
|
|
6
|
+
version="1.5.8",
|
|
7
7
|
author="Krishiv PB",
|
|
8
8
|
author_email="krylobloxyt@gmail.com",
|
|
9
9
|
description="Krims Code AI — Universal AI Gateway CLI (Native Python Edition)",
|
|
@@ -17,6 +17,7 @@ setup(
|
|
|
17
17
|
entry_points={
|
|
18
18
|
"console_scripts": [
|
|
19
19
|
"krims-pip=krims_pip.cli:main",
|
|
20
|
+
"krims-code=krims_pip.cli:main",
|
|
20
21
|
],
|
|
21
22
|
},
|
|
22
23
|
classifiers=[
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import os
|
|
3
|
-
import json
|
|
4
|
-
import getpass
|
|
5
|
-
from krims_code_sdk import KrimsClient, PROVIDERS
|
|
6
|
-
|
|
7
|
-
# ANSI color helper matching chalk
|
|
8
|
-
class Colors:
|
|
9
|
-
RED = "\033[31m"
|
|
10
|
-
CYAN = "\033[36m"
|
|
11
|
-
GREEN = "\033[32m"
|
|
12
|
-
YELLOW = "\033[33m"
|
|
13
|
-
BLUE = "\033[34m"
|
|
14
|
-
MAGENTA = "\033[35m"
|
|
15
|
-
WHITE = "\033[37m"
|
|
16
|
-
RESET = "\033[0m"
|
|
17
|
-
BOLD = "\033[1m"
|
|
18
|
-
DIM = "\033[2m"
|
|
19
|
-
|
|
20
|
-
@staticmethod
|
|
21
|
-
def hex(code):
|
|
22
|
-
h = code.lstrip('#')
|
|
23
|
-
r, g, b = tuple(int(h[i:i+2], 16) for i in (0, 2, 4))
|
|
24
|
-
return f"\033[38;2;{r};{g};{b}m"
|
|
25
|
-
|
|
26
|
-
# Config Path Resolver
|
|
27
|
-
def get_config_path():
|
|
28
|
-
home = os.path.expanduser("~")
|
|
29
|
-
return os.path.join(home, ".aether", "config.json")
|
|
30
|
-
|
|
31
|
-
def load_config():
|
|
32
|
-
config_path = get_config_path()
|
|
33
|
-
if os.path.exists(config_path):
|
|
34
|
-
try:
|
|
35
|
-
with open(config_path, "r", encoding="utf-8") as f:
|
|
36
|
-
return json.load(f)
|
|
37
|
-
except Exception:
|
|
38
|
-
pass
|
|
39
|
-
return {}
|
|
40
|
-
|
|
41
|
-
def save_config(config):
|
|
42
|
-
config_path = get_config_path()
|
|
43
|
-
os.makedirs(os.path.dirname(config_path), exist_ok=True)
|
|
44
|
-
with open(config_path, "w", encoding="utf-8") as f:
|
|
45
|
-
json.dump(config, f, indent=2)
|
|
46
|
-
|
|
47
|
-
def print_banner(config, current_mode="titan"):
|
|
48
|
-
c1 = Colors.hex('#FF3E3E') # Red-Orange
|
|
49
|
-
c2 = Colors.hex('#FF8500') # Orange
|
|
50
|
-
c3 = Colors.hex('#FFD000') # Yellow
|
|
51
|
-
c4 = Colors.hex('#00F2FF') # Cyan
|
|
52
|
-
c5 = Colors.hex('#0085FF') # Blue
|
|
53
|
-
c6 = Colors.hex('#7000FF') # Violet
|
|
54
|
-
c7 = Colors.hex('#B000FF') # Purple
|
|
55
|
-
dim = Colors.DIM
|
|
56
|
-
reset = Colors.RESET
|
|
57
|
-
|
|
58
|
-
username = getpass.getuser() or "Explorer"
|
|
59
|
-
cwd = os.getcwd()
|
|
60
|
-
home = os.path.expanduser("~")
|
|
61
|
-
display_cwd = cwd
|
|
62
|
-
if cwd.startswith(home):
|
|
63
|
-
display_cwd = "~" + cwd[len(home):]
|
|
64
|
-
|
|
65
|
-
# Resolve active providers
|
|
66
|
-
active_providers = []
|
|
67
|
-
for k, p in PROVIDERS.items():
|
|
68
|
-
env_key = p.get('envKey')
|
|
69
|
-
if env_key and os.environ.get(env_key):
|
|
70
|
-
active_providers.append(k)
|
|
71
|
-
elif env_key and config.get(env_key):
|
|
72
|
-
active_providers.append(k)
|
|
73
|
-
|
|
74
|
-
if active_providers:
|
|
75
|
-
active_names = ", ".join(set(active_providers))
|
|
76
|
-
mesh_status = f"{Colors.GREEN}● Online ({len(active_providers)} active node(s)){reset}"
|
|
77
|
-
else:
|
|
78
|
-
active_names = "Local math & offline logic only"
|
|
79
|
-
mesh_status = f"{Colors.YELLOW}○ Offline (Local fallbacks active){reset}"
|
|
80
|
-
|
|
81
|
-
# Truncate values to fit screen
|
|
82
|
-
max_val_width = 46
|
|
83
|
-
if len(display_cwd) > max_val_width:
|
|
84
|
-
display_cwd = "..." + display_cwd[-(max_val_width - 3):]
|
|
85
|
-
if len(active_names) > max_val_width:
|
|
86
|
-
active_names = active_names[:max_val_width - 3] + "..."
|
|
87
|
-
|
|
88
|
-
logo = [
|
|
89
|
-
c1(" █▄ ▄█"),
|
|
90
|
-
c2(" ██ ██ "),
|
|
91
|
-
c3(" ██ ▄█ "),
|
|
92
|
-
c4(" ███▀ "),
|
|
93
|
-
c5(" ██ ▀█ "),
|
|
94
|
-
c6(" ██ ██ "),
|
|
95
|
-
c7(" █▀ ▀█")
|
|
96
|
-
]
|
|
97
|
-
|
|
98
|
-
info = [
|
|
99
|
-
f" ⚡ {c4}KRIMS CODE COMMAND STATION v1.5.7{reset} • Welcome back, {c4}{username}{reset}",
|
|
100
|
-
dim(" " + "─" * 58),
|
|
101
|
-
f" {dim}Workspace{reset} : {display_cwd}",
|
|
102
|
-
f" {dim}Mode{reset} : {c4}{current_mode.upper()}{reset} {dim}— Ultimate reasoning fusion of Codex & Claude Code.{reset}",
|
|
103
|
-
f" {dim}Network{reset} : {mesh_status}",
|
|
104
|
-
f" {dim}Engine{reset} : {active_names}",
|
|
105
|
-
f" {dim}Packager{reset} : pip (krims-code-cli)"
|
|
106
|
-
]
|
|
107
|
-
|
|
108
|
-
print("")
|
|
109
|
-
for i in range(7):
|
|
110
|
-
print(logo[i] + info[i] + reset)
|
|
111
|
-
print("")
|
|
112
|
-
|
|
113
|
-
def run_chat(config, model=None, provider=None):
|
|
114
|
-
# Resolve default provider
|
|
115
|
-
prov_key = provider or config.get("DEFAULT_PROVIDER") or "google"
|
|
116
|
-
model_name = model or config.get("DEFAULT_MODEL") or ""
|
|
117
|
-
|
|
118
|
-
# Resolve key
|
|
119
|
-
prov_config = PROVIDERS.get(prov_key.lower(), {})
|
|
120
|
-
env_key = prov_config.get("envKey", "")
|
|
121
|
-
api_key = config.get(env_key) or os.environ.get(env_key) or ""
|
|
122
|
-
|
|
123
|
-
client = KrimsClient(provider=prov_key, model=model_name, api_key=api_key)
|
|
124
|
-
session = client.create_session()
|
|
125
|
-
|
|
126
|
-
print_banner(config)
|
|
127
|
-
print(f"{Colors.DIM}Type 'exit' or 'quit' to terminate session. Ctrl+C to abort.{Colors.RESET}\n")
|
|
128
|
-
|
|
129
|
-
while True:
|
|
130
|
-
try:
|
|
131
|
-
prompt = input(f"{Colors.hex('#00F2FF')}you > {Colors.RESET}")
|
|
132
|
-
if not prompt.strip():
|
|
133
|
-
continue
|
|
134
|
-
if prompt.strip().lower() in ['exit', 'quit']:
|
|
135
|
-
break
|
|
136
|
-
|
|
137
|
-
print(f"{Colors.DIM}krims is composing response...{Colors.RESET}")
|
|
138
|
-
res = session.ask(prompt)
|
|
139
|
-
print(f"\n{Colors.hex('#7000FF')}krims > {Colors.RESET}{res['text']}\n")
|
|
140
|
-
except KeyboardInterrupt:
|
|
141
|
-
print("\nSession terminated.")
|
|
142
|
-
break
|
|
143
|
-
except Exception as e:
|
|
144
|
-
print(f"\n{Colors.RED}Error: {e}{Colors.RESET}\n")
|
|
145
|
-
|
|
146
|
-
def run_ask(prompt, config):
|
|
147
|
-
prov_key = config.get("DEFAULT_PROVIDER") or "google"
|
|
148
|
-
model_name = config.get("DEFAULT_MODEL") or ""
|
|
149
|
-
prov_config = PROVIDERS.get(prov_key.lower(), {})
|
|
150
|
-
env_key = prov_config.get("envKey", "")
|
|
151
|
-
api_key = config.get(env_key) or os.environ.get(env_key) or ""
|
|
152
|
-
|
|
153
|
-
client = KrimsClient(provider=prov_key, model=model_name, api_key=api_key)
|
|
154
|
-
try:
|
|
155
|
-
res = client.ask(prompt)
|
|
156
|
-
print(res['text'])
|
|
157
|
-
except Exception as e:
|
|
158
|
-
print(f"Error: {e}", file=sys.stderr)
|
|
159
|
-
sys.exit(1)
|
|
160
|
-
|
|
161
|
-
def handle_config(args, config):
|
|
162
|
-
if len(args) == 0:
|
|
163
|
-
print("Usage: krims-pip config <get/set/list/delete> [key] [value]")
|
|
164
|
-
return
|
|
165
|
-
|
|
166
|
-
action = args[0].lower()
|
|
167
|
-
if action == "list":
|
|
168
|
-
for k, v in config.items():
|
|
169
|
-
print(f"{k}={v}")
|
|
170
|
-
elif action == "get" and len(args) >= 2:
|
|
171
|
-
print(config.get(args[1], ""))
|
|
172
|
-
elif action == "set" and len(args) >= 3:
|
|
173
|
-
config[args[1]] = args[2]
|
|
174
|
-
save_config(config)
|
|
175
|
-
print(f"Set {args[1]}={args[2]}")
|
|
176
|
-
elif action == "delete" and len(args) >= 2:
|
|
177
|
-
if args[1] in config:
|
|
178
|
-
del config[args[1]]
|
|
179
|
-
save_config(config)
|
|
180
|
-
print(f"Deleted {args[1]}")
|
|
181
|
-
else:
|
|
182
|
-
print(f"Key {args[1]} not found")
|
|
183
|
-
else:
|
|
184
|
-
print("Invalid config arguments.")
|
|
185
|
-
|
|
186
|
-
def main():
|
|
187
|
-
config = load_config()
|
|
188
|
-
args = sys.argv[1:]
|
|
189
|
-
|
|
190
|
-
if not args:
|
|
191
|
-
run_chat(config)
|
|
192
|
-
return
|
|
193
|
-
|
|
194
|
-
cmd = args[0].lower()
|
|
195
|
-
if cmd == "chat":
|
|
196
|
-
run_chat(config)
|
|
197
|
-
elif cmd == "ask" and len(args) >= 2:
|
|
198
|
-
run_ask(args[1], config)
|
|
199
|
-
elif cmd == "config":
|
|
200
|
-
handle_config(args[1:], config)
|
|
201
|
-
elif cmd in ["version", "-v", "--version"]:
|
|
202
|
-
print("Krims Code CLI v1.5.7 (Native Python Edition)")
|
|
203
|
-
elif cmd in ["help", "-h", "--help"]:
|
|
204
|
-
print("Krims Code CLI — Native Python Edition")
|
|
205
|
-
print("\nCommands:")
|
|
206
|
-
print(" chat Start stateful chat loop (default)")
|
|
207
|
-
print(" ask <prompt> Get single answer for prompt")
|
|
208
|
-
print(" config <get/set/list> Get or set keys")
|
|
209
|
-
print(" version Display version info")
|
|
210
|
-
else:
|
|
211
|
-
# Fallback to ask if they just write a prompt directly
|
|
212
|
-
run_ask(" ".join(args), config)
|
|
213
|
-
|
|
214
|
-
if __name__ == "__main__":
|
|
215
|
-
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|