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.
Files changed (148) hide show
  1. npcpy/__init__.py +0 -7
  2. npcpy/data/audio.py +16 -99
  3. npcpy/data/image.py +43 -42
  4. npcpy/data/load.py +83 -124
  5. npcpy/data/text.py +28 -28
  6. npcpy/data/video.py +8 -32
  7. npcpy/data/web.py +51 -23
  8. npcpy/ft/diff.py +110 -0
  9. npcpy/ft/ge.py +115 -0
  10. npcpy/ft/memory_trainer.py +171 -0
  11. npcpy/ft/model_ensembler.py +357 -0
  12. npcpy/ft/rl.py +360 -0
  13. npcpy/ft/sft.py +248 -0
  14. npcpy/ft/usft.py +128 -0
  15. npcpy/gen/audio_gen.py +24 -0
  16. npcpy/gen/embeddings.py +13 -13
  17. npcpy/gen/image_gen.py +262 -117
  18. npcpy/gen/response.py +615 -415
  19. npcpy/gen/video_gen.py +53 -7
  20. npcpy/llm_funcs.py +1869 -437
  21. npcpy/main.py +1 -1
  22. npcpy/memory/command_history.py +844 -510
  23. npcpy/memory/kg_vis.py +833 -0
  24. npcpy/memory/knowledge_graph.py +892 -1845
  25. npcpy/memory/memory_processor.py +81 -0
  26. npcpy/memory/search.py +188 -90
  27. npcpy/mix/debate.py +192 -3
  28. npcpy/npc_compiler.py +1672 -801
  29. npcpy/npc_sysenv.py +593 -1266
  30. npcpy/serve.py +3120 -0
  31. npcpy/sql/ai_function_tools.py +257 -0
  32. npcpy/sql/database_ai_adapters.py +186 -0
  33. npcpy/sql/database_ai_functions.py +163 -0
  34. npcpy/sql/model_runner.py +19 -19
  35. npcpy/sql/npcsql.py +706 -507
  36. npcpy/sql/sql_model_compiler.py +156 -0
  37. npcpy/tools.py +183 -0
  38. npcpy/work/plan.py +13 -279
  39. npcpy/work/trigger.py +3 -3
  40. npcpy-1.2.32.dist-info/METADATA +803 -0
  41. npcpy-1.2.32.dist-info/RECORD +54 -0
  42. npcpy/data/dataframes.py +0 -171
  43. npcpy/memory/deep_research.py +0 -125
  44. npcpy/memory/sleep.py +0 -557
  45. npcpy/modes/_state.py +0 -78
  46. npcpy/modes/alicanto.py +0 -1075
  47. npcpy/modes/guac.py +0 -785
  48. npcpy/modes/mcp_npcsh.py +0 -822
  49. npcpy/modes/npc.py +0 -213
  50. npcpy/modes/npcsh.py +0 -1158
  51. npcpy/modes/plonk.py +0 -409
  52. npcpy/modes/pti.py +0 -234
  53. npcpy/modes/serve.py +0 -1637
  54. npcpy/modes/spool.py +0 -312
  55. npcpy/modes/wander.py +0 -549
  56. npcpy/modes/yap.py +0 -572
  57. npcpy/npc_team/alicanto.npc +0 -2
  58. npcpy/npc_team/alicanto.png +0 -0
  59. npcpy/npc_team/assembly_lines/test_pipeline.py +0 -181
  60. npcpy/npc_team/corca.npc +0 -13
  61. npcpy/npc_team/foreman.npc +0 -7
  62. npcpy/npc_team/frederic.npc +0 -6
  63. npcpy/npc_team/frederic4.png +0 -0
  64. npcpy/npc_team/guac.png +0 -0
  65. npcpy/npc_team/jinxs/automator.jinx +0 -18
  66. npcpy/npc_team/jinxs/bash_executer.jinx +0 -31
  67. npcpy/npc_team/jinxs/calculator.jinx +0 -11
  68. npcpy/npc_team/jinxs/edit_file.jinx +0 -96
  69. npcpy/npc_team/jinxs/file_chat.jinx +0 -14
  70. npcpy/npc_team/jinxs/gui_controller.jinx +0 -28
  71. npcpy/npc_team/jinxs/image_generation.jinx +0 -29
  72. npcpy/npc_team/jinxs/internet_search.jinx +0 -30
  73. npcpy/npc_team/jinxs/local_search.jinx +0 -152
  74. npcpy/npc_team/jinxs/npcsh_executor.jinx +0 -31
  75. npcpy/npc_team/jinxs/python_executor.jinx +0 -8
  76. npcpy/npc_team/jinxs/screen_cap.jinx +0 -25
  77. npcpy/npc_team/jinxs/sql_executor.jinx +0 -33
  78. npcpy/npc_team/kadiefa.npc +0 -3
  79. npcpy/npc_team/kadiefa.png +0 -0
  80. npcpy/npc_team/npcsh.ctx +0 -9
  81. npcpy/npc_team/npcsh_sibiji.png +0 -0
  82. npcpy/npc_team/plonk.npc +0 -2
  83. npcpy/npc_team/plonk.png +0 -0
  84. npcpy/npc_team/plonkjr.npc +0 -2
  85. npcpy/npc_team/plonkjr.png +0 -0
  86. npcpy/npc_team/sibiji.npc +0 -5
  87. npcpy/npc_team/sibiji.png +0 -0
  88. npcpy/npc_team/spool.png +0 -0
  89. npcpy/npc_team/templates/analytics/celona.npc +0 -0
  90. npcpy/npc_team/templates/hr_support/raone.npc +0 -0
  91. npcpy/npc_team/templates/humanities/eriane.npc +0 -4
  92. npcpy/npc_team/templates/it_support/lineru.npc +0 -0
  93. npcpy/npc_team/templates/marketing/slean.npc +0 -4
  94. npcpy/npc_team/templates/philosophy/maurawa.npc +0 -0
  95. npcpy/npc_team/templates/sales/turnic.npc +0 -4
  96. npcpy/npc_team/templates/software/welxor.npc +0 -0
  97. npcpy/npc_team/yap.png +0 -0
  98. npcpy/routes.py +0 -958
  99. npcpy/work/mcp_helpers.py +0 -357
  100. npcpy/work/mcp_server.py +0 -194
  101. npcpy-1.0.26.data/data/npcpy/npc_team/alicanto.npc +0 -2
  102. npcpy-1.0.26.data/data/npcpy/npc_team/alicanto.png +0 -0
  103. npcpy-1.0.26.data/data/npcpy/npc_team/automator.jinx +0 -18
  104. npcpy-1.0.26.data/data/npcpy/npc_team/bash_executer.jinx +0 -31
  105. npcpy-1.0.26.data/data/npcpy/npc_team/calculator.jinx +0 -11
  106. npcpy-1.0.26.data/data/npcpy/npc_team/celona.npc +0 -0
  107. npcpy-1.0.26.data/data/npcpy/npc_team/corca.npc +0 -13
  108. npcpy-1.0.26.data/data/npcpy/npc_team/edit_file.jinx +0 -96
  109. npcpy-1.0.26.data/data/npcpy/npc_team/eriane.npc +0 -4
  110. npcpy-1.0.26.data/data/npcpy/npc_team/file_chat.jinx +0 -14
  111. npcpy-1.0.26.data/data/npcpy/npc_team/foreman.npc +0 -7
  112. npcpy-1.0.26.data/data/npcpy/npc_team/frederic.npc +0 -6
  113. npcpy-1.0.26.data/data/npcpy/npc_team/frederic4.png +0 -0
  114. npcpy-1.0.26.data/data/npcpy/npc_team/guac.png +0 -0
  115. npcpy-1.0.26.data/data/npcpy/npc_team/gui_controller.jinx +0 -28
  116. npcpy-1.0.26.data/data/npcpy/npc_team/image_generation.jinx +0 -29
  117. npcpy-1.0.26.data/data/npcpy/npc_team/internet_search.jinx +0 -30
  118. npcpy-1.0.26.data/data/npcpy/npc_team/kadiefa.npc +0 -3
  119. npcpy-1.0.26.data/data/npcpy/npc_team/kadiefa.png +0 -0
  120. npcpy-1.0.26.data/data/npcpy/npc_team/lineru.npc +0 -0
  121. npcpy-1.0.26.data/data/npcpy/npc_team/local_search.jinx +0 -152
  122. npcpy-1.0.26.data/data/npcpy/npc_team/maurawa.npc +0 -0
  123. npcpy-1.0.26.data/data/npcpy/npc_team/npcsh.ctx +0 -9
  124. npcpy-1.0.26.data/data/npcpy/npc_team/npcsh_executor.jinx +0 -31
  125. npcpy-1.0.26.data/data/npcpy/npc_team/npcsh_sibiji.png +0 -0
  126. npcpy-1.0.26.data/data/npcpy/npc_team/plonk.npc +0 -2
  127. npcpy-1.0.26.data/data/npcpy/npc_team/plonk.png +0 -0
  128. npcpy-1.0.26.data/data/npcpy/npc_team/plonkjr.npc +0 -2
  129. npcpy-1.0.26.data/data/npcpy/npc_team/plonkjr.png +0 -0
  130. npcpy-1.0.26.data/data/npcpy/npc_team/python_executor.jinx +0 -8
  131. npcpy-1.0.26.data/data/npcpy/npc_team/raone.npc +0 -0
  132. npcpy-1.0.26.data/data/npcpy/npc_team/screen_cap.jinx +0 -25
  133. npcpy-1.0.26.data/data/npcpy/npc_team/sibiji.npc +0 -5
  134. npcpy-1.0.26.data/data/npcpy/npc_team/sibiji.png +0 -0
  135. npcpy-1.0.26.data/data/npcpy/npc_team/slean.npc +0 -4
  136. npcpy-1.0.26.data/data/npcpy/npc_team/spool.png +0 -0
  137. npcpy-1.0.26.data/data/npcpy/npc_team/sql_executor.jinx +0 -33
  138. npcpy-1.0.26.data/data/npcpy/npc_team/test_pipeline.py +0 -181
  139. npcpy-1.0.26.data/data/npcpy/npc_team/turnic.npc +0 -4
  140. npcpy-1.0.26.data/data/npcpy/npc_team/welxor.npc +0 -0
  141. npcpy-1.0.26.data/data/npcpy/npc_team/yap.png +0 -0
  142. npcpy-1.0.26.dist-info/METADATA +0 -827
  143. npcpy-1.0.26.dist-info/RECORD +0 -139
  144. npcpy-1.0.26.dist-info/entry_points.txt +0 -11
  145. /npcpy/{modes → ft}/__init__.py +0 -0
  146. {npcpy-1.0.26.dist-info → npcpy-1.2.32.dist-info}/WHEEL +0 -0
  147. {npcpy-1.0.26.dist-info → npcpy-1.2.32.dist-info}/licenses/LICENSE +0 -0
  148. {npcpy-1.0.26.dist-info → npcpy-1.2.32.dist-info}/top_level.txt +0 -0
@@ -1,181 +0,0 @@
1
- import pandas as pd
2
- from sqlalchemy import create_engine
3
- import os
4
-
5
- # Sample market events data
6
- market_events_data = {
7
- "datetime": [
8
- "2023-10-15 09:00:00",
9
- "2023-10-16 10:30:00",
10
- "2023-10-17 11:45:00",
11
- "2023-10-18 13:15:00",
12
- "2023-10-19 14:30:00",
13
- ],
14
- "headline": [
15
- "Stock Market Rallies Amid Positive Economic Data",
16
- "Tech Giant Announces New Product Line",
17
- "Federal Reserve Hints at Interest Rate Pause",
18
- "Oil Prices Surge Following Supply Concerns",
19
- "Retail Sector Reports Record Q3 Earnings",
20
- ],
21
- }
22
-
23
- # Create a DataFrame
24
- market_events_df = pd.DataFrame(market_events_data)
25
-
26
- # Define database path relative to user's home directory
27
- db_path = os.path.expanduser("~/npcsh_history.db")
28
-
29
- # Create a connection to the SQLite database
30
- engine = create_engine(f"sqlite:///{db_path}")
31
- with engine.connect() as connection:
32
- # Write the data to a new table 'market_events', replacing existing data
33
- market_events_df.to_sql(
34
- "market_events", con=connection, if_exists="replace", index=False
35
- )
36
-
37
- print("Market events have been added to the database.")
38
-
39
- email_data = {
40
- "datetime": [
41
- "2023-10-10 10:00:00",
42
- "2023-10-11 11:00:00",
43
- "2023-10-12 12:00:00",
44
- "2023-10-13 13:00:00",
45
- "2023-10-14 14:00:00",
46
- ],
47
- "subject": [
48
- "Meeting Reminder",
49
- "Project Update",
50
- "Invoice Attached",
51
- "Weekly Report",
52
- "Holiday Notice",
53
- ],
54
- "sender": [
55
- "alice@example.com",
56
- "bob@example.com",
57
- "carol@example.com",
58
- "dave@example.com",
59
- "eve@example.com",
60
- ],
61
- "recipient": [
62
- "bob@example.com",
63
- "carol@example.com",
64
- "dave@example.com",
65
- "eve@example.com",
66
- "alice@example.com",
67
- ],
68
- "body": [
69
- "Don't forget the meeting tomorrow at 10 AM.",
70
- "The project is progressing well, see attached update.",
71
- "Please find your invoice attached.",
72
- "Here is the weekly report.",
73
- "The office will be closed on holidays, have a great time!",
74
- ],
75
- }
76
-
77
- # Create a DataFrame
78
- emails_df = pd.DataFrame(email_data)
79
-
80
- # Define database path relative to user's home directory
81
- db_path = os.path.expanduser("~/npcsh_history.db")
82
-
83
- # Create a connection to the SQLite database
84
- engine = create_engine(f"sqlite:///{db_path}")
85
- with engine.connect() as connection:
86
- # Write the data to a new table 'emails', replacing existing data
87
- emails_df.to_sql("emails", con=connection, if_exists="replace", index=False)
88
-
89
- print("Sample emails have been added to the database.")
90
-
91
-
92
- from npcpy.npc_compiler import PipelineRunner
93
- import os
94
-
95
- pipeline_runner = PipelineRunner(
96
- pipeline_file="morning_routine.pipe",
97
- npc_root_dir=os.path.abspath("."), # Use absolute path to parent directory
98
- db_path="~/npcsh_history.db",
99
- )
100
- pipeline_runner.execute_pipeline()
101
-
102
-
103
- import pandas as pd
104
- from sqlalchemy import create_engine
105
- import os
106
-
107
- # Sample data generation for news articles
108
- news_articles_data = {
109
- "news_article_id": list(range(1, 21)),
110
- "headline": [
111
- "Economy sees unexpected growth in Q4",
112
- "New tech gadget takes the world by storm",
113
- "Political debate heats up over new policy",
114
- "Health concerns rise amid new disease outbreak",
115
- "Sports team secures victory in last minute",
116
- "New economic policy introduced by government",
117
- "Breakthrough in AI technology announced",
118
- "Political leader delivers speech on reforms",
119
- "Healthcare systems pushed to limits",
120
- "Celebrated athlete breaks world record",
121
- "Controversial economic measures spark debate",
122
- "Innovative tech startup gains traction",
123
- "Political scandal shakes administration",
124
- "Healthcare workers protest for better pay",
125
- "Major sports event postponed due to weather",
126
- "Trade tensions impact global economy",
127
- "Tech company accused of data breach",
128
- "Election results lead to political upheaval",
129
- "Vaccine developments offer hope amid pandemic",
130
- "Sports league announces return to action",
131
- ],
132
- "content": ["Article content here..." for _ in range(20)],
133
- "publication_date": pd.date_range(start="1/1/2023", periods=20, freq="D"),
134
- }
135
-
136
- # Create a DataFrame
137
- news_df = pd.DataFrame(news_articles_data)
138
-
139
- # Define the database path
140
- db_path = os.path.expanduser("~/npcsh_history.db")
141
-
142
- # Create a connection to the SQLite database
143
- engine = create_engine(f"sqlite:///{db_path}")
144
- with engine.connect() as connection:
145
- # Write the data to a new table 'news_articles', replacing existing data
146
- news_df.to_sql("news_articles", con=connection, if_exists="replace", index=False)
147
-
148
- print("News articles have been added to the database.")
149
-
150
- from npcpy.npc_compiler import PipelineRunner
151
- import os
152
-
153
- runner = PipelineRunner(
154
- "./news_analysis.pipe",
155
- db_path=os.path.expanduser("~/npcsh_history.db"),
156
- npc_root_dir=os.path.abspath("."),
157
- )
158
- results = runner.execute_pipeline()
159
-
160
- print("\nResults:")
161
- print("\nClassifications (processed row by row):")
162
- print(results["classify_news"])
163
- print("\nAnalysis (processed in batch):")
164
- print(results["analyze_news"])
165
-
166
-
167
- from npcpy.npc_compiler import PipelineRunner
168
- import os
169
-
170
- runner = PipelineRunner(
171
- "./news_analysis_mixa.pipe",
172
- db_path=os.path.expanduser("~/npcsh_history.db"),
173
- npc_root_dir=os.path.abspath("."),
174
- )
175
- results = runner.execute_pipeline()
176
-
177
- print("\nResults:")
178
- print("\nClassifications (processed row by row):")
179
- print(results["classify_news"])
180
- print("\nAnalysis (processed in batch):")
181
- print(results["analyze_news"])
npcpy/npc_team/corca.npc DELETED
@@ -1,13 +0,0 @@
1
- name: corca
2
- primary_directive: |
3
- You are corca, a distinguished member of the NPC team.
4
- Your expertise is in the area of software development and
5
- you have a kanck for thinking through problems carefully.
6
- You favor solutions that prioritize simplicity and clarity and
7
- ought to always consider how some suggestion may increase rather than reduce tech debt
8
- unnecessarily. Now, the key is in this last term, "unnecessarily".
9
- You must distinguish carefully and when in doubt, opt to ask for further
10
- information or clarification with concrete clear options that make it
11
- easy for a user to choose.
12
- model: gpt-4o-mini
13
- provider: openai
@@ -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
npcpy/npc_team/guac.png DELETED
Binary file
@@ -1,18 +0,0 @@
1
- jinx_name: automator
2
- description: Issue npc shell requests. Uses one of the NPC macros.
3
- inputs:
4
- - request
5
- - type
6
- steps:
7
- - engine: "python"
8
- code: |
9
- type = '{{type}}'
10
- request = '{{request}}'
11
- if type == 'plan':
12
- from npcpy.work.plan import execute_plan_command
13
- output = execute_plan_command(request, npc=npc)
14
- elif type == 'trigger':
15
- from npcpy.work.trigger import execute_trigger_command
16
- output = execute_trigger_command(request, npc=npc)
17
- else:
18
- raise ValueError("Invalid type. Must be 'plan' or 'trigger'.")
@@ -1,31 +0,0 @@
1
- jinx_name: bash_executor
2
- description: Execute bash queries.
3
- inputs:
4
- - bash_command
5
- - user_request
6
- steps:
7
- - engine: python
8
- code: |
9
- import subprocess
10
- import os
11
- cmd = '{{bash_command}}' # Properly quote the command input
12
- def run_command(cmd):
13
- process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
14
- stdout, stderr = process.communicate()
15
- if stderr:
16
- print(f"Error: {stderr.decode('utf-8')}")
17
- return stderr
18
- return stdout
19
- result = run_command(cmd)
20
- output = result.decode('utf-8')
21
-
22
- - engine: natural
23
- code: |
24
-
25
- Here is the result of the bash command:
26
- ```
27
- {{ output }}
28
- ```
29
- This was the original user request: {{ user_request }}
30
-
31
- Please provide a response accordingly.
@@ -1,11 +0,0 @@
1
- jinx_name: calculator
2
- description: A jinx to simplify and evaluate mathematical expressions
3
- inputs:
4
- - expression
5
- steps:
6
- - code: |
7
- expression = '{{ expression }}'.strip()
8
- output = eval(expression)
9
- print('Result:', output)
10
-
11
- engine: python
@@ -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,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,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,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 %}
@@ -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]
@@ -1,8 +0,0 @@
1
- jinx_name: python_executor
2
- description: Execute scripts with python. Set the ultimate result as the "output"
3
- variable. It must be a string. Do not add unnecessary print statements.
4
- inputs:
5
- - code
6
- steps:
7
- - code: '{{code}}'
8
- engine: python