npcsh 1.1.13__tar.gz → 1.1.14__tar.gz

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 (87) hide show
  1. {npcsh-1.1.13 → npcsh-1.1.14}/PKG-INFO +1 -1
  2. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/_state.py +3 -3
  3. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh.egg-info/PKG-INFO +1 -1
  4. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh.egg-info/SOURCES.txt +2 -1
  5. {npcsh-1.1.13 → npcsh-1.1.14}/setup.py +1 -1
  6. npcsh-1.1.14/tests/test_tool_routing.py +81 -0
  7. {npcsh-1.1.13 → npcsh-1.1.14}/LICENSE +0 -0
  8. {npcsh-1.1.13 → npcsh-1.1.14}/README.md +0 -0
  9. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/__init__.py +0 -0
  10. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/alicanto.py +0 -0
  11. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/build.py +0 -0
  12. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/completion.py +0 -0
  13. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/config.py +0 -0
  14. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/corca.py +0 -0
  15. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/execution.py +0 -0
  16. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/guac.py +0 -0
  17. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/mcp_helpers.py +0 -0
  18. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/mcp_server.py +0 -0
  19. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc.py +0 -0
  20. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/alicanto.npc +0 -0
  21. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/alicanto.png +0 -0
  22. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/corca.npc +0 -0
  23. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/corca.png +0 -0
  24. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/corca_example.png +0 -0
  25. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/foreman.npc +0 -0
  26. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/frederic.npc +0 -0
  27. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/frederic4.png +0 -0
  28. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/guac.png +0 -0
  29. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/code/python.jinx +0 -0
  30. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/code/sh.jinx +0 -0
  31. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/code/sql.jinx +0 -0
  32. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/modes/alicanto.jinx +0 -0
  33. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/modes/corca.jinx +0 -0
  34. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/modes/guac.jinx +0 -0
  35. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/modes/plonk.jinx +0 -0
  36. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/modes/pti.jinx +0 -0
  37. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/modes/spool.jinx +0 -0
  38. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/modes/wander.jinx +0 -0
  39. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/modes/yap.jinx +0 -0
  40. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/npc_studio/npc-studio.jinx +0 -0
  41. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/agent.jinx +0 -0
  42. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/chat.jinx +0 -0
  43. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/cmd.jinx +0 -0
  44. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/compress.jinx +0 -0
  45. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/core/build.jinx +0 -0
  46. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/core/compile.jinx +0 -0
  47. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/core/help.jinx +0 -0
  48. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/core/init.jinx +0 -0
  49. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/core/jinxs.jinx +0 -0
  50. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/core/set.jinx +0 -0
  51. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/edit_file.jinx +0 -0
  52. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/load_file.jinx +0 -0
  53. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/ots.jinx +0 -0
  54. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/roll.jinx +0 -0
  55. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/sample.jinx +0 -0
  56. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/search.jinx +0 -0
  57. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/serve.jinx +0 -0
  58. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/sleep.jinx +0 -0
  59. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/trigger.jinx +0 -0
  60. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/usage.jinx +0 -0
  61. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/jinxs/utils/vixynt.jinx +0 -0
  62. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/kadiefa.npc +0 -0
  63. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/kadiefa.png +0 -0
  64. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/npcsh.ctx +0 -0
  65. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/npcsh_sibiji.png +0 -0
  66. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/plonk.npc +0 -0
  67. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/plonk.png +0 -0
  68. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/plonkjr.npc +0 -0
  69. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/plonkjr.png +0 -0
  70. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/sibiji.npc +0 -0
  71. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/sibiji.png +0 -0
  72. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/spool.png +0 -0
  73. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npc_team/yap.png +0 -0
  74. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/npcsh.py +0 -0
  75. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/parsing.py +0 -0
  76. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/plonk.py +0 -0
  77. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/pti.py +0 -0
  78. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/routes.py +0 -0
  79. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/spool.py +0 -0
  80. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/ui.py +0 -0
  81. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/wander.py +0 -0
  82. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh/yap.py +0 -0
  83. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh.egg-info/dependency_links.txt +0 -0
  84. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh.egg-info/entry_points.txt +0 -0
  85. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh.egg-info/requires.txt +0 -0
  86. {npcsh-1.1.13 → npcsh-1.1.14}/npcsh.egg-info/top_level.txt +0 -0
  87. {npcsh-1.1.13 → npcsh-1.1.14}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: npcsh
3
- Version: 1.1.13
3
+ Version: 1.1.14
4
4
  Summary: npcsh is a command-line toolkit for using AI agents in novel ways.
5
5
  Home-page: https://github.com/NPC-Worldwide/npcsh
6
6
  Author: Christopher Agostino
@@ -2524,8 +2524,7 @@ def process_pipeline_command(
2524
2524
  # Only add tool_choice for providers that support it (not gemini)
2525
2525
  is_gemini = (exec_provider and "gemini" in exec_provider.lower()) or \
2526
2526
  (exec_model and "gemini" in exec_model.lower())
2527
- if not is_gemini:
2528
- llm_kwargs["tool_choice"] = {"type": "auto"}
2527
+ llm_kwargs["tool_choice"] = 'auto'
2529
2528
 
2530
2529
  llm_result = get_llm_response(
2531
2530
  full_llm_cmd,
@@ -2552,7 +2551,8 @@ def process_pipeline_command(
2552
2551
  images=state.attachments,
2553
2552
  stream=stream_final,
2554
2553
  context=info,
2555
- extra_globals=application_globals_for_jinx
2554
+ extra_globals=application_globals_for_jinx,
2555
+ tool_capable=tool_capable,
2556
2556
  )
2557
2557
  except KeyboardInterrupt:
2558
2558
  print(colored("\nLLM processing interrupted by user.", "yellow"))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: npcsh
3
- Version: 1.1.13
3
+ Version: 1.1.14
4
4
  Summary: npcsh is a command-line toolkit for using AI agents in novel ways.
5
5
  Home-page: https://github.com/NPC-Worldwide/npcsh
6
6
  Author: Christopher Agostino
@@ -81,4 +81,5 @@ npcsh/npc_team/jinxs/utils/core/compile.jinx
81
81
  npcsh/npc_team/jinxs/utils/core/help.jinx
82
82
  npcsh/npc_team/jinxs/utils/core/init.jinx
83
83
  npcsh/npc_team/jinxs/utils/core/jinxs.jinx
84
- npcsh/npc_team/jinxs/utils/core/set.jinx
84
+ npcsh/npc_team/jinxs/utils/core/set.jinx
85
+ tests/test_tool_routing.py
@@ -78,7 +78,7 @@ extra_files = package_files("npcsh/npc_team/")
78
78
 
79
79
  setup(
80
80
  name="npcsh",
81
- version="1.1.13",
81
+ version="1.1.14",
82
82
  packages=find_packages(exclude=["tests*"]),
83
83
  install_requires=base_requirements, # Only install base requirements by default
84
84
  extras_require={
@@ -0,0 +1,81 @@
1
+ import pytest
2
+
3
+ import npcsh._state as state_module
4
+ from npcsh._state import ShellState, process_pipeline_command
5
+
6
+
7
+ @pytest.fixture(autouse=True)
8
+ def stub_available_models(monkeypatch):
9
+ monkeypatch.setattr(state_module, "get_locally_available_models", lambda path: {})
10
+
11
+
12
+ def test_model_supports_tool_calls_uses_heuristics(monkeypatch):
13
+ # Force ollama inspection to be inconclusive so heuristics are used.
14
+ monkeypatch.setattr(state_module, "_ollama_supports_tools", lambda model: None)
15
+ assert not state_module.model_supports_tool_calls("gemma3:4b", "ollama")
16
+ assert state_module.model_supports_tool_calls("qwen3:0.6b", "ollama")
17
+
18
+
19
+ def test_react_flow_used_for_non_tool_models(tmp_path, monkeypatch):
20
+ calls = {"check": 0, "llm": 0}
21
+
22
+ def fake_check_llm_command(*args, **kwargs):
23
+ calls["check"] += 1
24
+ return {"output": "react-path", "messages": kwargs.get("messages", [])}
25
+
26
+ monkeypatch.setattr(state_module, "model_supports_tool_calls", lambda m, p: False)
27
+ monkeypatch.setattr(state_module, "check_llm_command", fake_check_llm_command)
28
+ monkeypatch.setattr(state_module, "get_llm_response", lambda *a, **k: None)
29
+
30
+ shell_state = ShellState(current_path=str(tmp_path))
31
+ updated_state, output = process_pipeline_command(
32
+ "explain something", None, shell_state, stream_final=False, router=None
33
+ )
34
+
35
+ assert calls["check"] == 1
36
+ assert output == "react-path"
37
+ # user message should be appended
38
+ assert updated_state.messages and updated_state.messages[0]["role"] == "user"
39
+
40
+
41
+ def test_tool_call_flow_for_tool_capable_models(tmp_path, monkeypatch):
42
+ calls = {"check": 0, "llm": 0}
43
+
44
+ def fake_get_llm_response(*args, **kwargs):
45
+ calls["llm"] += 1
46
+ msgs = kwargs.get("messages", [])
47
+ return {"response": "tool-route", "messages": msgs + [{"role": "assistant", "content": "tool-route"}]}
48
+
49
+ monkeypatch.setattr(state_module, "model_supports_tool_calls", lambda m, p: True)
50
+ monkeypatch.setattr(state_module, "get_llm_response", fake_get_llm_response)
51
+ monkeypatch.setattr(
52
+ state_module,
53
+ "collect_llm_tools",
54
+ lambda _state: (
55
+ [
56
+ {
57
+ "type": "function",
58
+ "function": {"name": "dummy", "description": "d", "parameters": {"type": "object", "properties": {}}},
59
+ }
60
+ ],
61
+ {"dummy": lambda **kwargs: "ok"},
62
+ ),
63
+ )
64
+ monkeypatch.setattr(
65
+ state_module,
66
+ "check_llm_command",
67
+ lambda *args, **kwargs: (
68
+ calls.__setitem__("check", calls["check"] + 1)
69
+ or {"output": "should-not-run", "messages": kwargs.get("messages", [])}
70
+ ),
71
+ )
72
+
73
+ shell_state = ShellState(current_path=str(tmp_path))
74
+ updated_state, output = process_pipeline_command(
75
+ "explain something", None, shell_state, stream_final=False, router=None
76
+ )
77
+
78
+ assert calls["llm"] == 1
79
+ assert calls["check"] == 0
80
+ assert output == "tool-route"
81
+ assert updated_state.messages and updated_state.messages[-1]["role"] == "assistant"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes