npcsh 1.0.3__py3-none-any.whl → 1.0.5__py3-none-any.whl
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/_state.py +6 -8
- npcsh/npcsh.py +102 -165
- {npcsh-1.0.3.dist-info → npcsh-1.0.5.dist-info}/METADATA +1 -1
- {npcsh-1.0.3.dist-info → npcsh-1.0.5.dist-info}/RECORD +8 -8
- {npcsh-1.0.3.dist-info → npcsh-1.0.5.dist-info}/WHEEL +0 -0
- {npcsh-1.0.3.dist-info → npcsh-1.0.5.dist-info}/entry_points.txt +0 -0
- {npcsh-1.0.3.dist-info → npcsh-1.0.5.dist-info}/licenses/LICENSE +0 -0
- {npcsh-1.0.3.dist-info → npcsh-1.0.5.dist-info}/top_level.txt +0 -0
npcsh/_state.py
CHANGED
|
@@ -411,7 +411,6 @@ BASH_COMMANDS = [
|
|
|
411
411
|
"info",
|
|
412
412
|
"whatis",
|
|
413
413
|
"whereis",
|
|
414
|
-
"which",
|
|
415
414
|
"date",
|
|
416
415
|
"cal",
|
|
417
416
|
"bc",
|
|
@@ -548,17 +547,21 @@ def validate_bash_command(command_parts: list) -> bool:
|
|
|
548
547
|
"--count",
|
|
549
548
|
"--heading",
|
|
550
549
|
],
|
|
551
|
-
"requires_arg":
|
|
550
|
+
"requires_arg": False,
|
|
552
551
|
},
|
|
553
552
|
"open": {
|
|
554
553
|
"flags": ["-a", "-e", "-t", "-f", "-F", "-W", "-n", "-g", "-h"],
|
|
555
554
|
"requires_arg": True,
|
|
556
555
|
},
|
|
557
|
-
|
|
556
|
+
|
|
558
557
|
}
|
|
559
558
|
|
|
560
559
|
base_command = command_parts[0]
|
|
561
560
|
|
|
561
|
+
if base_command == 'which':
|
|
562
|
+
return False # disable which arbitrarily cause the command parsing for it is too finnicky.
|
|
563
|
+
|
|
564
|
+
|
|
562
565
|
if base_command not in COMMAND_PATTERNS:
|
|
563
566
|
return True # Allow other commands to pass through
|
|
564
567
|
|
|
@@ -578,11 +581,6 @@ def validate_bash_command(command_parts: list) -> bool:
|
|
|
578
581
|
# Check if 'who' has any arguments (it shouldn't)
|
|
579
582
|
if base_command == "who" and args:
|
|
580
583
|
return False
|
|
581
|
-
|
|
582
|
-
# Handle 'which' with '-a' flag
|
|
583
|
-
if base_command == "which" and "-a" in flags:
|
|
584
|
-
return True # Allow 'which -a' with or without arguments.
|
|
585
|
-
|
|
586
584
|
# Check if any required arguments are missing
|
|
587
585
|
if pattern.get("requires_arg", False) and not args:
|
|
588
586
|
return False
|
npcsh/npcsh.py
CHANGED
|
@@ -37,7 +37,7 @@ from npcsh._state import (
|
|
|
37
37
|
interactive_commands,
|
|
38
38
|
BASH_COMMANDS,
|
|
39
39
|
start_interactive_session,
|
|
40
|
-
|
|
40
|
+
validate_bash_command
|
|
41
41
|
)
|
|
42
42
|
|
|
43
43
|
from npcpy.npc_sysenv import (
|
|
@@ -81,9 +81,6 @@ except Exception as e:
|
|
|
81
81
|
print(f"Warning: Failed to initialize ChromaDB client at {EMBEDDINGS_DB_PATH}: {e}")
|
|
82
82
|
chroma_client = None
|
|
83
83
|
|
|
84
|
-
# --- Custom Exceptions ---
|
|
85
|
-
class CommandNotFoundError(Exception):
|
|
86
|
-
pass
|
|
87
84
|
|
|
88
85
|
|
|
89
86
|
from npcsh._state import initial_state, ShellState
|
|
@@ -404,14 +401,7 @@ def handle_bash_command(
|
|
|
404
401
|
cmd_str: str,
|
|
405
402
|
stdin_input: Optional[str],
|
|
406
403
|
state: ShellState,
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
command_name = cmd_parts[0]
|
|
410
|
-
|
|
411
|
-
if command_name in TERMINAL_EDITORS:
|
|
412
|
-
output = open_terminal_editor(cmd_str)
|
|
413
|
-
return state, output
|
|
414
|
-
|
|
404
|
+
) -> Tuple[bool, str]:
|
|
415
405
|
try:
|
|
416
406
|
process = subprocess.Popen(
|
|
417
407
|
cmd_parts,
|
|
@@ -421,39 +411,23 @@ def handle_bash_command(
|
|
|
421
411
|
text=True,
|
|
422
412
|
cwd=state.current_path
|
|
423
413
|
)
|
|
424
|
-
|
|
425
414
|
stdout, stderr = process.communicate(input=stdin_input)
|
|
426
415
|
|
|
427
416
|
if process.returncode != 0:
|
|
428
|
-
|
|
429
|
-
# If it failed because command not found, raise specific error for fallback
|
|
430
|
-
if "No such file or directory" in err_msg or "command not found" in err_msg:
|
|
431
|
-
raise CommandNotFoundError(err_msg)
|
|
432
|
-
# Otherwise, return the error output
|
|
433
|
-
full_output = stdout.strip() + ("\n" + colored(f"stderr: {err_msg}", "red") if err_msg else "")
|
|
434
|
-
return state, full_output.strip()
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
output = stdout.strip() if stdout else ""
|
|
438
|
-
if stderr:
|
|
439
|
-
# Log stderr but don't necessarily include in piped output unless requested
|
|
440
|
-
print(colored(f"stderr: {stderr.strip()}", "yellow"), file=sys.stderr)
|
|
417
|
+
return False, stderr.strip() if stderr else f"Command '{cmd_str}' failed with return code {process.returncode}."
|
|
441
418
|
|
|
419
|
+
if stderr.strip():
|
|
420
|
+
print(colored(f"stderr: {stderr.strip()}", "yellow"), file=sys.stderr)
|
|
421
|
+
|
|
422
|
+
if cmd_parts[0] in ["ls", "find", "dir"]:
|
|
423
|
+
return True, format_file_listing(stdout.strip())
|
|
442
424
|
|
|
443
|
-
|
|
444
|
-
output = format_file_listing(output)
|
|
445
|
-
elif not output and process.returncode == 0 and not stderr:
|
|
446
|
-
output = "" # No output is valid, don't print success message if piping
|
|
447
|
-
|
|
448
|
-
return state, output
|
|
425
|
+
return True, stdout.strip()
|
|
449
426
|
|
|
450
427
|
except FileNotFoundError:
|
|
451
|
-
|
|
452
|
-
except PermissionError
|
|
453
|
-
|
|
454
|
-
except Exception as e:
|
|
455
|
-
return state, colored(f"Error executing command '{cmd_str}': {e}", "red")
|
|
456
|
-
|
|
428
|
+
return False, f"Command not found: {cmd_parts[0]}"
|
|
429
|
+
except PermissionError:
|
|
430
|
+
return False, f"Permission denied: {cmd_str}"
|
|
457
431
|
|
|
458
432
|
def execute_slash_command(command: str, stdin_input: Optional[str], state: ShellState, stream: bool) -> Tuple[ShellState, Any]:
|
|
459
433
|
"""Executes slash commands using the router or checking NPC/Team jinxs."""
|
|
@@ -527,7 +501,6 @@ def execute_slash_command(command: str, stdin_input: Optional[str], state: Shell
|
|
|
527
501
|
|
|
528
502
|
return state, colored(f"Unknown slash command or jinx: {command_name}", "red")
|
|
529
503
|
|
|
530
|
-
|
|
531
504
|
def process_pipeline_command(
|
|
532
505
|
cmd_segment: str,
|
|
533
506
|
stdin_input: Optional[str],
|
|
@@ -553,84 +526,60 @@ def process_pipeline_command(
|
|
|
553
526
|
if cmd_to_process.startswith("/"):
|
|
554
527
|
return execute_slash_command(cmd_to_process, stdin_input, state, stream_final)
|
|
555
528
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
return state, stdin_input
|
|
529
|
+
cmd_parts = parse_command_safely(cmd_to_process)
|
|
530
|
+
if not cmd_parts:
|
|
531
|
+
return state, stdin_input
|
|
560
532
|
|
|
533
|
+
if validate_bash_command(cmd_parts):
|
|
561
534
|
command_name = cmd_parts[0]
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
if is_unambiguous_bash:
|
|
571
|
-
if command_name in interactive_commands:
|
|
572
|
-
return handle_interactive_command(cmd_parts, state)
|
|
573
|
-
elif command_name == "cd":
|
|
574
|
-
return handle_cd_command(cmd_parts, state)
|
|
575
|
-
else:
|
|
576
|
-
return handle_bash_command(cmd_parts, cmd_to_process, stdin_input, state)
|
|
535
|
+
if command_name in interactive_commands:
|
|
536
|
+
return handle_interactive_command(cmd_parts, state)
|
|
537
|
+
if command_name == "cd":
|
|
538
|
+
return handle_cd_command(cmd_parts, state)
|
|
539
|
+
|
|
540
|
+
success, result = handle_bash_command(cmd_parts, cmd_to_process, stdin_input, state)
|
|
541
|
+
if success:
|
|
542
|
+
return state, result
|
|
577
543
|
else:
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
provider=exec_provider,
|
|
588
|
-
api_url=state.api_url,
|
|
589
|
-
api_key=state.api_key,
|
|
590
|
-
npc=state.npc,
|
|
591
|
-
team=state.team,
|
|
592
|
-
messages=state.messages,
|
|
593
|
-
images=state.attachments,
|
|
594
|
-
stream=stream_final,
|
|
595
|
-
context=None,
|
|
596
|
-
shell=True,
|
|
544
|
+
print(colored(f"Bash command failed. Asking LLM for a fix: {result}", "yellow"), file=sys.stderr)
|
|
545
|
+
fixer_prompt = f"The command '{cmd_to_process}' failed with the error: '{result}'. Provide the correct command."
|
|
546
|
+
response = execute_llm_command(
|
|
547
|
+
fixer_prompt,
|
|
548
|
+
model=exec_model,
|
|
549
|
+
provider=exec_provider,
|
|
550
|
+
npc=state.npc,
|
|
551
|
+
stream=stream_final,
|
|
552
|
+
messages=state.messages
|
|
597
553
|
)
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
return state, output
|
|
602
|
-
else:
|
|
603
|
-
return state, llm_result
|
|
604
|
-
|
|
605
|
-
except CommandNotFoundError as e:
|
|
606
|
-
print(colored(f"Command not found, falling back to LLM: {e}", "yellow"), file=sys.stderr)
|
|
554
|
+
state.messages = response['messages']
|
|
555
|
+
return state, response['response']
|
|
556
|
+
else:
|
|
607
557
|
full_llm_cmd = f"{cmd_to_process} {stdin_input}" if stdin_input else cmd_to_process
|
|
558
|
+
path_cmd = 'The current working directory is: ' + state.current_path
|
|
559
|
+
ls_files = 'Files in the current directory (full paths):\n' + "\n".join([os.path.join(state.current_path, f) for f in os.listdir(state.current_path)]) if os.path.exists(state.current_path) else 'No files found in the current directory.'
|
|
560
|
+
platform_info = f"Platform: {platform.system()} {platform.release()} ({platform.machine()})"
|
|
561
|
+
info = path_cmd + '\n' + ls_files + '\n' + platform_info + '\n'
|
|
562
|
+
|
|
608
563
|
llm_result = check_llm_command(
|
|
609
|
-
full_llm_cmd,
|
|
610
|
-
model=exec_model,
|
|
564
|
+
full_llm_cmd,
|
|
565
|
+
model=exec_model,
|
|
611
566
|
provider=exec_provider,
|
|
612
|
-
api_url=state.api_url,
|
|
613
|
-
api_key=state.api_key,
|
|
567
|
+
api_url=state.api_url,
|
|
568
|
+
api_key=state.api_key,
|
|
614
569
|
npc=state.npc,
|
|
615
|
-
team=state.team,
|
|
616
|
-
messages=state.messages,
|
|
570
|
+
team=state.team,
|
|
571
|
+
messages=state.messages,
|
|
617
572
|
images=state.attachments,
|
|
618
|
-
stream=stream_final,
|
|
619
|
-
context=
|
|
620
|
-
shell=True
|
|
573
|
+
stream=stream_final,
|
|
574
|
+
context=info,
|
|
575
|
+
shell=True,
|
|
621
576
|
)
|
|
622
577
|
if isinstance(llm_result, dict):
|
|
623
578
|
state.messages = llm_result.get("messages", state.messages)
|
|
624
579
|
output = llm_result.get("output")
|
|
625
580
|
return state, output
|
|
626
581
|
else:
|
|
627
|
-
return state, llm_result
|
|
628
|
-
|
|
629
|
-
except Exception as e:
|
|
630
|
-
import traceback
|
|
631
|
-
traceback.print_exc()
|
|
632
|
-
return state, colored(f"Error processing command '{cmd_segment[:50]}...': {e}", "red")
|
|
633
|
-
|
|
582
|
+
return state, llm_result
|
|
634
583
|
def check_mode_switch(command:str , state: ShellState):
|
|
635
584
|
if command in ['/cmd', '/agent', '/chat', '/ride']:
|
|
636
585
|
state.current_mode = command[1:]
|
|
@@ -729,8 +678,6 @@ def execute_command(
|
|
|
729
678
|
try:
|
|
730
679
|
bash_state, bash_output = handle_bash_command(cmd_parts, command, None, state)
|
|
731
680
|
return bash_state, bash_output
|
|
732
|
-
except CommandNotFoundError:
|
|
733
|
-
pass # Fall through to LLM
|
|
734
681
|
except Exception as bash_err:
|
|
735
682
|
return state, colored(f"Bash execution failed: {bash_err}", "red")
|
|
736
683
|
except Exception:
|
|
@@ -1215,46 +1162,51 @@ def setup_shell() -> Tuple[CommandHistory, Team, Optional[NPC]]:
|
|
|
1215
1162
|
team_dir = project_team_path
|
|
1216
1163
|
default_forenpc_name = "forenpc"
|
|
1217
1164
|
else:
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1165
|
+
if not os.path.exists('.npcsh_global'):
|
|
1166
|
+
resp = input(f"No npc_team found in {os.getcwd()}. Create a new team here? [Y/n]: ").strip().lower()
|
|
1167
|
+
if resp in ("", "y", "yes"):
|
|
1168
|
+
team_dir = project_team_path
|
|
1169
|
+
os.makedirs(team_dir, exist_ok=True)
|
|
1170
|
+
default_forenpc_name = "forenpc"
|
|
1171
|
+
forenpc_directive = input(
|
|
1172
|
+
f"Enter a primary directive for {default_forenpc_name} (default: 'You are the forenpc of the team...'): "
|
|
1173
|
+
).strip() or "You are the forenpc of the team, coordinating activities between NPCs on the team, verifying that results from NPCs are high quality and can help to adequately answer user requests."
|
|
1174
|
+
forenpc_model = input("Enter a model for your forenpc (default: llama3.2): ").strip() or "llama3.2"
|
|
1175
|
+
forenpc_provider = input("Enter a provider for your forenpc (default: ollama): ").strip() or "ollama"
|
|
1176
|
+
|
|
1177
|
+
with open(os.path.join(team_dir, f"{default_forenpc_name}.npc"), "w") as f:
|
|
1178
|
+
yaml.dump({
|
|
1179
|
+
"name": default_forenpc_name, "primary_directive": forenpc_directive,
|
|
1180
|
+
"model": forenpc_model, "provider": forenpc_provider
|
|
1181
|
+
}, f)
|
|
1182
|
+
|
|
1183
|
+
ctx_path = os.path.join(team_dir, "team.ctx")
|
|
1184
|
+
folder_context = input("Enter a short description for this project/team (optional): ").strip()
|
|
1185
|
+
team_ctx_data = {
|
|
1186
|
+
"forenpc": default_forenpc_name, "model": forenpc_model,
|
|
1187
|
+
"provider": forenpc_provider, "api_key": None, "api_url": None,
|
|
1188
|
+
"context": folder_context if folder_context else None
|
|
1189
|
+
}
|
|
1190
|
+
use_jinxs = input("Use global jinxs folder (g) or copy to this project (c)? [g/c, default: g]: ").strip().lower()
|
|
1191
|
+
if use_jinxs == "c":
|
|
1192
|
+
global_jinxs_dir = os.path.expanduser("~/.npcsh/npc_team/jinxs")
|
|
1193
|
+
if os.path.exists(global_jinxs_dir):
|
|
1194
|
+
shutil.copytree(global_jinxs_dir, os.path.join(team_dir, "jinxs"), dirs_exist_ok=True)
|
|
1195
|
+
else:
|
|
1196
|
+
team_ctx_data["use_global_jinxs"] = True
|
|
1249
1197
|
|
|
1250
|
-
|
|
1251
|
-
|
|
1198
|
+
with open(ctx_path, "w") as f:
|
|
1199
|
+
yaml.dump(team_ctx_data, f)
|
|
1200
|
+
else:
|
|
1201
|
+
render_markdown('From now on, npcsh will assume you will use the global team when activating from this folder. \n If you change your mind and want to initialize a team, use /init from within npcsh, `npc init` or `rm .npcsh_global` from the current working directory.')
|
|
1202
|
+
with open(".npcsh_global", "w") as f:
|
|
1203
|
+
pass
|
|
1204
|
+
team_dir = global_team_path
|
|
1205
|
+
default_forenpc_name = "sibiji"
|
|
1252
1206
|
elif os.path.exists(global_team_path):
|
|
1253
1207
|
team_dir = global_team_path
|
|
1254
|
-
default_forenpc_name = "sibiji"
|
|
1255
|
-
|
|
1256
|
-
print("No global npc_team found. Please run 'npcpy init' or create a team first.")
|
|
1257
|
-
sys.exit(1)
|
|
1208
|
+
default_forenpc_name = "sibiji"
|
|
1209
|
+
|
|
1258
1210
|
|
|
1259
1211
|
team_ctx = {}
|
|
1260
1212
|
for filename in os.listdir(team_dir):
|
|
@@ -1368,6 +1320,12 @@ def run_repl(command_history: CommandHistory, initial_state: ShellState):
|
|
|
1368
1320
|
|
|
1369
1321
|
def exit_shell(state):
|
|
1370
1322
|
print("\nGoodbye!")
|
|
1323
|
+
# update the team ctx file to update the context and the preferences
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
|
|
1371
1329
|
#print('beginning knowledge consolidation')
|
|
1372
1330
|
#try:
|
|
1373
1331
|
# breathe_result = breathe(state.messages, state.chat_model, state.chat_provider, state.npc)
|
|
@@ -1431,27 +1389,6 @@ def run_repl(command_history: CommandHistory, initial_state: ShellState):
|
|
|
1431
1389
|
# Ctrl+D: exit shell cleanly
|
|
1432
1390
|
exit_shell(state)
|
|
1433
1391
|
|
|
1434
|
-
def run_non_interactive(command_history: CommandHistory, initial_state: ShellState):
|
|
1435
|
-
state = initial_state
|
|
1436
|
-
# print("Running in non-interactive mode...", file=sys.stderr) # Optional debug
|
|
1437
|
-
|
|
1438
|
-
for line in sys.stdin:
|
|
1439
|
-
user_input = line.strip()
|
|
1440
|
-
if not user_input:
|
|
1441
|
-
continue
|
|
1442
|
-
if user_input.lower() in ["exit", "quit"]:
|
|
1443
|
-
break
|
|
1444
|
-
|
|
1445
|
-
state.current_path = os.getcwd()
|
|
1446
|
-
state, output = execute_command(user_input, state)
|
|
1447
|
-
# Non-interactive: just print raw output, don't process results complexly
|
|
1448
|
-
if state.stream_output and isgenerator(output):
|
|
1449
|
-
for chunk in output: print(str(chunk), end='')
|
|
1450
|
-
print()
|
|
1451
|
-
elif output is not None:
|
|
1452
|
-
print(output)
|
|
1453
|
-
# Maybe still log history?
|
|
1454
|
-
# process_result(user_input, state, output, command_history)
|
|
1455
1392
|
|
|
1456
1393
|
def main() -> None:
|
|
1457
1394
|
parser = argparse.ArgumentParser(description="npcsh - An NPC-powered shell.")
|
|
@@ -1469,6 +1406,9 @@ def main() -> None:
|
|
|
1469
1406
|
initial_state.team = team
|
|
1470
1407
|
#import pdb
|
|
1471
1408
|
#pdb.set_trace()
|
|
1409
|
+
|
|
1410
|
+
# add a -g global command to indicate if to use the global or project, otherwise go thru normal flow
|
|
1411
|
+
|
|
1472
1412
|
if args.command:
|
|
1473
1413
|
state = initial_state
|
|
1474
1414
|
state.current_path = os.getcwd()
|
|
@@ -1478,9 +1418,6 @@ def main() -> None:
|
|
|
1478
1418
|
print()
|
|
1479
1419
|
elif output is not None:
|
|
1480
1420
|
print(output)
|
|
1481
|
-
|
|
1482
|
-
elif not sys.stdin.isatty():
|
|
1483
|
-
run_non_interactive(command_history, initial_state)
|
|
1484
1421
|
else:
|
|
1485
1422
|
run_repl(command_history, initial_state)
|
|
1486
1423
|
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
npcsh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
npcsh/_state.py,sha256=
|
|
2
|
+
npcsh/_state.py,sha256=3DbJ9X6Ol5ubXFjy-OrV2ioDt6qMLvh4CAsoLCJ5kbg,27347
|
|
3
3
|
npcsh/alicanto.py,sha256=zJF5YwSNvtbK2EUKXzG45WOCMsSFu5cek5jCR7FgiuE,44709
|
|
4
4
|
npcsh/guac.py,sha256=Ocmk_c4NUtGsC3JOtmkbgLvD6u-XtBPRFRYcckpgUJU,33099
|
|
5
5
|
npcsh/mcp_helpers.py,sha256=Ktd2yXuBnLL2P7OMalgGLj84PXJSzaucjqmJVvWx6HA,12723
|
|
6
6
|
npcsh/mcp_npcsh.py,sha256=SfmplH62GS9iI6q4vuQLVUS6tkrok6L7JxODx_iH7ps,36158
|
|
7
7
|
npcsh/mcp_server.py,sha256=l2Ra0lpFrUu334pvp0Q9ajF2n73KvZswFi0FgbDhh9k,5884
|
|
8
8
|
npcsh/npc.py,sha256=JEP0nqbqRGvAthj9uT0ZfbGc322g3Ge3rRDKbpIdI1s,7907
|
|
9
|
-
npcsh/npcsh.py,sha256=
|
|
9
|
+
npcsh/npcsh.py,sha256=yRpTvpy8OiVCyWpHfNGfuueojwy2ZHnoZii91S4fKaQ,55229
|
|
10
10
|
npcsh/plonk.py,sha256=U2e9yUJZN95Girzzvgrh-40zOdl5zO3AHPsIjoyLv2M,15261
|
|
11
11
|
npcsh/pti.py,sha256=jGHGE5SeIcDkV8WlOEHCKQCnYAL4IPS-kUBHrUz0oDA,10019
|
|
12
12
|
npcsh/routes.py,sha256=ufQVc6aqgC14_YHV88iwV53TN1Pk095NB6gFDqQqfB4,37208
|
|
13
13
|
npcsh/spool.py,sha256=GhnSFX9uAtrB4m_ijuyA5tufH12DrWdABw0z8FmiCHc,11497
|
|
14
14
|
npcsh/wander.py,sha256=BiN6eYyFnEsFzo8MFLRkdZ8xS9sTKkQpjiCcy9chMcc,23225
|
|
15
15
|
npcsh/yap.py,sha256=h5KNt9sNOrDPhGe_zfn_yFIeQhizX09zocjcPWH7m3k,20905
|
|
16
|
-
npcsh-1.0.
|
|
17
|
-
npcsh-1.0.
|
|
18
|
-
npcsh-1.0.
|
|
19
|
-
npcsh-1.0.
|
|
20
|
-
npcsh-1.0.
|
|
21
|
-
npcsh-1.0.
|
|
16
|
+
npcsh-1.0.5.dist-info/licenses/LICENSE,sha256=IKBvAECHP-aCiJtE4cHGCE5Yl0tozYz02PomGeWS3y4,1070
|
|
17
|
+
npcsh-1.0.5.dist-info/METADATA,sha256=f9x6EEZT5YlU83DcV-uLA5egMSVHYF0qyHF3DczuRMs,22747
|
|
18
|
+
npcsh-1.0.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
19
|
+
npcsh-1.0.5.dist-info/entry_points.txt,sha256=qxOYTm3ym3JWyWf2nv2Mk71uMcJIdUoNEJ8VYMkyHiY,214
|
|
20
|
+
npcsh-1.0.5.dist-info/top_level.txt,sha256=kHSNgKMCkfjV95-DH0YSp1LLBi0HXdF3w57j7MQON3E,6
|
|
21
|
+
npcsh-1.0.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|