npcsh 1.1.15__py3-none-any.whl → 1.1.17__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- npcsh/_state.py +69 -12
- npcsh/benchmark/__init__.py +22 -0
- npcsh/benchmark/npcsh_agent.py +262 -0
- npcsh/benchmark/runner.py +569 -0
- npcsh/npc_team/jinxs/bin/benchmark.jinx +146 -0
- npcsh/npc_team/jinxs/bin/nql.jinx +7 -7
- npcsh/npc_team/jinxs/bin/roll.jinx +20 -23
- npcsh/npc_team/jinxs/bin/sample.jinx +6 -7
- npcsh/npc_team/jinxs/bin/spool.jinx +4 -4
- npcsh/npc_team/jinxs/bin/sync.jinx +6 -6
- npcsh/npc_team/jinxs/bin/vixynt.jinx +8 -8
- npcsh/npc_team/jinxs/bin/wander.jinx +109 -19
- npcsh/npc_team/jinxs/bin/yap.jinx +5 -5
- npcsh/npc_team/jinxs/incognide/add_tab.jinx +11 -0
- npcsh/npc_team/jinxs/incognide/close_pane.jinx +9 -0
- npcsh/npc_team/jinxs/incognide/close_tab.jinx +10 -0
- npcsh/npc_team/jinxs/incognide/confirm.jinx +10 -0
- npcsh/npc_team/jinxs/incognide/focus_pane.jinx +9 -0
- npcsh/npc_team/jinxs/{npc_studio/npc-studio.jinx → incognide/incognide.jinx} +2 -2
- npcsh/npc_team/jinxs/incognide/list_panes.jinx +8 -0
- npcsh/npc_team/jinxs/incognide/navigate.jinx +10 -0
- npcsh/npc_team/jinxs/incognide/notify.jinx +10 -0
- npcsh/npc_team/jinxs/incognide/open_pane.jinx +13 -0
- npcsh/npc_team/jinxs/incognide/read_pane.jinx +9 -0
- npcsh/npc_team/jinxs/incognide/run_terminal.jinx +10 -0
- npcsh/npc_team/jinxs/incognide/send_message.jinx +10 -0
- npcsh/npc_team/jinxs/incognide/split_pane.jinx +12 -0
- npcsh/npc_team/jinxs/incognide/switch_npc.jinx +10 -0
- npcsh/npc_team/jinxs/incognide/switch_tab.jinx +10 -0
- npcsh/npc_team/jinxs/incognide/write_file.jinx +11 -0
- npcsh/npc_team/jinxs/incognide/zen_mode.jinx +9 -0
- npcsh/npc_team/jinxs/lib/browser/browser_action.jinx +4 -4
- npcsh/npc_team/jinxs/lib/browser/browser_screenshot.jinx +1 -1
- npcsh/npc_team/jinxs/lib/browser/open_browser.jinx +2 -2
- npcsh/npc_team/jinxs/lib/computer_use/click.jinx +2 -2
- npcsh/npc_team/jinxs/lib/computer_use/key_press.jinx +1 -1
- npcsh/npc_team/jinxs/lib/computer_use/launch_app.jinx +1 -1
- npcsh/npc_team/jinxs/lib/computer_use/screenshot.jinx +1 -1
- npcsh/npc_team/jinxs/lib/computer_use/trigger.jinx +2 -2
- npcsh/npc_team/jinxs/lib/computer_use/type_text.jinx +1 -1
- npcsh/npc_team/jinxs/lib/computer_use/wait.jinx +1 -1
- npcsh/npc_team/jinxs/lib/core/chat.jinx +4 -4
- npcsh/npc_team/jinxs/lib/core/cmd.jinx +4 -4
- npcsh/npc_team/jinxs/lib/core/compress.jinx +8 -8
- npcsh/npc_team/jinxs/lib/core/edit_file.jinx +3 -0
- npcsh/npc_team/jinxs/lib/core/ots.jinx +7 -7
- npcsh/npc_team/jinxs/lib/core/search/db_search.jinx +44 -0
- npcsh/npc_team/jinxs/lib/core/search/file_search.jinx +94 -0
- npcsh/npc_team/jinxs/lib/core/search/kg_search.jinx +96 -0
- npcsh/npc_team/jinxs/lib/core/search/mem_search.jinx +80 -0
- npcsh/npc_team/jinxs/lib/core/search/web_search.jinx +51 -0
- npcsh/npc_team/jinxs/lib/core/search.jinx +52 -129
- npcsh/npc_team/jinxs/lib/core/sh.jinx +1 -1
- npcsh/npc_team/jinxs/lib/core/sleep.jinx +7 -7
- npcsh/npc_team/jinxs/lib/core/sql.jinx +7 -7
- npcsh/npc_team/jinxs/lib/orchestration/convene.jinx +7 -7
- npcsh/npc_team/jinxs/lib/orchestration/delegate.jinx +8 -9
- npcsh/npc_team/jinxs/lib/research/arxiv.jinx +2 -2
- npcsh/npc_team/jinxs/lib/research/paper_search.jinx +3 -3
- npcsh/npc_team/jinxs/lib/research/semantic_scholar.jinx +2 -2
- npcsh/npc_team/jinxs/lib/utils/build.jinx +5 -5
- npcsh/npc_team/jinxs/lib/utils/compile.jinx +2 -2
- npcsh/npc_team/jinxs/lib/utils/help.jinx +1 -1
- npcsh/npc_team/jinxs/lib/utils/init.jinx +5 -5
- npcsh/npc_team/jinxs/lib/utils/jinxs.jinx +1 -1
- npcsh/npc_team/jinxs/lib/utils/serve.jinx +2 -2
- npcsh/npc_team/jinxs/lib/utils/set.jinx +2 -2
- npcsh/npc_team/jinxs/lib/utils/switch.jinx +3 -3
- npcsh/npc_team/jinxs/lib/utils/switches.jinx +1 -1
- npcsh/npc_team/jinxs/lib/utils/teamviz.jinx +2 -2
- npcsh/npc_team/sibiji.npc +1 -1
- npcsh/npcsh.py +81 -43
- npcsh-1.1.17.data/data/npcsh/npc_team/add_tab.jinx +11 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/arxiv.jinx +2 -2
- npcsh-1.1.17.data/data/npcsh/npc_team/benchmark.jinx +146 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/browser_action.jinx +4 -4
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/browser_screenshot.jinx +1 -1
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/build.jinx +5 -5
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/chat.jinx +4 -4
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/click.jinx +2 -2
- npcsh-1.1.17.data/data/npcsh/npc_team/close_pane.jinx +9 -0
- npcsh-1.1.17.data/data/npcsh/npc_team/close_tab.jinx +10 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/cmd.jinx +4 -4
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/compile.jinx +2 -2
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/compress.jinx +8 -8
- npcsh-1.1.17.data/data/npcsh/npc_team/confirm.jinx +10 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/convene.jinx +7 -7
- npcsh-1.1.17.data/data/npcsh/npc_team/db_search.jinx +44 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/delegate.jinx +8 -9
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/edit_file.jinx +3 -0
- npcsh-1.1.17.data/data/npcsh/npc_team/file_search.jinx +94 -0
- npcsh-1.1.17.data/data/npcsh/npc_team/focus_pane.jinx +9 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/help.jinx +1 -1
- npcsh-1.1.15.data/data/npcsh/npc_team/npc-studio.jinx → npcsh-1.1.17.data/data/npcsh/npc_team/incognide.jinx +2 -2
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/init.jinx +5 -5
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/jinxs.jinx +1 -1
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/key_press.jinx +1 -1
- npcsh-1.1.17.data/data/npcsh/npc_team/kg_search.jinx +96 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/launch_app.jinx +1 -1
- npcsh-1.1.17.data/data/npcsh/npc_team/list_panes.jinx +8 -0
- npcsh-1.1.17.data/data/npcsh/npc_team/mem_search.jinx +80 -0
- npcsh-1.1.17.data/data/npcsh/npc_team/navigate.jinx +10 -0
- npcsh-1.1.17.data/data/npcsh/npc_team/notify.jinx +10 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/nql.jinx +7 -7
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/open_browser.jinx +2 -2
- npcsh-1.1.17.data/data/npcsh/npc_team/open_pane.jinx +13 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/ots.jinx +7 -7
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/paper_search.jinx +3 -3
- npcsh-1.1.17.data/data/npcsh/npc_team/read_pane.jinx +9 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/roll.jinx +20 -23
- npcsh-1.1.17.data/data/npcsh/npc_team/run_terminal.jinx +10 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/sample.jinx +6 -7
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/screenshot.jinx +1 -1
- npcsh-1.1.17.data/data/npcsh/npc_team/search.jinx +54 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/semantic_scholar.jinx +2 -2
- npcsh-1.1.17.data/data/npcsh/npc_team/send_message.jinx +10 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/serve.jinx +2 -2
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/set.jinx +2 -2
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/sh.jinx +1 -1
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/sibiji.npc +1 -1
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/sleep.jinx +7 -7
- npcsh-1.1.17.data/data/npcsh/npc_team/split_pane.jinx +12 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/spool.jinx +4 -4
- npcsh-1.1.17.data/data/npcsh/npc_team/sql.jinx +16 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/switch.jinx +3 -3
- npcsh-1.1.17.data/data/npcsh/npc_team/switch_npc.jinx +10 -0
- npcsh-1.1.17.data/data/npcsh/npc_team/switch_tab.jinx +10 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/switches.jinx +1 -1
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/sync.jinx +6 -6
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/teamviz.jinx +2 -2
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/trigger.jinx +2 -2
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/type_text.jinx +1 -1
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/vixynt.jinx +8 -8
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/wait.jinx +1 -1
- npcsh-1.1.17.data/data/npcsh/npc_team/wander.jinx +242 -0
- npcsh-1.1.17.data/data/npcsh/npc_team/web_search.jinx +51 -0
- npcsh-1.1.17.data/data/npcsh/npc_team/write_file.jinx +11 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/yap.jinx +5 -5
- npcsh-1.1.17.data/data/npcsh/npc_team/zen_mode.jinx +9 -0
- {npcsh-1.1.15.dist-info → npcsh-1.1.17.dist-info}/METADATA +10 -7
- npcsh-1.1.17.dist-info/RECORD +219 -0
- {npcsh-1.1.15.dist-info → npcsh-1.1.17.dist-info}/entry_points.txt +2 -0
- npcsh-1.1.15.data/data/npcsh/npc_team/search.jinx +0 -131
- npcsh-1.1.15.data/data/npcsh/npc_team/sql.jinx +0 -16
- npcsh-1.1.15.data/data/npcsh/npc_team/wander.jinx +0 -152
- npcsh-1.1.15.dist-info/RECORD +0 -170
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/alicanto.npc +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/alicanto.png +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/close_browser.jinx +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/corca.npc +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/corca.png +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/corca_example.png +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/frederic.npc +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/frederic4.png +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/guac.npc +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/guac.png +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/kadiefa.npc +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/kadiefa.png +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/load_file.jinx +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/npcsh.ctx +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/npcsh_sibiji.png +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/paste.jinx +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/plonk.npc +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/plonk.png +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/plonkjr.npc +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/plonkjr.png +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/python.jinx +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/shh.jinx +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/sibiji.png +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/spool.png +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/usage.jinx +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/verbose.jinx +0 -0
- {npcsh-1.1.15.data → npcsh-1.1.17.data}/data/npcsh/npc_team/yap.png +0 -0
- {npcsh-1.1.15.dist-info → npcsh-1.1.17.dist-info}/WHEEL +0 -0
- {npcsh-1.1.15.dist-info → npcsh-1.1.17.dist-info}/licenses/LICENSE +0 -0
- {npcsh-1.1.15.dist-info → npcsh-1.1.17.dist-info}/top_level.txt +0 -0
npcsh/npcsh.py
CHANGED
|
@@ -180,51 +180,54 @@ def run_repl(command_history: CommandHistory, initial_state: ShellState, router,
|
|
|
180
180
|
def exit_shell(current_state: ShellState):
|
|
181
181
|
print("\nGoodbye!")
|
|
182
182
|
print(colored("Processing and archiving all session knowledge...", "cyan"))
|
|
183
|
-
|
|
184
|
-
engine = command_history.engine
|
|
185
183
|
|
|
186
|
-
|
|
187
|
-
try:
|
|
188
|
-
print(f" -> Archiving knowledge for: T='{team_name}', N='{npc_name}', P='{path}'")
|
|
189
|
-
|
|
190
|
-
convo_id = current_state.conversation_id
|
|
191
|
-
all_messages = command_history.get_conversations_by_id(convo_id)
|
|
192
|
-
|
|
193
|
-
scope_messages = [
|
|
194
|
-
m for m in all_messages
|
|
195
|
-
if m.get('directory_path') == path and m.get('team') == team_name and m.get('npc') == npc_name
|
|
196
|
-
]
|
|
197
|
-
|
|
198
|
-
full_text = "\n".join([f"{m['role']}: {m['content']}" for m in scope_messages if m.get('content')])
|
|
199
|
-
|
|
200
|
-
if not full_text.strip():
|
|
201
|
-
print(" ...No content for this scope, skipping.")
|
|
202
|
-
continue
|
|
184
|
+
engine = command_history.engine
|
|
203
185
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
186
|
+
try:
|
|
187
|
+
for team_name, npc_name, path in session_scopes:
|
|
188
|
+
try:
|
|
189
|
+
print(f" -> Archiving knowledge for: T='{team_name}', N='{npc_name}', P='{path}'")
|
|
190
|
+
|
|
191
|
+
convo_id = current_state.conversation_id
|
|
192
|
+
all_messages = command_history.get_conversations_by_id(convo_id)
|
|
193
|
+
|
|
194
|
+
scope_messages = [
|
|
195
|
+
m for m in all_messages
|
|
196
|
+
if m.get('directory_path') == path and m.get('team') == team_name and m.get('npc') == npc_name
|
|
197
|
+
]
|
|
198
|
+
|
|
199
|
+
full_text = "\n".join([f"{m['role']}: {m['content']}" for m in scope_messages if m.get('content')])
|
|
200
|
+
|
|
201
|
+
if not full_text.strip():
|
|
202
|
+
print(" ...No content for this scope, skipping.")
|
|
203
|
+
continue
|
|
204
|
+
|
|
205
|
+
current_kg = load_kg_from_db(engine, team_name, npc_name, path)
|
|
206
|
+
|
|
207
|
+
evolved_kg, _ = kg_evolve_incremental(
|
|
208
|
+
existing_kg=current_kg,
|
|
209
|
+
new_content_text=full_text,
|
|
210
|
+
model=current_state.npc.model,
|
|
211
|
+
provider=current_state.npc.provider,
|
|
212
|
+
npc= current_state.npc,
|
|
213
|
+
get_concepts=True,
|
|
214
|
+
link_concepts_facts = True,
|
|
215
|
+
link_concepts_concepts = True,
|
|
216
|
+
link_facts_facts = True,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
save_kg_to_db(engine,
|
|
220
|
+
evolved_kg,
|
|
221
|
+
team_name,
|
|
222
|
+
npc_name,
|
|
223
|
+
path)
|
|
224
|
+
|
|
225
|
+
except Exception as e:
|
|
226
|
+
import traceback
|
|
227
|
+
print(colored(f"Failed to process KG for scope ({team_name}, {npc_name}, {path}): {e}", "red"))
|
|
228
|
+
traceback.print_exc()
|
|
229
|
+
except KeyboardInterrupt:
|
|
230
|
+
print(colored("\nSkipping knowledge archival.", "yellow"))
|
|
228
231
|
|
|
229
232
|
sys.exit(0)
|
|
230
233
|
|
|
@@ -381,8 +384,43 @@ def main(npc_name: str = None) -> None:
|
|
|
381
384
|
parser.add_argument(
|
|
382
385
|
"-n", "--npc", type=str, help="Start with a specific NPC active."
|
|
383
386
|
)
|
|
387
|
+
parser.add_argument(
|
|
388
|
+
"--refresh", action="store_true", help="Force refresh of NPCs and jinxs from package."
|
|
389
|
+
)
|
|
384
390
|
args = parser.parse_args()
|
|
385
391
|
|
|
392
|
+
# Handle refresh flag - reset initialization and re-copy files
|
|
393
|
+
if args.refresh:
|
|
394
|
+
from npcsh._state import initialize_base_npcs_if_needed
|
|
395
|
+
import shutil
|
|
396
|
+
|
|
397
|
+
npcshrc_path = os.path.expanduser("~/.npcshrc")
|
|
398
|
+
if os.path.exists(npcshrc_path):
|
|
399
|
+
with open(npcshrc_path, "r") as f:
|
|
400
|
+
content = f.read()
|
|
401
|
+
content = content.replace("export NPCSH_INITIALIZED=1", "export NPCSH_INITIALIZED=0")
|
|
402
|
+
with open(npcshrc_path, "w") as f:
|
|
403
|
+
f.write(content)
|
|
404
|
+
|
|
405
|
+
os.environ["NPCSH_INITIALIZED"] = "0"
|
|
406
|
+
|
|
407
|
+
# Remove existing jinxs and NPCs to force fresh copy
|
|
408
|
+
user_npc_team = os.path.expanduser("~/.npcsh/npc_team")
|
|
409
|
+
jinxs_dir = os.path.join(user_npc_team, "jinxs")
|
|
410
|
+
if os.path.exists(jinxs_dir):
|
|
411
|
+
shutil.rmtree(jinxs_dir)
|
|
412
|
+
print("Cleared existing jinxs directory")
|
|
413
|
+
|
|
414
|
+
for f in os.listdir(user_npc_team) if os.path.exists(user_npc_team) else []:
|
|
415
|
+
if f.endswith(".npc"):
|
|
416
|
+
os.remove(os.path.join(user_npc_team, f))
|
|
417
|
+
print(f"Removed {f}")
|
|
418
|
+
|
|
419
|
+
db_path = os.path.expanduser("~/.npcsh/npcsh_history.db")
|
|
420
|
+
print("Reinitializing NPCs and jinxs...")
|
|
421
|
+
initialize_base_npcs_if_needed(db_path)
|
|
422
|
+
print("Refresh complete!")
|
|
423
|
+
|
|
386
424
|
command_history, team, default_npc = setup_shell()
|
|
387
425
|
|
|
388
426
|
if team and hasattr(team, 'jinxs_dict'):
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
jinx_name: benchmark
|
|
2
|
+
description: Run Terminal-Bench evaluation to benchmark npcsh performance with different models
|
|
3
|
+
inputs:
|
|
4
|
+
- model: ""
|
|
5
|
+
- provider: ""
|
|
6
|
+
- action: "check"
|
|
7
|
+
- concurrent: "4"
|
|
8
|
+
- npc_name: ""
|
|
9
|
+
|
|
10
|
+
steps:
|
|
11
|
+
- name: run_benchmark
|
|
12
|
+
engine: python
|
|
13
|
+
code: |
|
|
14
|
+
import os
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
action = {{ action | default("check") | tojson }}.strip().lower()
|
|
18
|
+
model = {{ model | default("") | tojson }}.strip()
|
|
19
|
+
provider = {{ provider | default("") | tojson }}.strip()
|
|
20
|
+
concurrent = int({{ concurrent | default("4") | tojson }} or "4")
|
|
21
|
+
npc_name_input = {{ npc_name | default("") | tojson }}.strip() or None
|
|
22
|
+
|
|
23
|
+
if not model:
|
|
24
|
+
model = npc.model if npc and npc.model
|
|
25
|
+
if not provider:
|
|
26
|
+
provider = npc.provider if npc and npc.provider else "anthropic"
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
from npcsh.benchmark import BenchmarkRunner, run_benchmark
|
|
30
|
+
BENCHMARK_AVAILABLE = True
|
|
31
|
+
except ImportError:
|
|
32
|
+
BENCHMARK_AVAILABLE = False
|
|
33
|
+
|
|
34
|
+
if action == "check":
|
|
35
|
+
output = "## Terminal-Bench Integration Status\n\n"
|
|
36
|
+
|
|
37
|
+
if not BENCHMARK_AVAILABLE:
|
|
38
|
+
output += "**Status:** Benchmark module not fully loaded (harbor not installed)\n\n"
|
|
39
|
+
else:
|
|
40
|
+
output += "**Status:** Ready\n\n"
|
|
41
|
+
|
|
42
|
+
if BENCHMARK_AVAILABLE:
|
|
43
|
+
runner = BenchmarkRunner()
|
|
44
|
+
deps = runner.check_dependencies()
|
|
45
|
+
output += "### Dependencies:\n"
|
|
46
|
+
for dep, installed in deps.items():
|
|
47
|
+
status = "Installed" if installed else "Not installed"
|
|
48
|
+
output += "- **{}**: {}\n".format(dep, status)
|
|
49
|
+
|
|
50
|
+
if not all(deps.values()):
|
|
51
|
+
output += "\n### Installation:\n"
|
|
52
|
+
output += "```bash\n"
|
|
53
|
+
output += "pip install harbor terminal-bench\n"
|
|
54
|
+
output += "```\n"
|
|
55
|
+
|
|
56
|
+
output += "\n### Usage:\n"
|
|
57
|
+
output += "```\n"
|
|
58
|
+
output += "/benchmark action=quick\n"
|
|
59
|
+
output += "/benchmark action=run model=gpt-4o provider=openai\n"
|
|
60
|
+
output += "/benchmark action=list\n"
|
|
61
|
+
output += "```\n"
|
|
62
|
+
|
|
63
|
+
elif action == "list":
|
|
64
|
+
if not BENCHMARK_AVAILABLE:
|
|
65
|
+
output = "Error: Benchmark module not available. Run `/benchmark` first."
|
|
66
|
+
else:
|
|
67
|
+
runner = BenchmarkRunner()
|
|
68
|
+
runs = runner.list_past_runs()
|
|
69
|
+
|
|
70
|
+
if not runs:
|
|
71
|
+
output = "No past benchmark runs found."
|
|
72
|
+
else:
|
|
73
|
+
output = "## Past Benchmark Runs ({} total)\n\n".format(len(runs))
|
|
74
|
+
for run in runs[:10]:
|
|
75
|
+
timestamp = run.get('timestamp', 'unknown')[:19]
|
|
76
|
+
model_name = run.get('model', 'unknown')
|
|
77
|
+
result = run.get('result', {})
|
|
78
|
+
accuracy = result.get('accuracy', 0)
|
|
79
|
+
passed = result.get('passed_tasks', 0)
|
|
80
|
+
total = result.get('total_tasks', 0)
|
|
81
|
+
|
|
82
|
+
output += "### {}\n".format(timestamp)
|
|
83
|
+
output += "- **Model:** {}\n".format(model_name)
|
|
84
|
+
output += "- **Accuracy:** {:.1%}\n".format(accuracy)
|
|
85
|
+
output += "- **Tasks:** {}/{}\n\n".format(passed, total)
|
|
86
|
+
|
|
87
|
+
elif action == "quick":
|
|
88
|
+
if not BENCHMARK_AVAILABLE:
|
|
89
|
+
output = "Error: Install with: pip install harbor terminal-bench"
|
|
90
|
+
else:
|
|
91
|
+
output = "## Quick Test: {}/{}\n\n".format(provider, model)
|
|
92
|
+
output += "Running quick test with 3 tasks...\n\n"
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
from npcsh.benchmark import quick_test
|
|
96
|
+
result = quick_test(model=model, provider=provider)
|
|
97
|
+
|
|
98
|
+
status = "PASS" if result.success else "FAIL"
|
|
99
|
+
output += "**Status:** {}\n".format(status)
|
|
100
|
+
output += "**Accuracy:** {:.1%}\n".format(result.accuracy)
|
|
101
|
+
output += "**Tasks:** {}/{}\n".format(result.passed_tasks, result.total_tasks)
|
|
102
|
+
output += "**Duration:** {:.1f}s\n".format(result.duration_seconds)
|
|
103
|
+
|
|
104
|
+
if result.error:
|
|
105
|
+
output += "\n**Error:** {}\n".format(result.error)
|
|
106
|
+
|
|
107
|
+
output += "\n**Output:** {}\n".format(result.output_dir)
|
|
108
|
+
|
|
109
|
+
except Exception as e:
|
|
110
|
+
output = "Error running quick test: {}".format(e)
|
|
111
|
+
|
|
112
|
+
elif action == "run":
|
|
113
|
+
if not BENCHMARK_AVAILABLE:
|
|
114
|
+
output = "Error: Install with: pip install harbor terminal-bench"
|
|
115
|
+
else:
|
|
116
|
+
output = "## Benchmark Run: {}/{}\n\n".format(provider, model)
|
|
117
|
+
output += "Running Terminal-Bench 2.0 with {} concurrent tasks...\n\n".format(concurrent)
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
runner = BenchmarkRunner()
|
|
121
|
+
result = runner.run(
|
|
122
|
+
model=model,
|
|
123
|
+
provider=provider,
|
|
124
|
+
n_concurrent=concurrent,
|
|
125
|
+
npc_name=npc_name_input,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
status = "SUCCESS" if result.success else "FAILED"
|
|
129
|
+
output += "**Status:** {}\n".format(status)
|
|
130
|
+
output += "**Accuracy:** {:.1%}\n".format(result.accuracy)
|
|
131
|
+
output += "**Tasks Passed:** {}/{}\n".format(result.passed_tasks, result.total_tasks)
|
|
132
|
+
output += "**Duration:** {:.1f}s\n".format(result.duration_seconds)
|
|
133
|
+
output += "**Total Tokens:** {:,}\n".format(result.total_tokens)
|
|
134
|
+
output += "**Total Cost:** ${:.4f}\n".format(result.total_cost_usd)
|
|
135
|
+
|
|
136
|
+
if result.error:
|
|
137
|
+
output += "\n**Error:** {}\n".format(result.error)
|
|
138
|
+
|
|
139
|
+
output += "\n**Results saved to:** {}\n".format(result.output_dir)
|
|
140
|
+
|
|
141
|
+
except Exception as e:
|
|
142
|
+
import traceback
|
|
143
|
+
output = "Error running benchmark: {}\n\n{}".format(e, traceback.format_exc())
|
|
144
|
+
|
|
145
|
+
else:
|
|
146
|
+
output = "Unknown action: {}\n\nAvailable: check, run, quick, list".format(action)
|
|
@@ -12,14 +12,14 @@ description: |
|
|
|
12
12
|
- get_page: Get page title, URL, and visible text
|
|
13
13
|
- get_elements: Get interactive elements with their selectors
|
|
14
14
|
- press_key: Press a key (enter, tab, escape, etc)
|
|
15
|
-
Selectors: CSS (
|
|
15
|
+
Selectors: CSS (
|
|
16
16
|
inputs:
|
|
17
|
-
|
|
17
|
+
- action:
|
|
18
18
|
description: "Action: click, type, type_and_enter, set_value, select, wait, scroll, get_text, get_page, get_elements, press_key"
|
|
19
|
-
|
|
19
|
+
- selector:
|
|
20
20
|
description: "CSS selector or XPath (prefix xpath: for XPath)"
|
|
21
21
|
default: ""
|
|
22
|
-
|
|
22
|
+
- value:
|
|
23
23
|
description: "Value for type/select, or scroll direction, or key name"
|
|
24
24
|
default: ""
|
|
25
25
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
jinx_name: "build"
|
|
2
2
|
description: "Build deployment artifacts for NPC team"
|
|
3
3
|
inputs:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
- target: "flask"
|
|
5
|
+
- outdir: "./build"
|
|
6
|
+
- team: "./npc_team"
|
|
7
|
+
- port: 5337
|
|
8
|
+
- cors: ""
|
|
9
9
|
steps:
|
|
10
10
|
- name: "execute_build"
|
|
11
11
|
engine: "python"
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
jinx_name: chat
|
|
2
2
|
description: Simple chat mode - LLM conversation without tool execution
|
|
3
3
|
inputs:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
- query: null
|
|
5
|
+
- model: null
|
|
6
|
+
- provider: null
|
|
7
|
+
- stream: true
|
|
8
8
|
|
|
9
9
|
steps:
|
|
10
10
|
- name: chat_response
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
jinx_name: studio.close_pane
|
|
2
|
+
description: Close a pane in NPC Studio. Use paneId="active" or omit to close the active pane.
|
|
3
|
+
inputs:
|
|
4
|
+
- paneId: "active"
|
|
5
|
+
steps:
|
|
6
|
+
- name: frontend_action
|
|
7
|
+
engine: python
|
|
8
|
+
code: |
|
|
9
|
+
context['output'] = "Action executed by frontend"
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
jinx_name: cmd
|
|
2
2
|
description: Command mode - LLM generates and executes shell commands
|
|
3
3
|
inputs:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
- query: null
|
|
5
|
+
- model: null
|
|
6
|
+
- provider: null
|
|
7
|
+
- stream: true
|
|
8
8
|
|
|
9
9
|
steps:
|
|
10
10
|
- name: cmd_execute
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
jinx_name: "compile"
|
|
2
2
|
description: "Compile NPC profiles"
|
|
3
3
|
inputs:
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
- npc_file_path: ""
|
|
5
|
+
- npc_team_dir: "./npc_team"
|
|
6
6
|
steps:
|
|
7
7
|
- name: "compile_npcs"
|
|
8
8
|
engine: "python"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
jinx_name: "compress"
|
|
2
2
|
description: "Manages conversation and knowledge context. Defaults to compacting context. Use flags for other operations."
|
|
3
3
|
inputs:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
- flush: ""
|
|
5
|
+
- sleep: False
|
|
6
|
+
- dream: False
|
|
7
|
+
- ops: ""
|
|
8
|
+
- model: ""
|
|
9
|
+
- provider: ""
|
|
10
10
|
steps:
|
|
11
11
|
- name: "manage_context_and_memory"
|
|
12
12
|
engine: "python"
|
|
@@ -53,8 +53,8 @@ steps:
|
|
|
53
53
|
operations_config = [op.strip() for op in operations_str.split(',')] if operations_str else None
|
|
54
54
|
if not llm_model and current_npc: llm_model = current_npc.model
|
|
55
55
|
if not llm_provider and current_npc: llm_provider = current_npc.provider
|
|
56
|
-
if not llm_model: llm_model = "
|
|
57
|
-
if not llm_provider: llm_provider = "
|
|
56
|
+
if not llm_model: llm_model = state.chat_model if state else "llama3.2"
|
|
57
|
+
if not llm_provider: llm_provider = state.chat_provider if state else "ollama"
|
|
58
58
|
|
|
59
59
|
team_name = current_team.name if current_team else "__none__"
|
|
60
60
|
npc_name = current_npc.name if current_npc else "__none__"
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
jinx_name: convene
|
|
2
2
|
description: Run a cycle of discussions between NPCs on a topic. The orchestrator convenes agents to discuss and synthesize.
|
|
3
3
|
inputs:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
- topic: ""
|
|
5
|
+
- npcs: "alicanto,corca,guac"
|
|
6
|
+
- rounds: 3
|
|
7
|
+
- model: null
|
|
8
|
+
- provider: null
|
|
9
9
|
steps:
|
|
10
10
|
- name: convene_discussion
|
|
11
11
|
engine: python
|
|
@@ -21,8 +21,8 @@ steps:
|
|
|
21
21
|
team = context.get('team')
|
|
22
22
|
messages = context.get('messages', [])
|
|
23
23
|
|
|
24
|
-
model = context.get('model') or (npc.model if npc else '
|
|
25
|
-
provider = context.get('provider') or (npc.provider if npc else '
|
|
24
|
+
model = context.get('model') or (npc.model if npc else (state.chat_model if state else 'llama3.2'))
|
|
25
|
+
provider = context.get('provider') or (npc.provider if npc else (state.chat_provider if state else 'ollama'))
|
|
26
26
|
|
|
27
27
|
if not topic:
|
|
28
28
|
context['output'] = """Usage: /convene <topic>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
jinx_name: db_search
|
|
2
|
+
description: Search conversation history database using brainblast
|
|
3
|
+
inputs:
|
|
4
|
+
- query: ""
|
|
5
|
+
- db_path: ""
|
|
6
|
+
- limit: "20"
|
|
7
|
+
|
|
8
|
+
steps:
|
|
9
|
+
- name: search_db
|
|
10
|
+
engine: python
|
|
11
|
+
code: |
|
|
12
|
+
import os
|
|
13
|
+
|
|
14
|
+
query = context.get('query', '').strip()
|
|
15
|
+
if not query:
|
|
16
|
+
lines = [
|
|
17
|
+
"Usage: /db_search <query>",
|
|
18
|
+
"",
|
|
19
|
+
"Searches conversation history using brainblast for semantic matching.",
|
|
20
|
+
"",
|
|
21
|
+
"Options:",
|
|
22
|
+
" db_path - Path to history database",
|
|
23
|
+
" limit - Max results to return (default 20)",
|
|
24
|
+
"",
|
|
25
|
+
"Examples:",
|
|
26
|
+
" /db_search python debugging",
|
|
27
|
+
" /db_search api errors limit=50",
|
|
28
|
+
]
|
|
29
|
+
context['output'] = "\n".join(lines)
|
|
30
|
+
else:
|
|
31
|
+
db_path = context.get('db_path') or os.path.expanduser("~/.npcsh/npcsh_history.db")
|
|
32
|
+
limit = int(context.get('limit') or 20)
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
cmd_history = CommandHistory(db_path)
|
|
36
|
+
result = execute_brainblast_command(
|
|
37
|
+
command=query,
|
|
38
|
+
command_history=cmd_history,
|
|
39
|
+
limit=limit
|
|
40
|
+
)
|
|
41
|
+
context['output'] = result.get('output', 'Brainblast search completed.')
|
|
42
|
+
except Exception as e:
|
|
43
|
+
import traceback
|
|
44
|
+
context['output'] = "DB search error: " + str(e) + "\n" + traceback.format_exc()
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
jinx_name: delegate
|
|
2
2
|
description: Delegate a task to another NPC with review and feedback loop until completion. Choose the NPC whose directive best matches the task.
|
|
3
3
|
inputs:
|
|
4
|
-
|
|
4
|
+
- npc_name:
|
|
5
5
|
description: "Name of the NPC to delegate to"
|
|
6
|
-
|
|
6
|
+
- task:
|
|
7
7
|
description: "The task or request to delegate to the NPC"
|
|
8
|
-
|
|
8
|
+
- max_iterations: "10"
|
|
9
9
|
steps:
|
|
10
10
|
- name: delegate_with_review
|
|
11
11
|
engine: python
|
|
@@ -43,8 +43,7 @@ steps:
|
|
|
43
43
|
sep = '-' * 60
|
|
44
44
|
print(colored("\n" + sep, "cyan"))
|
|
45
45
|
print(colored(" Delegating to @" + target_name, "yellow", attrs=["bold"]))
|
|
46
|
-
|
|
47
|
-
print(colored(" Task: " + task_preview, "white", attrs=["dark"]))
|
|
46
|
+
print(colored(" Task: " + task_request, "white", attrs=["dark"]))
|
|
48
47
|
print(colored(sep + "\n", "cyan"))
|
|
49
48
|
print(colored(" [{}] Model: {}".format(target_name, target_npc.model), "white", attrs=["dark"]))
|
|
50
49
|
jinx_list = ', '.join(list(target_jinxs.keys())[:8])
|
|
@@ -127,8 +126,8 @@ steps:
|
|
|
127
126
|
|
|
128
127
|
review_result = get_llm_response(
|
|
129
128
|
review_prompt,
|
|
130
|
-
model=getattr(orchestrator, 'model', '
|
|
131
|
-
provider=getattr(orchestrator, 'provider', '
|
|
129
|
+
model=getattr(orchestrator, 'model', None) or (state.chat_model if state else 'llama3.2'),
|
|
130
|
+
provider=getattr(orchestrator, 'provider', None) or (state.chat_provider if state else 'ollama'),
|
|
132
131
|
npc=orchestrator,
|
|
133
132
|
temperature=0.3
|
|
134
133
|
)
|
|
@@ -150,12 +149,12 @@ steps:
|
|
|
150
149
|
task_complete = True
|
|
151
150
|
print(colored("\n Task completed successfully", "green", attrs=["bold"]))
|
|
152
151
|
if summary:
|
|
153
|
-
print(colored(" Summary: " + summary
|
|
152
|
+
print(colored(" Summary: " + summary, "white", attrs=["dark"]))
|
|
154
153
|
final_output = "[{}] Task completed.\n{}".format(target_name, summary)
|
|
155
154
|
else:
|
|
156
155
|
print(colored("\n Task incomplete - providing feedback", "yellow"))
|
|
157
156
|
if feedback:
|
|
158
|
-
print(colored(" Feedback: " + feedback
|
|
157
|
+
print(colored(" Feedback: " + feedback, "white", attrs=["dark"]))
|
|
159
158
|
|
|
160
159
|
followup_lines = [
|
|
161
160
|
"Continue the previous task. Feedback from orchestrator:",
|
|
@@ -45,6 +45,9 @@ steps:
|
|
|
45
45
|
- "replacement": For "replace", the text to replace with
|
|
46
46
|
- "insertion": For "insert_after" and "insert_before", the text to insert
|
|
47
47
|
2. "explanation": Brief explanation of the changes made
|
|
48
|
+
|
|
49
|
+
Example response:
|
|
50
|
+
{"modifications": [{"type": "replace", "original": "old code", "replacement": "new code"}], "explanation": "Updated the code"}
|
|
48
51
|
"""
|
|
49
52
|
|
|
50
53
|
response = get_llm_response(prompt, model=npc.model, provider=npc.provider, npc=npc, format="json")
|