npcsh 1.1.16__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.
Files changed (176) hide show
  1. npcsh/_state.py +24 -9
  2. npcsh/benchmark/__init__.py +22 -0
  3. npcsh/benchmark/npcsh_agent.py +262 -0
  4. npcsh/benchmark/runner.py +569 -0
  5. npcsh/npc_team/jinxs/bin/benchmark.jinx +146 -0
  6. npcsh/npc_team/jinxs/bin/nql.jinx +7 -7
  7. npcsh/npc_team/jinxs/bin/roll.jinx +20 -23
  8. npcsh/npc_team/jinxs/bin/sample.jinx +6 -7
  9. npcsh/npc_team/jinxs/bin/spool.jinx +4 -4
  10. npcsh/npc_team/jinxs/bin/sync.jinx +6 -6
  11. npcsh/npc_team/jinxs/bin/vixynt.jinx +8 -8
  12. npcsh/npc_team/jinxs/bin/wander.jinx +109 -19
  13. npcsh/npc_team/jinxs/bin/yap.jinx +5 -5
  14. npcsh/npc_team/jinxs/incognide/add_tab.jinx +11 -0
  15. npcsh/npc_team/jinxs/incognide/close_pane.jinx +9 -0
  16. npcsh/npc_team/jinxs/incognide/close_tab.jinx +10 -0
  17. npcsh/npc_team/jinxs/incognide/confirm.jinx +10 -0
  18. npcsh/npc_team/jinxs/incognide/focus_pane.jinx +9 -0
  19. npcsh/npc_team/jinxs/{npc_studio/npc-studio.jinx → incognide/incognide.jinx} +2 -2
  20. npcsh/npc_team/jinxs/incognide/list_panes.jinx +8 -0
  21. npcsh/npc_team/jinxs/incognide/navigate.jinx +10 -0
  22. npcsh/npc_team/jinxs/incognide/notify.jinx +10 -0
  23. npcsh/npc_team/jinxs/incognide/open_pane.jinx +13 -0
  24. npcsh/npc_team/jinxs/incognide/read_pane.jinx +9 -0
  25. npcsh/npc_team/jinxs/incognide/run_terminal.jinx +10 -0
  26. npcsh/npc_team/jinxs/incognide/send_message.jinx +10 -0
  27. npcsh/npc_team/jinxs/incognide/split_pane.jinx +12 -0
  28. npcsh/npc_team/jinxs/incognide/switch_npc.jinx +10 -0
  29. npcsh/npc_team/jinxs/incognide/switch_tab.jinx +10 -0
  30. npcsh/npc_team/jinxs/incognide/write_file.jinx +11 -0
  31. npcsh/npc_team/jinxs/incognide/zen_mode.jinx +9 -0
  32. npcsh/npc_team/jinxs/lib/browser/browser_action.jinx +4 -4
  33. npcsh/npc_team/jinxs/lib/browser/browser_screenshot.jinx +1 -1
  34. npcsh/npc_team/jinxs/lib/browser/open_browser.jinx +2 -2
  35. npcsh/npc_team/jinxs/lib/computer_use/click.jinx +2 -2
  36. npcsh/npc_team/jinxs/lib/computer_use/key_press.jinx +1 -1
  37. npcsh/npc_team/jinxs/lib/computer_use/launch_app.jinx +1 -1
  38. npcsh/npc_team/jinxs/lib/computer_use/screenshot.jinx +1 -1
  39. npcsh/npc_team/jinxs/lib/computer_use/trigger.jinx +2 -2
  40. npcsh/npc_team/jinxs/lib/computer_use/type_text.jinx +1 -1
  41. npcsh/npc_team/jinxs/lib/computer_use/wait.jinx +1 -1
  42. npcsh/npc_team/jinxs/lib/core/chat.jinx +4 -4
  43. npcsh/npc_team/jinxs/lib/core/cmd.jinx +4 -4
  44. npcsh/npc_team/jinxs/lib/core/compress.jinx +8 -8
  45. npcsh/npc_team/jinxs/lib/core/edit_file.jinx +3 -0
  46. npcsh/npc_team/jinxs/lib/core/ots.jinx +7 -7
  47. npcsh/npc_team/jinxs/lib/core/search/db_search.jinx +44 -0
  48. npcsh/npc_team/jinxs/lib/core/search/file_search.jinx +94 -0
  49. npcsh/npc_team/jinxs/lib/core/search/kg_search.jinx +96 -0
  50. npcsh/npc_team/jinxs/lib/core/search/mem_search.jinx +80 -0
  51. npcsh/npc_team/jinxs/lib/core/search/web_search.jinx +51 -0
  52. npcsh/npc_team/jinxs/lib/core/search.jinx +52 -129
  53. npcsh/npc_team/jinxs/lib/core/sh.jinx +1 -1
  54. npcsh/npc_team/jinxs/lib/core/sleep.jinx +7 -7
  55. npcsh/npc_team/jinxs/lib/core/sql.jinx +7 -7
  56. npcsh/npc_team/jinxs/lib/orchestration/convene.jinx +7 -7
  57. npcsh/npc_team/jinxs/lib/orchestration/delegate.jinx +8 -9
  58. npcsh/npc_team/jinxs/lib/research/arxiv.jinx +2 -2
  59. npcsh/npc_team/jinxs/lib/research/paper_search.jinx +3 -3
  60. npcsh/npc_team/jinxs/lib/research/semantic_scholar.jinx +2 -2
  61. npcsh/npc_team/jinxs/lib/utils/build.jinx +5 -5
  62. npcsh/npc_team/jinxs/lib/utils/compile.jinx +2 -2
  63. npcsh/npc_team/jinxs/lib/utils/help.jinx +1 -1
  64. npcsh/npc_team/jinxs/lib/utils/init.jinx +5 -5
  65. npcsh/npc_team/jinxs/lib/utils/jinxs.jinx +1 -1
  66. npcsh/npc_team/jinxs/lib/utils/serve.jinx +2 -2
  67. npcsh/npc_team/jinxs/lib/utils/set.jinx +2 -2
  68. npcsh/npc_team/jinxs/lib/utils/switch.jinx +3 -3
  69. npcsh/npc_team/jinxs/lib/utils/switches.jinx +1 -1
  70. npcsh/npc_team/jinxs/lib/utils/teamviz.jinx +2 -2
  71. npcsh/npc_team/sibiji.npc +1 -1
  72. npcsh/npcsh.py +81 -43
  73. npcsh-1.1.17.data/data/npcsh/npc_team/add_tab.jinx +11 -0
  74. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/arxiv.jinx +2 -2
  75. npcsh-1.1.17.data/data/npcsh/npc_team/benchmark.jinx +146 -0
  76. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/browser_action.jinx +4 -4
  77. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/browser_screenshot.jinx +1 -1
  78. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/build.jinx +5 -5
  79. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/chat.jinx +4 -4
  80. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/click.jinx +2 -2
  81. npcsh-1.1.17.data/data/npcsh/npc_team/close_pane.jinx +9 -0
  82. npcsh-1.1.17.data/data/npcsh/npc_team/close_tab.jinx +10 -0
  83. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/cmd.jinx +4 -4
  84. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/compile.jinx +2 -2
  85. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/compress.jinx +8 -8
  86. npcsh-1.1.17.data/data/npcsh/npc_team/confirm.jinx +10 -0
  87. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/convene.jinx +7 -7
  88. npcsh-1.1.17.data/data/npcsh/npc_team/db_search.jinx +44 -0
  89. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/delegate.jinx +8 -9
  90. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/edit_file.jinx +3 -0
  91. npcsh-1.1.17.data/data/npcsh/npc_team/file_search.jinx +94 -0
  92. npcsh-1.1.17.data/data/npcsh/npc_team/focus_pane.jinx +9 -0
  93. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/help.jinx +1 -1
  94. npcsh-1.1.16.data/data/npcsh/npc_team/npc-studio.jinx → npcsh-1.1.17.data/data/npcsh/npc_team/incognide.jinx +2 -2
  95. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/init.jinx +5 -5
  96. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/jinxs.jinx +1 -1
  97. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/key_press.jinx +1 -1
  98. npcsh-1.1.17.data/data/npcsh/npc_team/kg_search.jinx +96 -0
  99. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/launch_app.jinx +1 -1
  100. npcsh-1.1.17.data/data/npcsh/npc_team/list_panes.jinx +8 -0
  101. npcsh-1.1.17.data/data/npcsh/npc_team/mem_search.jinx +80 -0
  102. npcsh-1.1.17.data/data/npcsh/npc_team/navigate.jinx +10 -0
  103. npcsh-1.1.17.data/data/npcsh/npc_team/notify.jinx +10 -0
  104. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/nql.jinx +7 -7
  105. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/open_browser.jinx +2 -2
  106. npcsh-1.1.17.data/data/npcsh/npc_team/open_pane.jinx +13 -0
  107. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/ots.jinx +7 -7
  108. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/paper_search.jinx +3 -3
  109. npcsh-1.1.17.data/data/npcsh/npc_team/read_pane.jinx +9 -0
  110. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/roll.jinx +20 -23
  111. npcsh-1.1.17.data/data/npcsh/npc_team/run_terminal.jinx +10 -0
  112. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/sample.jinx +6 -7
  113. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/screenshot.jinx +1 -1
  114. npcsh-1.1.17.data/data/npcsh/npc_team/search.jinx +54 -0
  115. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/semantic_scholar.jinx +2 -2
  116. npcsh-1.1.17.data/data/npcsh/npc_team/send_message.jinx +10 -0
  117. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/serve.jinx +2 -2
  118. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/set.jinx +2 -2
  119. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/sh.jinx +1 -1
  120. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/sibiji.npc +1 -1
  121. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/sleep.jinx +7 -7
  122. npcsh-1.1.17.data/data/npcsh/npc_team/split_pane.jinx +12 -0
  123. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/spool.jinx +4 -4
  124. npcsh-1.1.17.data/data/npcsh/npc_team/sql.jinx +16 -0
  125. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/switch.jinx +3 -3
  126. npcsh-1.1.17.data/data/npcsh/npc_team/switch_npc.jinx +10 -0
  127. npcsh-1.1.17.data/data/npcsh/npc_team/switch_tab.jinx +10 -0
  128. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/switches.jinx +1 -1
  129. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/sync.jinx +6 -6
  130. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/teamviz.jinx +2 -2
  131. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/trigger.jinx +2 -2
  132. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/type_text.jinx +1 -1
  133. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/vixynt.jinx +8 -8
  134. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/wait.jinx +1 -1
  135. npcsh-1.1.17.data/data/npcsh/npc_team/wander.jinx +242 -0
  136. npcsh-1.1.17.data/data/npcsh/npc_team/web_search.jinx +51 -0
  137. npcsh-1.1.17.data/data/npcsh/npc_team/write_file.jinx +11 -0
  138. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/yap.jinx +5 -5
  139. npcsh-1.1.17.data/data/npcsh/npc_team/zen_mode.jinx +9 -0
  140. {npcsh-1.1.16.dist-info → npcsh-1.1.17.dist-info}/METADATA +10 -7
  141. npcsh-1.1.17.dist-info/RECORD +219 -0
  142. {npcsh-1.1.16.dist-info → npcsh-1.1.17.dist-info}/entry_points.txt +2 -0
  143. npcsh-1.1.16.data/data/npcsh/npc_team/search.jinx +0 -131
  144. npcsh-1.1.16.data/data/npcsh/npc_team/sql.jinx +0 -16
  145. npcsh-1.1.16.data/data/npcsh/npc_team/wander.jinx +0 -152
  146. npcsh-1.1.16.dist-info/RECORD +0 -170
  147. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/alicanto.npc +0 -0
  148. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/alicanto.png +0 -0
  149. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/close_browser.jinx +0 -0
  150. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/corca.npc +0 -0
  151. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/corca.png +0 -0
  152. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/corca_example.png +0 -0
  153. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/frederic.npc +0 -0
  154. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/frederic4.png +0 -0
  155. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/guac.npc +0 -0
  156. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/guac.png +0 -0
  157. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/kadiefa.npc +0 -0
  158. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/kadiefa.png +0 -0
  159. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/load_file.jinx +0 -0
  160. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/npcsh.ctx +0 -0
  161. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/npcsh_sibiji.png +0 -0
  162. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/paste.jinx +0 -0
  163. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/plonk.npc +0 -0
  164. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/plonk.png +0 -0
  165. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/plonkjr.npc +0 -0
  166. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/plonkjr.png +0 -0
  167. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/python.jinx +0 -0
  168. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/shh.jinx +0 -0
  169. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/sibiji.png +0 -0
  170. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/spool.png +0 -0
  171. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/usage.jinx +0 -0
  172. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/verbose.jinx +0 -0
  173. {npcsh-1.1.16.data → npcsh-1.1.17.data}/data/npcsh/npc_team/yap.png +0 -0
  174. {npcsh-1.1.16.dist-info → npcsh-1.1.17.dist-info}/WHEEL +0 -0
  175. {npcsh-1.1.16.dist-info → npcsh-1.1.17.dist-info}/licenses/LICENSE +0 -0
  176. {npcsh-1.1.16.dist-info → npcsh-1.1.17.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,10 @@
1
+ jinx_name: studio.run_terminal
2
+ description: Execute a command in a terminal pane.
3
+ inputs:
4
+ - paneId: "active"
5
+ - command: ""
6
+ steps:
7
+ - name: frontend_action
8
+ engine: python
9
+ code: |
10
+ context['output'] = "Action executed by frontend"
@@ -0,0 +1,10 @@
1
+ jinx_name: studio.send_message
2
+ description: Send a message in a chat pane.
3
+ inputs:
4
+ - paneId: "active"
5
+ - message: ""
6
+ steps:
7
+ - name: frontend_action
8
+ engine: python
9
+ code: |
10
+ context['output'] = "Action executed by frontend"
@@ -0,0 +1,12 @@
1
+ jinx_name: studio.split_pane
2
+ description: Split an existing pane to create a new pane alongside it.
3
+ inputs:
4
+ - paneId: "active"
5
+ - direction: "right"
6
+ - type: ""
7
+ - path: ""
8
+ steps:
9
+ - name: frontend_action
10
+ engine: python
11
+ code: |
12
+ context['output'] = "Action executed by frontend"
@@ -0,0 +1,10 @@
1
+ jinx_name: studio.switch_npc
2
+ description: Switch the active NPC in a chat pane.
3
+ inputs:
4
+ - paneId: "active"
5
+ - npcName: ""
6
+ steps:
7
+ - name: frontend_action
8
+ engine: python
9
+ code: |
10
+ context['output'] = "Action executed by frontend"
@@ -0,0 +1,10 @@
1
+ jinx_name: studio.switch_tab
2
+ description: Switch to a specific tab in a pane.
3
+ inputs:
4
+ - paneId: "active"
5
+ - tabIndex: 0
6
+ steps:
7
+ - name: frontend_action
8
+ engine: python
9
+ code: |
10
+ context['output'] = "Action executed by frontend"
@@ -0,0 +1,11 @@
1
+ jinx_name: studio.write_file
2
+ description: Write content to an editor pane. Updates the file content in the pane.
3
+ inputs:
4
+ - paneId: "active"
5
+ - content: ""
6
+ - path: ""
7
+ steps:
8
+ - name: frontend_action
9
+ engine: python
10
+ code: |
11
+ context['output'] = "Action executed by frontend"
@@ -0,0 +1,9 @@
1
+ jinx_name: studio.zen_mode
2
+ description: Toggle zen mode (fullscreen) for a pane.
3
+ inputs:
4
+ - paneId: "active"
5
+ steps:
6
+ - name: frontend_action
7
+ engine: python
8
+ code: |
9
+ context['output'] = "Action executed by frontend"
@@ -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 (#id, .class, input[name="x"]) or xpath://... for XPath
15
+ Selectors: CSS (
16
16
  inputs:
17
- - action:
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
- - selector:
19
+ - selector:
20
20
  description: "CSS selector or XPath (prefix xpath: for XPath)"
21
21
  default: ""
22
- - value:
22
+ - value:
23
23
  description: "Value for type/select, or scroll direction, or key name"
24
24
  default: ""
25
25
 
@@ -1,7 +1,7 @@
1
1
  jinx_name: browser_screenshot
2
2
  description: Take a screenshot of the current browser page.
3
3
  inputs:
4
- - filename:
4
+ - filename:
5
5
  description: "Optional filename for screenshot"
6
6
  default: ""
7
7
 
@@ -3,9 +3,9 @@ description: |
3
3
  Open a browser and navigate to a URL. The browser stays open for follow-up commands.
4
4
  Use this to start browser automation.
5
5
  inputs:
6
- - url:
6
+ - url:
7
7
  description: "URL to navigate to"
8
- - browser: "firefox"
8
+ - browser: "firefox"
9
9
 
10
10
  steps:
11
11
  - name: open_browser
@@ -1,8 +1,8 @@
1
1
  jinx_name: click
2
2
  description: Click at screen coordinates (0-100 percentage)
3
3
  inputs:
4
- - x: 50 # X coordinate as percentage (0-100)
5
- - y: 50 # Y coordinate as percentage (0-100)
4
+ - x: 50
5
+ - y: 50
6
6
 
7
7
  steps:
8
8
  - name: perform_click
@@ -6,7 +6,7 @@ description: |
6
6
  For combinations use + like: ctrl+a, ctrl+c, ctrl+v, alt+tab, ctrl+shift+t
7
7
  For regular letters/numbers, use type_text instead.
8
8
  inputs:
9
- - key: "enter"
9
+ - key: "enter"
10
10
 
11
11
  steps:
12
12
  - name: perform_key
@@ -1,7 +1,7 @@
1
1
  jinx_name: launch_app
2
2
  description: Launch an application on the system
3
3
  inputs:
4
- - command: "" # Command to launch (e.g., "open -a Firefox" on macOS)
4
+ - command: ""
5
5
 
6
6
  steps:
7
7
  - name: perform_launch
@@ -1,7 +1,7 @@
1
1
  jinx_name: screenshot
2
2
  description: Capture a screenshot of the current screen
3
3
  inputs:
4
- - output_path: null # Optional path to save screenshot
4
+ - output_path: null
5
5
 
6
6
  steps:
7
7
  - name: capture_screenshot
@@ -1,8 +1,8 @@
1
1
  jinx_name: "trigger"
2
2
  description: "Creates a persistent listener (--listen) or a scheduled task (--cron)."
3
3
  inputs:
4
- - listen: "" # The description for a persistent, event-driven listener.
5
- - cron: "" # The description for a scheduled, time-based task.
4
+ - listen: ""
5
+ - cron: ""
6
6
  steps:
7
7
  - name: "execute_command"
8
8
  engine: "python"
@@ -1,7 +1,7 @@
1
1
  jinx_name: type_text
2
2
  description: Type text using keyboard
3
3
  inputs:
4
- - text: "" # Text to type
4
+ - text: ""
5
5
 
6
6
  steps:
7
7
  - name: perform_type
@@ -1,7 +1,7 @@
1
1
  jinx_name: wait
2
2
  description: Wait/pause for a specified duration in seconds
3
3
  inputs:
4
- - duration: 1 # Duration to wait in seconds
4
+ - duration: 1
5
5
 
6
6
  steps:
7
7
  - name: perform_wait
@@ -1,10 +1,10 @@
1
1
  jinx_name: chat
2
2
  description: Simple chat mode - LLM conversation without tool execution
3
3
  inputs:
4
- - query: null
5
- - model: null
6
- - provider: null
7
- - stream: true
4
+ - query: null
5
+ - model: null
6
+ - provider: null
7
+ - stream: true
8
8
 
9
9
  steps:
10
10
  - name: chat_response
@@ -1,10 +1,10 @@
1
1
  jinx_name: cmd
2
2
  description: Command mode - LLM generates and executes shell commands
3
3
  inputs:
4
- - query: null
5
- - model: null
6
- - provider: null
7
- - stream: true
4
+ - query: null
5
+ - model: null
6
+ - provider: null
7
+ - stream: true
8
8
 
9
9
  steps:
10
10
  - name: cmd_execute
@@ -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
- - flush: "" # The number of recent messages to flush.
5
- - sleep: False # If true, evolves the knowledge graph.
6
- - dream: False # Used with --sleep. Runs creative synthesis.
7
- - ops: "" # Used with --sleep. Comma-separated list of KG operations.
8
- - model: "" # Used with --sleep. LLM model for KG evolution.
9
- - provider: "" # Used with --sleep. LLM provider for KG evolution.
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 = "gemini-1.5-pro"
57
- if not llm_provider: llm_provider = "gemini"
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__"
@@ -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")
@@ -1,10 +1,10 @@
1
1
  jinx_name: "ots"
2
2
  description: "Take screenshot and analyze with vision model. Usage: /ots <prompt>"
3
3
  inputs:
4
- - prompt
5
- - image_paths_args: ""
6
- - vmodel: ""
7
- - vprovider: ""
4
+ - prompt
5
+ - image_paths_args: ""
6
+ - vmodel: ""
7
+ - vprovider: ""
8
8
  steps:
9
9
  - name: "analyze_screenshot_or_image"
10
10
  engine: "python"
@@ -38,10 +38,10 @@ steps:
38
38
  print(f"📸 Screenshot captured: {screenshot_info.get('filename', os.path.basename(screenshot_info['file_path']))}")
39
39
 
40
40
  if not vision_model:
41
- vision_model = getattr(current_npc, 'model', 'gemma3:4b')
42
-
41
+ vision_model = getattr(current_npc, 'model', None) or (state.vision_model if state else 'llama3.2')
42
+
43
43
  if not vision_provider:
44
- vision_provider = getattr(current_npc, 'provider', 'ollama')
44
+ vision_provider = getattr(current_npc, 'provider', None) or (state.vision_provider if state else 'ollama')
45
45
 
46
46
  response_data = get_llm_response(
47
47
  prompt=user_prompt,
@@ -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()
@@ -0,0 +1,94 @@
1
+ jinx_name: file_search
2
+ description: Search file contents using RAG (Retrieval Augmented Generation)
3
+ inputs:
4
+ - query: ""
5
+ - file_paths: ""
6
+ - emodel: ""
7
+ - eprovider: ""
8
+ - vector_db_path: ""
9
+ - recursive: "false"
10
+
11
+ steps:
12
+ - name: search_files
13
+ engine: python
14
+ code: |
15
+ import os
16
+ import glob as globmod
17
+
18
+ query = context.get('query', '').strip()
19
+ file_paths_str = context.get('file_paths', '').strip()
20
+
21
+ if not query or not file_paths_str:
22
+ lines = [
23
+ "Usage: /file_search <query> file_paths=<path1,path2,...>",
24
+ "",
25
+ "Options:",
26
+ " file_paths - Comma-separated file paths or glob patterns (required)",
27
+ " emodel - Embedding model",
28
+ " eprovider - Embedding provider",
29
+ " vector_db_path - Path to vector database",
30
+ " recursive - Use recursive glob for patterns (default false)",
31
+ "",
32
+ "Examples:",
33
+ " /file_search how does auth work file_paths=src/*.py",
34
+ " /file_search database schema file_paths=docs/,README.md",
35
+ ]
36
+ context['output'] = "\n".join(lines)
37
+ else:
38
+ recursive = context.get('recursive', 'false').lower() == 'true'
39
+ emodel = context.get('emodel') or None
40
+ eprovider = context.get('eprovider') or None
41
+ try:
42
+ emodel = emodel or (state.embedding_model if 'state' in dir() and state else None)
43
+ eprovider = eprovider or (state.embedding_provider if 'state' in dir() and state else None)
44
+ except:
45
+ pass
46
+ vector_db_path = context.get('vector_db_path') or os.path.expanduser("~/.npcsh/npcsh_chroma.db")
47
+
48
+ try:
49
+ resolved_paths = []
50
+ for path_spec in file_paths_str.split(','):
51
+ path_spec = path_spec.strip()
52
+ if not path_spec:
53
+ continue
54
+ expanded = os.path.expanduser(path_spec)
55
+ if '*' in expanded or '?' in expanded:
56
+ if recursive:
57
+ matches = globmod.glob(expanded, recursive=True)
58
+ else:
59
+ matches = globmod.glob(expanded)
60
+ resolved_paths.extend(matches)
61
+ else:
62
+ resolved_paths.append(os.path.abspath(expanded))
63
+
64
+ file_contents = []
65
+ loaded_files = []
66
+ for path in resolved_paths:
67
+ if os.path.isfile(path):
68
+ chunks = load_file_contents(path)
69
+ basename = os.path.basename(path)
70
+ file_contents.extend([basename + ": " + chunk for chunk in chunks])
71
+ loaded_files.append(basename)
72
+ elif os.path.isdir(path):
73
+ for root, dirs, files in os.walk(path):
74
+ for f in files:
75
+ fpath = os.path.join(root, f)
76
+ chunks = load_file_contents(fpath)
77
+ file_contents.extend([f + ": " + chunk for chunk in chunks])
78
+ loaded_files.append(f)
79
+
80
+ if not file_contents:
81
+ context['output'] = "No files found or loaded from: " + file_paths_str
82
+ else:
83
+ result = execute_rag_command(
84
+ command=query,
85
+ vector_db_path=vector_db_path,
86
+ embedding_model=emodel,
87
+ embedding_provider=eprovider,
88
+ file_contents=file_contents
89
+ )
90
+ response = result.get('response', 'No RAG response.')
91
+ context['output'] = "Searched " + str(len(loaded_files)) + " files:\n\n" + response
92
+ except Exception as e:
93
+ import traceback
94
+ context['output'] = "File search error: " + str(e) + "\n" + traceback.format_exc()
@@ -0,0 +1,96 @@
1
+ jinx_name: kg_search
2
+ description: Search the knowledge graph for facts and concepts
3
+ inputs:
4
+ - query: ""
5
+ - type: "facts"
6
+ - concept: ""
7
+ - npc_name: ""
8
+ - team_name: ""
9
+ - db_path: ""
10
+
11
+ steps:
12
+ - name: search_kg
13
+ engine: python
14
+ code: |
15
+ import os
16
+ from npcpy.memory.knowledge_graph import kg_search_facts, kg_list_concepts, kg_get_facts_for_concept, kg_get_all_facts
17
+
18
+ query = context.get('query', '').strip()
19
+ search_type = context.get('type', 'facts').lower()
20
+ concept = context.get('concept', '').strip()
21
+
22
+ if not query and search_type == 'facts' and not concept:
23
+ lines = [
24
+ "Usage: /kg_search <query> [type=facts|concepts|all]",
25
+ "",
26
+ "Options:",
27
+ " type - Search type (facts, concepts, all). Default is facts",
28
+ " concept - Get facts for a specific concept",
29
+ " npc_name - Filter by NPC name",
30
+ " team_name - Filter by team name",
31
+ " db_path - Path to history database",
32
+ "",
33
+ "Examples:",
34
+ " /kg_search python",
35
+ " /kg_search type=concepts",
36
+ " /kg_search concept=coding",
37
+ " /kg_search type=all",
38
+ ]
39
+ context['output'] = "\n".join(lines)
40
+ else:
41
+ db_path = context.get('db_path') or os.path.expanduser("~/.npcsh/npcsh_history.db")
42
+
43
+ try:
44
+ cmd_history = CommandHistory(db_path)
45
+ engine = cmd_history.engine
46
+
47
+ team_obj = None
48
+ try:
49
+ team_obj = state.team if 'state' in dir() and state else None
50
+ except:
51
+ pass
52
+ npc_obj = npc if 'npc' in dir() else None
53
+
54
+ if concept:
55
+ facts = kg_get_facts_for_concept(engine, concept, npc=npc_obj, team=team_obj)
56
+ if not facts:
57
+ context['output'] = "No facts found for concept '" + concept + "'"
58
+ else:
59
+ lines = ["Facts for concept '" + concept + "':", ""]
60
+ for i, fact in enumerate(facts, 1):
61
+ lines.append(str(i) + ". " + str(fact))
62
+ context['output'] = "\n".join(lines)
63
+
64
+ elif search_type == 'concepts':
65
+ concepts = kg_list_concepts(engine, npc=npc_obj, team=team_obj)
66
+ if not concepts:
67
+ context['output'] = "No concepts found in knowledge graph."
68
+ else:
69
+ lines = ["Found " + str(len(concepts)) + " concepts:", ""]
70
+ for i, c in enumerate(concepts, 1):
71
+ lines.append(str(i) + ". " + str(c))
72
+ context['output'] = "\n".join(lines)
73
+
74
+ elif search_type == 'all':
75
+ facts = kg_get_all_facts(engine, npc=npc_obj, team=team_obj)
76
+ if not facts:
77
+ context['output'] = "No facts in knowledge graph."
78
+ else:
79
+ lines = ["All facts (" + str(len(facts)) + " total):", ""]
80
+ for i, fact in enumerate(facts, 1):
81
+ lines.append(str(i) + ". " + str(fact))
82
+ context['output'] = "\n".join(lines)
83
+
84
+ else:
85
+ facts = kg_search_facts(engine, query, npc=npc_obj, team=team_obj)
86
+ if not facts:
87
+ context['output'] = "No KG facts found for '" + query + "'"
88
+ else:
89
+ lines = ["Found " + str(len(facts)) + " facts:", ""]
90
+ for i, fact in enumerate(facts, 1):
91
+ lines.append(str(i) + ". " + str(fact))
92
+ context['output'] = "\n".join(lines)
93
+
94
+ except Exception as e:
95
+ import traceback
96
+ context['output'] = "KG search error: " + str(e) + "\n" + traceback.format_exc()
@@ -0,0 +1,80 @@
1
+ jinx_name: mem_search
2
+ description: Search memories (approved, pending, or all)
3
+ inputs:
4
+ - query: ""
5
+ - status: "all"
6
+ - npc_name: ""
7
+ - team_name: ""
8
+ - max_results: "10"
9
+ - db_path: ""
10
+
11
+ steps:
12
+ - name: search_memories
13
+ engine: python
14
+ code: |
15
+ import os
16
+
17
+ query = context.get('query', '').strip()
18
+ if not query:
19
+ lines = [
20
+ "Usage: /mem_search <query> [status=all|approved|pending]",
21
+ "",
22
+ "Options:",
23
+ " status - Filter by status (all, approved, pending). Default is all",
24
+ " npc_name - Filter by NPC name",
25
+ " team_name - Filter by team name",
26
+ " max_results - Max results to return (default 10)",
27
+ " db_path - Path to history database",
28
+ ]
29
+ context['output'] = "\n".join(lines)
30
+ else:
31
+ status_filter = context.get('status', 'all').lower()
32
+ npc_name = context.get('npc_name') or (npc.name if npc else None)
33
+ team_name = context.get('team_name') or None
34
+ try:
35
+ team_name = team_name or (state.team.name if 'state' in dir() and state and state.team else None)
36
+ except:
37
+ pass
38
+ max_results = int(context.get('max_results') or 10)
39
+ db_path = context.get('db_path') or os.path.expanduser("~/.npcsh/npcsh_history.db")
40
+ current_path = os.getcwd()
41
+
42
+ try:
43
+ cmd_history = CommandHistory(db_path)
44
+
45
+ if status_filter == 'approved':
46
+ state_obj = state if 'state' in dir() else None
47
+ memories = get_relevant_memories(
48
+ command_history=cmd_history,
49
+ npc_name=npc_name or '__none__',
50
+ team_name=team_name or '__none__',
51
+ path=current_path,
52
+ query=query,
53
+ max_memories=max_results,
54
+ state=state_obj
55
+ )
56
+ else:
57
+ memories = cmd_history.search_memories(
58
+ query=query,
59
+ npc_name=npc_name,
60
+ team_name=team_name,
61
+ status=status_filter if status_filter != 'all' else None,
62
+ limit=max_results
63
+ )
64
+
65
+ if not memories:
66
+ context['output'] = "No memories found for '" + query + "' (status=" + status_filter + ")"
67
+ else:
68
+ lines = ["Found " + str(len(memories)) + " memories (status=" + status_filter + "):", ""]
69
+ for i, mem in enumerate(memories, 1):
70
+ if isinstance(mem, dict):
71
+ ts = mem.get('timestamp', 'unknown')
72
+ content = mem.get('final_memory') or mem.get('initial_memory') or mem.get('content', '')
73
+ status = mem.get('status', '')
74
+ lines.append(str(i) + ". [" + str(ts) + "] (" + status + ") " + str(content))
75
+ else:
76
+ lines.append(str(i) + ". " + str(mem))
77
+ context['output'] = "\n".join(lines)
78
+ except Exception as e:
79
+ import traceback
80
+ context['output'] = "Memory search error: " + str(e) + "\n" + traceback.format_exc()