npcsh 1.1.3__py3-none-any.whl → 1.1.5__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 (106) hide show
  1. npcsh/_state.py +48 -64
  2. npcsh/npc_team/corca_example.png +0 -0
  3. npcsh/npc_team/jinxs/{python_executor.jinx → code/python.jinx} +1 -1
  4. npcsh/npc_team/jinxs/{bash_executer.jinx → code/sh.jinx} +1 -1
  5. npcsh/npc_team/jinxs/code/sql.jinx +18 -0
  6. npcsh/npc_team/jinxs/modes/alicanto.jinx +88 -0
  7. npcsh/npc_team/jinxs/modes/corca.jinx +28 -0
  8. npcsh/npc_team/jinxs/modes/guac.jinx +46 -0
  9. npcsh/npc_team/jinxs/modes/plonk.jinx +57 -0
  10. npcsh/npc_team/jinxs/modes/pti.jinx +28 -0
  11. npcsh/npc_team/jinxs/modes/spool.jinx +40 -0
  12. npcsh/npc_team/jinxs/modes/wander.jinx +81 -0
  13. npcsh/npc_team/jinxs/modes/yap.jinx +25 -0
  14. npcsh/npc_team/jinxs/utils/breathe.jinx +20 -0
  15. npcsh/npc_team/jinxs/utils/core/build.jinx +65 -0
  16. npcsh/npc_team/jinxs/utils/core/compile.jinx +50 -0
  17. npcsh/npc_team/jinxs/utils/core/help.jinx +52 -0
  18. npcsh/npc_team/jinxs/utils/core/init.jinx +41 -0
  19. npcsh/npc_team/jinxs/utils/core/jinxs.jinx +32 -0
  20. npcsh/npc_team/jinxs/utils/core/set.jinx +40 -0
  21. npcsh/npc_team/jinxs/{edit_file.jinx → utils/edit_file.jinx} +1 -1
  22. npcsh/npc_team/jinxs/utils/flush.jinx +39 -0
  23. npcsh/npc_team/jinxs/utils/npc-studio.jinx +82 -0
  24. npcsh/npc_team/jinxs/utils/ots.jinx +92 -0
  25. npcsh/npc_team/jinxs/utils/plan.jinx +33 -0
  26. npcsh/npc_team/jinxs/utils/roll.jinx +66 -0
  27. npcsh/npc_team/jinxs/utils/sample.jinx +56 -0
  28. npcsh/npc_team/jinxs/utils/search/brainblast.jinx +51 -0
  29. npcsh/npc_team/jinxs/utils/search/rag.jinx +70 -0
  30. npcsh/npc_team/jinxs/utils/search/search.jinx +192 -0
  31. npcsh/npc_team/jinxs/utils/serve.jinx +29 -0
  32. npcsh/npc_team/jinxs/utils/sleep.jinx +116 -0
  33. npcsh/npc_team/jinxs/utils/trigger.jinx +36 -0
  34. npcsh/npc_team/jinxs/utils/vixynt.jinx +129 -0
  35. npcsh/npcsh.py +14 -12
  36. npcsh/routes.py +80 -1420
  37. npcsh-1.1.5.data/data/npcsh/npc_team/alicanto.jinx +88 -0
  38. npcsh-1.1.5.data/data/npcsh/npc_team/brainblast.jinx +51 -0
  39. npcsh-1.1.5.data/data/npcsh/npc_team/breathe.jinx +20 -0
  40. npcsh-1.1.5.data/data/npcsh/npc_team/build.jinx +65 -0
  41. npcsh-1.1.5.data/data/npcsh/npc_team/compile.jinx +50 -0
  42. npcsh-1.1.5.data/data/npcsh/npc_team/corca.jinx +28 -0
  43. npcsh-1.1.5.data/data/npcsh/npc_team/corca_example.png +0 -0
  44. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/edit_file.jinx +1 -1
  45. npcsh-1.1.5.data/data/npcsh/npc_team/flush.jinx +39 -0
  46. npcsh-1.1.5.data/data/npcsh/npc_team/guac.jinx +46 -0
  47. npcsh-1.1.5.data/data/npcsh/npc_team/help.jinx +52 -0
  48. npcsh-1.1.5.data/data/npcsh/npc_team/init.jinx +41 -0
  49. npcsh-1.1.5.data/data/npcsh/npc_team/jinxs.jinx +32 -0
  50. npcsh-1.1.5.data/data/npcsh/npc_team/npc-studio.jinx +82 -0
  51. npcsh-1.1.5.data/data/npcsh/npc_team/ots.jinx +92 -0
  52. npcsh-1.1.5.data/data/npcsh/npc_team/plan.jinx +33 -0
  53. npcsh-1.1.5.data/data/npcsh/npc_team/plonk.jinx +57 -0
  54. npcsh-1.1.5.data/data/npcsh/npc_team/pti.jinx +28 -0
  55. npcsh-1.1.3.data/data/npcsh/npc_team/python_executor.jinx → npcsh-1.1.5.data/data/npcsh/npc_team/python.jinx +1 -1
  56. npcsh-1.1.5.data/data/npcsh/npc_team/rag.jinx +70 -0
  57. npcsh-1.1.5.data/data/npcsh/npc_team/roll.jinx +66 -0
  58. npcsh-1.1.5.data/data/npcsh/npc_team/sample.jinx +56 -0
  59. npcsh-1.1.5.data/data/npcsh/npc_team/search.jinx +192 -0
  60. npcsh-1.1.5.data/data/npcsh/npc_team/serve.jinx +29 -0
  61. npcsh-1.1.5.data/data/npcsh/npc_team/set.jinx +40 -0
  62. npcsh-1.1.3.data/data/npcsh/npc_team/bash_executer.jinx → npcsh-1.1.5.data/data/npcsh/npc_team/sh.jinx +1 -1
  63. npcsh-1.1.5.data/data/npcsh/npc_team/sleep.jinx +116 -0
  64. npcsh-1.1.5.data/data/npcsh/npc_team/spool.jinx +40 -0
  65. npcsh-1.1.5.data/data/npcsh/npc_team/sql.jinx +18 -0
  66. npcsh-1.1.5.data/data/npcsh/npc_team/trigger.jinx +36 -0
  67. npcsh-1.1.5.data/data/npcsh/npc_team/vixynt.jinx +129 -0
  68. npcsh-1.1.5.data/data/npcsh/npc_team/wander.jinx +81 -0
  69. npcsh-1.1.5.data/data/npcsh/npc_team/yap.jinx +25 -0
  70. {npcsh-1.1.3.dist-info → npcsh-1.1.5.dist-info}/METADATA +1 -1
  71. npcsh-1.1.5.dist-info/RECORD +132 -0
  72. npcsh/npc_team/jinxs/image_generation.jinx +0 -29
  73. npcsh/npc_team/jinxs/internet_search.jinx +0 -31
  74. npcsh/npc_team/jinxs/screen_cap.jinx +0 -25
  75. npcsh-1.1.3.data/data/npcsh/npc_team/image_generation.jinx +0 -29
  76. npcsh-1.1.3.data/data/npcsh/npc_team/internet_search.jinx +0 -31
  77. npcsh-1.1.3.data/data/npcsh/npc_team/screen_cap.jinx +0 -25
  78. npcsh-1.1.3.dist-info/RECORD +0 -78
  79. /npcsh/npc_team/jinxs/{kg_search.jinx → utils/search/kg_search.jinx} +0 -0
  80. /npcsh/npc_team/jinxs/{memory_search.jinx → utils/search/memory_search.jinx} +0 -0
  81. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/alicanto.npc +0 -0
  82. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/alicanto.png +0 -0
  83. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/corca.npc +0 -0
  84. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/corca.png +0 -0
  85. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/foreman.npc +0 -0
  86. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/frederic.npc +0 -0
  87. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/frederic4.png +0 -0
  88. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/guac.png +0 -0
  89. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/kadiefa.npc +0 -0
  90. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/kadiefa.png +0 -0
  91. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/kg_search.jinx +0 -0
  92. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/memory_search.jinx +0 -0
  93. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/npcsh.ctx +0 -0
  94. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/npcsh_sibiji.png +0 -0
  95. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/plonk.npc +0 -0
  96. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/plonk.png +0 -0
  97. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/plonkjr.npc +0 -0
  98. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/plonkjr.png +0 -0
  99. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/sibiji.npc +0 -0
  100. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/sibiji.png +0 -0
  101. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/spool.png +0 -0
  102. {npcsh-1.1.3.data → npcsh-1.1.5.data}/data/npcsh/npc_team/yap.png +0 -0
  103. {npcsh-1.1.3.dist-info → npcsh-1.1.5.dist-info}/WHEEL +0 -0
  104. {npcsh-1.1.3.dist-info → npcsh-1.1.5.dist-info}/entry_points.txt +0 -0
  105. {npcsh-1.1.3.dist-info → npcsh-1.1.5.dist-info}/licenses/LICENSE +0 -0
  106. {npcsh-1.1.3.dist-info → npcsh-1.1.5.dist-info}/top_level.txt +0 -0
npcsh/_state.py CHANGED
@@ -1875,17 +1875,15 @@ def execute_slash_command(command: str,
1875
1875
  all_command_parts = shlex.split(command)
1876
1876
  command_name = all_command_parts[0].lstrip('/')
1877
1877
 
1878
-
1879
1878
  if command_name in ['n', 'npc']:
1880
1879
  npc_to_switch_to = all_command_parts[1] if len(all_command_parts) > 1 else None
1881
1880
  if npc_to_switch_to and state.team and npc_to_switch_to in state.team.npcs:
1882
1881
  state.npc = state.team.npcs[npc_to_switch_to]
1883
- return state, f"Switched to NPC: {npc_to_switch_to}"
1882
+ return state, {"output": f"Switched to NPC: {npc_to_switch_to}", "messages": state.messages}
1884
1883
  else:
1885
1884
  available_npcs = list(state.team.npcs.keys()) if state.team else []
1886
- return state, colored(f"NPC '{npc_to_switch_to}' not found. Available NPCs: {', '.join(available_npcs)}", "red")
1885
+ return state, {"output": colored(f"NPC '{npc_to_switch_to}' not found. Available NPCs: {', '.join(available_npcs)}", "red"), "messages": state.messages}
1887
1886
 
1888
-
1889
1887
  handler = router.get_route(command_name)
1890
1888
  if handler:
1891
1889
  parsed_flags, positional_args = parse_generic_command_flags(all_command_parts[1:])
@@ -1901,12 +1899,10 @@ def execute_slash_command(command: str,
1901
1899
  'positional_args': positional_args,
1902
1900
  'plonk_context': state.team.shared_context.get('PLONK_CONTEXT') if state.team and hasattr(state.team, 'shared_context') else None,
1903
1901
 
1904
-
1905
1902
  'model': state.npc.model if isinstance(state.npc, NPC) and state.npc.model else state.chat_model,
1906
1903
  'provider': state.npc.provider if isinstance(state.npc, NPC) and state.npc.provider else state.chat_provider,
1907
1904
  'npc': state.npc,
1908
1905
 
1909
-
1910
1906
  'sprovider': state.search_provider,
1911
1907
  'emodel': state.embedding_model,
1912
1908
  'eprovider': state.embedding_provider,
@@ -1927,7 +1923,6 @@ def execute_slash_command(command: str,
1927
1923
 
1928
1924
  render_markdown(f'- Calling {command_name} handler {kwarg_part} ')
1929
1925
 
1930
-
1931
1926
  if 'model' in normalized_flags and 'provider' not in normalized_flags:
1932
1927
  inferred_provider = lookup_provider(normalized_flags['model'])
1933
1928
  if inferred_provider:
@@ -1943,20 +1938,22 @@ def execute_slash_command(command: str,
1943
1938
  handler_kwargs.update(normalized_flags)
1944
1939
 
1945
1940
  try:
1946
- result_dict = handler(command=command,
1947
- **handler_kwargs)
1948
- if isinstance(result_dict, dict):
1949
- state.messages = result_dict.get("messages", state.messages)
1950
- return state, result_dict
1941
+ result = handler(command=command, **handler_kwargs)
1942
+
1943
+ if isinstance(result, dict):
1944
+ state.messages = result.get("messages", state.messages)
1945
+ return state, result
1946
+ elif isinstance(result, str):
1947
+ return state, {"output": result, "messages": state.messages}
1951
1948
  else:
1952
- return state, result_dict
1949
+ return state, {"output": str(result), "messages": state.messages}
1950
+
1953
1951
  except Exception as e:
1954
1952
  import traceback
1955
1953
  print(f"Error executing slash command '{command_name}':", file=sys.stderr)
1956
1954
  traceback.print_exc()
1957
- return state, colored(f"Error executing slash command '{command_name}': {e}", "red")
1955
+ return state, {"output": colored(f"Error executing slash command '{command_name}': {e}", "red"), "messages": state.messages}
1958
1956
 
1959
-
1960
1957
  active_npc = state.npc if isinstance(state.npc, NPC) else None
1961
1958
  jinx_to_execute = None
1962
1959
  executor = None
@@ -1970,14 +1967,12 @@ def execute_slash_command(command: str,
1970
1967
  if jinx_to_execute:
1971
1968
  args = all_command_parts[1:]
1972
1969
  try:
1973
-
1974
1970
  input_values = {}
1975
1971
  if hasattr(jinx_to_execute, 'inputs') and jinx_to_execute.inputs:
1976
1972
  for i, input_name in enumerate(jinx_to_execute.inputs):
1977
1973
  if i < len(args):
1978
1974
  input_values[input_name] = args[i]
1979
1975
 
1980
-
1981
1976
  if isinstance(executor, NPC):
1982
1977
  jinx_output = jinx_to_execute.execute(
1983
1978
  input_values=input_values,
@@ -1994,25 +1989,24 @@ def execute_slash_command(command: str,
1994
1989
  )
1995
1990
  if isinstance(jinx_output, dict) and 'messages' in jinx_output:
1996
1991
  state.messages = jinx_output['messages']
1997
- return state, str(jinx_output.get('output', jinx_output))
1992
+ return state, jinx_output
1998
1993
  elif isinstance(jinx_output, dict):
1999
- return state, str(jinx_output.get('output', jinx_output))
2000
- else:
2001
1994
  return state, jinx_output
1995
+ else:
1996
+ return state, {"output": str(jinx_output), "messages": state.messages}
2002
1997
 
2003
1998
  except Exception as e:
2004
1999
  import traceback
2005
2000
  print(f"Error executing jinx '{command_name}':", file=sys.stderr)
2006
2001
  traceback.print_exc()
2007
- return state, colored(f"Error executing jinx '{command_name}': {e}", "red")
2002
+ return state, {"output": colored(f"Error executing jinx '{command_name}': {e}", "red"), "messages": state.messages}
2003
+
2008
2004
  if state.team and command_name in state.team.npcs:
2009
2005
  new_npc = state.team.npcs[command_name]
2010
2006
  state.npc = new_npc
2011
- return state, f"Switched to NPC: {new_npc.name}"
2012
-
2013
- return state, colored(f"Unknown slash command, jinx, or NPC: {command_name}", "red")
2014
-
2007
+ return state, {"output": f"Switched to NPC: {new_npc.name}", "messages": state.messages}
2015
2008
 
2009
+ return state, {"output": colored(f"Unknown slash command, jinx, or NPC: {command_name}", "red"), "messages": state.messages}
2016
2010
 
2017
2011
 
2018
2012
  def process_pipeline_command(
@@ -2190,7 +2184,7 @@ def check_mode_switch(command:str , state: ShellState):
2190
2184
  def execute_command(
2191
2185
  command: str,
2192
2186
  state: ShellState,
2193
- review = True,
2187
+ review = False,
2194
2188
  router = None,
2195
2189
  command_history = None,
2196
2190
  ) -> Tuple[ShellState, Any]:
@@ -2319,7 +2313,6 @@ def execute_command(
2319
2313
  return state, response['response']
2320
2314
 
2321
2315
  def setup_shell() -> Tuple[CommandHistory, Team, Optional[NPC]]:
2322
-
2323
2316
  setup_npcsh_config()
2324
2317
 
2325
2318
  db_path = os.getenv("NPCSH_DB_PATH", HISTORY_DB_DEFAULT_PATH)
@@ -2327,14 +2320,11 @@ def setup_shell() -> Tuple[CommandHistory, Team, Optional[NPC]]:
2327
2320
  os.makedirs(os.path.dirname(db_path), exist_ok=True)
2328
2321
  command_history = CommandHistory(db_path)
2329
2322
 
2330
-
2331
2323
  if not is_npcsh_initialized():
2332
2324
  print("Initializing NPCSH...")
2333
2325
  initialize_base_npcs_if_needed(db_path)
2334
2326
  print("NPCSH initialization complete. Restart or source ~/.npcshrc.")
2335
2327
 
2336
-
2337
-
2338
2328
  try:
2339
2329
  history_file = setup_readline()
2340
2330
  atexit.register(save_readline_history)
@@ -2397,7 +2387,6 @@ def setup_shell() -> Tuple[CommandHistory, Team, Optional[NPC]]:
2397
2387
  team_dir = global_team_path
2398
2388
  default_forenpc_name = "sibiji"
2399
2389
 
2400
-
2401
2390
  team_ctx = {}
2402
2391
  team_ctx_path = get_team_ctx_path(team_dir)
2403
2392
  if team_ctx_path:
@@ -2410,34 +2399,12 @@ def setup_shell() -> Tuple[CommandHistory, Team, Optional[NPC]]:
2410
2399
 
2411
2400
  print('forenpc_name:', forenpc_name)
2412
2401
 
2413
- if team_ctx.get("use_global_jinxs", False):
2414
- jinxs_dir = os.path.expanduser("~/.npcsh/npc_team/jinxs")
2415
- else:
2416
- jinxs_dir = os.path.join(team_dir, "jinxs")
2417
-
2418
- jinxs_list = load_jinxs_from_directory(jinxs_dir)
2419
- jinxs_dict = {jinx.jinx_name: jinx for jinx in jinxs_list}
2420
-
2421
- forenpc_obj = None
2422
2402
  forenpc_path = os.path.join(team_dir, f"{forenpc_name}.npc")
2423
-
2424
2403
  print('forenpc_path:', forenpc_path)
2425
2404
 
2426
- if os.path.exists(forenpc_path):
2427
- forenpc_obj = NPC(file = forenpc_path,
2428
- jinxs=jinxs_list,
2429
- db_conn=command_history.engine)
2430
- if forenpc_obj.model is None:
2431
- forenpc_obj.model= team_ctx.get("model", initial_state.chat_model)
2432
- if forenpc_obj.provider is None:
2433
- forenpc_obj.provider=team_ctx.get('provider', initial_state.chat_provider)
2434
-
2435
- else:
2436
- print(f"Warning: Forenpc file '{forenpc_name}.npc' not found in {team_dir}.")
2437
-
2438
- team = Team(team_path=team_dir,
2439
- forenpc=forenpc_obj,
2440
- jinxs=jinxs_dict)
2405
+ team = Team(team_path=team_dir, db_conn=command_history.engine)
2406
+
2407
+ forenpc_obj = team.forenpc if hasattr(team, 'forenpc') and team.forenpc else None
2441
2408
 
2442
2409
  for npc_name, npc_obj in team.npcs.items():
2443
2410
  if not npc_obj.model:
@@ -2445,12 +2412,12 @@ def setup_shell() -> Tuple[CommandHistory, Team, Optional[NPC]]:
2445
2412
  if not npc_obj.provider:
2446
2413
  npc_obj.provider = initial_state.chat_provider
2447
2414
 
2448
-
2449
2415
  if team.forenpc and isinstance(team.forenpc, NPC):
2450
2416
  if not team.forenpc.model:
2451
2417
  team.forenpc.model = initial_state.chat_model
2452
2418
  if not team.forenpc.provider:
2453
2419
  team.forenpc.provider = initial_state.chat_provider
2420
+
2454
2421
  team_name_from_ctx = team_ctx.get("name")
2455
2422
  if team_name_from_ctx:
2456
2423
  team.name = team_name_from_ctx
@@ -2464,11 +2431,19 @@ def setup_shell() -> Tuple[CommandHistory, Team, Optional[NPC]]:
2464
2431
  else:
2465
2432
  team.name = "npcsh"
2466
2433
 
2467
-
2468
2434
  return command_history, team, forenpc_obj
2469
2435
 
2470
-
2471
-
2436
+ def initialize_router_with_jinxs(team, router):
2437
+ """Load global and team Jinxs into router"""
2438
+ global_jinxs_dir = os.path.expanduser("~/.npcsh/npc_team/jinxs")
2439
+ router.load_jinx_routes(global_jinxs_dir)
2440
+
2441
+ if team and team.team_path:
2442
+ team_jinxs_dir = os.path.join(team.team_path, "jinxs")
2443
+ if os.path.exists(team_jinxs_dir):
2444
+ router.load_jinx_routes(team_jinxs_dir)
2445
+
2446
+ return router
2472
2447
 
2473
2448
  from npcpy.memory.memory_processor import memory_approval_ui
2474
2449
  from npcpy.ft.memory_trainer import MemoryTrainer
@@ -2688,13 +2663,22 @@ def process_result(
2688
2663
  result_state.attachments = None
2689
2664
 
2690
2665
  final_output_str = None
2691
- output_content = output.get('output') if isinstance(output, dict) else output
2692
- model_for_stream = output.get('model', active_npc.model) if isinstance(output, dict) else active_npc.model
2693
- provider_for_stream = output.get('provider', active_npc.provider) if isinstance(output, dict) else active_npc.provider
2666
+
2667
+ if isinstance(output, dict):
2668
+ output_content = output.get('output')
2669
+ model_for_stream = output.get('model', active_npc.model)
2670
+ provider_for_stream = output.get('provider', active_npc.provider)
2671
+ else:
2672
+ output_content = output
2673
+ model_for_stream = active_npc.model
2674
+ provider_for_stream = active_npc.provider
2694
2675
 
2695
2676
  print('\n')
2696
2677
  if user_input == '/help':
2697
- render_markdown(output.get('output'))
2678
+ if isinstance(output_content, str):
2679
+ render_markdown(output_content)
2680
+ else:
2681
+ render_markdown(str(output_content))
2698
2682
  elif result_state.stream_output:
2699
2683
  final_output_str = print_and_process_stream_with_markdown(
2700
2684
  output_content,
Binary file
@@ -1,4 +1,4 @@
1
- jinx_name: python_executor
1
+ jinx_name: python
2
2
  description: Execute scripts with python. You must set the ultimate result as the "output"
3
3
  variable. It MUST be a string.
4
4
  Do not add unnecessary print statements.
@@ -1,4 +1,4 @@
1
- jinx_name: bash_executor
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.
3
3
  inputs:
4
4
  - bash_command
@@ -0,0 +1,18 @@
1
+ jinx_name: sql_executor
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. Returns a LLM summary so no post-summary is required
5
+ inputs:
6
+ - sql_query
7
+ - user_query
8
+ - interpret: true
9
+ steps:
10
+ - engine: python
11
+ code: |
12
+ import pandas as pd
13
+ query = "{{ sql_query }}"
14
+ try:
15
+ df = pd.read_sql_query(query, npc.db_conn)
16
+ except Exception as e:
17
+ df = pd.DataFrame({'Error': [str(e)]})
18
+ output = df.to_string()
@@ -0,0 +1,88 @@
1
+ jinx_name: "alicanto"
2
+ description: "Conduct deep research with multiple perspectives, identifying gold insights and cliff warnings"
3
+ inputs:
4
+ - query: "" # Required research query.
5
+ - num_npcs: 5 # Number of NPCs to involve in research.
6
+ - depth: 3 # Depth of research.
7
+ - model: "" # LLM model to use. Defaults to NPCSH_CHAT_MODEL or NPC's model.
8
+ - provider: "" # LLM provider to use. Defaults to NPCSH_CHAT_PROVIDER or NPC's provider.
9
+ - max_steps: 20 # Maximum number of steps in Alicanto research.
10
+ - skip_research: True # Whether to skip the research phase.
11
+ - exploration: "" # Exploration factor (float).
12
+ - creativity: "" # Creativity factor (float).
13
+ - format: "" # Output format (report, summary, full).
14
+ steps:
15
+ - name: "conduct_alicanto_research"
16
+ engine: "python"
17
+ code: |
18
+ import traceback
19
+ import logging
20
+ from npcsh.alicanto import alicanto
21
+ # Assuming NPCSH_CHAT_MODEL and NPCSH_CHAT_PROVIDER are accessible
22
+
23
+ query = context.get('query')
24
+ num_npcs = int(context.get('num_npcs', 5)) # Ensure int type
25
+ depth = int(context.get('depth', 3)) # Ensure int type
26
+ llm_model = context.get('model')
27
+ llm_provider = context.get('provider')
28
+ max_steps = int(context.get('max_steps', 20)) # Ensure int type
29
+ skip_research = context.get('skip_research', True)
30
+ exploration_factor = context.get('exploration')
31
+ creativity_factor = context.get('creativity')
32
+ output_format = context.get('format')
33
+ output_messages = context.get('messages', [])
34
+ current_npc = context.get('npc')
35
+
36
+ if not query or not query.strip():
37
+ context['output'] = "Usage: /alicanto <research query> [--num-npcs N] [--depth N] [--exploration 0.3] [--creativity 0.5] [--format report|summary|full]"
38
+ context['messages'] = output_messages
39
+ exit()
40
+
41
+ # Fallback for model/provider if not explicitly set in Jinx inputs
42
+ if not llm_model and current_npc and current_npc.model:
43
+ llm_model = current_npc.model
44
+ if not llm_provider and current_npc and current_npc.provider:
45
+ llm_provider = current_npc.provider
46
+
47
+ # Final fallbacks (these would ideally come from npcsh._state config)
48
+ # Assuming NPCSH_CHAT_MODEL and NPCSH_CHAT_PROVIDER exist and are imported implicitly or set by environment
49
+ # Hardcoding defaults for demonstration if not available through NPC or _state
50
+ if not llm_model: llm_model = "gemini-1.5-pro"
51
+ if not llm_provider: llm_provider = "gemini"
52
+
53
+ try:
54
+ logging.info(f"Starting Alicanto research on: {query}")
55
+
56
+ alicanto_kwargs = {
57
+ 'query': query,
58
+ 'num_npcs': num_npcs,
59
+ 'depth': depth,
60
+ 'model': llm_model,
61
+ 'provider': llm_provider,
62
+ 'max_steps': max_steps,
63
+ 'skip_research': skip_research,
64
+ }
65
+
66
+ if exploration_factor: alicanto_kwargs['exploration_factor'] = float(exploration_factor)
67
+ if creativity_factor: alicanto_kwargs['creativity_factor'] = float(creativity_factor)
68
+ if output_format: alicanto_kwargs['output_format'] = output_format
69
+
70
+ result = alicanto(**alicanto_kwargs)
71
+
72
+ output_result = ""
73
+ if isinstance(result, dict):
74
+ if "integration" in result:
75
+ output_result = result["integration"]
76
+ else:
77
+ output_result = "Alicanto research completed. Full results available in returned data."
78
+ else:
79
+ output_result = str(result)
80
+
81
+ context['output'] = output_result
82
+ context['messages'] = output_messages
83
+ context['alicanto_result'] = result # Store full result in context
84
+ except Exception as e:
85
+ traceback.print_exc()
86
+ logging.error(f"Error during Alicanto research: {e}")
87
+ context['output'] = f"Error during Alicanto research: {e}"
88
+ context['messages'] = output_messages
@@ -0,0 +1,28 @@
1
+ jinx_name: "corca"
2
+ description: "Enter the Corca MCP-powered agentic shell. Usage: /corca [--mcp-server-path path]"
3
+ inputs:
4
+ - command: "/corca" # The full command string, e.g., "/corca --mcp-server-path /tmp/mcp"
5
+ steps:
6
+ - name: "enter_corca"
7
+ engine: "python"
8
+ code: |
9
+ # Assume npcsh._state and enter_corca_mode are accessible in the environment
10
+
11
+ from npcsh._state import initial_state, setup_shell
12
+ from npcsh.corca import enter_corca_mode
13
+
14
+
15
+ full_command_str = context.get('command')
16
+ output_messages = context.get('messages', [])
17
+
18
+ command_history, team, default_npc = setup_shell()
19
+
20
+ result = enter_corca_mode(
21
+ command=full_command_str,
22
+ command_history=command_history,
23
+ shell_state=initial_state,
24
+ **context # Pass all context as kwargs to enter_corca_mode as it expects
25
+ )
26
+
27
+ context['output'] = result.get('output', 'Entered Corca mode.')
28
+ context['messages'] = result.get('messages', output_messages)
@@ -0,0 +1,46 @@
1
+ jinx_name: "guac"
2
+ description: "Enter guac mode for plotting and data visualization."
3
+ inputs:
4
+ - config_dir: "" # Optional configuration directory.
5
+ - plots_dir: "" # Optional directory for plots.
6
+ - refresh_period: 100 # Refresh period for guac mode.
7
+ - lang: "" # Language setting for guac mode.
8
+ steps:
9
+ - name: "enter_guac"
10
+ engine: "python"
11
+ code: |
12
+ import os
13
+ from sqlalchemy import create_engine
14
+ from npcpy.npc_compiler import NPC, Team
15
+ from npcsh.guac import enter_guac_mode
16
+
17
+ config_dir = context.get('config_dir')
18
+ plots_dir = context.get('plots_dir')
19
+ refresh_period = context.get('refresh_period')
20
+ lang = context.get('lang')
21
+ output_messages = context.get('messages', [])
22
+
23
+ db_path = os.path.expanduser('~/npcsh_history.db')
24
+ db_conn = create_engine(f'sqlite:///{db_path}')
25
+
26
+ npc_file = os.path.expanduser('~/.npcsh/guac/npc_team/guac.npc')
27
+ npc_team_dir = os.path.expanduser('~/.npcsh/guac/npc_team/')
28
+
29
+ # Ensure directories exist for guac NPC/Team
30
+ os.makedirs(os.path.dirname(npc_file), exist_ok=True)
31
+
32
+ guac_npc = NPC(file=npc_file, db_conn=db_conn)
33
+ guac_team = Team(npc_team_dir, db_conn=db_conn)
34
+
35
+ enter_guac_mode(
36
+ npc=guac_npc,
37
+ team=guac_team,
38
+ config_dir=config_dir,
39
+ plots_dir=plots_dir,
40
+ npc_team_dir=npc_team_dir,
41
+ refresh_period=int(refresh_period), # Ensure int type
42
+ lang=lang
43
+ )
44
+
45
+ context['output'] = 'Exiting Guac Mode'
46
+ context['messages'] = output_messages
@@ -0,0 +1,57 @@
1
+ jinx_name: "plonk"
2
+ description: "Use vision model to interact with GUI. Usage: /plonk <task description>"
3
+ inputs:
4
+ - task_description: "" # Required task description for GUI interaction.
5
+ - vmodel: "" # Vision model to use. Defaults to NPCSH_VISION_MODEL or NPC's model.
6
+ - vprovider: "" # Vision model provider. Defaults to NPCSH_VISION_PROVIDER or NPC's provider.
7
+ steps:
8
+ - name: "execute_plonk"
9
+ engine: "python"
10
+ code: |
11
+ import traceback
12
+ from npcsh.plonk import execute_plonk_command, format_plonk_summary
13
+ # Assuming NPCSH_VISION_MODEL and NPCSH_VISION_PROVIDER are accessible
14
+
15
+ task_description = context.get('task_description')
16
+ vision_model = context.get('vmodel')
17
+ vision_provider = context.get('vprovider')
18
+ plonk_context = context.get('plonk_context') # Passed from original context
19
+ current_npc = context.get('npc')
20
+ output_messages = context.get('messages', [])
21
+
22
+ if not task_description or not task_description.strip():
23
+ context['output'] = "Usage: /plonk <task_description> [--vmodel model_name] [--vprovider provider_name]"
24
+ context['messages'] = output_messages
25
+ exit()
26
+
27
+ # Fallback for model/provider if not explicitly set in Jinx inputs
28
+ if not vision_model and current_npc and current_npc.model:
29
+ vision_model = current_npc.model
30
+ if not vision_provider and current_npc and current_npc.provider:
31
+ vision_provider = current_npc.provider
32
+
33
+ # Final fallbacks (these would ideally come from npcsh._state config)
34
+ if not vision_model: vision_model = "gemini-1.5-pro-vision" # Example default
35
+ if not vision_provider: vision_provider = "gemini" # Example default
36
+
37
+ try:
38
+ summary_data = execute_plonk_command(
39
+ request=task_description,
40
+ model=vision_model,
41
+ provider=vision_provider,
42
+ npc=current_npc,
43
+ plonk_context=plonk_context,
44
+ debug=True # Assuming debug is often desired for plonk
45
+ )
46
+
47
+ if summary_data and isinstance(summary_data, list):
48
+ output_report = format_plonk_summary(summary_data)
49
+ context['output'] = output_report
50
+ else:
51
+ context['output'] = "Plonk command did not complete within the maximum number of iterations."
52
+
53
+ except Exception as e:
54
+ traceback.print_exc()
55
+ context['output'] = f"Error executing plonk command: {e}"
56
+
57
+ context['messages'] = output_messages
@@ -0,0 +1,28 @@
1
+ jinx_name: "pti"
2
+ description: "Enter Pardon-The-Interruption mode for human-in-the-loop reasoning."
3
+ inputs:
4
+ - command_args: "" # The full command string or specific arguments for PTI mode.
5
+ steps:
6
+ - name: "enter_pti"
7
+ engine: "python"
8
+ code: |
9
+ import traceback
10
+ from npcsh.pti import enter_pti_mode
11
+
12
+ command_args = context.get('command_args', '') # The full command string from router
13
+ output_messages = context.get('messages', [])
14
+
15
+ try:
16
+ # enter_pti_mode likely expects the full command string for its own parsing
17
+ result = enter_pti_mode(command=command_args, **context)
18
+
19
+ if isinstance(result, dict):
20
+ context['output'] = result.get('output', 'Entered PTI mode.')
21
+ context['messages'] = result.get('messages', output_messages)
22
+ else:
23
+ context['output'] = str(result)
24
+ context['messages'] = output_messages
25
+ except Exception as e:
26
+ traceback.print_exc()
27
+ context['output'] = f"Error entering pti mode: {e}"
28
+ context['messages'] = output_messages
@@ -0,0 +1,40 @@
1
+ jinx_name: "spool"
2
+ description: "Enter interactive chat (spool) mode"
3
+ inputs: [] # Spool mode typically takes its parameters directly from the environment/kwargs
4
+ steps:
5
+ - name: "enter_spool"
6
+ engine: "python"
7
+ code: |
8
+ import traceback
9
+ from npcpy.npc_compiler import NPC, Team
10
+ from npcsh.spool import enter_spool_mode
11
+
12
+ output_messages = context.get('messages', [])
13
+ current_npc = context.get('npc')
14
+ current_team = context.get('team')
15
+
16
+ try:
17
+ # Handle potential string NPC name if passed from CLI
18
+ if isinstance(current_npc, str) and current_team:
19
+ npc_name = current_npc
20
+ if npc_name in current_team.npcs:
21
+ current_npc = current_team.npcs[npc_name]
22
+ else:
23
+ context['output'] = f"Error: NPC '{npc_name}' not found in team. Available NPCs: {', '.join(current_team.npcs.keys())}"
24
+ context['messages'] = output_messages
25
+ exit()
26
+ context['npc'] = current_npc # Ensure the NPC object is updated in context
27
+
28
+ result = enter_spool_mode(**context) # Pass all context as kwargs
29
+
30
+ if isinstance(result, dict):
31
+ context['output'] = result.get('output', 'Exited Spool Mode.')
32
+ context['messages'] = result.get('messages', output_messages)
33
+ else:
34
+ context['output'] = str(result)
35
+ context['messages'] = output_messages
36
+
37
+ except Exception as e:
38
+ traceback.print_exc()
39
+ context['output'] = f"Error entering spool mode: {e}"
40
+ context['messages'] = output_messages
@@ -0,0 +1,81 @@
1
+ jinx_name: "wander"
2
+ description: "Enter wander mode (experimental)"
3
+ inputs:
4
+ - problem: "" # The problem to wander about.
5
+ - environment: "" # Optional environment for wander mode.
6
+ - low_temp: 0.5 # Low temperature setting for LLM.
7
+ - high_temp: 1.9 # High temperature setting for LLM.
8
+ - interruption_likelihood: 1.0 # Likelihood of interruption.
9
+ - sample_rate: 0.4 # Sample rate.
10
+ - n_high_temp_streams: 5 # Number of high temperature streams.
11
+ - include_events: False # Whether to include events.
12
+ - num_events: 3 # Number of events to include.
13
+ steps:
14
+ - name: "enter_wander"
15
+ engine: "python"
16
+ code: |
17
+ import traceback
18
+ from npcsh.wander import enter_wander_mode
19
+
20
+ problem = context.get('problem')
21
+ environment = context.get('environment')
22
+ low_temp = float(context.get('low_temp', 0.5)) # Ensure float type
23
+ high_temp = float(context.get('high_temp', 1.9)) # Ensure float type
24
+ interruption_likelihood = float(context.get('interruption_likelihood', 1.0)) # Ensure float type
25
+ sample_rate = float(context.get('sample_rate', 0.4)) # Ensure float type
26
+ n_high_temp_streams = int(context.get('n_high_temp_streams', 5)) # Ensure int type
27
+ include_events = context.get('include_events', False) # Boolean type
28
+ num_events = int(context.get('num_events', 3)) # Ensure int type
29
+
30
+ current_npc = context.get('npc')
31
+ llm_model = context.get('model')
32
+ llm_provider = context.get('provider')
33
+ output_messages = context.get('messages', [])
34
+
35
+ if not problem or not problem.strip():
36
+ context['output'] = "Usage: /wander <problem> [key=value...]"
37
+ context['messages'] = output_messages
38
+ exit()
39
+
40
+ # Fallback for model/provider if not explicitly set in Jinx inputs
41
+ if not llm_model and current_npc and current_npc.model:
42
+ llm_model = current_npc.model
43
+ if not llm_provider and current_npc and current_npc.provider:
44
+ llm_provider = current_npc.provider
45
+
46
+ # Final fallbacks (these would ideally come from npcsh._state config)
47
+ if not llm_model: llm_model = "gemini-1.5-pro" # Example default
48
+ if not llm_provider: llm_provider = "gemini" # Example default
49
+
50
+ try:
51
+ mode_args = {
52
+ 'problem': problem,
53
+ 'npc': current_npc,
54
+ 'model': llm_model,
55
+ 'provider': llm_provider,
56
+ 'environment': environment,
57
+ 'low_temp': low_temp,
58
+ 'high_temp': high_temp,
59
+ 'interruption_likelihood': interruption_likelihood,
60
+ 'sample_rate': sample_rate,
61
+ 'n_high_temp_streams': n_high_temp_streams,
62
+ 'include_events': include_events,
63
+ 'num_events': num_events
64
+ }
65
+
66
+ result = enter_wander_mode(**mode_args)
67
+
68
+ output_result = ""
69
+ if isinstance(result, list) and result:
70
+ output_result = result[-1].get("insight", "Wander mode session complete.")
71
+ else:
72
+ output_result = str(result) if result else "Wander mode session complete."
73
+
74
+ output_messages.append({"role": "assistant", "content": output_result})
75
+ context['output'] = output_result
76
+ context['messages'] = output_messages
77
+
78
+ except Exception as e:
79
+ traceback.print_exc()
80
+ context['output'] = f"Error during wander mode: {e}"
81
+ context['messages'] = output_messages