npcsh 1.0.36__py3-none-any.whl → 1.1.1__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.
Files changed (42) hide show
  1. npcsh/_state.py +150 -14
  2. npcsh/corca.py +16 -15
  3. npcsh/mcp_server.py +119 -7
  4. npcsh/npc_team/corca.npc +1 -2
  5. npcsh/npc_team/jinxs/kg_search.jinx +43 -0
  6. npcsh/npc_team/jinxs/memory_search.jinx +36 -0
  7. npcsh/npcsh.py +14 -5
  8. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/corca.npc +1 -2
  9. npcsh-1.1.1.data/data/npcsh/npc_team/kg_search.jinx +43 -0
  10. npcsh-1.1.1.data/data/npcsh/npc_team/memory_search.jinx +36 -0
  11. {npcsh-1.0.36.dist-info → npcsh-1.1.1.dist-info}/METADATA +1 -1
  12. npcsh-1.1.1.dist-info/RECORD +77 -0
  13. npcsh-1.0.36.dist-info/RECORD +0 -73
  14. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/alicanto.npc +0 -0
  15. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/alicanto.png +0 -0
  16. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/bash_executer.jinx +0 -0
  17. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/corca.png +0 -0
  18. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/edit_file.jinx +0 -0
  19. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/foreman.npc +0 -0
  20. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/frederic.npc +0 -0
  21. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/frederic4.png +0 -0
  22. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/guac.png +0 -0
  23. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/image_generation.jinx +0 -0
  24. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/internet_search.jinx +0 -0
  25. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/kadiefa.npc +0 -0
  26. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/kadiefa.png +0 -0
  27. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/npcsh.ctx +0 -0
  28. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/npcsh_sibiji.png +0 -0
  29. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/plonk.npc +0 -0
  30. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/plonk.png +0 -0
  31. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/plonkjr.npc +0 -0
  32. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/plonkjr.png +0 -0
  33. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/python_executor.jinx +0 -0
  34. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/screen_cap.jinx +0 -0
  35. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/sibiji.npc +0 -0
  36. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/sibiji.png +0 -0
  37. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/spool.png +0 -0
  38. {npcsh-1.0.36.data → npcsh-1.1.1.data}/data/npcsh/npc_team/yap.png +0 -0
  39. {npcsh-1.0.36.dist-info → npcsh-1.1.1.dist-info}/WHEEL +0 -0
  40. {npcsh-1.0.36.dist-info → npcsh-1.1.1.dist-info}/entry_points.txt +0 -0
  41. {npcsh-1.0.36.dist-info → npcsh-1.1.1.dist-info}/licenses/LICENSE +0 -0
  42. {npcsh-1.0.36.dist-info → npcsh-1.1.1.dist-info}/top_level.txt +0 -0
npcsh/_state.py CHANGED
@@ -2193,16 +2193,51 @@ def execute_command(
2193
2193
  state: ShellState,
2194
2194
  review = True,
2195
2195
  router = None,
2196
+ command_history = None,
2196
2197
  ) -> Tuple[ShellState, Any]:
2197
2198
 
2198
2199
  if not command.strip():
2199
2200
  return state, ""
2201
+
2200
2202
  mode_change, state = check_mode_switch(command, state)
2201
2203
  if mode_change:
2202
2204
  return state, 'Mode changed.'
2203
2205
 
2206
+ npc_name = state.npc.name if isinstance(state.npc, NPC) else "__none__"
2207
+ team_name = state.team.name if state.team else "__none__"
2208
+
2209
+ if command_history:
2210
+ relevant_memories = get_relevant_memories(
2211
+ command_history=command_history,
2212
+ npc_name=npc_name,
2213
+ team_name=team_name,
2214
+ path=state.current_path,
2215
+ query=command,
2216
+ max_memories=5,
2217
+ state=state
2218
+ )
2219
+ print('Memory jogged...')
2220
+ print(relevant_memories)
2221
+
2222
+ if relevant_memories:
2223
+ memory_context = "\n".join([
2224
+ f"- {m.get('final_memory', '')}"
2225
+ for m in relevant_memories
2226
+ ])
2227
+ memory_msg = {
2228
+ "role": "system",
2229
+ "content": f"Relevant memories:\n{memory_context}"
2230
+ }
2231
+ if not state.messages or \
2232
+ state.messages[0].get("role") != "system":
2233
+ state.messages.insert(0, memory_msg)
2234
+ else:
2235
+ state.messages[0]["content"] += \
2236
+ f"\n\n{memory_msg['content']}"
2237
+
2204
2238
  original_command_for_embedding = command
2205
2239
  commands = split_by_pipes(command)
2240
+
2206
2241
  stdin_for_next = None
2207
2242
  final_output = None
2208
2243
  current_state = state
@@ -2448,28 +2483,129 @@ def setup_shell() -> Tuple[CommandHistory, Team, Optional[NPC]]:
2448
2483
  team_name_from_ctx = team_ctx.get("name")
2449
2484
  if team_name_from_ctx:
2450
2485
  team.name = team_name_from_ctx
2451
- elif team_dir and os.path.basename(team_dir) != 'npc_team':
2452
- team.name = os.path.basename(team_dir)
2486
+ elif team_dir:
2487
+ normalized_dir = os.path.normpath(team_dir)
2488
+ basename = os.path.basename(normalized_dir)
2489
+ if basename and basename != 'npc_team':
2490
+ team.name = basename
2491
+ else:
2492
+ team.name = "npcsh"
2453
2493
  else:
2454
- team.name = "global_team"
2494
+ team.name = "npcsh"
2495
+
2455
2496
 
2456
2497
  return command_history, team, forenpc_obj
2457
2498
 
2458
2499
 
2459
2500
 
2460
2501
 
2461
- from npcpy.memory.memory_processor import MemoryApprovalQueue, MemoryItem, memory_approval_ui
2502
+ from npcpy.memory.memory_processor import memory_approval_ui
2462
2503
  from npcpy.ft.memory_trainer import MemoryTrainer
2463
2504
  from npcpy.llm_funcs import get_facts
2464
2505
 
2465
- _memory_queue = None
2506
+ def get_relevant_memories(
2507
+ command_history: CommandHistory,
2508
+ npc_name: str,
2509
+ team_name: str,
2510
+ path: str,
2511
+ query: Optional[str] = None,
2512
+ max_memories: int = 10,
2513
+ state: Optional[ShellState] = None
2514
+ ) -> List[Dict]:
2515
+
2516
+ engine = command_history.engine
2517
+
2518
+ all_memories = command_history.get_memories_for_scope(
2519
+ npc=npc_name,
2520
+ team=team_name,
2521
+ directory_path=path,
2522
+ status='human-approved'
2523
+ )
2524
+
2525
+ if not all_memories:
2526
+ return []
2527
+
2528
+ if len(all_memories) <= max_memories and not query:
2529
+ return all_memories
2530
+
2531
+ if query:
2532
+ query_lower = query.lower()
2533
+ keyword_matches = [
2534
+ m for m in all_memories
2535
+ if query_lower in (m.get('final_memory') or m.get('initial_memory') or '').lower()
2536
+ ]
2537
+
2538
+ if keyword_matches:
2539
+ return keyword_matches[:max_memories]
2540
+
2541
+ if state and state.embedding_model and state.embedding_provider:
2542
+ try:
2543
+ from npcpy.gen.embeddings import get_embeddings
2544
+
2545
+ search_text = query if query else "recent context"
2546
+ query_embedding = get_embeddings(
2547
+ [search_text],
2548
+ state.embedding_model,
2549
+ state.embedding_provider
2550
+ )[0]
2551
+
2552
+ memory_texts = [
2553
+ m.get('final_memory', '') for m in all_memories
2554
+ ]
2555
+ memory_embeddings = get_embeddings(
2556
+ memory_texts,
2557
+ state.embedding_model,
2558
+ state.embedding_provider
2559
+ )
2560
+
2561
+ import numpy as np
2562
+ similarities = []
2563
+ for mem_emb in memory_embeddings:
2564
+ similarity = np.dot(query_embedding, mem_emb) / (
2565
+ np.linalg.norm(query_embedding) *
2566
+ np.linalg.norm(mem_emb)
2567
+ )
2568
+ similarities.append(similarity)
2569
+
2570
+ sorted_indices = np.argsort(similarities)[::-1]
2571
+ return [all_memories[i] for i in sorted_indices[:max_memories]]
2572
+
2573
+ except Exception as e:
2574
+ print(colored(
2575
+ f"RAG search failed, using recent: {e}",
2576
+ "yellow"
2577
+ ))
2578
+
2579
+ return all_memories[-max_memories:]
2580
+
2466
2581
 
2467
- def get_memory_queue(command_history):
2468
- global _memory_queue
2469
- if _memory_queue is None:
2470
- _memory_queue = MemoryApprovalQueue(command_history)
2471
- _memory_queue.start_background_processing()
2472
- return _memory_queue
2582
+ def search_kg_facts(
2583
+ self,
2584
+ npc: str,
2585
+ team: str,
2586
+ directory_path: str,
2587
+ query: str
2588
+ ) -> List[Dict]:
2589
+
2590
+ kg = load_kg_from_db(
2591
+ self.engine,
2592
+ team,
2593
+ npc,
2594
+ directory_path
2595
+ )
2596
+
2597
+ if not kg or 'facts' not in kg:
2598
+ return []
2599
+
2600
+ query_lower = query.lower()
2601
+ matching_facts = []
2602
+
2603
+ for fact in kg['facts']:
2604
+ statement = fact.get('statement', '').lower()
2605
+ if query_lower in statement:
2606
+ matching_facts.append(fact)
2607
+
2608
+ return matching_facts
2473
2609
 
2474
2610
  def format_memory_context(memory_examples):
2475
2611
  if not memory_examples:
@@ -2556,8 +2692,8 @@ def process_result(
2556
2692
  output: Any,
2557
2693
  command_history: CommandHistory,
2558
2694
  ):
2559
- team_name = result_state.team.name if result_state.team else "__none__"
2560
- npc_name = result_state.npc.name if isinstance(result_state.npc, NPC) else "__none__"
2695
+ team_name = result_state.team.name if result_state.team else "npcsh"
2696
+ npc_name = result_state.npc.name if isinstance(result_state.npc, NPC) else "npcsh"
2561
2697
 
2562
2698
  active_npc = result_state.npc if isinstance(result_state.npc, NPC) else NPC(
2563
2699
  name="default",
@@ -2637,7 +2773,7 @@ def process_result(
2637
2773
  model=active_npc.model,
2638
2774
  provider=active_npc.provider,
2639
2775
  npc=active_npc,
2640
- context=memory_context
2776
+ context=memory_context + 'Memories should be fully self contained. They should not use vague pronouns or words like that or this or it. Do not generate more than 1-2 memories at a time.'
2641
2777
  )
2642
2778
 
2643
2779
  if facts:
npcsh/corca.py CHANGED
@@ -396,8 +396,8 @@ def execute_command_corca(command: str, state: ShellState, command_history, sele
396
396
  cprint("Warning: Corca agent has no tools. No MCP server connected.", "yellow", file=sys.stderr)
397
397
 
398
398
  if len(state.messages) > 20:
399
- compressed_state = state.npc.compress_planning_state(messages)
400
- state.messages = [{"role": "system", "content": state.npc.get_system_message() + f' Your current task: {compressed_state}'}]
399
+ compressed_state = state.npc.compress_planning_state(state.messages)
400
+ state.messages = [{"role": "system", "content": state.npc.get_system_prompt() + f' Your current task: {compressed_state}'}]
401
401
  print("Compressed messages during tool execution.")
402
402
 
403
403
  response_dict = get_llm_response_with_handling(
@@ -640,27 +640,28 @@ def _resolve_and_copy_mcp_server_path(
640
640
 
641
641
  cprint("No MCP server script found in any expected location.", "yellow")
642
642
  return None
643
-
644
-
645
643
  def print_corca_welcome_message():
646
644
  turq = "\033[38;2;64;224;208m"
647
645
  chrome = "\033[38;2;211;211;211m"
646
+ orange = "\033[38;2;255;165;0m"
648
647
  reset = "\033[0m"
649
648
 
650
649
  print(
651
650
  f"""
652
- Welcome to {turq}C{chrome}o{turq}r{chrome}c{turq}a{reset}!
653
- {turq} {turq} {turq} {chrome} {chrome}
654
- {turq} ____ {turq} ___ {turq} ____ {chrome} ____ {chrome} __ _
655
- {turq} / __|{turq} / _ \\ {turq}| __\\{chrome} / __| {chrome}/ _` |
656
- {turq} | |__ {turq}| (_) |{turq}| | {chrome}| |__{chrome} | (_| |
657
- {turq} \\____| {turq}\\___/ {turq}| | {chrome}\\____| {chrome}\\__,_|
658
- {turq} {turq} {turq} {chrome} {chrome}
659
- {reset}
660
- An MCP-powered shell for advanced agentic workflows.
651
+ {turq} ██████ ██████ ██████ ██████ ██████{reset}
652
+ {turq}██ ██ ██ ██ ██ ██ ██ ██ ██🦌🦌██{reset}
653
+ {turq}██ ██ ██ ██ ██ ██ ██🦌🦌██{reset}
654
+ {chrome}██ ██ ██ ████████ ██ ████████{reset}
655
+ {chrome}██ ██ ██ ██ ███ ██ ██ ██{reset}
656
+ {chrome}██ ██ ██ ██ ██ ███ ██ ██ ██ ██{reset}
657
+ {orange} ██████ ██████ ██ ███ ███████ ██ ██{reset}
658
+
659
+ {chrome} 🦌 C O R C A 🦌{reset}
660
+
661
+ {turq}MCP-powered shell for agentic workflows{reset}
661
662
  """
662
- )
663
-
663
+ )
664
+
664
665
  def create_corca_state_and_mcp_client(conversation_id, command_history, npc=None, team=None,
665
666
  current_path=None, mcp_server_path_from_request: Optional[str] = None):
666
667
  from npcsh._state import ShellState
npcsh/mcp_server.py CHANGED
@@ -14,6 +14,7 @@ from typing import Optional, Dict, Any, List, Union, Callable
14
14
  from mcp.server.fastmcp import FastMCP
15
15
  import importlib
16
16
 
17
+ from sqlalchemy import text
17
18
 
18
19
 
19
20
  import os
@@ -46,14 +47,129 @@ mcp = FastMCP("npcsh_mcp")
46
47
  DEFAULT_WORKSPACE = os.path.join(os.getcwd(), "workspace")
47
48
  os.makedirs(DEFAULT_WORKSPACE, exist_ok=True)
48
49
 
50
+ @mcp.tool()
51
+ async def add_memory(
52
+ npc_name: str,
53
+ team_name: str,
54
+ content: str,
55
+ memory_type: str = "observation",
56
+ directory_path: str = None
57
+ ) -> str:
58
+ """
59
+ Add a memory entry to the database.
60
+
61
+ Args:
62
+ npc_name: Name of the NPC this memory belongs to
63
+ team_name: Name of the team the NPC belongs to
64
+ content: The memory content to store
65
+ memory_type: Type of memory (observation, preference, achievement, etc.)
66
+ directory_path: Directory path context (defaults to current working directory)
67
+
68
+ Returns:
69
+ Success message with memory ID or error message
70
+ """
71
+ if directory_path is None:
72
+ directory_path = os.getcwd()
73
+
74
+ try:
75
+ from npcpy.memory.command_history import generate_message_id
76
+ message_id = generate_message_id()
77
+
78
+ memory_id = command_history.add_memory_to_database(
79
+ message_id=message_id,
80
+ conversation_id='mcp_direct',
81
+ npc=npc_name,
82
+ team=team_name,
83
+ directory_path=directory_path,
84
+ initial_memory=content,
85
+ status='active',
86
+ model=None,
87
+ provider=None
88
+ )
89
+ return f"Memory created successfully with ID: {memory_id}"
90
+ except Exception as e:
91
+ return f"Error creating memory: {str(e)}"
49
92
 
50
93
  @mcp.tool()
51
- async def run_server_command(command: str) -> str:
94
+ async def search_memory(
95
+ query: str,
96
+ npc_name: str = None,
97
+ team_name: str = None,
98
+ directory_path: str = None,
99
+ status_filter: str = None,
100
+ limit: int = 10
101
+ ) -> str:
102
+ """
103
+ Search memories in the database.
104
+
105
+ Args:
106
+ query: Search query text
107
+ npc_name: Filter by specific NPC (optional)
108
+ team_name: Filter by specific team (optional)
109
+ directory_path: Filter by directory path (optional)
110
+ status_filter: Filter by memory status (active, archived, etc.)
111
+ limit: Maximum number of results to return
112
+
113
+ Returns:
114
+ JSON string of matching memories or error message
115
+ """
116
+ if directory_path is None:
117
+ directory_path = os.getcwd()
118
+
119
+ try:
120
+ results = command_history.search_memory(
121
+ query=query,
122
+ npc=npc_name,
123
+ team=team_name,
124
+ directory_path=directory_path,
125
+ status_filter=status_filter,
126
+ limit=limit
127
+ )
128
+ return json.dumps(results, indent=2)
129
+ except Exception as e:
130
+ return f"Error searching memories: {str(e)}"
131
+
132
+ @mcp.tool()
133
+ async def query_npcsh_database(sql_query: str) -> str:
134
+ """
135
+ Execute a SQL query against the npcsh_history.db database.
136
+
137
+ Args:
138
+ sql_query: SQL query to execute (SELECT statements only for safety)
139
+
140
+ Returns:
141
+ JSON string of query results or error message
142
+ """
143
+ # Safety check - only allow SELECT queries
144
+ if not sql_query.strip().upper().startswith('SELECT'):
145
+ return "Error: Only SELECT queries are allowed for safety"
146
+
147
+ try:
148
+ with command_history.engine.connect() as conn:
149
+ result = conn.execute(text(sql_query))
150
+ rows = result.fetchall()
151
+
152
+ if not rows:
153
+ return "Query executed successfully but returned no results"
154
+
155
+ # Convert to list of dictionaries
156
+ columns = result.keys()
157
+ results = []
158
+ for row in rows:
159
+ row_dict = dict(zip(columns, row))
160
+ results.append(row_dict)
161
+
162
+ return json.dumps(results, indent=2, default=str)
163
+ except Exception as e:
164
+ return f"Database query error: {str(e)}"
165
+ @mcp.tool()
166
+ async def run_server_command(command: str, wd: str) -> str:
52
167
  """
53
168
  Run a terminal command in the workspace.
54
169
 
55
170
  Args:
56
171
  command: The shell command to run
172
+ wd: The working directory to run the command in
57
173
 
58
174
  Returns:
59
175
  The command output or an error message.
@@ -61,7 +177,7 @@ async def run_server_command(command: str) -> str:
61
177
  try:
62
178
  result = subprocess.run(
63
179
  command,
64
- cwd=DEFAULT_WORKSPACE,
180
+ cwd=wd,
65
181
  shell=True,
66
182
  capture_output=True,
67
183
  text=True,
@@ -147,11 +263,7 @@ print("Loading tools from npcpy modules...")
147
263
 
148
264
 
149
265
  def register_selected_npcpy_tools():
150
- tools = [generate_group_candidates,
151
- abstract,
152
- extract_facts,
153
- zoom_in,
154
- execute_llm_command,
266
+ tools = [
155
267
  gen_image,
156
268
  load_file_contents,
157
269
  capture_screenshot,
npcsh/npc_team/corca.npc CHANGED
@@ -9,5 +9,4 @@ primary_directive: |
9
9
  You must distinguish carefully and when in doubt, opt to ask for further
10
10
  information or clarification with concrete clear options that make it
11
11
  easy for a user to choose.
12
- model: gpt-4o-mini
13
- provider: openai
12
+
@@ -0,0 +1,43 @@
1
+ jinx_name: search_kg
2
+ description: Search knowledge graph for relevant facts
3
+ inputs:
4
+ - query
5
+ steps:
6
+ - name: retrieve_facts
7
+ engine: python
8
+ code: |
9
+ from npcpy.memory.command_history import load_kg_from_db
10
+ import os
11
+
12
+ kg = load_kg_from_db(
13
+ command_history.engine,
14
+ team.name if team else '__none__',
15
+ npc.name if hasattr(npc, 'name') else '__none__',
16
+ os.getcwd()
17
+ )
18
+
19
+ query_lower = '{{ query }}'.lower()
20
+ matching_facts = []
21
+
22
+ if kg and 'facts' in kg:
23
+ for fact in kg['facts']:
24
+ statement = fact.get('statement', '').lower()
25
+ if query_lower in statement:
26
+ matching_facts.append(fact)
27
+
28
+ output = []
29
+ for i, fact in enumerate(matching_facts[:10], 1):
30
+ statement = fact.get('statement', '')
31
+ fact_type = fact.get('type', 'unknown')
32
+ output.append(f"{i}. [{fact_type}] {statement}")
33
+
34
+ output = "\n".join(output) if output else "No facts found"
35
+
36
+ - name: analyze_facts
37
+ engine: natural
38
+ code: |
39
+ Knowledge graph facts for query "{{ query }}":
40
+
41
+ {{ retrieve_facts }}
42
+
43
+ Analyze how these facts relate to the query.
@@ -0,0 +1,36 @@
1
+ jinx_name: search_memories
2
+ description: Search through approved memories for relevant context
3
+ inputs:
4
+ - query
5
+ steps:
6
+ - name: retrieve_memories
7
+ engine: python
8
+ code: |
9
+ from npcsh._state import get_relevant_memories
10
+ import os
11
+
12
+ memories = get_relevant_memories(
13
+ command_history=command_history,
14
+ npc_name=npc.name if hasattr(npc, 'name') else '__none__',
15
+ team_name=team.name if team else '__none__',
16
+ path=os.getcwd(),
17
+ query='{{ query }}',
18
+ max_memories=10,
19
+ state=state
20
+ )
21
+
22
+ output = []
23
+ for i, mem in enumerate(memories, 1):
24
+ content = mem.get('final_memory', mem.get('initial_memory', ''))
25
+ output.append(f"{i}. {content}")
26
+
27
+ output = "\n".join(output) if output else "No memories found"
28
+
29
+ - name: format_results
30
+ engine: natural
31
+ code: |
32
+ Found memories for query "{{ query }}":
33
+
34
+ {{ retrieve_memories }}
35
+
36
+ Summarize the key points from these memories.
npcsh/npcsh.py CHANGED
@@ -52,15 +52,22 @@ def print_welcome_message():
52
52
 
53
53
  print(
54
54
  """
55
+ ___________________________________________
56
+ ___________________________________________
57
+ ___________________________________________
58
+
55
59
  Welcome to \033[1;94mnpc\033[0m\033[1;38;5;202msh\033[0m!
56
60
  \033[1;94m \033[0m\033[1;38;5;202m _ \\\\
57
61
  \033[1;94m _ __ _ __ ___ \033[0m\033[1;38;5;202m ___ | |___ \\\\
58
- \033[1;94m| '_ \\ | ' \\ / __|\033[0m\033[1;38;5;202m / __/ | |_ _| \\\\
62
+ \033[1;94m| '_ \\ | '_ \\ / __|\033[0m\033[1;38;5;202m / __/ | |_ _| \\\\
59
63
  \033[1;94m| | | || |_) |( |__ \033[0m\033[1;38;5;202m \\_ \\ | | | | //
60
64
  \033[1;94m|_| |_|| .__/ \\___|\033[0m\033[1;38;5;202m |___/ |_| |_| //
61
- \033[1;94m| | \033[0m\033[1;38;5;202m //
62
- \033[1;94m| |
63
- \033[1;94m|_|
65
+ \033[1;94m|🤖| \033[0m\033[1;38;5;202m //
66
+ \033[1;94m|🤖|
67
+ \033[1;94m|🤖|
68
+ ___________________________________________
69
+ ___________________________________________
70
+ ___________________________________________
64
71
 
65
72
  Begin by asking a question, issuing a bash command, or typing '/help' for more information.
66
73
 
@@ -197,7 +204,9 @@ def run_repl(command_history: CommandHistory, initial_state: ShellState):
197
204
  state, output = execute_command(user_input,
198
205
  state,
199
206
  review = True,
200
- router=router)
207
+ router=router,
208
+ command_history=command_history)
209
+
201
210
  process_result(user_input,
202
211
  state,
203
212
  output,
@@ -9,5 +9,4 @@ primary_directive: |
9
9
  You must distinguish carefully and when in doubt, opt to ask for further
10
10
  information or clarification with concrete clear options that make it
11
11
  easy for a user to choose.
12
- model: gpt-4o-mini
13
- provider: openai
12
+
@@ -0,0 +1,43 @@
1
+ jinx_name: search_kg
2
+ description: Search knowledge graph for relevant facts
3
+ inputs:
4
+ - query
5
+ steps:
6
+ - name: retrieve_facts
7
+ engine: python
8
+ code: |
9
+ from npcpy.memory.command_history import load_kg_from_db
10
+ import os
11
+
12
+ kg = load_kg_from_db(
13
+ command_history.engine,
14
+ team.name if team else '__none__',
15
+ npc.name if hasattr(npc, 'name') else '__none__',
16
+ os.getcwd()
17
+ )
18
+
19
+ query_lower = '{{ query }}'.lower()
20
+ matching_facts = []
21
+
22
+ if kg and 'facts' in kg:
23
+ for fact in kg['facts']:
24
+ statement = fact.get('statement', '').lower()
25
+ if query_lower in statement:
26
+ matching_facts.append(fact)
27
+
28
+ output = []
29
+ for i, fact in enumerate(matching_facts[:10], 1):
30
+ statement = fact.get('statement', '')
31
+ fact_type = fact.get('type', 'unknown')
32
+ output.append(f"{i}. [{fact_type}] {statement}")
33
+
34
+ output = "\n".join(output) if output else "No facts found"
35
+
36
+ - name: analyze_facts
37
+ engine: natural
38
+ code: |
39
+ Knowledge graph facts for query "{{ query }}":
40
+
41
+ {{ retrieve_facts }}
42
+
43
+ Analyze how these facts relate to the query.
@@ -0,0 +1,36 @@
1
+ jinx_name: search_memories
2
+ description: Search through approved memories for relevant context
3
+ inputs:
4
+ - query
5
+ steps:
6
+ - name: retrieve_memories
7
+ engine: python
8
+ code: |
9
+ from npcsh._state import get_relevant_memories
10
+ import os
11
+
12
+ memories = get_relevant_memories(
13
+ command_history=command_history,
14
+ npc_name=npc.name if hasattr(npc, 'name') else '__none__',
15
+ team_name=team.name if team else '__none__',
16
+ path=os.getcwd(),
17
+ query='{{ query }}',
18
+ max_memories=10,
19
+ state=state
20
+ )
21
+
22
+ output = []
23
+ for i, mem in enumerate(memories, 1):
24
+ content = mem.get('final_memory', mem.get('initial_memory', ''))
25
+ output.append(f"{i}. {content}")
26
+
27
+ output = "\n".join(output) if output else "No memories found"
28
+
29
+ - name: format_results
30
+ engine: natural
31
+ code: |
32
+ Found memories for query "{{ query }}":
33
+
34
+ {{ retrieve_memories }}
35
+
36
+ Summarize the key points from these memories.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: npcsh
3
- Version: 1.0.36
3
+ Version: 1.1.1
4
4
  Summary: npcsh is a command-line toolkit for using AI agents in novel ways.
5
5
  Home-page: https://github.com/NPC-Worldwide/npcsh
6
6
  Author: Christopher Agostino
@@ -0,0 +1,77 @@
1
+ npcsh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ npcsh/_state.py,sha256=MNlQfrlF3zXe1WM_xOqSG5eCwLPJrr5SmSv1DycjFqk,97039
3
+ npcsh/alicanto.py,sha256=xcYlKZY6_NcnPUADosGKRuY5SVeZ_4msw82-fE2JZN8,42117
4
+ npcsh/corca.py,sha256=XoMsPMYMXRpj5izLdlrE-uKzPX49HaCVf-YnrVBtonQ,54815
5
+ npcsh/guac.py,sha256=sVdLYVkzkQw6TE7crtLUX0QJZFkzQthWZTe1p7IfAQE,80412
6
+ npcsh/mcp_helpers.py,sha256=9TsCfcquGu_vX4WaKlY3J3P13-uxruQKrXng-jJ5YyY,11176
7
+ npcsh/mcp_server.py,sha256=Lfpabnwi_xu0UudJxQ_YNyyCn2f0_JjzorhWmIeclwY,8777
8
+ npcsh/npc.py,sha256=OjCDu03hAcXyqPbzMeBBr1cBnmQsB1FBhd7kLNsWALc,8330
9
+ npcsh/npcsh.py,sha256=fNWgO3zCnHkjjzWKR8rBeaK6TcGGYwdG3uVq2CfPwi4,9180
10
+ npcsh/plonk.py,sha256=IfOuiE5FBvk-EIsrWFjGy0SrNywDpn4a49E7seBtEmY,14246
11
+ npcsh/pti.py,sha256=UciiiH2Kz4ERQFy0-FX6BQEU2VxYQEUril-_Cvj76Y0,7853
12
+ npcsh/routes.py,sha256=MMsHSoVp6r8OeoABO6stM4lSba4fOGz_QpzEIWS1nos,44437
13
+ npcsh/spool.py,sha256=oCive2dbn1o3UGUJnFMzfON6g4bOnauuzyyQBgul6RI,9839
14
+ npcsh/wander.py,sha256=8WOX8az8BXjizXGraEvu-ZVphi6PECKZzo9alTK4gmA,21730
15
+ npcsh/yap.py,sha256=QU-j9eg8zixXG6nyjoIYXsanJ4FjPnzhS4aJ241HLxw,18467
16
+ npcsh/npc_team/alicanto.npc,sha256=y9yDY3lq8ZwxQxpnrgle8w5IJwZqvxDepZFU4OaZCtg,148
17
+ npcsh/npc_team/alicanto.png,sha256=A7xeMbcoKGjlkELxJEVifCEZLVWbOKZarTN5ZFJG-FM,3519858
18
+ npcsh/npc_team/corca.npc,sha256=NtZW1mQ_AMOHlfMCfl8A3uA00UMuHuO95FzRg6kUixo,631
19
+ npcsh/npc_team/corca.png,sha256=0lF70hKu6tY-37YmIPVF2cuaPzvnQ4-UtQOzuAbKEf4,1666776
20
+ npcsh/npc_team/foreman.npc,sha256=WqB8jLfBToGmr8c1vip1KOnTHxfXlGXwDUGnZoDMQr0,327
21
+ npcsh/npc_team/frederic.npc,sha256=EE2dOUItp-VKuW3ZMSHffmIEO4evjPcU2W_C4P3WXbY,362
22
+ npcsh/npc_team/frederic4.png,sha256=ll8uoV0npnPp5HVJWv7h0xDSeuq4pqsk_gYGBHLS0VY,1590744
23
+ npcsh/npc_team/guac.png,sha256=MCE7eJuEJwLJEzc9FS7lL62Mm-38jQRHkxXogPfOTuw,211470
24
+ npcsh/npc_team/kadiefa.npc,sha256=Yl5a4wrfe4F2f6Ndw_ukzlVVX7NE9g_mG-3QqJSkg_o,381
25
+ npcsh/npc_team/kadiefa.png,sha256=3CAwL8crKIwJko6o75Z6OYYEEM9Rk--yGzCJg7zoszg,3062528
26
+ npcsh/npc_team/npcsh.ctx,sha256=-jKYaPm2YbZHAGgWAXhyPIwhiNe1H1ZRFg1Zc7tHSxk,1049
27
+ npcsh/npc_team/npcsh_sibiji.png,sha256=9fUqgYMsSHmaH-kBTBQ7N5UCS5-eLZF94Log0O3mtFg,4544
28
+ npcsh/npc_team/plonk.npc,sha256=u1m2a1D512XGQ2kC3eWDAY8Y2IvpkNU73DI_CPE65UE,90
29
+ npcsh/npc_team/plonk.png,sha256=IU5ey-Dl4HEKlwnf75RSWNSHpF8rVqGmdbsa0deL4rQ,2727773
30
+ npcsh/npc_team/plonkjr.npc,sha256=It-i-BEuG0XddKk0d85onk2aJr9Pe5pLnJzNaCWaQIM,87
31
+ npcsh/npc_team/plonkjr.png,sha256=MqLEGwsyECUeODZIti0HQQrMMVxA6XERpW01R06NbpY,2606710
32
+ npcsh/npc_team/sibiji.npc,sha256=Hb4wXKIObKKgibwnio5hLec9yd_9bKDCA87Nm2zijFA,216
33
+ npcsh/npc_team/sibiji.png,sha256=1dlZb7J3E62FcVo9CVOzLb8nu1bIUV7cr97nsFocHCM,35615
34
+ npcsh/npc_team/spool.png,sha256=LWTLkwDxXBfLuSUCX32_lo5yAmLYGsA67Xpsz-7MmWU,2876725
35
+ npcsh/npc_team/yap.png,sha256=_l7UbWnXJdsy4Mx-x5l9DT0R6ize3HTnkwQQnOFlI18,1548649
36
+ npcsh/npc_team/jinxs/bash_executer.jinx,sha256=C_oQccOY8cKevMMPLRdznlMOccQvLgyzyOIThXvmrD8,692
37
+ npcsh/npc_team/jinxs/edit_file.jinx,sha256=4PaJs8g_cdeDpbQwQSBycU5RDA0rczEC_NpLfLjo74Y,3490
38
+ npcsh/npc_team/jinxs/image_generation.jinx,sha256=bQxZdEm0_eqvf_OJSHw3qarp8Klp3LlBDv1_HY3COo4,1307
39
+ npcsh/npc_team/jinxs/internet_search.jinx,sha256=s8zVxwKFUAof_VzQrwB5dpAQdeJ6hUBkbIdRsT-I5mo,1267
40
+ npcsh/npc_team/jinxs/kg_search.jinx,sha256=zZiXLWtu9MwLn_HDEGmYfYF3ntfqbVqjM6IjhHyu634,1250
41
+ npcsh/npc_team/jinxs/memory_search.jinx,sha256=KoHA-FvZ325UQiBNnvnKboz2uIy4i1J6q55frybWPEM,1040
42
+ npcsh/npc_team/jinxs/python_executor.jinx,sha256=vZz3pZaj1BnPFHMs_wpyjRc0b32JR4rLhZfulCMDF1s,398
43
+ npcsh/npc_team/jinxs/screen_cap.jinx,sha256=-4DG0EiEe61N_kMhVqqHKhLVGOLuZQT9ax6IZk20NjI,960
44
+ npcsh-1.1.1.data/data/npcsh/npc_team/alicanto.npc,sha256=y9yDY3lq8ZwxQxpnrgle8w5IJwZqvxDepZFU4OaZCtg,148
45
+ npcsh-1.1.1.data/data/npcsh/npc_team/alicanto.png,sha256=A7xeMbcoKGjlkELxJEVifCEZLVWbOKZarTN5ZFJG-FM,3519858
46
+ npcsh-1.1.1.data/data/npcsh/npc_team/bash_executer.jinx,sha256=C_oQccOY8cKevMMPLRdznlMOccQvLgyzyOIThXvmrD8,692
47
+ npcsh-1.1.1.data/data/npcsh/npc_team/corca.npc,sha256=NtZW1mQ_AMOHlfMCfl8A3uA00UMuHuO95FzRg6kUixo,631
48
+ npcsh-1.1.1.data/data/npcsh/npc_team/corca.png,sha256=0lF70hKu6tY-37YmIPVF2cuaPzvnQ4-UtQOzuAbKEf4,1666776
49
+ npcsh-1.1.1.data/data/npcsh/npc_team/edit_file.jinx,sha256=4PaJs8g_cdeDpbQwQSBycU5RDA0rczEC_NpLfLjo74Y,3490
50
+ npcsh-1.1.1.data/data/npcsh/npc_team/foreman.npc,sha256=WqB8jLfBToGmr8c1vip1KOnTHxfXlGXwDUGnZoDMQr0,327
51
+ npcsh-1.1.1.data/data/npcsh/npc_team/frederic.npc,sha256=EE2dOUItp-VKuW3ZMSHffmIEO4evjPcU2W_C4P3WXbY,362
52
+ npcsh-1.1.1.data/data/npcsh/npc_team/frederic4.png,sha256=ll8uoV0npnPp5HVJWv7h0xDSeuq4pqsk_gYGBHLS0VY,1590744
53
+ npcsh-1.1.1.data/data/npcsh/npc_team/guac.png,sha256=MCE7eJuEJwLJEzc9FS7lL62Mm-38jQRHkxXogPfOTuw,211470
54
+ npcsh-1.1.1.data/data/npcsh/npc_team/image_generation.jinx,sha256=bQxZdEm0_eqvf_OJSHw3qarp8Klp3LlBDv1_HY3COo4,1307
55
+ npcsh-1.1.1.data/data/npcsh/npc_team/internet_search.jinx,sha256=s8zVxwKFUAof_VzQrwB5dpAQdeJ6hUBkbIdRsT-I5mo,1267
56
+ npcsh-1.1.1.data/data/npcsh/npc_team/kadiefa.npc,sha256=Yl5a4wrfe4F2f6Ndw_ukzlVVX7NE9g_mG-3QqJSkg_o,381
57
+ npcsh-1.1.1.data/data/npcsh/npc_team/kadiefa.png,sha256=3CAwL8crKIwJko6o75Z6OYYEEM9Rk--yGzCJg7zoszg,3062528
58
+ npcsh-1.1.1.data/data/npcsh/npc_team/kg_search.jinx,sha256=zZiXLWtu9MwLn_HDEGmYfYF3ntfqbVqjM6IjhHyu634,1250
59
+ npcsh-1.1.1.data/data/npcsh/npc_team/memory_search.jinx,sha256=KoHA-FvZ325UQiBNnvnKboz2uIy4i1J6q55frybWPEM,1040
60
+ npcsh-1.1.1.data/data/npcsh/npc_team/npcsh.ctx,sha256=-jKYaPm2YbZHAGgWAXhyPIwhiNe1H1ZRFg1Zc7tHSxk,1049
61
+ npcsh-1.1.1.data/data/npcsh/npc_team/npcsh_sibiji.png,sha256=9fUqgYMsSHmaH-kBTBQ7N5UCS5-eLZF94Log0O3mtFg,4544
62
+ npcsh-1.1.1.data/data/npcsh/npc_team/plonk.npc,sha256=u1m2a1D512XGQ2kC3eWDAY8Y2IvpkNU73DI_CPE65UE,90
63
+ npcsh-1.1.1.data/data/npcsh/npc_team/plonk.png,sha256=IU5ey-Dl4HEKlwnf75RSWNSHpF8rVqGmdbsa0deL4rQ,2727773
64
+ npcsh-1.1.1.data/data/npcsh/npc_team/plonkjr.npc,sha256=It-i-BEuG0XddKk0d85onk2aJr9Pe5pLnJzNaCWaQIM,87
65
+ npcsh-1.1.1.data/data/npcsh/npc_team/plonkjr.png,sha256=MqLEGwsyECUeODZIti0HQQrMMVxA6XERpW01R06NbpY,2606710
66
+ npcsh-1.1.1.data/data/npcsh/npc_team/python_executor.jinx,sha256=vZz3pZaj1BnPFHMs_wpyjRc0b32JR4rLhZfulCMDF1s,398
67
+ npcsh-1.1.1.data/data/npcsh/npc_team/screen_cap.jinx,sha256=-4DG0EiEe61N_kMhVqqHKhLVGOLuZQT9ax6IZk20NjI,960
68
+ npcsh-1.1.1.data/data/npcsh/npc_team/sibiji.npc,sha256=Hb4wXKIObKKgibwnio5hLec9yd_9bKDCA87Nm2zijFA,216
69
+ npcsh-1.1.1.data/data/npcsh/npc_team/sibiji.png,sha256=1dlZb7J3E62FcVo9CVOzLb8nu1bIUV7cr97nsFocHCM,35615
70
+ npcsh-1.1.1.data/data/npcsh/npc_team/spool.png,sha256=LWTLkwDxXBfLuSUCX32_lo5yAmLYGsA67Xpsz-7MmWU,2876725
71
+ npcsh-1.1.1.data/data/npcsh/npc_team/yap.png,sha256=_l7UbWnXJdsy4Mx-x5l9DT0R6ize3HTnkwQQnOFlI18,1548649
72
+ npcsh-1.1.1.dist-info/licenses/LICENSE,sha256=IKBvAECHP-aCiJtE4cHGCE5Yl0tozYz02PomGeWS3y4,1070
73
+ npcsh-1.1.1.dist-info/METADATA,sha256=1DQHEJY2KjNAeuNsdkFI92VvsOGqaFKs3LTk-D9qEhY,25485
74
+ npcsh-1.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
75
+ npcsh-1.1.1.dist-info/entry_points.txt,sha256=S5yIuGm8ZXQ4siHYgN5gs0J7bxgobSEULXf8L5HaW5o,206
76
+ npcsh-1.1.1.dist-info/top_level.txt,sha256=kHSNgKMCkfjV95-DH0YSp1LLBi0HXdF3w57j7MQON3E,6
77
+ npcsh-1.1.1.dist-info/RECORD,,
@@ -1,73 +0,0 @@
1
- npcsh/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- npcsh/_state.py,sha256=96NR32dMOytt1XIUvvO4CGODx3i4hMnaPJ-IlMJAMUE,93032
3
- npcsh/alicanto.py,sha256=xcYlKZY6_NcnPUADosGKRuY5SVeZ_4msw82-fE2JZN8,42117
4
- npcsh/corca.py,sha256=PasQqTEZ8OS1JD2Ow5qclGmCcsl89Ju9jK78bLPmbcA,54435
5
- npcsh/guac.py,sha256=sVdLYVkzkQw6TE7crtLUX0QJZFkzQthWZTe1p7IfAQE,80412
6
- npcsh/mcp_helpers.py,sha256=9TsCfcquGu_vX4WaKlY3J3P13-uxruQKrXng-jJ5YyY,11176
7
- npcsh/mcp_server.py,sha256=krc1rhiSU9gI76w99Ph3Mk7OyUVzfiEXKMvVid-7-Ik,5201
8
- npcsh/npc.py,sha256=OjCDu03hAcXyqPbzMeBBr1cBnmQsB1FBhd7kLNsWALc,8330
9
- npcsh/npcsh.py,sha256=3WLkZxHGzRekVGxHiJUA4VFyhC3A1jwX11aB0kgzE9s,8818
10
- npcsh/plonk.py,sha256=IfOuiE5FBvk-EIsrWFjGy0SrNywDpn4a49E7seBtEmY,14246
11
- npcsh/pti.py,sha256=UciiiH2Kz4ERQFy0-FX6BQEU2VxYQEUril-_Cvj76Y0,7853
12
- npcsh/routes.py,sha256=MMsHSoVp6r8OeoABO6stM4lSba4fOGz_QpzEIWS1nos,44437
13
- npcsh/spool.py,sha256=oCive2dbn1o3UGUJnFMzfON6g4bOnauuzyyQBgul6RI,9839
14
- npcsh/wander.py,sha256=8WOX8az8BXjizXGraEvu-ZVphi6PECKZzo9alTK4gmA,21730
15
- npcsh/yap.py,sha256=QU-j9eg8zixXG6nyjoIYXsanJ4FjPnzhS4aJ241HLxw,18467
16
- npcsh/npc_team/alicanto.npc,sha256=y9yDY3lq8ZwxQxpnrgle8w5IJwZqvxDepZFU4OaZCtg,148
17
- npcsh/npc_team/alicanto.png,sha256=A7xeMbcoKGjlkELxJEVifCEZLVWbOKZarTN5ZFJG-FM,3519858
18
- npcsh/npc_team/corca.npc,sha256=HI3Bs6KlUBPMz7icF1TRE8-V3f3EdU_VxvQxEpru3L4,662
19
- npcsh/npc_team/corca.png,sha256=0lF70hKu6tY-37YmIPVF2cuaPzvnQ4-UtQOzuAbKEf4,1666776
20
- npcsh/npc_team/foreman.npc,sha256=WqB8jLfBToGmr8c1vip1KOnTHxfXlGXwDUGnZoDMQr0,327
21
- npcsh/npc_team/frederic.npc,sha256=EE2dOUItp-VKuW3ZMSHffmIEO4evjPcU2W_C4P3WXbY,362
22
- npcsh/npc_team/frederic4.png,sha256=ll8uoV0npnPp5HVJWv7h0xDSeuq4pqsk_gYGBHLS0VY,1590744
23
- npcsh/npc_team/guac.png,sha256=MCE7eJuEJwLJEzc9FS7lL62Mm-38jQRHkxXogPfOTuw,211470
24
- npcsh/npc_team/kadiefa.npc,sha256=Yl5a4wrfe4F2f6Ndw_ukzlVVX7NE9g_mG-3QqJSkg_o,381
25
- npcsh/npc_team/kadiefa.png,sha256=3CAwL8crKIwJko6o75Z6OYYEEM9Rk--yGzCJg7zoszg,3062528
26
- npcsh/npc_team/npcsh.ctx,sha256=-jKYaPm2YbZHAGgWAXhyPIwhiNe1H1ZRFg1Zc7tHSxk,1049
27
- npcsh/npc_team/npcsh_sibiji.png,sha256=9fUqgYMsSHmaH-kBTBQ7N5UCS5-eLZF94Log0O3mtFg,4544
28
- npcsh/npc_team/plonk.npc,sha256=u1m2a1D512XGQ2kC3eWDAY8Y2IvpkNU73DI_CPE65UE,90
29
- npcsh/npc_team/plonk.png,sha256=IU5ey-Dl4HEKlwnf75RSWNSHpF8rVqGmdbsa0deL4rQ,2727773
30
- npcsh/npc_team/plonkjr.npc,sha256=It-i-BEuG0XddKk0d85onk2aJr9Pe5pLnJzNaCWaQIM,87
31
- npcsh/npc_team/plonkjr.png,sha256=MqLEGwsyECUeODZIti0HQQrMMVxA6XERpW01R06NbpY,2606710
32
- npcsh/npc_team/sibiji.npc,sha256=Hb4wXKIObKKgibwnio5hLec9yd_9bKDCA87Nm2zijFA,216
33
- npcsh/npc_team/sibiji.png,sha256=1dlZb7J3E62FcVo9CVOzLb8nu1bIUV7cr97nsFocHCM,35615
34
- npcsh/npc_team/spool.png,sha256=LWTLkwDxXBfLuSUCX32_lo5yAmLYGsA67Xpsz-7MmWU,2876725
35
- npcsh/npc_team/yap.png,sha256=_l7UbWnXJdsy4Mx-x5l9DT0R6ize3HTnkwQQnOFlI18,1548649
36
- npcsh/npc_team/jinxs/bash_executer.jinx,sha256=C_oQccOY8cKevMMPLRdznlMOccQvLgyzyOIThXvmrD8,692
37
- npcsh/npc_team/jinxs/edit_file.jinx,sha256=4PaJs8g_cdeDpbQwQSBycU5RDA0rczEC_NpLfLjo74Y,3490
38
- npcsh/npc_team/jinxs/image_generation.jinx,sha256=bQxZdEm0_eqvf_OJSHw3qarp8Klp3LlBDv1_HY3COo4,1307
39
- npcsh/npc_team/jinxs/internet_search.jinx,sha256=s8zVxwKFUAof_VzQrwB5dpAQdeJ6hUBkbIdRsT-I5mo,1267
40
- npcsh/npc_team/jinxs/python_executor.jinx,sha256=vZz3pZaj1BnPFHMs_wpyjRc0b32JR4rLhZfulCMDF1s,398
41
- npcsh/npc_team/jinxs/screen_cap.jinx,sha256=-4DG0EiEe61N_kMhVqqHKhLVGOLuZQT9ax6IZk20NjI,960
42
- npcsh-1.0.36.data/data/npcsh/npc_team/alicanto.npc,sha256=y9yDY3lq8ZwxQxpnrgle8w5IJwZqvxDepZFU4OaZCtg,148
43
- npcsh-1.0.36.data/data/npcsh/npc_team/alicanto.png,sha256=A7xeMbcoKGjlkELxJEVifCEZLVWbOKZarTN5ZFJG-FM,3519858
44
- npcsh-1.0.36.data/data/npcsh/npc_team/bash_executer.jinx,sha256=C_oQccOY8cKevMMPLRdznlMOccQvLgyzyOIThXvmrD8,692
45
- npcsh-1.0.36.data/data/npcsh/npc_team/corca.npc,sha256=HI3Bs6KlUBPMz7icF1TRE8-V3f3EdU_VxvQxEpru3L4,662
46
- npcsh-1.0.36.data/data/npcsh/npc_team/corca.png,sha256=0lF70hKu6tY-37YmIPVF2cuaPzvnQ4-UtQOzuAbKEf4,1666776
47
- npcsh-1.0.36.data/data/npcsh/npc_team/edit_file.jinx,sha256=4PaJs8g_cdeDpbQwQSBycU5RDA0rczEC_NpLfLjo74Y,3490
48
- npcsh-1.0.36.data/data/npcsh/npc_team/foreman.npc,sha256=WqB8jLfBToGmr8c1vip1KOnTHxfXlGXwDUGnZoDMQr0,327
49
- npcsh-1.0.36.data/data/npcsh/npc_team/frederic.npc,sha256=EE2dOUItp-VKuW3ZMSHffmIEO4evjPcU2W_C4P3WXbY,362
50
- npcsh-1.0.36.data/data/npcsh/npc_team/frederic4.png,sha256=ll8uoV0npnPp5HVJWv7h0xDSeuq4pqsk_gYGBHLS0VY,1590744
51
- npcsh-1.0.36.data/data/npcsh/npc_team/guac.png,sha256=MCE7eJuEJwLJEzc9FS7lL62Mm-38jQRHkxXogPfOTuw,211470
52
- npcsh-1.0.36.data/data/npcsh/npc_team/image_generation.jinx,sha256=bQxZdEm0_eqvf_OJSHw3qarp8Klp3LlBDv1_HY3COo4,1307
53
- npcsh-1.0.36.data/data/npcsh/npc_team/internet_search.jinx,sha256=s8zVxwKFUAof_VzQrwB5dpAQdeJ6hUBkbIdRsT-I5mo,1267
54
- npcsh-1.0.36.data/data/npcsh/npc_team/kadiefa.npc,sha256=Yl5a4wrfe4F2f6Ndw_ukzlVVX7NE9g_mG-3QqJSkg_o,381
55
- npcsh-1.0.36.data/data/npcsh/npc_team/kadiefa.png,sha256=3CAwL8crKIwJko6o75Z6OYYEEM9Rk--yGzCJg7zoszg,3062528
56
- npcsh-1.0.36.data/data/npcsh/npc_team/npcsh.ctx,sha256=-jKYaPm2YbZHAGgWAXhyPIwhiNe1H1ZRFg1Zc7tHSxk,1049
57
- npcsh-1.0.36.data/data/npcsh/npc_team/npcsh_sibiji.png,sha256=9fUqgYMsSHmaH-kBTBQ7N5UCS5-eLZF94Log0O3mtFg,4544
58
- npcsh-1.0.36.data/data/npcsh/npc_team/plonk.npc,sha256=u1m2a1D512XGQ2kC3eWDAY8Y2IvpkNU73DI_CPE65UE,90
59
- npcsh-1.0.36.data/data/npcsh/npc_team/plonk.png,sha256=IU5ey-Dl4HEKlwnf75RSWNSHpF8rVqGmdbsa0deL4rQ,2727773
60
- npcsh-1.0.36.data/data/npcsh/npc_team/plonkjr.npc,sha256=It-i-BEuG0XddKk0d85onk2aJr9Pe5pLnJzNaCWaQIM,87
61
- npcsh-1.0.36.data/data/npcsh/npc_team/plonkjr.png,sha256=MqLEGwsyECUeODZIti0HQQrMMVxA6XERpW01R06NbpY,2606710
62
- npcsh-1.0.36.data/data/npcsh/npc_team/python_executor.jinx,sha256=vZz3pZaj1BnPFHMs_wpyjRc0b32JR4rLhZfulCMDF1s,398
63
- npcsh-1.0.36.data/data/npcsh/npc_team/screen_cap.jinx,sha256=-4DG0EiEe61N_kMhVqqHKhLVGOLuZQT9ax6IZk20NjI,960
64
- npcsh-1.0.36.data/data/npcsh/npc_team/sibiji.npc,sha256=Hb4wXKIObKKgibwnio5hLec9yd_9bKDCA87Nm2zijFA,216
65
- npcsh-1.0.36.data/data/npcsh/npc_team/sibiji.png,sha256=1dlZb7J3E62FcVo9CVOzLb8nu1bIUV7cr97nsFocHCM,35615
66
- npcsh-1.0.36.data/data/npcsh/npc_team/spool.png,sha256=LWTLkwDxXBfLuSUCX32_lo5yAmLYGsA67Xpsz-7MmWU,2876725
67
- npcsh-1.0.36.data/data/npcsh/npc_team/yap.png,sha256=_l7UbWnXJdsy4Mx-x5l9DT0R6ize3HTnkwQQnOFlI18,1548649
68
- npcsh-1.0.36.dist-info/licenses/LICENSE,sha256=IKBvAECHP-aCiJtE4cHGCE5Yl0tozYz02PomGeWS3y4,1070
69
- npcsh-1.0.36.dist-info/METADATA,sha256=PU22LzEtIdClDgg_fCnc9yRRU-5c8E9CaR54AZs1d9A,25486
70
- npcsh-1.0.36.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
71
- npcsh-1.0.36.dist-info/entry_points.txt,sha256=S5yIuGm8ZXQ4siHYgN5gs0J7bxgobSEULXf8L5HaW5o,206
72
- npcsh-1.0.36.dist-info/top_level.txt,sha256=kHSNgKMCkfjV95-DH0YSp1LLBi0HXdF3w57j7MQON3E,6
73
- npcsh-1.0.36.dist-info/RECORD,,
File without changes