npcpy 1.0.26__py3-none-any.whl → 1.2.32__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.
- npcpy/__init__.py +0 -7
- npcpy/data/audio.py +16 -99
- npcpy/data/image.py +43 -42
- npcpy/data/load.py +83 -124
- npcpy/data/text.py +28 -28
- npcpy/data/video.py +8 -32
- npcpy/data/web.py +51 -23
- npcpy/ft/diff.py +110 -0
- npcpy/ft/ge.py +115 -0
- npcpy/ft/memory_trainer.py +171 -0
- npcpy/ft/model_ensembler.py +357 -0
- npcpy/ft/rl.py +360 -0
- npcpy/ft/sft.py +248 -0
- npcpy/ft/usft.py +128 -0
- npcpy/gen/audio_gen.py +24 -0
- npcpy/gen/embeddings.py +13 -13
- npcpy/gen/image_gen.py +262 -117
- npcpy/gen/response.py +615 -415
- npcpy/gen/video_gen.py +53 -7
- npcpy/llm_funcs.py +1869 -437
- npcpy/main.py +1 -1
- npcpy/memory/command_history.py +844 -510
- npcpy/memory/kg_vis.py +833 -0
- npcpy/memory/knowledge_graph.py +892 -1845
- npcpy/memory/memory_processor.py +81 -0
- npcpy/memory/search.py +188 -90
- npcpy/mix/debate.py +192 -3
- npcpy/npc_compiler.py +1672 -801
- npcpy/npc_sysenv.py +593 -1266
- npcpy/serve.py +3120 -0
- npcpy/sql/ai_function_tools.py +257 -0
- npcpy/sql/database_ai_adapters.py +186 -0
- npcpy/sql/database_ai_functions.py +163 -0
- npcpy/sql/model_runner.py +19 -19
- npcpy/sql/npcsql.py +706 -507
- npcpy/sql/sql_model_compiler.py +156 -0
- npcpy/tools.py +183 -0
- npcpy/work/plan.py +13 -279
- npcpy/work/trigger.py +3 -3
- npcpy-1.2.32.dist-info/METADATA +803 -0
- npcpy-1.2.32.dist-info/RECORD +54 -0
- npcpy/data/dataframes.py +0 -171
- npcpy/memory/deep_research.py +0 -125
- npcpy/memory/sleep.py +0 -557
- npcpy/modes/_state.py +0 -78
- npcpy/modes/alicanto.py +0 -1075
- npcpy/modes/guac.py +0 -785
- npcpy/modes/mcp_npcsh.py +0 -822
- npcpy/modes/npc.py +0 -213
- npcpy/modes/npcsh.py +0 -1158
- npcpy/modes/plonk.py +0 -409
- npcpy/modes/pti.py +0 -234
- npcpy/modes/serve.py +0 -1637
- npcpy/modes/spool.py +0 -312
- npcpy/modes/wander.py +0 -549
- npcpy/modes/yap.py +0 -572
- npcpy/npc_team/alicanto.npc +0 -2
- npcpy/npc_team/alicanto.png +0 -0
- npcpy/npc_team/assembly_lines/test_pipeline.py +0 -181
- npcpy/npc_team/corca.npc +0 -13
- npcpy/npc_team/foreman.npc +0 -7
- npcpy/npc_team/frederic.npc +0 -6
- npcpy/npc_team/frederic4.png +0 -0
- npcpy/npc_team/guac.png +0 -0
- npcpy/npc_team/jinxs/automator.jinx +0 -18
- npcpy/npc_team/jinxs/bash_executer.jinx +0 -31
- npcpy/npc_team/jinxs/calculator.jinx +0 -11
- npcpy/npc_team/jinxs/edit_file.jinx +0 -96
- npcpy/npc_team/jinxs/file_chat.jinx +0 -14
- npcpy/npc_team/jinxs/gui_controller.jinx +0 -28
- npcpy/npc_team/jinxs/image_generation.jinx +0 -29
- npcpy/npc_team/jinxs/internet_search.jinx +0 -30
- npcpy/npc_team/jinxs/local_search.jinx +0 -152
- npcpy/npc_team/jinxs/npcsh_executor.jinx +0 -31
- npcpy/npc_team/jinxs/python_executor.jinx +0 -8
- npcpy/npc_team/jinxs/screen_cap.jinx +0 -25
- npcpy/npc_team/jinxs/sql_executor.jinx +0 -33
- npcpy/npc_team/kadiefa.npc +0 -3
- npcpy/npc_team/kadiefa.png +0 -0
- npcpy/npc_team/npcsh.ctx +0 -9
- npcpy/npc_team/npcsh_sibiji.png +0 -0
- npcpy/npc_team/plonk.npc +0 -2
- npcpy/npc_team/plonk.png +0 -0
- npcpy/npc_team/plonkjr.npc +0 -2
- npcpy/npc_team/plonkjr.png +0 -0
- npcpy/npc_team/sibiji.npc +0 -5
- npcpy/npc_team/sibiji.png +0 -0
- npcpy/npc_team/spool.png +0 -0
- npcpy/npc_team/templates/analytics/celona.npc +0 -0
- npcpy/npc_team/templates/hr_support/raone.npc +0 -0
- npcpy/npc_team/templates/humanities/eriane.npc +0 -4
- npcpy/npc_team/templates/it_support/lineru.npc +0 -0
- npcpy/npc_team/templates/marketing/slean.npc +0 -4
- npcpy/npc_team/templates/philosophy/maurawa.npc +0 -0
- npcpy/npc_team/templates/sales/turnic.npc +0 -4
- npcpy/npc_team/templates/software/welxor.npc +0 -0
- npcpy/npc_team/yap.png +0 -0
- npcpy/routes.py +0 -958
- npcpy/work/mcp_helpers.py +0 -357
- npcpy/work/mcp_server.py +0 -194
- npcpy-1.0.26.data/data/npcpy/npc_team/alicanto.npc +0 -2
- npcpy-1.0.26.data/data/npcpy/npc_team/alicanto.png +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/automator.jinx +0 -18
- npcpy-1.0.26.data/data/npcpy/npc_team/bash_executer.jinx +0 -31
- npcpy-1.0.26.data/data/npcpy/npc_team/calculator.jinx +0 -11
- npcpy-1.0.26.data/data/npcpy/npc_team/celona.npc +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/corca.npc +0 -13
- npcpy-1.0.26.data/data/npcpy/npc_team/edit_file.jinx +0 -96
- npcpy-1.0.26.data/data/npcpy/npc_team/eriane.npc +0 -4
- npcpy-1.0.26.data/data/npcpy/npc_team/file_chat.jinx +0 -14
- npcpy-1.0.26.data/data/npcpy/npc_team/foreman.npc +0 -7
- npcpy-1.0.26.data/data/npcpy/npc_team/frederic.npc +0 -6
- npcpy-1.0.26.data/data/npcpy/npc_team/frederic4.png +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/guac.png +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/gui_controller.jinx +0 -28
- npcpy-1.0.26.data/data/npcpy/npc_team/image_generation.jinx +0 -29
- npcpy-1.0.26.data/data/npcpy/npc_team/internet_search.jinx +0 -30
- npcpy-1.0.26.data/data/npcpy/npc_team/kadiefa.npc +0 -3
- npcpy-1.0.26.data/data/npcpy/npc_team/kadiefa.png +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/lineru.npc +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/local_search.jinx +0 -152
- npcpy-1.0.26.data/data/npcpy/npc_team/maurawa.npc +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/npcsh.ctx +0 -9
- npcpy-1.0.26.data/data/npcpy/npc_team/npcsh_executor.jinx +0 -31
- npcpy-1.0.26.data/data/npcpy/npc_team/npcsh_sibiji.png +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/plonk.npc +0 -2
- npcpy-1.0.26.data/data/npcpy/npc_team/plonk.png +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/plonkjr.npc +0 -2
- npcpy-1.0.26.data/data/npcpy/npc_team/plonkjr.png +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/python_executor.jinx +0 -8
- npcpy-1.0.26.data/data/npcpy/npc_team/raone.npc +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/screen_cap.jinx +0 -25
- npcpy-1.0.26.data/data/npcpy/npc_team/sibiji.npc +0 -5
- npcpy-1.0.26.data/data/npcpy/npc_team/sibiji.png +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/slean.npc +0 -4
- npcpy-1.0.26.data/data/npcpy/npc_team/spool.png +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/sql_executor.jinx +0 -33
- npcpy-1.0.26.data/data/npcpy/npc_team/test_pipeline.py +0 -181
- npcpy-1.0.26.data/data/npcpy/npc_team/turnic.npc +0 -4
- npcpy-1.0.26.data/data/npcpy/npc_team/welxor.npc +0 -0
- npcpy-1.0.26.data/data/npcpy/npc_team/yap.png +0 -0
- npcpy-1.0.26.dist-info/METADATA +0 -827
- npcpy-1.0.26.dist-info/RECORD +0 -139
- npcpy-1.0.26.dist-info/entry_points.txt +0 -11
- /npcpy/{modes → ft}/__init__.py +0 -0
- {npcpy-1.0.26.dist-info → npcpy-1.2.32.dist-info}/WHEEL +0 -0
- {npcpy-1.0.26.dist-info → npcpy-1.2.32.dist-info}/licenses/LICENSE +0 -0
- {npcpy-1.0.26.dist-info → npcpy-1.2.32.dist-info}/top_level.txt +0 -0
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
jinx_name: file_editor
|
|
2
|
-
description: Examines a file, determines what changes are needed, and applies those
|
|
3
|
-
changes.
|
|
4
|
-
inputs:
|
|
5
|
-
- file_path
|
|
6
|
-
- edit_instructions
|
|
7
|
-
- backup: true
|
|
8
|
-
steps:
|
|
9
|
-
- name: "edit_file"
|
|
10
|
-
engine: "python"
|
|
11
|
-
code: |
|
|
12
|
-
import os
|
|
13
|
-
from npcpy.llm_funcs import get_llm_response
|
|
14
|
-
|
|
15
|
-
# Get inputs
|
|
16
|
-
file_path = os.path.expanduser("{{ file_path }}")
|
|
17
|
-
edit_instructions = "{{ edit_instructions }}"
|
|
18
|
-
backup_str = "{{ backup }}"
|
|
19
|
-
create_backup = backup_str.lower() not in ('false', 'no', '0', '')
|
|
20
|
-
|
|
21
|
-
# Read file content
|
|
22
|
-
with open(file_path, 'r') as f:
|
|
23
|
-
original_content = f.read()
|
|
24
|
-
|
|
25
|
-
# Create backup if requested
|
|
26
|
-
if create_backup:
|
|
27
|
-
backup_path = file_path + ".bak"
|
|
28
|
-
with open(backup_path, 'w') as f:
|
|
29
|
-
f.write(original_content)
|
|
30
|
-
|
|
31
|
-
# Make the prompt for the LLM
|
|
32
|
-
prompt = """You are a code editing assistant. Analyze this file and make the requested changes.
|
|
33
|
-
|
|
34
|
-
File content:
|
|
35
|
-
""" + original_content + """
|
|
36
|
-
|
|
37
|
-
Edit instructions: """ + edit_instructions + """
|
|
38
|
-
|
|
39
|
-
Return a JSON object with these fields:
|
|
40
|
-
1. "modifications": An array of modification objects, where each object has:
|
|
41
|
-
- "type": One of "replace", "insert_after", "insert_before", or "delete"
|
|
42
|
-
- "target": For "insert_after" and "insert_before", the text to insert after/before
|
|
43
|
-
For "delete", the text to delete
|
|
44
|
-
- "original": For "replace", the text to be replaced
|
|
45
|
-
- "replacement": For "replace", the text to replace with
|
|
46
|
-
- "insertion": For "insert_after" and "insert_before", the text to insert
|
|
47
|
-
2. "explanation": Brief explanation of the changes made
|
|
48
|
-
"""
|
|
49
|
-
print('getting llm response')
|
|
50
|
-
# Get the LLM response with JSON formatting
|
|
51
|
-
response = get_llm_response(prompt, model=npc.model, provider=npc.provider, npc=npc, format="json")
|
|
52
|
-
|
|
53
|
-
result = response.get("response", {})
|
|
54
|
-
modifications = result.get("modifications", [])
|
|
55
|
-
explanation = result.get("explanation", "No explanation provided")
|
|
56
|
-
|
|
57
|
-
# Apply modifications
|
|
58
|
-
updated_content = original_content
|
|
59
|
-
changes_applied = 0
|
|
60
|
-
|
|
61
|
-
for mod in modifications:
|
|
62
|
-
print(mod)
|
|
63
|
-
mod_type = mod.get("type")
|
|
64
|
-
|
|
65
|
-
if mod_type == "replace":
|
|
66
|
-
original = mod.get("original")
|
|
67
|
-
replacement = mod.get("replacement")
|
|
68
|
-
if original in updated_content:
|
|
69
|
-
updated_content = updated_content.replace(original, replacement)
|
|
70
|
-
changes_applied += 1
|
|
71
|
-
|
|
72
|
-
elif mod_type == "insert_after":
|
|
73
|
-
target = mod.get("target")
|
|
74
|
-
insertion = mod.get("insertion")
|
|
75
|
-
if target in updated_content:
|
|
76
|
-
updated_content = updated_content.replace(target, target + insertion)
|
|
77
|
-
changes_applied += 1
|
|
78
|
-
|
|
79
|
-
elif mod_type == "insert_before":
|
|
80
|
-
target = mod.get("target")
|
|
81
|
-
insertion = mod.get("insertion")
|
|
82
|
-
if target in updated_content:
|
|
83
|
-
updated_content = updated_content.replace(target, insertion + target)
|
|
84
|
-
changes_applied += 1
|
|
85
|
-
|
|
86
|
-
elif mod_type == "delete":
|
|
87
|
-
target = mod.get("target")
|
|
88
|
-
if target in updated_content:
|
|
89
|
-
updated_content = updated_content.replace(target, "")
|
|
90
|
-
changes_applied += 1
|
|
91
|
-
|
|
92
|
-
# Write the updated content
|
|
93
|
-
with open(file_path, 'w') as f:
|
|
94
|
-
f.write(updated_content)
|
|
95
|
-
|
|
96
|
-
output = "Applied " + str(changes_applied) + " changes to " + file_path + "\n\n" + explanation
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
name: eriane
|
|
2
|
-
primary_directive: you are an expert in the humanities and you must draw from your vast knowledge of history, literature, art, and philosophy to aid users in their requests, pulling real useful examples that can make users better understand results.
|
|
3
|
-
model: gpt-4o-mini
|
|
4
|
-
provider: openai
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
jinx_name: file_chat
|
|
2
|
-
description: Enter spool mode with a list of files that will be loaded in automatically
|
|
3
|
-
for rag for user responses.
|
|
4
|
-
inputs:
|
|
5
|
-
- files_list
|
|
6
|
-
steps:
|
|
7
|
-
- engine: python
|
|
8
|
-
code: |
|
|
9
|
-
from npcpy.modes.spool import enter_spool_mode
|
|
10
|
-
|
|
11
|
-
files_list = {{files_list}}
|
|
12
|
-
output = enter_spool_mode(
|
|
13
|
-
files = files_list
|
|
14
|
-
)
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
name: foreman
|
|
2
|
-
primary_directive: You are the foreman of an NPC team. It is your duty
|
|
3
|
-
to delegate tasks to your team members or to other specialized teams
|
|
4
|
-
in order to complete the project. You are responsible for the
|
|
5
|
-
completion of the project and the safety of your team members.
|
|
6
|
-
model: gpt-4o-mini
|
|
7
|
-
provider: openai
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
name: frederic
|
|
2
|
-
primary_directive: |
|
|
3
|
-
You are frederic the polar bear. Your job is help users think through problems and
|
|
4
|
-
to provide straightforward ways forward on problems. Cut through the ice
|
|
5
|
-
to get to what matters and keep things simple. You are to respond in a
|
|
6
|
-
witty tone like richard feynman but with the romantic tambor of Frederic Chopin.
|
|
Binary file
|
|
Binary file
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
jinx_name: gui_controller
|
|
2
|
-
description: Controls Guis by issuuing keyboard commands and key presses at certain
|
|
3
|
-
locations.
|
|
4
|
-
inputs:
|
|
5
|
-
- query
|
|
6
|
-
- provider: ''
|
|
7
|
-
steps:
|
|
8
|
-
- engine: "python"
|
|
9
|
-
code: |
|
|
10
|
-
from npcpy.data.web import search_web
|
|
11
|
-
from npcpy.npc_sysenv import NPCSH_SEARCH_PROVIDER
|
|
12
|
-
query = "{{ query }}"
|
|
13
|
-
provider = '{{ provider }}'
|
|
14
|
-
if provider.strip() != '':
|
|
15
|
-
results = search_web(query, num_results=5, provider = provider)
|
|
16
|
-
else:
|
|
17
|
-
results = search_web(query, num_results=5, provider = NPCSH_SEARCH_PROVIDER)
|
|
18
|
-
|
|
19
|
-
print('QUERY in jinx', query)
|
|
20
|
-
results = search_web(query, num_results=5, provider = NPCSH_SEARCH_PROVIDER)
|
|
21
|
-
print('RESULTS in jinx', results)
|
|
22
|
-
- engine: "natural"
|
|
23
|
-
code: |
|
|
24
|
-
Using the following information extracted from the web:
|
|
25
|
-
|
|
26
|
-
{{ results }}
|
|
27
|
-
|
|
28
|
-
Answer the users question: {{ query }}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
jinx_name: image_generation_jinx
|
|
2
|
-
description: 'Generates images based on a text prompt.'
|
|
3
|
-
inputs:
|
|
4
|
-
- prompt
|
|
5
|
-
- output_name
|
|
6
|
-
- model: runwayml/stable-diffusion-v1-5
|
|
7
|
-
- provider: diffusers
|
|
8
|
-
steps:
|
|
9
|
-
- engine: "python"
|
|
10
|
-
code: |
|
|
11
|
-
image_prompt = '{{prompt}}'.strip()
|
|
12
|
-
from npcpy.llm_funcs import gen_image
|
|
13
|
-
# Generate the image
|
|
14
|
-
pil_image = gen_image(
|
|
15
|
-
image_prompt,
|
|
16
|
-
npc=npc,
|
|
17
|
-
model='{{model}}', # You can adjust the model as needed
|
|
18
|
-
provider='{{provider}}'
|
|
19
|
-
)
|
|
20
|
-
if pil_image:
|
|
21
|
-
image_generated = True
|
|
22
|
-
else:
|
|
23
|
-
image_generated = False
|
|
24
|
-
# save the image
|
|
25
|
-
output_name = '{{output_name}}'
|
|
26
|
-
pil_image.save(f'{output_name}.png')
|
|
27
|
-
# open the image to display it
|
|
28
|
-
pil_image.show()
|
|
29
|
-
output = output_name
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
jinx_name: internet_search
|
|
2
|
-
description: Searches the web for information based on a query in order to verify
|
|
3
|
-
timiely details (e.g. current events) or to corroborate information in uncertain
|
|
4
|
-
situations. Should be mainly only used when users specifically request a search,
|
|
5
|
-
otherwise an LLMs basic knowledge should be sufficient.
|
|
6
|
-
inputs:
|
|
7
|
-
- query
|
|
8
|
-
- provider: ''
|
|
9
|
-
steps:
|
|
10
|
-
- engine: "python"
|
|
11
|
-
code: |
|
|
12
|
-
from npcpy.data.web import search_web
|
|
13
|
-
from npcpy.npc_sysenv import NPCSH_SEARCH_PROVIDER
|
|
14
|
-
query = "{{ query }}"
|
|
15
|
-
provider = '{{ provider }}'
|
|
16
|
-
if provider.strip() != '':
|
|
17
|
-
results = search_web(query, num_results=5, provider = provider)
|
|
18
|
-
else:
|
|
19
|
-
results = search_web(query, num_results=5, provider = NPCSH_SEARCH_PROVIDER)
|
|
20
|
-
|
|
21
|
-
print('QUERY in jinx', query)
|
|
22
|
-
results = search_web(query, num_results=5, provider = NPCSH_SEARCH_PROVIDER)
|
|
23
|
-
print('RESULTS in jinx', results)
|
|
24
|
-
- engine: "natural"
|
|
25
|
-
code: |
|
|
26
|
-
Using the following information extracted from the web:
|
|
27
|
-
|
|
28
|
-
{{ results }}
|
|
29
|
-
|
|
30
|
-
Answer the users question: {{ query }}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
name: kadiefa
|
|
2
|
-
primary_directive: |
|
|
3
|
-
You are kadiefa, the exploratory snow leopard. You love to find new paths and to explore hidden gems. You go into caverns no cat has ventured into before. You climb peaks that others call crazy. You are at the height of your power. Your role is to lead the way for users to explore complex research questions and to think outside of the box.
|
|
Binary file
|
|
File without changes
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
jinx_name: local_search`
|
|
2
|
-
description: 'Searches files in current and downstream directories to find items related
|
|
3
|
-
to the user''s query using fuzzy matching.
|
|
4
|
-
|
|
5
|
-
Returns only relevant snippets (10 lines around matches) to avoid including too
|
|
6
|
-
much irrelevant content.
|
|
7
|
-
|
|
8
|
-
Intended for fuzzy searches, not for understanding file sizes.'
|
|
9
|
-
inputs:
|
|
10
|
-
- query
|
|
11
|
-
- summarize: false
|
|
12
|
-
- file_filter: none
|
|
13
|
-
- depth: 2
|
|
14
|
-
- fuzzy_threshold: 70
|
|
15
|
-
steps:
|
|
16
|
-
- engine: python
|
|
17
|
-
code: |
|
|
18
|
-
# Search parameters are directly available
|
|
19
|
-
query = "{{ query }}"
|
|
20
|
-
file_filter = "{{ file_filter | default('None') }}"
|
|
21
|
-
if isinstance(file_filter, str) and file_filter.lower() == 'none':
|
|
22
|
-
file_filter = None
|
|
23
|
-
max_depth = {{ depth | default(2) }}
|
|
24
|
-
fuzzy_threshold = {{ fuzzy_threshold | default(70) }}
|
|
25
|
-
|
|
26
|
-
import os
|
|
27
|
-
import fnmatch
|
|
28
|
-
from pathlib import Path
|
|
29
|
-
from thefuzz import fuzz # Fuzzy string matching library
|
|
30
|
-
|
|
31
|
-
def find_files(file_filter=None, max_depth=2):
|
|
32
|
-
default_extensions = ['.py', '.txt', '.md',
|
|
33
|
-
'.json', '.yml', '.yaml',
|
|
34
|
-
'.log', '.csv', '.html',
|
|
35
|
-
'.js', '.css']
|
|
36
|
-
matches = []
|
|
37
|
-
root_path = Path('.').resolve() # Resolve to absolute path
|
|
38
|
-
|
|
39
|
-
# First, check files in the current directory
|
|
40
|
-
for path in root_path.iterdir():
|
|
41
|
-
if path.is_file():
|
|
42
|
-
# Skip hidden files
|
|
43
|
-
if path.name.startswith('.'):
|
|
44
|
-
continue
|
|
45
|
-
|
|
46
|
-
# If no filter specified, include files with default extensions
|
|
47
|
-
if file_filter is None:
|
|
48
|
-
if path.suffix in default_extensions:
|
|
49
|
-
matches.append(str(path))
|
|
50
|
-
else:
|
|
51
|
-
# If filter specified, check if file matches the filter
|
|
52
|
-
filters = [file_filter] if isinstance(file_filter, str) else file_filter
|
|
53
|
-
for f in filters:
|
|
54
|
-
if (fnmatch.fnmatch(path.name, f) or
|
|
55
|
-
fnmatch.fnmatch(str(path), f'*{f}*')):
|
|
56
|
-
matches.append(str(path))
|
|
57
|
-
break
|
|
58
|
-
|
|
59
|
-
# Then, check subdirectories with depth control
|
|
60
|
-
for path in root_path.rglob('*'):
|
|
61
|
-
# Skip hidden folders and common directories to ignore
|
|
62
|
-
if '/.' in str(path) or '__pycache__' in str(path) or '.git' in str(path) or 'node_modules' in str(path) or 'venv' in str(path):
|
|
63
|
-
continue
|
|
64
|
-
|
|
65
|
-
# Skip if we've gone too deep
|
|
66
|
-
relative_depth = len(path.relative_to(root_path).parts)
|
|
67
|
-
if relative_depth > max_depth:
|
|
68
|
-
continue
|
|
69
|
-
|
|
70
|
-
if path.is_file():
|
|
71
|
-
# If no filter specified, include files with default extensions
|
|
72
|
-
if file_filter is None:
|
|
73
|
-
if path.suffix in default_extensions:
|
|
74
|
-
matches.append(str(path))
|
|
75
|
-
else:
|
|
76
|
-
# If filter specified, check if file matches the filter
|
|
77
|
-
filters = [file_filter] if isinstance(file_filter, str) else file_filter
|
|
78
|
-
for f in filters:
|
|
79
|
-
if (fnmatch.fnmatch(path.name, f) or
|
|
80
|
-
fnmatch.fnmatch(str(path), f'*{f}*')):
|
|
81
|
-
matches.append(str(path))
|
|
82
|
-
break
|
|
83
|
-
|
|
84
|
-
return matches
|
|
85
|
-
|
|
86
|
-
# Find and load files
|
|
87
|
-
files = find_files(file_filter, max_depth)
|
|
88
|
-
|
|
89
|
-
# Process documents
|
|
90
|
-
relevant_chunks = []
|
|
91
|
-
for file_path in files:
|
|
92
|
-
with open(file_path, 'r', encoding='utf-8') as f:
|
|
93
|
-
lines = f.readlines() # Read file as lines
|
|
94
|
-
if lines:
|
|
95
|
-
# Join lines into a single string for fuzzy matching
|
|
96
|
-
content = ''.join(lines)
|
|
97
|
-
match_score = fuzz.partial_ratio(query.lower(), content.lower())
|
|
98
|
-
if match_score >= fuzzy_threshold:
|
|
99
|
-
# Find the best matching line
|
|
100
|
-
best_line_index = -1
|
|
101
|
-
best_line_score = 0
|
|
102
|
-
for i, line in enumerate(lines):
|
|
103
|
-
line_score = fuzz.partial_ratio(query.lower(), line.lower())
|
|
104
|
-
if line_score > best_line_score:
|
|
105
|
-
best_line_score = line_score
|
|
106
|
-
best_line_index = i
|
|
107
|
-
|
|
108
|
-
# Extract 10 lines around the best matching line
|
|
109
|
-
if best_line_index != -1:
|
|
110
|
-
start = max(0, best_line_index - 5) # 5 lines before
|
|
111
|
-
end = min(len(lines), best_line_index + 6) # 5 lines after
|
|
112
|
-
snippet = ''.join(lines[start:end])
|
|
113
|
-
relevant_chunks.append({
|
|
114
|
-
'path': file_path,
|
|
115
|
-
'snippet': snippet,
|
|
116
|
-
'ext': Path(file_path).suffix.lower(),
|
|
117
|
-
'score': match_score
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
# Sort results by match score (highest first)
|
|
121
|
-
relevant_chunks.sort(key=lambda x: x['score'], reverse=True)
|
|
122
|
-
|
|
123
|
-
# Format results
|
|
124
|
-
if relevant_chunks:
|
|
125
|
-
context_text = "Here are the most relevant code sections:\n\n"
|
|
126
|
-
for chunk in relevant_chunks:
|
|
127
|
-
file_path = chunk['path'].replace('./', '')
|
|
128
|
-
context_text += f"File: {file_path} (match score: {chunk['score']})\n"
|
|
129
|
-
context_text += f"```{chunk['ext'][1:] if chunk['ext'] else ''}\n"
|
|
130
|
-
context_text += f"{chunk['snippet'].strip()}\n"
|
|
131
|
-
context_text += "```\n\n"
|
|
132
|
-
else:
|
|
133
|
-
context_text = "No relevant code sections found.\n"
|
|
134
|
-
|
|
135
|
-
output = context_text
|
|
136
|
-
|
|
137
|
-
- engine: natural
|
|
138
|
-
code: |
|
|
139
|
-
{% if summarize %}
|
|
140
|
-
You are a helpful coding assistant.
|
|
141
|
-
Please help with this query:
|
|
142
|
-
|
|
143
|
-
`{{ query }}`
|
|
144
|
-
|
|
145
|
-
The user is attempting to carry out a local search. This search returned the following results:
|
|
146
|
-
|
|
147
|
-
`{{ results }}`
|
|
148
|
-
|
|
149
|
-
Please analyze the code sections above and provide a clear, helpful response that directly addresses the query.
|
|
150
|
-
If you reference specific files or code sections in your response, indicate which file they came from.
|
|
151
|
-
Make sure to explain your reasoning and how the provided code relates to the query.
|
|
152
|
-
{% endif %}
|
|
File without changes
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
context: |
|
|
2
|
-
The npcsh NPC team is devoted to providing a safe and helpful
|
|
3
|
-
environment for users where they can work and be as successful as possible.
|
|
4
|
-
npcsh is a command-line tool that makes it easy for users to harness
|
|
5
|
-
the power of LLMs from a command line shell.
|
|
6
|
-
databases:
|
|
7
|
-
- ~/npcsh_history.db
|
|
8
|
-
mcp_servers:
|
|
9
|
-
- ~/.npcsh/mcp_server.py
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
jinx_name: npcsh_executor
|
|
2
|
-
description: Issue npc shell requests. Uses one of the NPC macros.
|
|
3
|
-
inputs:
|
|
4
|
-
- request
|
|
5
|
-
steps:
|
|
6
|
-
- name: 'get_command_help'
|
|
7
|
-
engine: 'python'
|
|
8
|
-
code: |
|
|
9
|
-
from npcpy.routes import router, get_help_text
|
|
10
|
-
router_info = get_help_text()
|
|
11
|
-
output = router_info
|
|
12
|
-
- name: 'generate_npc_command'
|
|
13
|
-
engine: 'natural'
|
|
14
|
-
code: |
|
|
15
|
-
Based on the output: {{output}}
|
|
16
|
-
|
|
17
|
-
generate a npcsh command that can be executed to satisfy this user request:
|
|
18
|
-
{{request}}
|
|
19
|
-
Do not include any other comments, Your response should only be
|
|
20
|
-
|
|
21
|
-
the command string verbatim like '/<command> args --kwargs
|
|
22
|
-
- name: 'run command'
|
|
23
|
-
engine: 'python'
|
|
24
|
-
code: |
|
|
25
|
-
from npcpy.modes.npcsh import execute_slash_command
|
|
26
|
-
from npcpy.modes._state import initial_state
|
|
27
|
-
|
|
28
|
-
llm_response = '{{generate_npc_command}}'
|
|
29
|
-
llm_response = llm_response[1:]
|
|
30
|
-
response = execute_slash_command(llm_response, None, initial_state, False)
|
|
31
|
-
output = response[1]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
jinx_name: screen_capture_analysis_jinx
|
|
2
|
-
description: Captures the whole screen and sends the image for analysis
|
|
3
|
-
inputs:
|
|
4
|
-
- prompt
|
|
5
|
-
steps:
|
|
6
|
-
- engine: "python"
|
|
7
|
-
code: |
|
|
8
|
-
import os
|
|
9
|
-
from npcpy.data.image import capture_screenshot
|
|
10
|
-
out = capture_screenshot(full=True)
|
|
11
|
-
prompt = "{{prompt}}"
|
|
12
|
-
# Now properly use get_llm_response to analyze the image
|
|
13
|
-
# Create a prompt that includes the user's request and instructions
|
|
14
|
-
analysis_prompt = prompt + "\n\nAttached is a screenshot of my screen currently. Please use this to evaluate the situation. If the user asked for you to explain what's on their screen or something similar, they are referring to the details contained within the attached image."
|
|
15
|
-
llm_response = get_llm_response(
|
|
16
|
-
prompt=analysis_prompt,
|
|
17
|
-
model=npc.model if npc else None,
|
|
18
|
-
provider=npc.provider if npc else None,
|
|
19
|
-
api_url=npc.api_url if npc else None,
|
|
20
|
-
api_key=npc.api_key if npc else None,
|
|
21
|
-
npc=npc,
|
|
22
|
-
images=[out['file_path']],
|
|
23
|
-
)
|
|
24
|
-
output = llm_response['response']
|
|
25
|
-
|
|
Binary file
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
name: slean
|
|
2
|
-
primary_directive: Assist with marketing issues, challenges and questions. When responding, be careful to always think through the problems as if you are a wmarketing wiz who has launched and hyper scaled companies through effective marketing by always thinking outside the box.
|
|
3
|
-
model: gpt-4o-mini
|
|
4
|
-
provider: openai
|
|
Binary file
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
jinx_name: data_pull
|
|
2
|
-
description: Execute queries on the ~/npcsh_history.db to pull data. The database
|
|
3
|
-
contains only information about conversations and other user-provided data. It does
|
|
4
|
-
not store any information about individual files. Avoid using percent signs unless absolutely necessary.
|
|
5
|
-
inputs:
|
|
6
|
-
- sql_query
|
|
7
|
-
- user_query
|
|
8
|
-
- interpret: true
|
|
9
|
-
steps:
|
|
10
|
-
- engine: python
|
|
11
|
-
code: |
|
|
12
|
-
import pandas as pd
|
|
13
|
-
query = "{{ sql_query }}"
|
|
14
|
-
print('HEY', query, type(query))
|
|
15
|
-
try:
|
|
16
|
-
df = pd.read_sql_query(query, npc.db_conn)
|
|
17
|
-
except Exception as e:
|
|
18
|
-
df = pd.DataFrame({'Error': [str(e)]})
|
|
19
|
-
output = df.to_string()
|
|
20
|
-
|
|
21
|
-
- engine: natural
|
|
22
|
-
code: |
|
|
23
|
-
{% if interpret %}
|
|
24
|
-
Here is the result of the SQL query:
|
|
25
|
-
```
|
|
26
|
-
{{ df.to_string()[:10000] }} # Convert DataFrame to string for a nicer display, avoid doing more than 10000 in case data pull is huge
|
|
27
|
-
```
|
|
28
|
-
Please interpret the results according to the query:
|
|
29
|
-
{{user_query}}
|
|
30
|
-
Do not leave any information out it is critical that you directly address the user's full request.
|
|
31
|
-
|
|
32
|
-
{% endif %}
|
|
33
|
-
|