Skip to content

Commit 4ef9197

Browse files
authored
Merge pull request #97 from cagostino/chris/calc_tool_bug
Chris/calc tool bug
2 parents 35c7c2a + 88347b7 commit 4ef9197

File tree

9 files changed

+61
-184
lines changed

9 files changed

+61
-184
lines changed

npcsh/llm_funcs.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,8 @@ def handle_tool_call(
956956
retrieved_docs=None,
957957
n_docs: int = 5,
958958
stream=False,
959+
n_attempts=3,
960+
attempt=0,
959961
) -> Union[str, Dict[str, Any]]:
960962
"""
961963
Function Description:
@@ -1000,9 +1002,12 @@ def handle_tool_call(
10001002
The user wants to use the tool '{tool_name}' with the following request:
10011003
'{command}'
10021004
Here is the tool file:
1003-
{tool}
1005+
```
1006+
{tool.to_dict()}
1007+
```
10041008
10051009
Please extract the required inputs for the tool as a JSON object.
1010+
They must be exactly as they are named in the tool.
10061011
Return only the JSON object without any markdown formatting.
10071012
"""
10081013
if npc and hasattr(npc, "shared_context"):
@@ -1015,6 +1020,7 @@ def handle_tool_call(
10151020

10161021
# print(f"Tool prompt: {prompt}")
10171022

1023+
# print(prompt)
10181024
response = get_llm_response(
10191025
prompt,
10201026
format="json",
@@ -1048,8 +1054,30 @@ def handle_tool_call(
10481054
if inp not in input_values:
10491055
missing_inputs.append(inp)
10501056
if len(missing_inputs) > 0:
1051-
print(f"Missing required inputs for tool '{tool_name}': {missing_inputs}")
1052-
return f"Missing inputs for tool '{tool_name}': {missing_inputs}"
1057+
# print(f"Missing required inputs for tool '{tool_name}': {missing_inputs}")
1058+
if attempt < n_attempts:
1059+
print(f"attempt {attempt+1} to generate inputs failed, trying again")
1060+
print("missing inputs", missing_inputs)
1061+
print("llm response", response)
1062+
print("input values", input_values)
1063+
return handle_tool_call(
1064+
command,
1065+
tool_name,
1066+
command_history,
1067+
model=model,
1068+
provider=provider,
1069+
messages=messages,
1070+
npc=npc,
1071+
retrieved_docs=retrieved_docs,
1072+
n_docs=n_docs,
1073+
stream=stream,
1074+
attempt=attempt + 1,
1075+
n_attempts=n_attempts,
1076+
)
1077+
return {
1078+
"output": f"Missing inputs for tool '{tool_name}': {missing_inputs}",
1079+
"messages": messages,
1080+
}
10531081

10541082
# try:
10551083
tool_output = tool.execute(

npcsh/npc_compiler.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,9 @@ def __init__(
323323
self.model = model
324324
self.db_conn = db_conn
325325
self.tables = self.db_conn.execute(
326-
"SELECT name FROM sqlite_master WHERE type='table';"
326+
"SELECT name, sql FROM sqlite_master WHERE type='table';"
327327
).fetchall()
328+
328329
self.provider = provider
329330
self.api_url = api_url
330331
self.all_tools = all_tools or []

npcsh/npc_team/tools/calculator.tool

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
tool_name: "calculator"
22
description: "A tool to simplify and evaluate mathematical expressions"
33
inputs:
4-
- "expression"
4+
- expression
55
steps:
66
- engine: python
77
code: |
8-
output = eval(inputs['expression'])
8+
output = eval('{{ expression }}')

npcsh/npc_team/tools/image_generation.tool

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ steps:
77
- engine: "python"
88
code: |
99
# Clean and prepare the prompt
10-
image_prompt = inputs['prompt'].strip()
10+
image_prompt = '{{prompt}}'.strip()
1111
#print(f"Prompt: {image_prompt}")
1212

1313
# Generate the image

npcsh/npc_team/tools/screen_cap.tool

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ steps:
1515

1616
out = capture_screenshot(npc = npc, full = True)
1717

18-
llm_response = analyze_image_base( inputs['prompt'] + "\n\nAttached is a screenshot of my screen currently. Please use this to evaluate the situation. If the user asked for you to explain what's on their screen or something similar, they are referring to the details contained within the attached image. You do not need to actually view their screen. You do not need to mention that you cannot view or interpret images directly. You only need to answer the user's request based on the attached screenshot!",
18+
llm_response = analyze_image_base( '{{prompt}}' + "\n\nAttached is a screenshot of my screen currently. Please use this to evaluate the situation. If the user asked for you to explain what's on their screen or something similar, they are referring to the details contained within the attached image. You do not need to actually view their screen. You do not need to mention that you cannot view or interpret images directly. You only need to answer the user's request based on the attached screenshot!",
1919
out['file_path'],
2020
out['filename'],
2121
npc=npc,

npcsh/npc_team/tools/sql_executor.tool

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@ tool_name: sql_executor
22
description: Execute SQL queries on the ~/npcsh_history.db and display the result. The database contains only information about conversations and other user-provided data. It does not store any information about individual files.
33
inputs:
44
- sql_query
5-
- interpret: "false" # Note that this is not a boolean, but a string
5+
- interpret: false # Note that this is not a boolean, but a string
66

77
steps:
88
- engine: python
99
code: |
1010
import pandas as pd
11-
df = pd.read_sql_query(inputs['sql_query'], npc.db_conn)
11+
try:
12+
df = pd.read_sql_query('{{sql_query}}', npc.db_conn)
13+
except pandas.errors.DatabaseError as e:
14+
df = pd.DataFrame({'Error': [str(e)]})
15+
16+
1217
output = df.to_string()
1318

1419
- engine: natural
1520
code: |
16-
{% if inputs['interpret'] == "true" %}
21+
{% if interpret %}
1722
Here is the result of the SQL query:
1823
```
1924
{{ df.to_string() }} # Convert DataFrame to string for a nicer display

npcsh/npc_team/tools/stats_calculator.tool

Lines changed: 0 additions & 164 deletions
This file was deleted.

npcsh/shell_helpers.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,10 +1659,11 @@ def parse_piped_command(current_command):
16591659

16601660
try:
16611661
command_parts = shlex.split(current_command)
1662+
# print(command_parts)
16621663
except ValueError:
16631664
# Fallback if quote parsing fails
16641665
command_parts = current_command.split()
1665-
1666+
# print(command_parts)
16661667
# Base command is the first part
16671668
base_command = command_parts[0]
16681669

@@ -1725,13 +1726,16 @@ def execute_command(
17251726
output = ""
17261727
location = os.getcwd()
17271728
db_conn = sqlite3.connect(db_path)
1729+
# print(f"Executing command: {command}")
17281730
if len(command.strip()) == 0:
17291731
return {"messages": messages, "output": output}
1732+
17301733
if messages is None:
17311734
messages = []
17321735

17331736
# Split commands by pipe, preserving the original parsing logic
17341737
commands = command.split("|")
1738+
# print(commands)
17351739
available_models = get_available_models()
17361740

17371741
# Track piped output between commands
@@ -1801,21 +1805,22 @@ def execute_command(
18011805
subcommands = result.get("subcommands", [])
18021806

18031807
else:
1808+
# print(single_command)
18041809
try:
18051810
command_parts = shlex.split(single_command)
1811+
# print(command_parts)
18061812
except ValueError as e:
18071813
if "No closing quotation" in str(e):
18081814
# Attempt to close unclosed quotes
1809-
single_command += '"'
1815+
if single_command.count('"') % 2 == 1:
1816+
single_command += '"'
1817+
elif single_command.count("'") % 2 == 1:
1818+
single_command += "'"
18101819
try:
18111820
command_parts = shlex.split(single_command)
18121821
except ValueError:
1813-
return {
1814-
"messages": messages,
1815-
"output": "Error: Unmatched quotation in command",
1816-
}
1817-
else:
1818-
return {"messages": messages, "output": f"Error: {str(e)}"}
1822+
# fall back to regular split
1823+
command_parts = single_command.split()
18191824

18201825
# ALL EXISTING COMMAND HANDLING LOGIC REMAINS UNCHANGED
18211826
if command_parts[0] in interactive_commands:
@@ -1912,6 +1917,8 @@ def execute_command(
19121917
output = colored(f"Error executing command: {e}", "red")
19131918

19141919
else:
1920+
# print("LLM command")
1921+
# print(single_command)
19151922
# LLM command processing with existing logic
19161923
output = check_llm_command(
19171924
single_command,

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def get_setup_message():
5757

5858
setup(
5959
name="npcsh",
60-
version="0.3.7",
60+
version="0.3.8",
6161
packages=find_packages(exclude=["tests*"]),
6262
install_requires=[
6363
"redis",

0 commit comments

Comments
 (0)