npcsh 1.1.21__py3-none-any.whl → 1.1.23__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 (188) hide show
  1. npcsh/_state.py +282 -125
  2. npcsh/benchmark/npcsh_agent.py +77 -232
  3. npcsh/benchmark/templates/install-npcsh.sh.j2 +12 -4
  4. npcsh/config.py +5 -2
  5. npcsh/mcp_server.py +9 -1
  6. npcsh/npc_team/alicanto.npc +8 -6
  7. npcsh/npc_team/corca.npc +5 -12
  8. npcsh/npc_team/frederic.npc +6 -9
  9. npcsh/npc_team/guac.npc +4 -4
  10. npcsh/npc_team/jinxs/lib/core/delegate.jinx +1 -1
  11. npcsh/npc_team/jinxs/lib/core/edit_file.jinx +84 -62
  12. npcsh/npc_team/jinxs/lib/core/sh.jinx +1 -1
  13. npcsh/npc_team/jinxs/lib/core/skill.jinx +59 -0
  14. npcsh/npc_team/jinxs/lib/utils/help.jinx +194 -10
  15. npcsh/npc_team/jinxs/lib/utils/init.jinx +528 -37
  16. npcsh/npc_team/jinxs/lib/utils/jinxs.jinx +0 -1
  17. npcsh/npc_team/jinxs/lib/utils/serve.jinx +938 -21
  18. npcsh/npc_team/jinxs/modes/alicanto.jinx +102 -41
  19. npcsh/npc_team/jinxs/modes/build.jinx +378 -0
  20. npcsh-1.1.21.data/data/npcsh/npc_team/config_tui.jinx → npcsh/npc_team/jinxs/modes/config.jinx +1 -1
  21. npcsh/npc_team/jinxs/modes/convene.jinx +670 -0
  22. npcsh/npc_team/jinxs/modes/corca.jinx +777 -387
  23. npcsh/npc_team/jinxs/modes/crond.jinx +818 -0
  24. npcsh/npc_team/jinxs/modes/kg.jinx +69 -2
  25. npcsh/npc_team/jinxs/modes/plonk.jinx +86 -15
  26. npcsh/npc_team/jinxs/modes/roll.jinx +368 -55
  27. npcsh/npc_team/jinxs/modes/skills.jinx +621 -0
  28. npcsh/npc_team/jinxs/modes/yap.jinx +1092 -177
  29. npcsh/npc_team/jinxs/skills/code-review/SKILL.md +45 -0
  30. npcsh/npc_team/jinxs/skills/debugging/SKILL.md +44 -0
  31. npcsh/npc_team/jinxs/skills/git-workflow.jinx +44 -0
  32. npcsh/npc_team/kadiefa.npc +6 -6
  33. npcsh/npc_team/npcsh.ctx +16 -0
  34. npcsh/npc_team/plonk.npc +5 -9
  35. npcsh/npc_team/sibiji.npc +15 -7
  36. npcsh/npcsh.py +1 -0
  37. npcsh/routes.py +0 -4
  38. npcsh/yap.py +22 -4
  39. npcsh-1.1.23.data/data/npcsh/npc_team/SKILL.md +44 -0
  40. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/alicanto.jinx +102 -41
  41. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/alicanto.npc +8 -6
  42. npcsh-1.1.23.data/data/npcsh/npc_team/build.jinx +378 -0
  43. npcsh/npc_team/jinxs/modes/config_tui.jinx → npcsh-1.1.23.data/data/npcsh/npc_team/config.jinx +1 -1
  44. npcsh-1.1.23.data/data/npcsh/npc_team/convene.jinx +670 -0
  45. npcsh-1.1.23.data/data/npcsh/npc_team/corca.jinx +820 -0
  46. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/corca.npc +5 -12
  47. npcsh-1.1.23.data/data/npcsh/npc_team/crond.jinx +818 -0
  48. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/delegate.jinx +1 -1
  49. npcsh-1.1.23.data/data/npcsh/npc_team/edit_file.jinx +119 -0
  50. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/frederic.npc +6 -9
  51. npcsh-1.1.23.data/data/npcsh/npc_team/git-workflow.jinx +44 -0
  52. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/guac.npc +4 -4
  53. npcsh-1.1.23.data/data/npcsh/npc_team/help.jinx +236 -0
  54. npcsh-1.1.23.data/data/npcsh/npc_team/init.jinx +532 -0
  55. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/jinxs.jinx +0 -1
  56. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/kadiefa.npc +6 -6
  57. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/kg.jinx +69 -2
  58. npcsh-1.1.23.data/data/npcsh/npc_team/npcsh.ctx +34 -0
  59. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/plonk.jinx +86 -15
  60. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/plonk.npc +5 -9
  61. npcsh-1.1.23.data/data/npcsh/npc_team/roll.jinx +378 -0
  62. npcsh-1.1.23.data/data/npcsh/npc_team/serve.jinx +943 -0
  63. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/sh.jinx +1 -1
  64. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/sibiji.npc +15 -7
  65. npcsh-1.1.23.data/data/npcsh/npc_team/skill.jinx +59 -0
  66. npcsh-1.1.23.data/data/npcsh/npc_team/skills.jinx +621 -0
  67. npcsh-1.1.23.data/data/npcsh/npc_team/yap.jinx +1190 -0
  68. {npcsh-1.1.21.dist-info → npcsh-1.1.23.dist-info}/METADATA +404 -278
  69. npcsh-1.1.23.dist-info/RECORD +216 -0
  70. npcsh/npc_team/jinxs/incognide/add_tab.jinx +0 -11
  71. npcsh/npc_team/jinxs/incognide/close_pane.jinx +0 -9
  72. npcsh/npc_team/jinxs/incognide/close_tab.jinx +0 -10
  73. npcsh/npc_team/jinxs/incognide/confirm.jinx +0 -10
  74. npcsh/npc_team/jinxs/incognide/focus_pane.jinx +0 -9
  75. npcsh/npc_team/jinxs/incognide/list_panes.jinx +0 -8
  76. npcsh/npc_team/jinxs/incognide/navigate.jinx +0 -10
  77. npcsh/npc_team/jinxs/incognide/notify.jinx +0 -10
  78. npcsh/npc_team/jinxs/incognide/open_pane.jinx +0 -13
  79. npcsh/npc_team/jinxs/incognide/read_pane.jinx +0 -9
  80. npcsh/npc_team/jinxs/incognide/run_terminal.jinx +0 -10
  81. npcsh/npc_team/jinxs/incognide/send_message.jinx +0 -10
  82. npcsh/npc_team/jinxs/incognide/split_pane.jinx +0 -12
  83. npcsh/npc_team/jinxs/incognide/switch_npc.jinx +0 -10
  84. npcsh/npc_team/jinxs/incognide/switch_tab.jinx +0 -10
  85. npcsh/npc_team/jinxs/incognide/write_file.jinx +0 -11
  86. npcsh/npc_team/jinxs/incognide/zen_mode.jinx +0 -9
  87. npcsh/npc_team/jinxs/lib/core/convene.jinx +0 -232
  88. npcsh/npc_team/jinxs/lib/core/search/kg_search.jinx +0 -429
  89. npcsh/npc_team/jinxs/lib/core/search.jinx +0 -54
  90. npcsh/npc_team/jinxs/lib/utils/build.jinx +0 -65
  91. npcsh-1.1.21.data/data/npcsh/npc_team/add_tab.jinx +0 -11
  92. npcsh-1.1.21.data/data/npcsh/npc_team/build.jinx +0 -65
  93. npcsh-1.1.21.data/data/npcsh/npc_team/close_pane.jinx +0 -9
  94. npcsh-1.1.21.data/data/npcsh/npc_team/close_tab.jinx +0 -10
  95. npcsh-1.1.21.data/data/npcsh/npc_team/confirm.jinx +0 -10
  96. npcsh-1.1.21.data/data/npcsh/npc_team/convene.jinx +0 -232
  97. npcsh-1.1.21.data/data/npcsh/npc_team/corca.jinx +0 -430
  98. npcsh-1.1.21.data/data/npcsh/npc_team/edit_file.jinx +0 -97
  99. npcsh-1.1.21.data/data/npcsh/npc_team/focus_pane.jinx +0 -9
  100. npcsh-1.1.21.data/data/npcsh/npc_team/help.jinx +0 -52
  101. npcsh-1.1.21.data/data/npcsh/npc_team/init.jinx +0 -41
  102. npcsh-1.1.21.data/data/npcsh/npc_team/kg_search.jinx +0 -429
  103. npcsh-1.1.21.data/data/npcsh/npc_team/list_panes.jinx +0 -8
  104. npcsh-1.1.21.data/data/npcsh/npc_team/navigate.jinx +0 -10
  105. npcsh-1.1.21.data/data/npcsh/npc_team/notify.jinx +0 -10
  106. npcsh-1.1.21.data/data/npcsh/npc_team/npcsh.ctx +0 -18
  107. npcsh-1.1.21.data/data/npcsh/npc_team/open_pane.jinx +0 -13
  108. npcsh-1.1.21.data/data/npcsh/npc_team/read_pane.jinx +0 -9
  109. npcsh-1.1.21.data/data/npcsh/npc_team/roll.jinx +0 -65
  110. npcsh-1.1.21.data/data/npcsh/npc_team/run_terminal.jinx +0 -10
  111. npcsh-1.1.21.data/data/npcsh/npc_team/search.jinx +0 -54
  112. npcsh-1.1.21.data/data/npcsh/npc_team/send_message.jinx +0 -10
  113. npcsh-1.1.21.data/data/npcsh/npc_team/serve.jinx +0 -26
  114. npcsh-1.1.21.data/data/npcsh/npc_team/split_pane.jinx +0 -12
  115. npcsh-1.1.21.data/data/npcsh/npc_team/switch_npc.jinx +0 -10
  116. npcsh-1.1.21.data/data/npcsh/npc_team/switch_tab.jinx +0 -10
  117. npcsh-1.1.21.data/data/npcsh/npc_team/write_file.jinx +0 -11
  118. npcsh-1.1.21.data/data/npcsh/npc_team/yap.jinx +0 -275
  119. npcsh-1.1.21.data/data/npcsh/npc_team/zen_mode.jinx +0 -9
  120. npcsh-1.1.21.dist-info/RECORD +0 -243
  121. /npcsh/npc_team/jinxs/lib/{core → utils}/chat.jinx +0 -0
  122. /npcsh/npc_team/jinxs/lib/{core → utils}/cmd.jinx +0 -0
  123. /npcsh/npc_team/jinxs/{incognide → lib/utils}/incognide.jinx +0 -0
  124. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/alicanto.png +0 -0
  125. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/arxiv.jinx +0 -0
  126. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/benchmark.jinx +0 -0
  127. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/browser_action.jinx +0 -0
  128. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/browser_screenshot.jinx +0 -0
  129. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/chat.jinx +0 -0
  130. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/click.jinx +0 -0
  131. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/close_browser.jinx +0 -0
  132. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/cmd.jinx +0 -0
  133. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/compile.jinx +0 -0
  134. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/compress.jinx +0 -0
  135. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/corca.png +0 -0
  136. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/corca_example.png +0 -0
  137. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/db_search.jinx +0 -0
  138. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/file_search.jinx +0 -0
  139. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/frederic4.png +0 -0
  140. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/git.jinx +0 -0
  141. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/guac.jinx +0 -0
  142. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/guac.png +0 -0
  143. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/incognide.jinx +0 -0
  144. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/kadiefa.png +0 -0
  145. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/key_press.jinx +0 -0
  146. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/launch_app.jinx +0 -0
  147. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/load_file.jinx +0 -0
  148. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/memories.jinx +0 -0
  149. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/models.jinx +0 -0
  150. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/npcsh_sibiji.png +0 -0
  151. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/nql.jinx +0 -0
  152. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/open_browser.jinx +0 -0
  153. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/ots.jinx +0 -0
  154. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/papers.jinx +0 -0
  155. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/paste.jinx +0 -0
  156. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/plonk.png +0 -0
  157. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/plonkjr.png +0 -0
  158. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/pti.jinx +0 -0
  159. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/python.jinx +0 -0
  160. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/reattach.jinx +0 -0
  161. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/sample.jinx +0 -0
  162. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/screenshot.jinx +0 -0
  163. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/set.jinx +0 -0
  164. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/setup.jinx +0 -0
  165. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/shh.jinx +0 -0
  166. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/sibiji.png +0 -0
  167. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/sleep.jinx +0 -0
  168. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/spool.jinx +0 -0
  169. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/spool.png +0 -0
  170. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/sql.jinx +0 -0
  171. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/switch.jinx +0 -0
  172. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/switches.jinx +0 -0
  173. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/sync.jinx +0 -0
  174. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/team.jinx +0 -0
  175. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/teamviz.jinx +0 -0
  176. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/trigger.jinx +0 -0
  177. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/type_text.jinx +0 -0
  178. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/usage.jinx +0 -0
  179. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/verbose.jinx +0 -0
  180. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/vixynt.jinx +0 -0
  181. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/wait.jinx +0 -0
  182. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/wander.jinx +0 -0
  183. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/web_search.jinx +0 -0
  184. {npcsh-1.1.21.data → npcsh-1.1.23.data}/data/npcsh/npc_team/yap.png +0 -0
  185. {npcsh-1.1.21.dist-info → npcsh-1.1.23.dist-info}/WHEEL +0 -0
  186. {npcsh-1.1.21.dist-info → npcsh-1.1.23.dist-info}/entry_points.txt +0 -0
  187. {npcsh-1.1.21.dist-info → npcsh-1.1.23.dist-info}/licenses/LICENSE +0 -0
  188. {npcsh-1.1.21.dist-info → npcsh-1.1.23.dist-info}/top_level.txt +0 -0
@@ -1,54 +0,0 @@
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 %}
@@ -1,65 +0,0 @@
1
- jinx_name: "build"
2
- description: "Build deployment artifacts for NPC team"
3
- inputs:
4
- - target: "flask"
5
- - outdir: "./build"
6
- - team: "./npc_team"
7
- - port: 5337
8
- - cors: ""
9
- steps:
10
- - name: "execute_build"
11
- engine: "python"
12
- code: |
13
- import os
14
-
15
- # Assume these build functions are available in the execution environment
16
- # from a larger project context, e.g., from npcpy.build_funcs
17
- try:
18
- from npcpy.build_funcs import (
19
- build_flask_server,
20
- build_docker_compose,
21
- build_cli_executable,
22
- build_static_site,
23
- )
24
- except ImportError:
25
- # Provide mock functions for demonstration or error handling
26
- def build_flask_server(config, **kwargs): return {"output": f"Mock build flask: {config}", "messages": []}
27
- def build_docker_compose(config, **kwargs): return {"output": f"Mock build docker: {config}", "messages": []}
28
- def build_cli_executable(config, **kwargs): return {"output": f"Mock build cli: {config}", "messages": []}
29
- def build_static_site(config, **kwargs): return {"output": f"Mock build static: {config}", "messages": []}
30
-
31
- target = context.get('target') or 'flask'
32
- output_dir = context.get('outdir') or './build'
33
- team_path = context.get('team') or './npc_team'
34
- port = context.get('port') or 5337
35
- cors_origins_str = context.get('cors') or ''
36
-
37
- cors_origins = [origin.strip() for origin in cors_origins_str.split(',') if origin.strip()] or None
38
-
39
- build_config = {
40
- 'team_path': os.path.abspath(os.path.expanduser(team_path)),
41
- 'output_dir': os.path.abspath(os.path.expanduser(output_dir)),
42
- 'target': target,
43
- 'port': port,
44
- 'cors_origins': cors_origins,
45
- }
46
-
47
- builders = {
48
- 'flask': build_flask_server,
49
- 'docker': build_docker_compose,
50
- 'cli': build_cli_executable,
51
- 'static': build_static_site,
52
- }
53
-
54
- output_messages = context.get('messages', [])
55
- output_result = ""
56
-
57
- if target not in builders:
58
- output_result = f"Unknown target: {target}. Available: {list(builders.keys())}"
59
- else:
60
- result = builders[target](build_config, messages=output_messages)
61
- output_result = result.get('output', 'Build command executed.')
62
- output_messages = result.get('messages', output_messages) # Update messages from builder call
63
-
64
- context['output'] = output_result
65
- context['messages'] = output_messages
@@ -1,11 +0,0 @@
1
- jinx_name: studio_add_tab
2
- description: Add a new tab to a pane.
3
- inputs:
4
- - paneId: "active"
5
- - type: ""
6
- - path: ""
7
- steps:
8
- - name: frontend_action
9
- engine: python
10
- code: |
11
- context['output'] = "Action executed by frontend"
@@ -1,65 +0,0 @@
1
- jinx_name: "build"
2
- description: "Build deployment artifacts for NPC team"
3
- inputs:
4
- - target: "flask"
5
- - outdir: "./build"
6
- - team: "./npc_team"
7
- - port: 5337
8
- - cors: ""
9
- steps:
10
- - name: "execute_build"
11
- engine: "python"
12
- code: |
13
- import os
14
-
15
- # Assume these build functions are available in the execution environment
16
- # from a larger project context, e.g., from npcpy.build_funcs
17
- try:
18
- from npcpy.build_funcs import (
19
- build_flask_server,
20
- build_docker_compose,
21
- build_cli_executable,
22
- build_static_site,
23
- )
24
- except ImportError:
25
- # Provide mock functions for demonstration or error handling
26
- def build_flask_server(config, **kwargs): return {"output": f"Mock build flask: {config}", "messages": []}
27
- def build_docker_compose(config, **kwargs): return {"output": f"Mock build docker: {config}", "messages": []}
28
- def build_cli_executable(config, **kwargs): return {"output": f"Mock build cli: {config}", "messages": []}
29
- def build_static_site(config, **kwargs): return {"output": f"Mock build static: {config}", "messages": []}
30
-
31
- target = context.get('target') or 'flask'
32
- output_dir = context.get('outdir') or './build'
33
- team_path = context.get('team') or './npc_team'
34
- port = context.get('port') or 5337
35
- cors_origins_str = context.get('cors') or ''
36
-
37
- cors_origins = [origin.strip() for origin in cors_origins_str.split(',') if origin.strip()] or None
38
-
39
- build_config = {
40
- 'team_path': os.path.abspath(os.path.expanduser(team_path)),
41
- 'output_dir': os.path.abspath(os.path.expanduser(output_dir)),
42
- 'target': target,
43
- 'port': port,
44
- 'cors_origins': cors_origins,
45
- }
46
-
47
- builders = {
48
- 'flask': build_flask_server,
49
- 'docker': build_docker_compose,
50
- 'cli': build_cli_executable,
51
- 'static': build_static_site,
52
- }
53
-
54
- output_messages = context.get('messages', [])
55
- output_result = ""
56
-
57
- if target not in builders:
58
- output_result = f"Unknown target: {target}. Available: {list(builders.keys())}"
59
- else:
60
- result = builders[target](build_config, messages=output_messages)
61
- output_result = result.get('output', 'Build command executed.')
62
- output_messages = result.get('messages', output_messages) # Update messages from builder call
63
-
64
- context['output'] = output_result
65
- context['messages'] = output_messages
@@ -1,9 +0,0 @@
1
- jinx_name: studio_close_pane
2
- description: Close a pane in NPC Studio. Use paneId="active" or omit to close the active pane.
3
- inputs:
4
- - paneId: "active"
5
- steps:
6
- - name: frontend_action
7
- engine: python
8
- code: |
9
- context['output'] = "Action executed by frontend"
@@ -1,10 +0,0 @@
1
- jinx_name: studio_close_tab
2
- description: Close 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"
@@ -1,10 +0,0 @@
1
- jinx_name: studio_confirm
2
- description: Show a confirmation dialog and return the user's choice.
3
- inputs:
4
- - message: ""
5
- - title: "Confirm"
6
- steps:
7
- - name: frontend_action
8
- engine: python
9
- code: |
10
- context['output'] = "Action executed by frontend"
@@ -1,232 +0,0 @@
1
- jinx_name: convene
2
- description: Run a cycle of discussions between NPCs on a topic. The orchestrator convenes agents to discuss and synthesize.
3
- inputs:
4
- - topic: ""
5
- - npcs: "alicanto,corca,guac"
6
- - rounds: 3
7
- - model: null
8
- - provider: null
9
- steps:
10
- - name: convene_discussion
11
- engine: python
12
- code: |
13
- from termcolor import colored
14
- from npcpy.llm_funcs import get_llm_response
15
-
16
- topic = context.get('topic', '')
17
- npcs_str = context.get('npcs', 'alicanto,corca,guac')
18
- rounds = int(context.get('rounds', 3))
19
-
20
- npc = context.get('npc')
21
- team = context.get('team')
22
- messages = context.get('messages', [])
23
-
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
-
27
- if not topic:
28
- context['output'] = """Usage: /convene <topic>
29
-
30
- Options:
31
- --npcs LIST Comma-separated NPC names (default: alicanto,corca,guac)
32
- --rounds N Number of discussion rounds (default: 3)
33
-
34
- Example: /convene "How should we approach the database migration?" --npcs corca,guac,frederic
35
- """
36
- exit()
37
-
38
- npc_names = [n.strip() for n in npcs_str.split(',')]
39
-
40
- print(f"""
41
- ██████ ██████ ███ ██ ██ ██ ███████ ███ ██ ███████
42
- ██ ██ ██ ████ ██ ██ ██ ██ ████ ██ ██
43
- ██ ██ ██ ██ ██ ██ ██ ██ █████ ██ ██ ██ █████
44
- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
45
- ██████ ██████ ██ ████ ████ ███████ ██ ████ ███████
46
-
47
- Convening Discussion
48
- Topic: {topic}
49
- Participants: {', '.join(npc_names)}
50
- Rounds: {rounds}
51
- """)
52
-
53
- # Get NPC personas
54
- participants = []
55
- for name in npc_names:
56
- if team and hasattr(team, 'npcs') and name in team.npcs:
57
- target_npc = team.npcs[name]
58
- persona = getattr(target_npc, 'primary_directive', f'{name} specialist')
59
- participants.append({'name': name, 'persona': persona, 'npc': target_npc})
60
- else:
61
- participants.append({'name': name, 'persona': f'{name} - general assistant', 'npc': None})
62
-
63
- import random
64
-
65
- discussion_log = []
66
-
67
- for round_num in range(1, rounds + 1):
68
- print(colored(f"\n{'='*60}", "cyan"))
69
- print(colored(f" ROUND {round_num}/{rounds}", "cyan", attrs=["bold"]))
70
- print(colored(f"{'='*60}", "cyan"))
71
-
72
- round_contributions = []
73
-
74
- for participant in participants:
75
- name = participant['name']
76
- persona = participant['persona']
77
-
78
- # Build context from previous contributions
79
- prev_context = ""
80
- if discussion_log:
81
- prev_context = "\n\nPrevious discussion:\n"
82
- for entry in discussion_log[-len(participants)*2:]:
83
- prev_context += f"[{entry['speaker']}]: {entry['contribution'][:200]}...\n"
84
-
85
- if round_contributions:
86
- prev_context += "\nThis round so far:\n"
87
- for entry in round_contributions:
88
- prev_context += f"[{entry['speaker']}]: {entry['contribution'][:200]}...\n"
89
-
90
- prompt = f"""You are {name}. {persona}
91
-
92
- Topic under discussion: "{topic}"
93
- {prev_context}
94
-
95
- Provide your perspective on this topic. Be concise but insightful.
96
- Build on what others have said if applicable.
97
- If you disagree with something, explain why constructively.
98
- """
99
-
100
- print(colored(f"\n[{name}]:", "yellow", attrs=["bold"]))
101
-
102
- resp = get_llm_response(
103
- prompt,
104
- model=model,
105
- provider=provider,
106
- npc=participant.get('npc') or npc,
107
- temperature=0.7
108
- )
109
-
110
- contribution = str(resp.get('response', ''))
111
- print(contribution)
112
-
113
- entry = {
114
- 'round': round_num,
115
- 'speaker': name,
116
- 'contribution': contribution
117
- }
118
- round_contributions.append(entry)
119
- discussion_log.append(entry)
120
-
121
- # Sample a followup from another participant
122
- other_participants = [p for p in participants if p['name'] != name]
123
- if other_participants:
124
- followup_participant = random.choice(other_participants)
125
- followup_name = followup_participant['name']
126
- followup_persona = followup_participant['persona']
127
-
128
- followup_prompt = f"""You are {followup_name}. {followup_persona}
129
-
130
- Topic: "{topic}"
131
-
132
- {name} just said: "{contribution[:500]}"
133
-
134
- Respond briefly to this specific point - agree, disagree, build on it, or ask a clarifying question.
135
- Keep it to 2-3 sentences.
136
- """
137
-
138
- print(colored(f"\n [{followup_name} responds]:", "cyan"))
139
-
140
- followup_resp = get_llm_response(
141
- followup_prompt,
142
- model=model,
143
- provider=provider,
144
- npc=followup_participant.get('npc') or npc,
145
- temperature=0.7
146
- )
147
-
148
- followup_contribution = str(followup_resp.get('response', ''))
149
- print(f" {followup_contribution}")
150
-
151
- discussion_log.append({
152
- 'round': round_num,
153
- 'speaker': followup_name,
154
- 'contribution': followup_contribution,
155
- 'type': 'followup'
156
- })
157
-
158
- # Probability of original speaker responding back vs someone else
159
- if random.random() < 0.4:
160
- # Original speaker responds
161
- responder = participant
162
- responder_name = name
163
- else:
164
- # Sample from others (could be followup person or someone else)
165
- responder = random.choice(other_participants)
166
- responder_name = responder['name']
167
-
168
- if random.random() < 0.6: # 60% chance of a counter-response
169
- counter_prompt = f"""You are {responder_name}. {responder['persona']}
170
-
171
- Topic: "{topic}"
172
-
173
- {followup_name} responded: "{followup_contribution}"
174
-
175
- Brief reaction (1-2 sentences). Move the discussion forward.
176
- """
177
-
178
- print(colored(f"\n [{responder_name}]:", "magenta"))
179
-
180
- counter_resp = get_llm_response(
181
- counter_prompt,
182
- model=model,
183
- provider=provider,
184
- npc=responder.get('npc') or npc,
185
- temperature=0.7
186
- )
187
-
188
- counter_contribution = str(counter_resp.get('response', ''))
189
- print(f" {counter_contribution}")
190
-
191
- discussion_log.append({
192
- 'round': round_num,
193
- 'speaker': responder_name,
194
- 'contribution': counter_contribution,
195
- 'type': 'counter'
196
- })
197
-
198
- # Synthesis
199
- print(colored(f"\n{'='*60}", "green"))
200
- print(colored(" SYNTHESIS", "green", attrs=["bold"]))
201
- print(colored(f"{'='*60}", "green"))
202
-
203
- all_contributions = "\n".join([
204
- f"[{e['speaker']} - Round {e['round']}]: {e['contribution']}"
205
- for e in discussion_log
206
- ])
207
-
208
- synthesis_prompt = f"""As the convener of this discussion on "{topic}", synthesize the key points:
209
-
210
- Full discussion:
211
- {all_contributions}
212
-
213
- Provide:
214
- 1. Key agreements and consensus points
215
- 2. Areas of disagreement or tension
216
- 3. Novel ideas that emerged
217
- 4. Recommended next steps or actions
218
- """
219
-
220
- resp = get_llm_response(synthesis_prompt, model=model, provider=provider, npc=npc, temperature=0.4)
221
- synthesis = str(resp.get('response', ''))
222
- print(synthesis)
223
-
224
- context['output'] = synthesis
225
- context['messages'] = messages
226
- context['convene_result'] = {
227
- 'topic': topic,
228
- 'participants': npc_names,
229
- 'rounds': rounds,
230
- 'discussion': discussion_log,
231
- 'synthesis': synthesis
232
- }