npcsh 1.0.4__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 -166
- {npcsh-1.0.4.dist-info → npcsh-1.0.5.dist-info}/METADATA +1 -1
- {npcsh-1.0.4.dist-info → npcsh-1.0.5.dist-info}/RECORD +8 -8
- {npcsh-1.0.4.dist-info → npcsh-1.0.5.dist-info}/WHEEL +0 -0
- {npcsh-1.0.4.dist-info → npcsh-1.0.5.dist-info}/entry_points.txt +0 -0
- {npcsh-1.0.4.dist-info → npcsh-1.0.5.dist-info}/licenses/LICENSE +0 -0
- {npcsh-1.0.4.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,85 +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
|
-
model=exec_model,
|
|
588
|
-
provider=exec_provider,
|
|
589
|
-
api_url=state.api_url,
|
|
590
|
-
api_key=state.api_key,
|
|
591
|
-
npc=state.npc,
|
|
592
|
-
team=state.team,
|
|
593
|
-
messages=state.messages,
|
|
594
|
-
images=state.attachments,
|
|
595
|
-
stream=stream_final,
|
|
596
|
-
context=info,
|
|
597
|
-
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
|
|
598
553
|
)
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
return state, output
|
|
603
|
-
else:
|
|
604
|
-
return state, llm_result
|
|
605
|
-
|
|
606
|
-
except CommandNotFoundError as e:
|
|
607
|
-
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:
|
|
608
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
|
+
|
|
609
563
|
llm_result = check_llm_command(
|
|
610
|
-
full_llm_cmd,
|
|
611
|
-
model=exec_model,
|
|
564
|
+
full_llm_cmd,
|
|
565
|
+
model=exec_model,
|
|
612
566
|
provider=exec_provider,
|
|
613
|
-
api_url=state.api_url,
|
|
614
|
-
api_key=state.api_key,
|
|
567
|
+
api_url=state.api_url,
|
|
568
|
+
api_key=state.api_key,
|
|
615
569
|
npc=state.npc,
|
|
616
|
-
team=state.team,
|
|
617
|
-
messages=state.messages,
|
|
570
|
+
team=state.team,
|
|
571
|
+
messages=state.messages,
|
|
618
572
|
images=state.attachments,
|
|
619
|
-
stream=stream_final,
|
|
620
|
-
context=
|
|
621
|
-
shell=True
|
|
573
|
+
stream=stream_final,
|
|
574
|
+
context=info,
|
|
575
|
+
shell=True,
|
|
622
576
|
)
|
|
623
577
|
if isinstance(llm_result, dict):
|
|
624
578
|
state.messages = llm_result.get("messages", state.messages)
|
|
625
579
|
output = llm_result.get("output")
|
|
626
580
|
return state, output
|
|
627
581
|
else:
|
|
628
|
-
return state, llm_result
|
|
629
|
-
|
|
630
|
-
except Exception as e:
|
|
631
|
-
import traceback
|
|
632
|
-
traceback.print_exc()
|
|
633
|
-
return state, colored(f"Error processing command '{cmd_segment[:50]}...': {e}", "red")
|
|
634
|
-
|
|
582
|
+
return state, llm_result
|
|
635
583
|
def check_mode_switch(command:str , state: ShellState):
|
|
636
584
|
if command in ['/cmd', '/agent', '/chat', '/ride']:
|
|
637
585
|
state.current_mode = command[1:]
|
|
@@ -730,8 +678,6 @@ def execute_command(
|
|
|
730
678
|
try:
|
|
731
679
|
bash_state, bash_output = handle_bash_command(cmd_parts, command, None, state)
|
|
732
680
|
return bash_state, bash_output
|
|
733
|
-
except CommandNotFoundError:
|
|
734
|
-
pass # Fall through to LLM
|
|
735
681
|
except Exception as bash_err:
|
|
736
682
|
return state, colored(f"Bash execution failed: {bash_err}", "red")
|
|
737
683
|
except Exception:
|
|
@@ -1216,46 +1162,51 @@ def setup_shell() -> Tuple[CommandHistory, Team, Optional[NPC]]:
|
|
|
1216
1162
|
team_dir = project_team_path
|
|
1217
1163
|
default_forenpc_name = "forenpc"
|
|
1218
1164
|
else:
|
|
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
|
-
|
|
1249
|
-
|
|
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
|
|
1250
1197
|
|
|
1251
|
-
|
|
1252
|
-
|
|
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"
|
|
1253
1206
|
elif os.path.exists(global_team_path):
|
|
1254
1207
|
team_dir = global_team_path
|
|
1255
|
-
default_forenpc_name = "sibiji"
|
|
1256
|
-
|
|
1257
|
-
print("No global npc_team found. Please run 'npcpy init' or create a team first.")
|
|
1258
|
-
sys.exit(1)
|
|
1208
|
+
default_forenpc_name = "sibiji"
|
|
1209
|
+
|
|
1259
1210
|
|
|
1260
1211
|
team_ctx = {}
|
|
1261
1212
|
for filename in os.listdir(team_dir):
|
|
@@ -1369,6 +1320,12 @@ def run_repl(command_history: CommandHistory, initial_state: ShellState):
|
|
|
1369
1320
|
|
|
1370
1321
|
def exit_shell(state):
|
|
1371
1322
|
print("\nGoodbye!")
|
|
1323
|
+
# update the team ctx file to update the context and the preferences
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
|
|
1372
1329
|
#print('beginning knowledge consolidation')
|
|
1373
1330
|
#try:
|
|
1374
1331
|
# breathe_result = breathe(state.messages, state.chat_model, state.chat_provider, state.npc)
|
|
@@ -1432,27 +1389,6 @@ def run_repl(command_history: CommandHistory, initial_state: ShellState):
|
|
|
1432
1389
|
# Ctrl+D: exit shell cleanly
|
|
1433
1390
|
exit_shell(state)
|
|
1434
1391
|
|
|
1435
|
-
def run_non_interactive(command_history: CommandHistory, initial_state: ShellState):
|
|
1436
|
-
state = initial_state
|
|
1437
|
-
# print("Running in non-interactive mode...", file=sys.stderr) # Optional debug
|
|
1438
|
-
|
|
1439
|
-
for line in sys.stdin:
|
|
1440
|
-
user_input = line.strip()
|
|
1441
|
-
if not user_input:
|
|
1442
|
-
continue
|
|
1443
|
-
if user_input.lower() in ["exit", "quit"]:
|
|
1444
|
-
break
|
|
1445
|
-
|
|
1446
|
-
state.current_path = os.getcwd()
|
|
1447
|
-
state, output = execute_command(user_input, state)
|
|
1448
|
-
# Non-interactive: just print raw output, don't process results complexly
|
|
1449
|
-
if state.stream_output and isgenerator(output):
|
|
1450
|
-
for chunk in output: print(str(chunk), end='')
|
|
1451
|
-
print()
|
|
1452
|
-
elif output is not None:
|
|
1453
|
-
print(output)
|
|
1454
|
-
# Maybe still log history?
|
|
1455
|
-
# process_result(user_input, state, output, command_history)
|
|
1456
1392
|
|
|
1457
1393
|
def main() -> None:
|
|
1458
1394
|
parser = argparse.ArgumentParser(description="npcsh - An NPC-powered shell.")
|
|
@@ -1470,6 +1406,9 @@ def main() -> None:
|
|
|
1470
1406
|
initial_state.team = team
|
|
1471
1407
|
#import pdb
|
|
1472
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
|
+
|
|
1473
1412
|
if args.command:
|
|
1474
1413
|
state = initial_state
|
|
1475
1414
|
state.current_path = os.getcwd()
|
|
@@ -1479,9 +1418,6 @@ def main() -> None:
|
|
|
1479
1418
|
print()
|
|
1480
1419
|
elif output is not None:
|
|
1481
1420
|
print(output)
|
|
1482
|
-
|
|
1483
|
-
elif not sys.stdin.isatty():
|
|
1484
|
-
run_non_interactive(command_history, initial_state)
|
|
1485
1421
|
else:
|
|
1486
1422
|
run_repl(command_history, initial_state)
|
|
1487
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
|