npcsh 1.1.16__py3-none-any.whl → 1.1.18__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 (217) hide show
  1. npcsh/_state.py +138 -100
  2. npcsh/alicanto.py +2 -2
  3. npcsh/benchmark/__init__.py +28 -0
  4. npcsh/benchmark/npcsh_agent.py +296 -0
  5. npcsh/benchmark/runner.py +611 -0
  6. npcsh/benchmark/templates/install-npcsh.sh.j2 +35 -0
  7. npcsh/build.py +2 -4
  8. npcsh/completion.py +2 -6
  9. npcsh/config.py +1 -3
  10. npcsh/conversation_viewer.py +389 -0
  11. npcsh/corca.py +0 -1
  12. npcsh/execution.py +0 -1
  13. npcsh/guac.py +0 -1
  14. npcsh/mcp_helpers.py +2 -3
  15. npcsh/mcp_server.py +5 -10
  16. npcsh/npc.py +10 -11
  17. npcsh/npc_team/jinxs/bin/benchmark.jinx +146 -0
  18. npcsh/npc_team/jinxs/bin/nql.jinx +7 -7
  19. npcsh/npc_team/jinxs/bin/roll.jinx +20 -23
  20. npcsh/npc_team/jinxs/bin/sample.jinx +6 -7
  21. npcsh/npc_team/jinxs/bin/sync.jinx +6 -6
  22. npcsh/npc_team/jinxs/bin/vixynt.jinx +8 -8
  23. npcsh/npc_team/jinxs/incognide/add_tab.jinx +11 -0
  24. npcsh/npc_team/jinxs/incognide/close_pane.jinx +9 -0
  25. npcsh/npc_team/jinxs/incognide/close_tab.jinx +10 -0
  26. npcsh/npc_team/jinxs/incognide/confirm.jinx +10 -0
  27. npcsh/npc_team/jinxs/incognide/focus_pane.jinx +9 -0
  28. npcsh/npc_team/jinxs/{npc_studio/npc-studio.jinx → incognide/incognide.jinx} +2 -2
  29. npcsh/npc_team/jinxs/incognide/list_panes.jinx +8 -0
  30. npcsh/npc_team/jinxs/incognide/navigate.jinx +10 -0
  31. npcsh/npc_team/jinxs/incognide/notify.jinx +10 -0
  32. npcsh/npc_team/jinxs/incognide/open_pane.jinx +13 -0
  33. npcsh/npc_team/jinxs/incognide/read_pane.jinx +9 -0
  34. npcsh/npc_team/jinxs/incognide/run_terminal.jinx +10 -0
  35. npcsh/npc_team/jinxs/incognide/send_message.jinx +10 -0
  36. npcsh/npc_team/jinxs/incognide/split_pane.jinx +12 -0
  37. npcsh/npc_team/jinxs/incognide/switch_npc.jinx +10 -0
  38. npcsh/npc_team/jinxs/incognide/switch_tab.jinx +10 -0
  39. npcsh/npc_team/jinxs/incognide/write_file.jinx +11 -0
  40. npcsh/npc_team/jinxs/incognide/zen_mode.jinx +9 -0
  41. npcsh/npc_team/jinxs/lib/browser/browser_action.jinx +4 -4
  42. npcsh/npc_team/jinxs/lib/browser/browser_screenshot.jinx +1 -1
  43. npcsh/npc_team/jinxs/lib/browser/open_browser.jinx +2 -2
  44. npcsh/npc_team/jinxs/lib/computer_use/click.jinx +2 -2
  45. npcsh/npc_team/jinxs/lib/computer_use/key_press.jinx +1 -1
  46. npcsh/npc_team/jinxs/lib/computer_use/launch_app.jinx +1 -1
  47. npcsh/npc_team/jinxs/lib/computer_use/screenshot.jinx +1 -1
  48. npcsh/npc_team/jinxs/lib/computer_use/trigger.jinx +2 -2
  49. npcsh/npc_team/jinxs/lib/computer_use/type_text.jinx +1 -1
  50. npcsh/npc_team/jinxs/lib/computer_use/wait.jinx +1 -1
  51. npcsh/npc_team/jinxs/lib/core/chat.jinx +4 -4
  52. npcsh/npc_team/jinxs/lib/core/cmd.jinx +4 -4
  53. npcsh/npc_team/jinxs/lib/core/compress.jinx +8 -8
  54. npcsh/npc_team/jinxs/lib/core/edit_file.jinx +3 -0
  55. npcsh/npc_team/jinxs/lib/core/ots.jinx +7 -7
  56. npcsh/npc_team/jinxs/lib/core/search/db_search.jinx +348 -0
  57. npcsh/npc_team/jinxs/lib/core/search/file_search.jinx +339 -0
  58. npcsh/npc_team/jinxs/lib/core/search/kg_search.jinx +418 -0
  59. npcsh/npc_team/jinxs/lib/core/search/mem_review.jinx +73 -0
  60. npcsh/npc_team/jinxs/lib/core/search/mem_search.jinx +388 -0
  61. npcsh/npc_team/jinxs/lib/core/search/web_search.jinx +283 -0
  62. npcsh/npc_team/jinxs/lib/core/search.jinx +52 -129
  63. npcsh/npc_team/jinxs/lib/core/sh.jinx +1 -1
  64. npcsh/npc_team/jinxs/lib/core/sleep.jinx +29 -18
  65. npcsh/npc_team/jinxs/lib/core/sql.jinx +15 -11
  66. npcsh/npc_team/jinxs/lib/orchestration/convene.jinx +7 -7
  67. npcsh/npc_team/jinxs/lib/orchestration/delegate.jinx +8 -9
  68. npcsh/npc_team/jinxs/lib/research/paper_search.jinx +389 -78
  69. npcsh/npc_team/jinxs/lib/research/semantic_scholar.jinx +373 -56
  70. npcsh/npc_team/jinxs/lib/utils/build.jinx +5 -5
  71. npcsh/npc_team/jinxs/lib/utils/compile.jinx +2 -2
  72. npcsh/npc_team/jinxs/lib/utils/help.jinx +1 -1
  73. npcsh/npc_team/jinxs/lib/utils/init.jinx +5 -5
  74. npcsh/npc_team/jinxs/lib/utils/jinxs.jinx +300 -145
  75. npcsh/npc_team/jinxs/lib/utils/serve.jinx +2 -2
  76. npcsh/npc_team/jinxs/lib/utils/set.jinx +2 -2
  77. npcsh/npc_team/jinxs/lib/utils/switch.jinx +3 -3
  78. npcsh/npc_team/jinxs/lib/utils/switches.jinx +1 -1
  79. npcsh/npc_team/jinxs/lib/utils/teamviz.jinx +2 -2
  80. npcsh/npc_team/jinxs/modes/alicanto.jinx +356 -0
  81. npcsh/npc_team/jinxs/modes/arxiv.jinx +720 -0
  82. npcsh/npc_team/jinxs/modes/corca.jinx +430 -0
  83. npcsh/npc_team/jinxs/modes/guac.jinx +544 -0
  84. npcsh/npc_team/jinxs/modes/plonk.jinx +379 -0
  85. npcsh/npc_team/jinxs/modes/pti.jinx +357 -0
  86. npcsh/npc_team/jinxs/modes/reattach.jinx +291 -0
  87. npcsh/npc_team/jinxs/modes/spool.jinx +350 -0
  88. npcsh/npc_team/jinxs/modes/wander.jinx +455 -0
  89. {npcsh-1.1.16.data/data/npcsh/npc_team → npcsh/npc_team/jinxs/modes}/yap.jinx +8 -2
  90. npcsh/npc_team/sibiji.npc +1 -1
  91. npcsh/npcsh.py +87 -46
  92. npcsh/plonk.py +0 -1
  93. npcsh/pti.py +0 -1
  94. npcsh/routes.py +1 -3
  95. npcsh/spool.py +0 -1
  96. npcsh/ui.py +0 -1
  97. npcsh/wander.py +0 -1
  98. npcsh/yap.py +0 -1
  99. npcsh-1.1.18.data/data/npcsh/npc_team/add_tab.jinx +11 -0
  100. npcsh-1.1.18.data/data/npcsh/npc_team/alicanto.jinx +356 -0
  101. npcsh-1.1.18.data/data/npcsh/npc_team/arxiv.jinx +720 -0
  102. npcsh-1.1.18.data/data/npcsh/npc_team/benchmark.jinx +146 -0
  103. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/browser_action.jinx +4 -4
  104. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/browser_screenshot.jinx +1 -1
  105. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/build.jinx +5 -5
  106. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/chat.jinx +4 -4
  107. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/click.jinx +2 -2
  108. npcsh-1.1.18.data/data/npcsh/npc_team/close_pane.jinx +9 -0
  109. npcsh-1.1.18.data/data/npcsh/npc_team/close_tab.jinx +10 -0
  110. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/cmd.jinx +4 -4
  111. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/compile.jinx +2 -2
  112. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/compress.jinx +8 -8
  113. npcsh-1.1.18.data/data/npcsh/npc_team/confirm.jinx +10 -0
  114. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/convene.jinx +7 -7
  115. npcsh-1.1.18.data/data/npcsh/npc_team/corca.jinx +430 -0
  116. npcsh-1.1.18.data/data/npcsh/npc_team/db_search.jinx +348 -0
  117. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/delegate.jinx +8 -9
  118. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/edit_file.jinx +3 -0
  119. npcsh-1.1.18.data/data/npcsh/npc_team/file_search.jinx +339 -0
  120. npcsh-1.1.18.data/data/npcsh/npc_team/focus_pane.jinx +9 -0
  121. npcsh-1.1.18.data/data/npcsh/npc_team/guac.jinx +544 -0
  122. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/help.jinx +1 -1
  123. npcsh-1.1.16.data/data/npcsh/npc_team/npc-studio.jinx → npcsh-1.1.18.data/data/npcsh/npc_team/incognide.jinx +2 -2
  124. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/init.jinx +5 -5
  125. npcsh-1.1.18.data/data/npcsh/npc_team/jinxs.jinx +331 -0
  126. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/key_press.jinx +1 -1
  127. npcsh-1.1.18.data/data/npcsh/npc_team/kg_search.jinx +418 -0
  128. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/launch_app.jinx +1 -1
  129. npcsh-1.1.18.data/data/npcsh/npc_team/list_panes.jinx +8 -0
  130. npcsh-1.1.18.data/data/npcsh/npc_team/mem_review.jinx +73 -0
  131. npcsh-1.1.18.data/data/npcsh/npc_team/mem_search.jinx +388 -0
  132. npcsh-1.1.18.data/data/npcsh/npc_team/navigate.jinx +10 -0
  133. npcsh-1.1.18.data/data/npcsh/npc_team/notify.jinx +10 -0
  134. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/nql.jinx +7 -7
  135. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/open_browser.jinx +2 -2
  136. npcsh-1.1.18.data/data/npcsh/npc_team/open_pane.jinx +13 -0
  137. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/ots.jinx +7 -7
  138. npcsh-1.1.18.data/data/npcsh/npc_team/paper_search.jinx +412 -0
  139. npcsh-1.1.18.data/data/npcsh/npc_team/plonk.jinx +379 -0
  140. npcsh-1.1.18.data/data/npcsh/npc_team/pti.jinx +357 -0
  141. npcsh-1.1.18.data/data/npcsh/npc_team/read_pane.jinx +9 -0
  142. npcsh-1.1.18.data/data/npcsh/npc_team/reattach.jinx +291 -0
  143. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/roll.jinx +20 -23
  144. npcsh-1.1.18.data/data/npcsh/npc_team/run_terminal.jinx +10 -0
  145. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/sample.jinx +6 -7
  146. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/screenshot.jinx +1 -1
  147. npcsh-1.1.18.data/data/npcsh/npc_team/search.jinx +54 -0
  148. npcsh-1.1.18.data/data/npcsh/npc_team/semantic_scholar.jinx +386 -0
  149. npcsh-1.1.18.data/data/npcsh/npc_team/send_message.jinx +10 -0
  150. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/serve.jinx +2 -2
  151. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/set.jinx +2 -2
  152. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/sh.jinx +1 -1
  153. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/sibiji.npc +1 -1
  154. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/sleep.jinx +29 -18
  155. npcsh-1.1.18.data/data/npcsh/npc_team/split_pane.jinx +12 -0
  156. npcsh-1.1.18.data/data/npcsh/npc_team/spool.jinx +350 -0
  157. npcsh-1.1.18.data/data/npcsh/npc_team/sql.jinx +20 -0
  158. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/switch.jinx +3 -3
  159. npcsh-1.1.18.data/data/npcsh/npc_team/switch_npc.jinx +10 -0
  160. npcsh-1.1.18.data/data/npcsh/npc_team/switch_tab.jinx +10 -0
  161. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/switches.jinx +1 -1
  162. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/sync.jinx +6 -6
  163. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/teamviz.jinx +2 -2
  164. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/trigger.jinx +2 -2
  165. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/type_text.jinx +1 -1
  166. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/vixynt.jinx +8 -8
  167. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/wait.jinx +1 -1
  168. npcsh-1.1.18.data/data/npcsh/npc_team/wander.jinx +455 -0
  169. npcsh-1.1.18.data/data/npcsh/npc_team/web_search.jinx +283 -0
  170. npcsh-1.1.18.data/data/npcsh/npc_team/write_file.jinx +11 -0
  171. {npcsh/npc_team/jinxs/bin → npcsh-1.1.18.data/data/npcsh/npc_team}/yap.jinx +8 -2
  172. npcsh-1.1.18.data/data/npcsh/npc_team/zen_mode.jinx +9 -0
  173. {npcsh-1.1.16.dist-info → npcsh-1.1.18.dist-info}/METADATA +99 -7
  174. npcsh-1.1.18.dist-info/RECORD +235 -0
  175. {npcsh-1.1.16.dist-info → npcsh-1.1.18.dist-info}/WHEEL +1 -1
  176. {npcsh-1.1.16.dist-info → npcsh-1.1.18.dist-info}/entry_points.txt +2 -3
  177. npcsh/npc_team/jinxs/bin/spool.jinx +0 -161
  178. npcsh/npc_team/jinxs/bin/wander.jinx +0 -152
  179. npcsh/npc_team/jinxs/lib/research/arxiv.jinx +0 -76
  180. npcsh-1.1.16.data/data/npcsh/npc_team/arxiv.jinx +0 -76
  181. npcsh-1.1.16.data/data/npcsh/npc_team/jinxs.jinx +0 -176
  182. npcsh-1.1.16.data/data/npcsh/npc_team/paper_search.jinx +0 -101
  183. npcsh-1.1.16.data/data/npcsh/npc_team/search.jinx +0 -131
  184. npcsh-1.1.16.data/data/npcsh/npc_team/semantic_scholar.jinx +0 -69
  185. npcsh-1.1.16.data/data/npcsh/npc_team/spool.jinx +0 -161
  186. npcsh-1.1.16.data/data/npcsh/npc_team/sql.jinx +0 -16
  187. npcsh-1.1.16.data/data/npcsh/npc_team/wander.jinx +0 -152
  188. npcsh-1.1.16.dist-info/RECORD +0 -170
  189. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/alicanto.npc +0 -0
  190. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/alicanto.png +0 -0
  191. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/close_browser.jinx +0 -0
  192. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/corca.npc +0 -0
  193. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/corca.png +0 -0
  194. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/corca_example.png +0 -0
  195. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/frederic.npc +0 -0
  196. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/frederic4.png +0 -0
  197. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/guac.npc +0 -0
  198. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/guac.png +0 -0
  199. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/kadiefa.npc +0 -0
  200. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/kadiefa.png +0 -0
  201. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/load_file.jinx +0 -0
  202. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/npcsh.ctx +0 -0
  203. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/npcsh_sibiji.png +0 -0
  204. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/paste.jinx +0 -0
  205. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/plonk.npc +0 -0
  206. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/plonk.png +0 -0
  207. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/plonkjr.npc +0 -0
  208. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/plonkjr.png +0 -0
  209. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/python.jinx +0 -0
  210. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/shh.jinx +0 -0
  211. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/sibiji.png +0 -0
  212. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/spool.png +0 -0
  213. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/usage.jinx +0 -0
  214. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/verbose.jinx +0 -0
  215. {npcsh-1.1.16.data → npcsh-1.1.18.data}/data/npcsh/npc_team/yap.png +0 -0
  216. {npcsh-1.1.16.dist-info → npcsh-1.1.18.dist-info}/licenses/LICENSE +0 -0
  217. {npcsh-1.1.16.dist-info → npcsh-1.1.18.dist-info}/top_level.txt +0 -0
@@ -1,131 +1,54 @@
1
- jinx_name: "search"
2
- description: >
3
- Executes a search across various sources.
4
- Usage:
5
- /search <query> (Default: Web Search)
6
- /search --memory <query> (Search approved memories)
7
- /search --kg <query> (Search the knowledge graph)
8
- /search --rag [-f <paths>] <query> (Execute a RAG search)
9
- /search --brainblast <query> (Advanced history search)
1
+ jinx_name: search
2
+ description: Unified search - routes to web_search, mem_search, kg_search, file_search, db_search
10
3
  inputs:
11
- - query: ""
12
- - sprovider: ""
13
- - memory: false
14
- - kg: false
15
- - rag: false
16
- - brainblast: false
17
- - file_paths: ""
18
- - history_db_path: "~/npcsh_history.db"
19
- - vector_db_path: "~/npcsh_chroma.db"
20
- - emodel: ""
21
- - eprovider: ""
22
- steps:
23
- - name: "execute_unified_search"
24
- engine: "python"
25
- code: |
26
- import os
27
- import traceback
28
- from npcpy.data.web import search_web
29
-
30
- # Access query from context
31
- query = context.get('query')
32
- if not query or not query.strip():
33
- context['output'] = "Usage: /search [--memory|--kg|--rag|--brainblast] <query>"
34
- else:
35
- # state is available as a GLOBAL variable (from extra_globals)
36
- # Access it directly, not from context
37
- try:
38
- current_state = state # This should work now
39
- except NameError:
40
- context['output'] = "Error: Shell state not available in jinx context"
41
- raise
42
-
43
- current_npc = current_state.npc
44
- current_team = current_state.team
45
-
46
- npc_name = getattr(current_npc, 'name', '__none__') if current_npc else '__none__'
47
- team_name = getattr(current_team, 'name', '__none__') if current_team else '__none__'
48
- current_path = os.getcwd()
49
- db_path = os.path.expanduser(context.get("history_db_path") or "~/.npcsh/npcsh_history.db")
50
-
51
- try:
52
- cmd_history = CommandHistory(db_path)
53
-
54
- if context.get('memory'):
55
- memories = get_relevant_memories(
56
- command_history=cmd_history,
57
- npc_name=npc_name,
58
- team_name=team_name,
59
- path=current_path,
60
- query=query,
61
- max_memories=10,
62
- state=current_state # Pass the state object
63
- )
64
- print(memories)
65
-
66
- if not memories:
67
- output = f"No memories found for query: '{query}'"
68
- else:
69
- output = f"Found {len(memories)} memories:\n\n" + "\n".join(
70
- f"{i}. [{mem.get('timestamp', 'unknown')}] {mem.get('final_memory') or mem.get('initial_memory')}"
71
- for i, mem in enumerate(memories, 1)
72
- )
73
-
74
- elif context.get('kg'):
75
- facts = search_kg_facts(
76
- cmd_history,
77
- npc_name,
78
- team_name,
79
- current_path,
80
- query
81
- )
82
- print(facts)
83
-
84
- if not facts:
85
- output = f"No KG facts found for query: '{query}'"
86
- else:
87
- output = f"Found {len(facts)} KG facts:\n\n" + "\n".join(
88
- f"{i}. {fact.get('statement')}" for i, fact in enumerate(facts, 1)
89
- )
90
-
91
- elif context.get('rag'):
92
- file_paths_str = context.get('file_paths', '')
93
- file_paths = [os.path.abspath(os.path.expanduser(p.strip())) for p in file_paths_str.split(',') if p.strip()]
94
- emodel = context.get('emodel') or current_state.embedding_model
95
- eprovider = context.get('eprovider') or current_state.embedding_provider
96
-
97
- file_contents = []
98
- for path in file_paths:
99
- chunks = load_file_contents(path)
100
- basename = os.path.basename(path)
101
- file_contents.extend([f"{basename}: {chunk}" for chunk in chunks])
102
-
103
- result = execute_rag_command(
104
- command=query,
105
- vector_db_path=os.path.expanduser(context.get('vector_db_path') or "~/.npcsh/npcsh_chroma.db"),
106
- embedding_model=emodel,
107
- embedding_provider=eprovider,
108
- file_contents=file_contents or None
109
- )
110
- print(result)
111
- output = result.get('response', 'No response from RAG.')
4
+ - query: ""
5
+ - type: "web"
6
+ - provider: ""
7
+ - num_results: ""
8
+ - status: ""
9
+ - npc_name: ""
10
+ - team_name: ""
11
+ - file_paths: ""
12
+ - emodel: ""
13
+ - eprovider: ""
14
+ - concept: ""
15
+ - db_path: ""
16
+ - limit: ""
112
17
 
113
- elif context.get('brainblast'):
114
- result = execute_brainblast_command(
115
- command=query,
116
- command_history=cmd_history,
117
- **context
118
- )
119
- print(result)
120
- output = result.get('output', 'Brainblast search executed.')
121
-
122
- else:
123
- # Default to web search
124
- provider = context.get('sprovider') or current_state.search_provider
125
- results = search_web(query, provider=provider)
126
- output = "\n".join([f"- {res}" for res in results]) if results else "No web results found."
127
-
128
- except Exception as e:
129
- output = f"An error occurred in the search jinx: {e}\n{traceback.format_exc()}"
130
-
131
- context['output'] = output
18
+ steps:
19
+ {% if type == "mem" %}
20
+ - name: search
21
+ engine: mem_search
22
+ query: "{{ query }}"
23
+ status: "{{ status }}"
24
+ npc_name: "{{ npc_name }}"
25
+ team_name: "{{ team_name }}"
26
+ db_path: "{{ db_path }}"
27
+ {% elif type == "kg" %}
28
+ - name: search
29
+ engine: kg_search
30
+ query: "{{ query }}"
31
+ concept: "{{ concept }}"
32
+ npc_name: "{{ npc_name }}"
33
+ team_name: "{{ team_name }}"
34
+ db_path: "{{ db_path }}"
35
+ {% elif type == "file" %}
36
+ - name: search
37
+ engine: file_search
38
+ query: "{{ query }}"
39
+ file_paths: "{{ file_paths }}"
40
+ emodel: "{{ emodel }}"
41
+ eprovider: "{{ eprovider }}"
42
+ {% elif type == "db" %}
43
+ - name: search
44
+ engine: db_search
45
+ query: "{{ query }}"
46
+ db_path: "{{ db_path }}"
47
+ limit: "{{ limit }}"
48
+ {% else %}
49
+ - name: search
50
+ engine: web_search
51
+ query: "{{ query }}"
52
+ provider: "{{ provider }}"
53
+ num_results: "{{ num_results }}"
54
+ {% endif %}
@@ -1,7 +1,7 @@
1
1
  jinx_name: sh
2
2
  description: Execute bash queries. Should be used to grep for file contents, list directories, explore information to answer user questions more practically. NEVER use ls -R on directories that may contain node_modules, .git, or other large dependency folders - this will exceed token limits. Use targeted ls commands instead.
3
3
  inputs:
4
- - bash_command
4
+ - bash_command
5
5
  steps:
6
6
  - name: execute_bash
7
7
  engine: python
@@ -1,10 +1,11 @@
1
1
  jinx_name: "sleep"
2
- description: "Evolve knowledge graph. Use --dream to also run creative synthesis."
2
+ description: "Evolve knowledge graph. Use --dream for creative synthesis, --backfill to import approved memories."
3
3
  inputs:
4
- - dream: False # Boolean flag to also run creative synthesis (dream process).
5
- - ops: "" # Comma-separated list of operations to configure KG sleep process.
6
- - model: "" # LLM model to use for KG evolution. Defaults to NPC's model.
7
- - provider: "" # LLM provider to use for KG evolution. Defaults to NPC's provider.
4
+ - dream: False
5
+ - backfill: False
6
+ - ops: ""
7
+ - model: ""
8
+ - provider: ""
8
9
  steps:
9
10
  - name: "evolve_knowledge_graph"
10
11
  engine: "python"
@@ -12,10 +13,10 @@ steps:
12
13
  import os
13
14
  import traceback
14
15
  from npcpy.memory.command_history import CommandHistory, load_kg_from_db, save_kg_to_db
15
- from npcpy.memory.knowledge_graph import kg_sleep_process, kg_dream_process
16
- # Assuming render_markdown is available if needed for logging progress
16
+ from npcpy.memory.knowledge_graph import kg_sleep_process, kg_dream_process, kg_backfill_from_memories
17
17
 
18
18
  is_dreaming = context.get('dream')
19
+ do_backfill = context.get('backfill')
19
20
  operations_str = context.get('ops')
20
21
  llm_model = context.get('model')
21
22
  llm_provider = context.get('provider')
@@ -26,25 +27,22 @@ steps:
26
27
  operations_config = None
27
28
  if operations_str and isinstance(operations_str, str):
28
29
  operations_config = [op.strip() for op in operations_str.split(',')]
29
-
30
+
30
31
  # Fallback for model/provider if not explicitly set in Jinx inputs
31
32
  if not llm_model and current_npc and current_npc.model:
32
33
  llm_model = current_npc.model
33
34
  if not llm_provider and current_npc and current_npc.provider:
34
35
  llm_provider = current_npc.provider
35
-
36
- # Final fallbacks (these would ideally come from npcsh._state config)
37
- if not llm_model: llm_model = "gemini-1.5-pro" # Example default
38
- if not llm_provider: llm_provider = "gemini" # Example default
36
+
37
+ # Final fallbacks from state
38
+ if not llm_model: llm_model = state.chat_model if state else "llama3.2"
39
+ if not llm_provider: llm_provider = state.chat_provider if state else "ollama"
39
40
 
40
41
  team_name = current_team.name if current_team else "__none__"
41
- npc_name = current_npc.name if isinstance(current_npc, type(None).__class__) else "__none__"
42
+ npc_name = current_npc.name if current_npc else "__none__"
42
43
  current_path = os.getcwd()
43
44
  scope_str = f"Team: '{team_name}', NPC: '{npc_name}', Path: '{current_path}'"
44
45
 
45
- # Assume render_markdown exists
46
- # render_markdown(f"- Checking knowledge graph for scope: {scope_str}")
47
-
48
46
  command_history = None
49
47
  try:
50
48
  db_path = os.getenv("NPCSH_DB_PATH", os.path.expanduser("~/npcsh_history.db"))
@@ -57,13 +55,26 @@ steps:
57
55
 
58
56
  output_result = ""
59
57
  try:
58
+ # Run backfill first if requested
59
+ if do_backfill:
60
+ print("Running backfill from approved memories...")
61
+ stats = kg_backfill_from_memories(
62
+ engine,
63
+ model=llm_model,
64
+ provider=llm_provider,
65
+ npc=current_npc,
66
+ get_concepts=True,
67
+ dry_run=False
68
+ )
69
+ output_result += f"Backfill: +{stats['facts_after'] - stats['facts_before']} facts, +{stats['concepts_after'] - stats['concepts_before']} concepts\n"
70
+
60
71
  current_kg = load_kg_from_db(engine, team_name, npc_name, current_path)
61
72
 
62
73
  if not current_kg or not current_kg.get('facts'):
63
74
  output_msg = f"Knowledge graph for the current scope is empty. Nothing to process.\n"
64
75
  output_msg += f" - Scope Checked: {scope_str}\n\n"
65
- output_msg += "**Hint:** Have a conversation or run some commands first to build up knowledge in this specific context. The KG is unique to each combination of Team, NPC, and directory."
66
- context['output'] = output_msg
76
+ output_msg += "**Hint:** Run `/sleep backfill=true` to import approved memories, or have conversations first."
77
+ context['output'] = output_result + output_msg if output_result else output_msg
67
78
  context['messages'] = output_messages
68
79
  exit()
69
80
 
@@ -1,16 +1,20 @@
1
1
  jinx_name: sql
2
- description: Execute queries on the ~/npcsh_history.db to pull data. The database
3
- contains only information about conversations and other user-provided data. It does
4
- not store any information about individual files. Avoid using percent signs unless absolutely necessary.
2
+ description: Execute queries on the ~/npcsh_history.db to pull data. The database contains only information about conversations and other user-provided data. It does not store any information about individual files.
5
3
  inputs:
6
- - sql_query
4
+ - sql_query: ""
5
+
7
6
  steps:
8
- - engine: python
7
+ - name: execute_sql
8
+ engine: python
9
9
  code: |
10
10
  import pandas as pd
11
- query = {{ sql_query | tojson }}
12
- try:
13
- df = pd.read_sql_query(query, npc.db_conn)
14
- except Exception as e:
15
- df = pd.DataFrame({'Error': [str(e)]})
16
- output = df.to_string()
11
+
12
+ query = context.get('sql_query', '').strip()
13
+ if not query:
14
+ context['output'] = "Usage: /sql <query>"
15
+ else:
16
+ try:
17
+ df = pd.read_sql_query(query, npc.db_conn)
18
+ context['output'] = df.to_string()
19
+ except Exception as e:
20
+ context['output'] = "SQL Error: " + str(e)
@@ -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
- - topic: ""
5
- - npcs: "alicanto,corca,guac"
6
- - rounds: 3
7
- - model: null
8
- - provider: null
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 'gemini-1.5-flash')
25
- provider = context.get('provider') or (npc.provider if npc else 'gemini')
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>
@@ -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
- - npc_name:
4
+ - npc_name:
5
5
  description: "Name of the NPC to delegate to"
6
- - task:
6
+ - task:
7
7
  description: "The task or request to delegate to the NPC"
8
- - max_iterations: "10"
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
- task_preview = task_request[:100] + ('...' if len(task_request) > 100 else '')
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', 'gemini-2.5-flash'),
131
- provider=getattr(orchestrator, 'provider', 'gemini'),
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[:200], "white", attrs=["dark"]))
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[:200] + "...", "white", attrs=["dark"]))
157
+ print(colored(" Feedback: " + feedback, "white", attrs=["dark"]))
159
158
 
160
159
  followup_lines = [
161
160
  "Continue the previous task. Feedback from orchestrator:",