npcsh 1.1.21__py3-none-any.whl → 1.1.22__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 +10 -5
- npcsh/benchmark/npcsh_agent.py +22 -14
- npcsh/benchmark/templates/install-npcsh.sh.j2 +2 -2
- npcsh/mcp_server.py +9 -1
- npcsh/npc_team/alicanto.npc +12 -6
- npcsh/npc_team/corca.npc +0 -1
- npcsh/npc_team/frederic.npc +2 -3
- npcsh/npc_team/jinxs/lib/core/edit_file.jinx +83 -61
- npcsh/npc_team/jinxs/modes/alicanto.jinx +102 -41
- npcsh/npc_team/jinxs/modes/build.jinx +378 -0
- npcsh/npc_team/jinxs/modes/convene.jinx +597 -0
- npcsh/npc_team/jinxs/modes/corca.jinx +777 -387
- npcsh/npc_team/jinxs/modes/kg.jinx +69 -2
- npcsh/npc_team/jinxs/modes/plonk.jinx +16 -7
- npcsh/npc_team/jinxs/modes/yap.jinx +628 -187
- npcsh/npc_team/kadiefa.npc +2 -1
- npcsh/npc_team/sibiji.npc +3 -3
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/alicanto.jinx +102 -41
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/alicanto.npc +12 -6
- npcsh-1.1.22.data/data/npcsh/npc_team/build.jinx +378 -0
- npcsh-1.1.22.data/data/npcsh/npc_team/corca.jinx +820 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/corca.npc +0 -1
- npcsh-1.1.22.data/data/npcsh/npc_team/edit_file.jinx +119 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/frederic.npc +2 -3
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/kadiefa.npc +2 -1
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/kg.jinx +69 -2
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/plonk.jinx +16 -7
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/sibiji.npc +3 -3
- npcsh-1.1.22.data/data/npcsh/npc_team/yap.jinx +716 -0
- {npcsh-1.1.21.dist-info → npcsh-1.1.22.dist-info}/METADATA +246 -281
- {npcsh-1.1.21.dist-info → npcsh-1.1.22.dist-info}/RECORD +127 -130
- npcsh/npc_team/jinxs/lib/core/search/kg_search.jinx +0 -429
- npcsh/npc_team/jinxs/lib/core/search.jinx +0 -54
- npcsh/npc_team/jinxs/lib/utils/build.jinx +0 -65
- npcsh-1.1.21.data/data/npcsh/npc_team/build.jinx +0 -65
- npcsh-1.1.21.data/data/npcsh/npc_team/corca.jinx +0 -430
- npcsh-1.1.21.data/data/npcsh/npc_team/edit_file.jinx +0 -97
- npcsh-1.1.21.data/data/npcsh/npc_team/kg_search.jinx +0 -429
- npcsh-1.1.21.data/data/npcsh/npc_team/search.jinx +0 -54
- npcsh-1.1.21.data/data/npcsh/npc_team/yap.jinx +0 -275
- /npcsh/npc_team/jinxs/lib/{core → utils}/chat.jinx +0 -0
- /npcsh/npc_team/jinxs/lib/{core → utils}/cmd.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/add_tab.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/alicanto.png +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/arxiv.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/benchmark.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/browser_action.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/browser_screenshot.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/chat.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/click.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/close_browser.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/close_pane.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/close_tab.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/cmd.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/compile.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/compress.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/config_tui.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/confirm.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/convene.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/corca.png +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/corca_example.png +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/db_search.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/delegate.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/file_search.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/focus_pane.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/frederic4.png +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/git.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/guac.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/guac.npc +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/guac.png +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/help.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/incognide.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/init.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/jinxs.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/kadiefa.png +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/key_press.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/launch_app.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/list_panes.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/load_file.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/memories.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/models.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/navigate.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/notify.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/npcsh.ctx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/npcsh_sibiji.png +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/nql.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/open_browser.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/open_pane.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/ots.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/papers.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/paste.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/plonk.npc +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/plonk.png +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/plonkjr.png +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/pti.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/python.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/read_pane.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/reattach.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/roll.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/run_terminal.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/sample.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/screenshot.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/send_message.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/serve.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/set.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/setup.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/sh.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/shh.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/sibiji.png +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/sleep.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/split_pane.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/spool.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/spool.png +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/sql.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/switch.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/switch_npc.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/switch_tab.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/switches.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/sync.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/team.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/teamviz.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/trigger.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/type_text.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/usage.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/verbose.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/vixynt.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/wait.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/wander.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/web_search.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/write_file.jinx +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/yap.png +0 -0
- {npcsh-1.1.21.data → npcsh-1.1.22.data}/data/npcsh/npc_team/zen_mode.jinx +0 -0
- {npcsh-1.1.21.dist-info → npcsh-1.1.22.dist-info}/WHEEL +0 -0
- {npcsh-1.1.21.dist-info → npcsh-1.1.22.dist-info}/entry_points.txt +0 -0
- {npcsh-1.1.21.dist-info → npcsh-1.1.22.dist-info}/licenses/LICENSE +0 -0
- {npcsh-1.1.21.dist-info → npcsh-1.1.22.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
jinx_name: edit_file
|
|
2
|
+
description: Creates or edits a file. If the file does not exist, creates it with
|
|
3
|
+
the specified content. If the file exists, examines it and applies 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
|
+
|
|
16
|
+
file_path = os.path.expanduser({{ file_path | tojson }})
|
|
17
|
+
edit_instructions = {{ edit_instructions | string | tojson }}
|
|
18
|
+
backup_str = {{ backup | default("true") | string | tojson }}
|
|
19
|
+
create_backup = backup_str.lower() not in ('false', 'no', '0', '')
|
|
20
|
+
|
|
21
|
+
# Ensure parent directory exists
|
|
22
|
+
os.makedirs(os.path.dirname(file_path) or '.', exist_ok=True)
|
|
23
|
+
|
|
24
|
+
# If file doesn't exist, create it
|
|
25
|
+
if not os.path.exists(file_path):
|
|
26
|
+
prompt = """You are a code writing assistant. Create the content for a new file based on these instructions.
|
|
27
|
+
|
|
28
|
+
Instructions: """ + edit_instructions + """
|
|
29
|
+
|
|
30
|
+
Return a JSON object with:
|
|
31
|
+
1. "content": The full content to write to the file
|
|
32
|
+
2. "explanation": Brief explanation of what was created
|
|
33
|
+
|
|
34
|
+
Example response:
|
|
35
|
+
{"content": "print('hello world')", "explanation": "Created a Python hello world script"}
|
|
36
|
+
"""
|
|
37
|
+
response = get_llm_response(prompt, model=npc.model, provider=npc.provider, npc=npc, format="json")
|
|
38
|
+
result = response.get("response", {})
|
|
39
|
+
content = result.get("content", edit_instructions)
|
|
40
|
+
explanation = result.get("explanation", "Created new file")
|
|
41
|
+
|
|
42
|
+
with open(file_path, 'w') as f:
|
|
43
|
+
f.write(content)
|
|
44
|
+
|
|
45
|
+
output = "Created " + file_path + "\n\n" + explanation
|
|
46
|
+
else:
|
|
47
|
+
with open(file_path, 'r') as f:
|
|
48
|
+
original_content = f.read()
|
|
49
|
+
|
|
50
|
+
if create_backup:
|
|
51
|
+
backup_path = file_path + ".bak"
|
|
52
|
+
with open(backup_path, 'w') as f:
|
|
53
|
+
f.write(original_content)
|
|
54
|
+
|
|
55
|
+
prompt = """You are a code editing assistant. Analyze this file and make the requested changes.
|
|
56
|
+
|
|
57
|
+
File content:
|
|
58
|
+
""" + original_content + """
|
|
59
|
+
|
|
60
|
+
Edit instructions: """ + edit_instructions + """
|
|
61
|
+
|
|
62
|
+
Return a JSON object with these fields:
|
|
63
|
+
1. "modifications": An array of modification objects, where each object has:
|
|
64
|
+
- "type": One of "replace", "insert_after", "insert_before", or "delete"
|
|
65
|
+
- "target": For "insert_after" and "insert_before", the text to insert after/before
|
|
66
|
+
For "delete", the text to delete
|
|
67
|
+
- "original": For "replace", the text to be replaced
|
|
68
|
+
- "replacement": For "replace", the text to replace with
|
|
69
|
+
- "insertion": For "insert_after" and "insert_before", the text to insert
|
|
70
|
+
2. "explanation": Brief explanation of the changes made
|
|
71
|
+
|
|
72
|
+
Example response:
|
|
73
|
+
{"modifications": [{"type": "replace", "original": "old code", "replacement": "new code"}], "explanation": "Updated the code"}
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
response = get_llm_response(prompt, model=npc.model, provider=npc.provider, npc=npc, format="json")
|
|
77
|
+
|
|
78
|
+
result = response.get("response", {})
|
|
79
|
+
modifications = result.get("modifications", [])
|
|
80
|
+
explanation = result.get("explanation", "No explanation provided")
|
|
81
|
+
|
|
82
|
+
updated_content = original_content
|
|
83
|
+
changes_applied = 0
|
|
84
|
+
|
|
85
|
+
for mod in modifications:
|
|
86
|
+
print(mod)
|
|
87
|
+
mod_type = mod.get("type")
|
|
88
|
+
|
|
89
|
+
if mod_type == "replace":
|
|
90
|
+
original = mod.get("original")
|
|
91
|
+
replacement = mod.get("replacement")
|
|
92
|
+
if original in updated_content:
|
|
93
|
+
updated_content = updated_content.replace(original, replacement)
|
|
94
|
+
changes_applied += 1
|
|
95
|
+
|
|
96
|
+
elif mod_type == "insert_after":
|
|
97
|
+
target = mod.get("target")
|
|
98
|
+
insertion = mod.get("insertion")
|
|
99
|
+
if target in updated_content:
|
|
100
|
+
updated_content = updated_content.replace(target, target + insertion)
|
|
101
|
+
changes_applied += 1
|
|
102
|
+
|
|
103
|
+
elif mod_type == "insert_before":
|
|
104
|
+
target = mod.get("target")
|
|
105
|
+
insertion = mod.get("insertion")
|
|
106
|
+
if target in updated_content:
|
|
107
|
+
updated_content = updated_content.replace(target, insertion + target)
|
|
108
|
+
changes_applied += 1
|
|
109
|
+
|
|
110
|
+
elif mod_type == "delete":
|
|
111
|
+
target = mod.get("target")
|
|
112
|
+
if target in updated_content:
|
|
113
|
+
updated_content = updated_content.replace(target, "")
|
|
114
|
+
changes_applied += 1
|
|
115
|
+
|
|
116
|
+
with open(file_path, 'w') as f:
|
|
117
|
+
f.write(updated_content)
|
|
118
|
+
|
|
119
|
+
output = "Applied " + str(changes_applied) + " changes to " + file_path + "\n\n" + explanation
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
jinx_name: kg
|
|
2
2
|
description: Interactive knowledge graph browser - explore facts, concepts, and links
|
|
3
3
|
interactive: true
|
|
4
|
-
inputs:
|
|
4
|
+
inputs:
|
|
5
|
+
- action: ""
|
|
6
|
+
- dream: false
|
|
7
|
+
- backfill: false
|
|
8
|
+
- ops: ""
|
|
5
9
|
steps:
|
|
6
10
|
- name: kg_browser
|
|
7
11
|
engine: python
|
|
@@ -12,7 +16,70 @@ steps:
|
|
|
12
16
|
import termios
|
|
13
17
|
import select
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
_kg_action = (context.get('action') or '').strip().lower()
|
|
20
|
+
|
|
21
|
+
if _kg_action in ('sleep', 'evolve', 'dream'):
|
|
22
|
+
# Route to KG evolution operations
|
|
23
|
+
import traceback
|
|
24
|
+
from npcpy.memory.command_history import CommandHistory, load_kg_from_db, save_kg_to_db
|
|
25
|
+
from npcpy.memory.knowledge_graph import kg_sleep_process, kg_dream_process, kg_backfill_from_memories
|
|
26
|
+
|
|
27
|
+
_npc = context.get('npc')
|
|
28
|
+
_team = context.get('team')
|
|
29
|
+
_msgs = context.get('messages', [])
|
|
30
|
+
_do_dream = _kg_action == 'dream' or str(context.get('dream', '')).lower() in ('true', '1', 'yes')
|
|
31
|
+
_do_backfill = str(context.get('backfill', '')).lower() in ('true', '1', 'yes')
|
|
32
|
+
_ops_str = context.get('ops', '')
|
|
33
|
+
_ops_config = [op.strip() for op in _ops_str.split(',') if op.strip()] if _ops_str else None
|
|
34
|
+
|
|
35
|
+
_model = (_npc.model if _npc and hasattr(_npc, 'model') else None) or (state.chat_model if state else 'llama3.2')
|
|
36
|
+
_provider = (_npc.provider if _npc and hasattr(_npc, 'provider') else None) or (state.chat_provider if state else 'ollama')
|
|
37
|
+
|
|
38
|
+
_team_name = _team.name if _team else '__none__'
|
|
39
|
+
_npc_name = _npc.name if _npc else '__none__'
|
|
40
|
+
_cur_path = os.getcwd()
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
_db_path = os.getenv('NPCSH_DB_PATH', os.path.expanduser('~/npcsh_history.db'))
|
|
44
|
+
_ch = CommandHistory(_db_path)
|
|
45
|
+
_eng = _ch.engine
|
|
46
|
+
|
|
47
|
+
_result = ''
|
|
48
|
+
if _do_backfill:
|
|
49
|
+
print('Backfilling from approved memories...')
|
|
50
|
+
_stats = kg_backfill_from_memories(_eng, model=_model, provider=_provider, npc=_npc, get_concepts=True, dry_run=False)
|
|
51
|
+
_result += f"Backfill: +{_stats['facts_after'] - _stats['facts_before']} facts, +{_stats['concepts_after'] - _stats['concepts_before']} concepts\n"
|
|
52
|
+
|
|
53
|
+
_kg = load_kg_from_db(_eng, _team_name, _npc_name, _cur_path)
|
|
54
|
+
if not _kg or not _kg.get('facts'):
|
|
55
|
+
context['output'] = _result + 'Knowledge graph is empty. Use /kg backfill=true or have conversations first.'
|
|
56
|
+
context['messages'] = _msgs
|
|
57
|
+
_ch.close()
|
|
58
|
+
exit()
|
|
59
|
+
|
|
60
|
+
_f0 = len(_kg.get('facts', []))
|
|
61
|
+
_c0 = len(_kg.get('concepts', []))
|
|
62
|
+
_label = 'Sleep'
|
|
63
|
+
|
|
64
|
+
_kg, _ = kg_sleep_process(existing_kg=_kg, model=_model, provider=_provider, npc=_npc, operations_config=_ops_config)
|
|
65
|
+
|
|
66
|
+
if _do_dream:
|
|
67
|
+
_label += ' & Dream'
|
|
68
|
+
_kg, _ = kg_dream_process(existing_kg=_kg, model=_model, provider=_provider, npc=_npc)
|
|
69
|
+
|
|
70
|
+
save_kg_to_db(_eng, _kg, _team_name, _npc_name, _cur_path)
|
|
71
|
+
_f1 = len(_kg.get('facts', []))
|
|
72
|
+
_c1 = len(_kg.get('concepts', []))
|
|
73
|
+
_result += f"{_label} complete. Facts: {_f0} -> {_f1} ({_f1-_f0:+}), Concepts: {_c0} -> {_c1} ({_c1-_c0:+})"
|
|
74
|
+
context['output'] = _result
|
|
75
|
+
context['messages'] = _msgs
|
|
76
|
+
_ch.close()
|
|
77
|
+
except Exception as e:
|
|
78
|
+
traceback.print_exc()
|
|
79
|
+
context['output'] = f'KG evolution error: {e}'
|
|
80
|
+
context['messages'] = _msgs
|
|
81
|
+
|
|
82
|
+
elif not sys.stdin.isatty():
|
|
16
83
|
context['output'] = "KG browser requires an interactive terminal."
|
|
17
84
|
|
|
18
85
|
else:
|
|
@@ -123,7 +123,7 @@ steps:
|
|
|
123
123
|
render_screen()
|
|
124
124
|
|
|
125
125
|
try:
|
|
126
|
-
ss = capture_screenshot()
|
|
126
|
+
ss = capture_screenshot(full=True)
|
|
127
127
|
if not ss or 'file_path' not in ss:
|
|
128
128
|
task['actions'].append({"action": "fail", "reason": "Screenshot failed"})
|
|
129
129
|
task['status'] = 'failed'
|
|
@@ -143,6 +143,9 @@ steps:
|
|
|
143
143
|
history_context += " - " + act.get('reason', '') + "\n"
|
|
144
144
|
|
|
145
145
|
prompt = "You are a GUI automation assistant. Analyze this screenshot and determine the next action.\n\n"
|
|
146
|
+
prompt += "IMPORTANT: Before taking new actions, VERIFY the current screenshot shows the expected result of your previous actions. "
|
|
147
|
+
prompt += "If the page is still loading or hasn't changed yet, use 'wait' with duration 2-3 seconds. "
|
|
148
|
+
prompt += "Do NOT blindly proceed — confirm each step worked before moving on.\n\n"
|
|
146
149
|
prompt += "TASK: " + task['text'] + "\n"
|
|
147
150
|
prompt += history_context + "\n"
|
|
148
151
|
prompt += "Available actions:\n"
|
|
@@ -150,7 +153,7 @@ steps:
|
|
|
150
153
|
prompt += "- type: Type text (use 'text' field)\n"
|
|
151
154
|
prompt += "- key: Press key like enter, tab, escape (use 'text' field)\n"
|
|
152
155
|
prompt += "- launch: Launch application (use 'command' field, e.g. " + app_examples + ")\n"
|
|
153
|
-
prompt += "- wait: Wait for 'duration' seconds\n"
|
|
156
|
+
prompt += "- wait: Wait for 'duration' seconds (use when page is loading or UI hasn't updated)\n"
|
|
154
157
|
prompt += "- done: Task completed successfully\n"
|
|
155
158
|
prompt += "- fail: Task cannot be completed\n\n"
|
|
156
159
|
prompt += "Respond with JSON, e.g.: " + json_schema_example
|
|
@@ -196,20 +199,20 @@ steps:
|
|
|
196
199
|
|
|
197
200
|
if action == 'click':
|
|
198
201
|
x, y = action_response.get('x', 50), action_response.get('y', 50)
|
|
199
|
-
perform_action(
|
|
202
|
+
perform_action({"type": "click", "x": x, "y": y})
|
|
200
203
|
act_record['x'] = x
|
|
201
204
|
act_record['y'] = y
|
|
202
205
|
elif action == 'type':
|
|
203
206
|
txt = action_response.get('text', '')
|
|
204
|
-
perform_action(
|
|
207
|
+
perform_action({"type": "type", "text": txt})
|
|
205
208
|
act_record['text'] = txt
|
|
206
209
|
elif action == 'key':
|
|
207
210
|
key = action_response.get('text', 'enter')
|
|
208
|
-
perform_action(
|
|
211
|
+
perform_action({"type": "key", "key": key})
|
|
209
212
|
act_record['key'] = key
|
|
210
213
|
elif action == 'launch':
|
|
211
214
|
cmd = action_response.get('command', '')
|
|
212
|
-
perform_action(
|
|
215
|
+
perform_action({"type": "launch", "command": cmd})
|
|
213
216
|
act_record['command'] = cmd
|
|
214
217
|
time.sleep(2)
|
|
215
218
|
elif action == 'wait':
|
|
@@ -219,7 +222,13 @@ steps:
|
|
|
219
222
|
|
|
220
223
|
task['actions'].append(act_record)
|
|
221
224
|
ui.status = action + " - " + reason[:40]
|
|
222
|
-
|
|
225
|
+
# Wait for UI to settle after state-changing actions
|
|
226
|
+
if action in ('key', 'click'):
|
|
227
|
+
time.sleep(2.0)
|
|
228
|
+
elif action == 'type':
|
|
229
|
+
time.sleep(0.5)
|
|
230
|
+
else:
|
|
231
|
+
time.sleep(0.3)
|
|
223
232
|
|
|
224
233
|
if ui.mode == 'step':
|
|
225
234
|
ui.mode = 'paused'
|
|
@@ -17,8 +17,8 @@ primary_directive: |
|
|
|
17
17
|
When delegating, match the task to the agent whose primary_directive best fits. Basic search inquiries can be handled by yourself. Do not delegate unnecessarily.
|
|
18
18
|
You have access to the delegate tool to pass tasks to other agents.
|
|
19
19
|
jinxs:
|
|
20
|
-
- lib/
|
|
21
|
-
- lib/
|
|
20
|
+
- lib/core/delegate
|
|
21
|
+
- lib/core/convene
|
|
22
22
|
- lib/core/sh
|
|
23
23
|
- lib/core/python
|
|
24
|
-
- lib/core/search
|
|
24
|
+
- lib/core/search/web_search
|