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,47 +1,44 @@
1
1
  jinx_name: "roll"
2
2
  description: "Generate a video from a text prompt."
3
3
  inputs:
4
- - prompt: "" # Required text prompt for video generation.
5
- - vgmodel: "" # Video generation model to use. Defaults to NPCSH_VIDEO_GEN_MODEL or NPC's model.
6
- - vgprovider: "" # Video generation provider to use. Defaults to NPCSH_VIDEO_GEN_PROVIDER or NPC's provider.
7
- - num_frames: 125 # Number of frames for the video.
8
- - width: 256 # Width of the video.
9
- - height: 256 # Height of the video.
10
- - output_path: "output.mp4" # Output file path for the video.
4
+ - prompt: ""
5
+ - vgmodel: ""
6
+ - vgprovider: ""
7
+ - num_frames: 125
8
+ - width: 256
9
+ - height: 256
10
+ - output_path: "output.mp4"
11
11
  steps:
12
12
  - name: "generate_video"
13
13
  engine: "python"
14
14
  code: |
15
15
  import traceback
16
16
  from npcpy.llm_funcs import gen_video
17
- # Assuming NPCSH_VIDEO_GEN_MODEL and NPCSH_VIDEO_GEN_PROVIDER are accessible
18
-
17
+
19
18
  prompt = context.get('prompt')
20
- num_frames = int(context.get('num_frames', 125)) # Ensure int type
21
- width = int(context.get('width', 256)) # Ensure int type
22
- height = int(context.get('height', 256)) # Ensure int type
19
+ num_frames = int(context.get('num_frames', 125))
20
+ width = int(context.get('width', 256))
21
+ height = int(context.get('height', 256))
23
22
  output_path = context.get('output_path')
24
23
  video_gen_model = context.get('vgmodel')
25
24
  video_gen_provider = context.get('vgprovider')
26
25
  output_messages = context.get('messages', [])
27
26
  current_npc = context.get('npc')
28
-
27
+
29
28
  if not prompt or not prompt.strip():
30
29
  context['output'] = "Usage: /roll <your prompt>"
31
30
  context['messages'] = output_messages
32
31
  exit()
33
32
 
34
- # Fallback for model/provider if not explicitly set in Jinx inputs
35
33
  if not video_gen_model and current_npc and current_npc.model:
36
34
  video_gen_model = current_npc.model
37
35
  if not video_gen_provider and current_npc and current_npc.provider:
38
36
  video_gen_provider = current_npc.provider
39
-
40
- # Final fallbacks (these would ideally come from npcsh._state config)
41
- if not video_gen_model:
42
- video_gen_model = "stable-video-diffusion" # Example default
43
- if not video_gen_provider:
44
- video_gen_provider = "diffusers" # Example default
37
+
38
+ if not video_gen_model:
39
+ video_gen_model = "stable-video-diffusion"
40
+ if not video_gen_provider:
41
+ video_gen_provider = "diffusers"
45
42
 
46
43
  try:
47
44
  result = gen_video(
@@ -53,9 +50,9 @@ steps:
53
50
  width=width,
54
51
  height=height,
55
52
  output_path=output_path,
56
- **context.get('api_kwargs', {}) # Assuming api_kwargs might be passed
53
+ **context.get('api_kwargs', {})
57
54
  )
58
-
55
+
59
56
  if isinstance(result, dict):
60
57
  context['output'] = result.get('output', 'Video generated.')
61
58
  context['messages'] = result.get('messages', output_messages)
@@ -65,4 +62,4 @@ steps:
65
62
  except Exception as e:
66
63
  traceback.print_exc()
67
64
  context['output'] = f"Error generating video: {e}"
68
- context['messages'] = output_messages
65
+ context['messages'] = output_messages
@@ -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"
@@ -1,9 +1,9 @@
1
1
  jinx_name: "sample"
2
2
  description: "Send a prompt directly to the LLM."
3
3
  inputs:
4
- - prompt: "" # Required text prompt to send to the LLM.
5
- - model: "" # LLM model to use. Defaults to NPC's model.
6
- - provider: "" # LLM provider to use. Defaults to NPC's provider.
4
+ - prompt: ""
5
+ - model: ""
6
+ - provider: ""
7
7
  steps:
8
8
  - name: "send_prompt_to_llm"
9
9
  engine: "python"
@@ -28,9 +28,9 @@ steps:
28
28
  if not llm_provider and current_npc and current_npc.provider:
29
29
  llm_provider = current_npc.provider
30
30
 
31
- # Final fallbacks (these would ideally come from npcsh._state config)
32
- if not llm_model: llm_model = "gemini-1.5-pro" # Example default
33
- if not llm_provider: llm_provider = "gemini" # Example default
31
+ # Final fallbacks from state
32
+ if not llm_model: llm_model = state.chat_model if state else "llama3.2"
33
+ if not llm_provider: llm_provider = state.chat_provider if state else "ollama"
34
34
 
35
35
  try:
36
36
  result = get_llm_response(
@@ -38,7 +38,6 @@ steps:
38
38
  model=llm_model,
39
39
  provider=llm_provider,
40
40
  npc=current_npc,
41
- **{k:v for k,v in context.items() if k not in ['messages', 'prompt', 'model', 'provider']} # Pass other context
42
41
  )
43
42
 
44
43
  if isinstance(result, dict):
@@ -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
@@ -0,0 +1,54 @@
1
+ jinx_name: search
2
+ description: Unified search - routes to web_search, mem_search, kg_search, file_search, db_search
3
+ inputs:
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: ""
17
+
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 %}
@@ -0,0 +1,386 @@
1
+ jinx_name: semantic_scholar
2
+ description: Search Semantic Scholar with interactive TUI. Requires S2_API_KEY env var.
3
+ inputs:
4
+ - query: ""
5
+ - limit: "20"
6
+ - text: "false"
7
+
8
+ steps:
9
+ - name: search_s2
10
+ engine: python
11
+ code: |
12
+ import os
13
+ import sys
14
+ import tty
15
+ import termios
16
+ import time
17
+ import requests
18
+ import webbrowser
19
+ import subprocess
20
+
21
+ query = context.get('query', '')
22
+ limit = int(context.get('limit', 20))
23
+ text_mode = context.get('text', '').lower() in ('true', '1', 'yes')
24
+
25
+ if not query:
26
+ lines = [
27
+ "Usage: /semantic_scholar <query>",
28
+ "",
29
+ "Options:",
30
+ " limit - Max results (default 20)",
31
+ " text - Text-only output, no TUI (true/false)",
32
+ "",
33
+ "TUI Controls:",
34
+ " j/k or arrows - Navigate",
35
+ " 1/2/3 - Sort by year/citations/author",
36
+ " y - Filter by year",
37
+ " p - Preview abstract/TL;DR",
38
+ " o - Open in browser",
39
+ " i - Open in incognide",
40
+ " d - Download paper info",
41
+ " q/ESC - Quit",
42
+ "",
43
+ "Examples:",
44
+ " /semantic_scholar machine learning",
45
+ " /semantic_scholar neural networks limit=50",
46
+ ]
47
+ context['output'] = "\n".join(lines)
48
+ else:
49
+ api_key = os.environ.get('S2_API_KEY')
50
+ if not api_key:
51
+ context['output'] = "Error: S2_API_KEY environment variable not set.\nGet one at https://www.semanticscholar.org/product/api"
52
+ else:
53
+ url = "https://api.semanticscholar.org/graph/v1/paper/search"
54
+ headers = {"x-api-key": api_key}
55
+ params = {
56
+ "query": query,
57
+ "limit": limit,
58
+ "fields": "title,abstract,authors,year,citationCount,url,tldr,venue,openAccessPdf"
59
+ }
60
+
61
+ try:
62
+ response = requests.get(url, headers=headers, params=params, timeout=30)
63
+ response.raise_for_status()
64
+ papers = response.json().get('data', [])
65
+
66
+ if not papers:
67
+ context['output'] = f"No papers found for: {query}"
68
+ elif text_mode:
69
+ # Text-only output
70
+ results = []
71
+ for i, paper in enumerate(papers, 1):
72
+ title = paper.get('title', 'No title')
73
+ year = paper.get('year', '?')
74
+ citations = paper.get('citationCount', 0)
75
+ authors = ', '.join([a.get('name', '') for a in paper.get('authors', [])[:3]])
76
+ if len(paper.get('authors', [])) > 3:
77
+ authors += ' et al.'
78
+ abstract = paper.get('abstract', '')[:200] + '...' if paper.get('abstract') else 'No abstract'
79
+ tldr = paper.get('tldr', {}).get('text', '') if paper.get('tldr') else ''
80
+ paper_url = paper.get('url', '')
81
+
82
+ results.append(f"{i}. {title} ({year})")
83
+ results.append(f" Authors: {authors}")
84
+ results.append(f" Citations: {citations}")
85
+ if tldr:
86
+ results.append(f" TL;DR: {tldr}")
87
+ else:
88
+ results.append(f" Abstract: {abstract}")
89
+ results.append(f" URL: {paper_url}")
90
+ results.append("")
91
+
92
+ context['output'] = f"Found {len(papers)} papers:\n\n" + "\n".join(results)
93
+ context['papers'] = papers
94
+ else:
95
+ # Interactive TUI mode
96
+ def get_terminal_size():
97
+ try:
98
+ size = os.get_terminal_size()
99
+ return size.columns, size.lines
100
+ except:
101
+ return 80, 24
102
+
103
+ width, height = get_terminal_size()
104
+ selected = 0
105
+ scroll = 0
106
+ list_height = height - 5
107
+ mode = 'list'
108
+ preview_scroll = 0
109
+ sort_mode = 'relevance' # relevance, year, citations, author
110
+ year_filter = None
111
+
112
+ def sort_papers(papers, sort_mode):
113
+ if sort_mode == 'year':
114
+ return sorted(papers, key=lambda x: x.get('year') or 0, reverse=True)
115
+ elif sort_mode == 'citations':
116
+ return sorted(papers, key=lambda x: x.get('citationCount') or 0, reverse=True)
117
+ elif sort_mode == 'author':
118
+ return sorted(papers, key=lambda x: (x.get('authors', [{}])[0].get('name', '') if x.get('authors') else ''))
119
+ return papers # relevance = original order
120
+
121
+ def filter_papers(papers, year_filter):
122
+ if not year_filter:
123
+ return papers
124
+ return [p for p in papers if p.get('year') and p.get('year') >= year_filter]
125
+
126
+ display_papers = filter_papers(sort_papers(papers, sort_mode), year_filter)
127
+
128
+ fd = sys.stdin.fileno()
129
+ old_settings = termios.tcgetattr(fd)
130
+
131
+ try:
132
+ tty.setcbreak(fd)
133
+ sys.stdout.write('\033[?25l')
134
+ sys.stdout.write('\033[2J\033[H')
135
+
136
+ while True:
137
+ width, height = get_terminal_size()
138
+ list_height = height - 5
139
+
140
+ if mode == 'list':
141
+ if selected < scroll:
142
+ scroll = selected
143
+ elif selected >= scroll + list_height:
144
+ scroll = selected - list_height + 1
145
+
146
+ sys.stdout.write('\033[H')
147
+
148
+ # Header
149
+ if mode == 'list':
150
+ sort_ind = {'relevance': '0', 'year': '1', 'citations': '2', 'author': '3'}[sort_mode]
151
+ yr = f" year>={year_filter}" if year_filter else ""
152
+ header = f" SEMANTIC SCHOLAR ({len(display_papers)} papers): '{query}' [sort:{sort_mode}({sort_ind}){yr}] "
153
+ else:
154
+ header = f" PREVIEW: {display_papers[selected].get('title', '')[:width-12]} "
155
+ sys.stdout.write(f'\033[44;37;1m{header.ljust(width)}\033[0m\n')
156
+
157
+ # Column headers
158
+ if mode == 'list':
159
+ col_header = f' {"YEAR":<6} {"CITE":<6} {"AUTHORS":<25} {"TITLE":<50}'
160
+ sys.stdout.write(f'\033[90m{col_header[:width]}\033[0m\n')
161
+ else:
162
+ sys.stdout.write(f'\033[90m{"─" * width}\033[0m\n')
163
+
164
+ if mode == 'list':
165
+ for i in range(list_height):
166
+ idx = scroll + i
167
+ sys.stdout.write(f'\033[{3+i};1H\033[K')
168
+ if idx >= len(display_papers):
169
+ continue
170
+
171
+ p = display_papers[idx]
172
+ year = str(p.get('year') or '?')[:6]
173
+ citations = str(p.get('citationCount') or 0)[:6]
174
+ authors = ', '.join([a.get('name', '')[:15] for a in p.get('authors', [])[:2]])
175
+ if len(p.get('authors', [])) > 2:
176
+ authors += ' et al.'
177
+ authors = authors[:25]
178
+ title = (p.get('title') or '')[:60].replace('\n', ' ')
179
+
180
+ line = f" {year:<6} {citations:<6} {authors:<25} {title}"
181
+ line = line[:width-1]
182
+
183
+ if idx == selected:
184
+ sys.stdout.write(f'\033[47;30;1m>{line}\033[0m')
185
+ else:
186
+ sys.stdout.write(f' {line}')
187
+
188
+ # Status bar
189
+ sys.stdout.write(f'\033[{height-2};1H\033[K\033[90m{"─" * width}\033[0m')
190
+ sel = display_papers[selected] if display_papers else {}
191
+ venue = (sel.get('venue') or '')[:30]
192
+ has_pdf = 'PDF' if sel.get('openAccessPdf') else ''
193
+ sys.stdout.write(f'\033[{height-1};1H\033[K {venue} {has_pdf}'.ljust(width))
194
+ sys.stdout.write(f'\033[{height};1H\033[K\033[44;37m j/k:Nav 0/1/2/3:Sort y:Year p:Preview o:Open i:Incog d:Download q:Quit [{selected+1}/{len(display_papers)}] \033[0m')
195
+
196
+ else: # preview mode
197
+ sel = display_papers[selected]
198
+ tldr = sel.get('tldr', {}).get('text', '') if sel.get('tldr') else ''
199
+ abstract = sel.get('abstract') or 'No abstract available'
200
+
201
+ # Build preview lines
202
+ preview_lines = [
203
+ f"Title: {sel.get('title', '')}",
204
+ "",
205
+ f"Year: {sel.get('year', '?')}",
206
+ f"Citations: {sel.get('citationCount', 0)}",
207
+ f"Venue: {sel.get('venue', '')}",
208
+ "",
209
+ "Authors:",
210
+ ]
211
+ for a in sel.get('authors', []):
212
+ preview_lines.append(f" - {a.get('name', '')}")
213
+ preview_lines.append("")
214
+
215
+ if tldr:
216
+ preview_lines.append("TL;DR:")
217
+ # Word wrap TL;DR
218
+ words = tldr.split()
219
+ line = ""
220
+ for w in words:
221
+ if len(line) + len(w) + 1 > width - 4:
222
+ preview_lines.append(f" {line}")
223
+ line = w
224
+ else:
225
+ line = f"{line} {w}" if line else w
226
+ if line:
227
+ preview_lines.append(f" {line}")
228
+ preview_lines.append("")
229
+
230
+ preview_lines.append("Abstract:")
231
+ # Word wrap abstract
232
+ words = abstract.split()
233
+ line = ""
234
+ for w in words:
235
+ if len(line) + len(w) + 1 > width - 4:
236
+ preview_lines.append(f" {line}")
237
+ line = w
238
+ else:
239
+ line = f"{line} {w}" if line else w
240
+ if line:
241
+ preview_lines.append(f" {line}")
242
+
243
+ preview_lines.append("")
244
+ preview_lines.append(f"URL: {sel.get('url', '')}")
245
+ if sel.get('openAccessPdf'):
246
+ preview_lines.append(f"PDF: {sel.get('openAccessPdf', {}).get('url', '')}")
247
+
248
+ for i in range(list_height):
249
+ idx = preview_scroll + i
250
+ sys.stdout.write(f'\033[{3+i};1H\033[K')
251
+ if idx < len(preview_lines):
252
+ sys.stdout.write(preview_lines[idx][:width-1])
253
+
254
+ sys.stdout.write(f'\033[{height-2};1H\033[K\033[90m{"─" * width}\033[0m')
255
+ sys.stdout.write(f'\033[{height-1};1H\033[K [{preview_scroll+1}/{len(preview_lines)} lines]')
256
+ sys.stdout.write(f'\033[{height};1H\033[K\033[44;37m j/k:Scroll b:Back o:Open d:Download q:Quit \033[0m')
257
+
258
+ sys.stdout.flush()
259
+
260
+ c = sys.stdin.read(1)
261
+
262
+ if c == '\x1b':
263
+ c2 = sys.stdin.read(1)
264
+ if c2 == '[':
265
+ c3 = sys.stdin.read(1)
266
+ if c3 == 'A': # Up
267
+ if mode == 'list' and selected > 0:
268
+ selected -= 1
269
+ elif mode == 'preview' and preview_scroll > 0:
270
+ preview_scroll -= 1
271
+ elif c3 == 'B': # Down
272
+ if mode == 'list' and selected < len(display_papers) - 1:
273
+ selected += 1
274
+ elif mode == 'preview' and preview_scroll < 100:
275
+ preview_scroll += 1
276
+ else:
277
+ if mode == 'preview':
278
+ mode = 'list'
279
+ sys.stdout.write('\033[2J\033[H')
280
+ else:
281
+ context['output'] = "Cancelled."
282
+ break
283
+ continue
284
+
285
+ if c == 'q' or c == '\x03':
286
+ context['output'] = "Cancelled."
287
+ break
288
+ elif c == 'k':
289
+ if mode == 'list' and selected > 0:
290
+ selected -= 1
291
+ elif mode == 'preview' and preview_scroll > 0:
292
+ preview_scroll -= 1
293
+ elif c == 'j':
294
+ if mode == 'list' and selected < len(display_papers) - 1:
295
+ selected += 1
296
+ elif mode == 'preview' and preview_scroll < 100:
297
+ preview_scroll += 1
298
+ elif c == '0':
299
+ sort_mode = 'relevance'
300
+ display_papers = filter_papers(sort_papers(papers, sort_mode), year_filter)
301
+ selected = 0
302
+ scroll = 0
303
+ elif c == '1':
304
+ sort_mode = 'year'
305
+ display_papers = filter_papers(sort_papers(papers, sort_mode), year_filter)
306
+ selected = 0
307
+ scroll = 0
308
+ elif c == '2':
309
+ sort_mode = 'citations'
310
+ display_papers = filter_papers(sort_papers(papers, sort_mode), year_filter)
311
+ selected = 0
312
+ scroll = 0
313
+ elif c == '3':
314
+ sort_mode = 'author'
315
+ display_papers = filter_papers(sort_papers(papers, sort_mode), year_filter)
316
+ selected = 0
317
+ scroll = 0
318
+ elif c == 'y' and mode == 'list':
319
+ # Cycle through year filters
320
+ import datetime
321
+ current_year = datetime.datetime.now().year
322
+ if year_filter is None:
323
+ year_filter = current_year - 1
324
+ elif year_filter == current_year - 1:
325
+ year_filter = current_year - 3
326
+ elif year_filter == current_year - 3:
327
+ year_filter = current_year - 5
328
+ else:
329
+ year_filter = None
330
+ display_papers = filter_papers(sort_papers(papers, sort_mode), year_filter)
331
+ selected = 0
332
+ scroll = 0
333
+ elif c == 'p' and mode == 'list' and display_papers:
334
+ mode = 'preview'
335
+ preview_scroll = 0
336
+ sys.stdout.write('\033[2J\033[H')
337
+ elif c == 'b' and mode == 'preview':
338
+ mode = 'list'
339
+ sys.stdout.write('\033[2J\033[H')
340
+ elif c == 'o' and display_papers:
341
+ sel = display_papers[selected]
342
+ paper_url = sel.get('url', '')
343
+ if paper_url:
344
+ webbrowser.open(paper_url)
345
+ elif c == 'i' and display_papers:
346
+ sel = display_papers[selected]
347
+ paper_url = sel.get('url', '')
348
+ if paper_url:
349
+ try:
350
+ subprocess.run(['npcsh', '-c', f'/navigate url={paper_url}'], check=False, capture_output=True)
351
+ except:
352
+ webbrowser.open(paper_url)
353
+ elif c == 'd' and display_papers:
354
+ sel = display_papers[selected]
355
+ # Save paper info to file
356
+ title = sel.get('title', 'paper')
357
+ safe_title = "".join(c if c.isalnum() or c in ' -_' else '_' for c in title)[:50]
358
+ filename = f"{safe_title}.txt"
359
+ with open(filename, 'w') as f:
360
+ f.write(f"Title: {sel.get('title', '')}\n")
361
+ f.write(f"Year: {sel.get('year', '')}\n")
362
+ f.write(f"Citations: {sel.get('citationCount', 0)}\n")
363
+ f.write(f"Venue: {sel.get('venue', '')}\n")
364
+ f.write(f"Authors: {', '.join([a.get('name', '') for a in sel.get('authors', [])])}\n")
365
+ f.write(f"URL: {sel.get('url', '')}\n")
366
+ if sel.get('openAccessPdf'):
367
+ f.write(f"PDF: {sel.get('openAccessPdf', {}).get('url', '')}\n")
368
+ f.write(f"\nAbstract:\n{sel.get('abstract', '')}\n")
369
+ if sel.get('tldr'):
370
+ f.write(f"\nTL;DR:\n{sel.get('tldr', {}).get('text', '')}\n")
371
+ context['output'] = f"Saved to: {filename}"
372
+ break
373
+ elif c in ('\r', '\n') and display_papers:
374
+ sel = display_papers[selected]
375
+ context['output'] = f"Selected: {sel.get('title', '')}\nURL: {sel.get('url', '')}"
376
+ context['selected_paper'] = sel
377
+ break
378
+
379
+ finally:
380
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
381
+ sys.stdout.write('\033[?25h')
382
+ sys.stdout.write('\033[2J\033[H')
383
+ sys.stdout.flush()
384
+
385
+ except requests.exceptions.RequestException as e:
386
+ context['output'] = f"Semantic Scholar API error: {e}"
@@ -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"
@@ -1,8 +1,8 @@
1
1
  jinx_name: "serve"
2
2
  description: "Serve an NPC Team"
3
3
  inputs:
4
- - port: 5337 # The port to run the Flask server on.
5
- - cors: "" # Comma-separated CORS origins.
4
+ - port: 5337
5
+ - cors: ""
6
6
  steps:
7
7
  - name: "start_flask_server"
8
8
  engine: "python"
@@ -1,8 +1,8 @@
1
1
  jinx_name: "set"
2
2
  description: "Set configuration values"
3
3
  inputs:
4
- - key: "" # The configuration key to set.
5
- - value: "" # The value to set for the configuration key.
4
+ - key: ""
5
+ - value: ""
6
6
  steps:
7
7
  - name: "set_config_value"
8
8
  engine: "python"
@@ -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
@@ -14,7 +14,7 @@ primary_directive: |
14
14
  You are sibiji, the orchestrator and general manager of the NPC team.
15
15
  Your role is to delegate tasks to appropriate specialist agents based on their expertise.
16
16
 
17
- When delegating, match the task to the agent whose primary_directive best fits.
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
20
  - lib/orchestration/delegate