PikoAi 0.1.12__py3-none-any.whl → 0.1.13__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.
@@ -7,7 +7,7 @@ import time
7
7
  sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../')))
8
8
  from Utils.ter_interface import TerminalInterface
9
9
  from Utils.executor_utils import parse_tool_call
10
- from Agents.Executor.prompts import get_system_prompt, get_task_prompt # Import prompts
10
+ from Agents.Executor.prompts import get_executor_prompt # Import prompts
11
11
 
12
12
  from typing import Optional
13
13
  from mistralai.models.sdkerror import SDKError # This might be an issue if LiteLLM doesn't use SDKError
@@ -22,7 +22,7 @@ from llm_interface.llm import LiteLLMInterface # Import LiteLLMInterface
22
22
  from Tools import tool_manager
23
23
 
24
24
  class RateLimiter:
25
- def __init__(self, wait_time: float = 5.0, max_retries: int = 3):
25
+ def __init__(self, wait_time: float = 1.0, max_retries: int = 3):
26
26
  self.wait_time = wait_time
27
27
  self.max_retries = max_retries
28
28
  self.last_call_time = None
@@ -44,7 +44,7 @@ class executor:
44
44
  # self.shell_executor = ShellExecutor() # Initialize ShellExecutor
45
45
  self.message = [
46
46
  {"role": "system", "content": self.system_prompt},
47
- {"role": "user", "content": self.task_prompt}
47
+ {"role": "user", "content": self.user_prompt}
48
48
  ]
49
49
  self.terminal = TerminalInterface()
50
50
  self.initialize_llm()
@@ -71,8 +71,7 @@ class executor:
71
71
  config = json.load(config_file)
72
72
  working_dir = config.get("working_directory", "")
73
73
 
74
- self.system_prompt = get_system_prompt(self.user_prompt, working_dir, tools_details)
75
- self.task_prompt = get_task_prompt()
74
+ self.system_prompt = get_executor_prompt(working_dir, tools_details)
76
75
 
77
76
  def run_inference(self):
78
77
  retries = 0
@@ -112,11 +111,6 @@ class executor:
112
111
  self.run_task()
113
112
 
114
113
  def run_task(self):
115
- # Remove tools_details parameter since it's in the prompt
116
- task_message = self.task_prompt
117
-
118
- self.message.append({"role": "user", "content": task_message})
119
-
120
114
  iteration = 0
121
115
  task_done = False
122
116
 
@@ -128,13 +122,13 @@ class executor:
128
122
  if tool_call:
129
123
  tool_name = tool_call['tool_name']
130
124
  tool_input = tool_call['input']
131
- print(f"\nIdentified tool call: {tool_name} with input {tool_input}")
125
+
132
126
 
133
127
  # Call the tool and append the result (no confirmation or special logic)
134
128
  try:
135
129
  tool_output_result = tool_manager.call_tool(tool_name, tool_input)
136
- self.terminal.tool_output_log(tool_output_result, tool_name)
137
- print(tool_output_result)
130
+ if tool_name not in ['execute_python_code', 'execute_shell_command']:
131
+ self.terminal.tool_output_log(tool_output_result, tool_name)
138
132
  self.message.append({"role": "user", "content": tool_output_result})
139
133
  except ValueError as e:
140
134
  error_msg = str(e)
@@ -142,10 +136,6 @@ class executor:
142
136
  self.message.append({"role": "user", "content": f"Tool Error: {error_msg}"})
143
137
 
144
138
  else: # Not a tool call, could be a direct response or requires clarification
145
- # This part handles responses that are not formatted as tool calls.
146
- # It might be a final answer, a question, or just conversational text.
147
- # The existing logic for TASK_DONE or asking for next step handles this.
148
- # No specific code/shell parsing here anymore as they are tools.
149
139
  pass # Explicitly pass if no tool call and no old code/shell logic.
150
140
 
151
141
  # Check if task is done
@@ -2,13 +2,15 @@
2
2
 
3
3
  import platform
4
4
 
5
- def get_system_prompt(user_prompt: str, working_dir: str, tools_details: str) -> str:
5
+ def get_executor_prompt(working_dir: str, tools_details: str) -> str:
6
6
  """
7
- Returns the system prompt for the Executor agent.
7
+ Returns the main executor prompt.
8
8
  """
9
9
  os_name = platform.system()
10
- return f"""You are a terminal-based operating system assistant designed to help users achieve their goals by executing tasks provided in text format. The current user goal is: {user_prompt}.
10
+ # tools_details is passed to the LLM but not directly included in this prompt string.
11
+ return f"""You are a terminal-based operating system assistant designed to help users achieve their goals.
11
12
 
13
+ This is important information about the environment:
12
14
  Working Directory: {working_dir}
13
15
  Operating System: {os_name}
14
16
 
@@ -31,53 +33,26 @@ You must break down the user's goal into smaller steps and perform one action at
31
33
  }}
32
34
  }}
33
35
  <<END_TOOL_CALL>>
34
- This includes executing Python code and shell commands:
35
- `execute_python_code`: {{"code": "your_python_code_here"}}
36
- `execute_shell_command`: {{"command": "your_shell_command_here"}}
36
+ - **Code Execution**: Write Python code when no tool is suitable or when custom logic is needed.
37
+ the code written will be executed immediately and not saved.
37
38
  - **Direct Response**: Provide a direct answer if the task doesn't require tools or code.
38
39
 
39
- ### Important Notes:
40
- - Perform only one action per step.
41
- - Always evaluate the output of each action before deciding the next step.
42
- - Continue performing actions until the user's goal is fully achieved. Only then, include 'TASK_DONE' in your response.
43
- - Do not end the task immediately after a tool call or code execution without evaluating its output.
44
-
45
- Now, carefully plan your approach and start with the first step to achieve the user's goal.
46
- """
47
40
 
48
- def get_task_prompt() -> str:
49
- """
50
- Returns the task prompt for the Executor agent.
51
- """
52
- return """
53
- Following are the things that you must read carefully and remember:
41
+ These are the things that you learned from the mistakes you made earlier :
42
+ - When given a data file and asked to understand data/do data analysis/ data visualisation or similar stuff
43
+ do not use file reader and read the whole data. Only use python code to do the analysis
44
+ - This is a standard Python environment, not a python notebook or a repl. previous execution
45
+ context is not preserved between executions.
46
+ - Don't execute dangerous commands like rm -rf * or access sensitive files
47
+ - If you are stuck, have tried to fix an issue (e.g., a linter error) multiple times (e.g., 3 times) without success, or need clarification, ask the USER for input. Explain the situation clearly.
48
+ - Upon creating anything (like a new project, website, data analysis png) always show the output.You can do this by executing shell commands.
49
+ - the python/shell code execution in tool call will be executed immediately and output will be shown. it wont be saved.
54
50
 
55
- - For tool calls, use:
56
- <<TOOL_CALL>>
57
- {
58
- "tool_name": "name_of_tool",
59
- "input": {
60
- "key": "value" // Use the correct parameter name for each tool
61
- }
62
- }
63
- <<END_TOOL_CALL>>
64
- Remember that executing Python code and shell commands is now done through specific tool calls (`execute_python_code` and `execute_shell_command`).
65
51
 
66
- After each action, always evaluate the output to decide your next step. Only include 'TASK_DONE'
67
- When the entire task is completed. Do not end the task immediately after a tool call or code execution without
68
- checking its output.
69
- You can only execute a single tool call or code execution at a time, then check its ouput
70
- then proceed with the next call
71
- Use the working directory as the current directory for all file operations unless otherwise specified.
72
-
73
-
74
-
75
- These are the things that you learn't from the mistakes you made earlier :
76
-
77
- - When given a data file and asked to understand data/do data analysis/ data visualisation or similar stuff
78
- do not use file reader and read the whole data. Only use python code to do the analysis
79
- - This is a standard Python environment, not a python notebook or a repl. previous execution
80
- context is not preserved between executions.
81
- - You have a get_user_input tool to ask user more context before, in between or after tasks
52
+ ** Important **
53
+ - Perform only one action per step (either a single tool call or a single code execution).
54
+ - Always evaluate the output of each action before deciding the next step.
55
+ - Continue performing actions until the user's goal is fully achieved. Only then, include 'TASK_DONE' in your response if that is the required signal for completion.
56
+ - Do not end the task immediately after a tool call or code execution without evaluating its output.
82
57
 
83
- """
58
+ """
Env/python_executor.py CHANGED
@@ -58,7 +58,7 @@ try:
58
58
  except Exception as e:
59
59
  print(f"Error: {{str(e)}}")
60
60
  """
61
-
61
+
62
62
 
63
63
  try:
64
64
  # Execute the code in a subprocess
@@ -75,19 +75,14 @@ except Exception as e:
75
75
  stderr_data = []
76
76
  start_time = time.time()
77
77
 
78
- # First read all stdout
79
- for line in self.process.stdout:
80
- # Check for timeout
81
- if time.time() - start_time > 30:
82
- self.process.kill()
83
- return {
84
- 'success': False,
85
- 'output': 'Execution timed out after 30 seconds',
86
- 'error': 'Timeout error'
87
- }
88
-
89
- stdout_data.append(line)
90
- print(line, end='', flush=True) # Print in real-time
78
+ # Read stdout character by character
79
+ while True:
80
+ char = self.process.stdout.read(1)
81
+ if char == '' and self.process.poll() is not None:
82
+ break # Process ended and no more output
83
+ if char:
84
+ stdout_data.append(char)
85
+ print(char, end='', flush=True) # Print in real-time, no extra newline
91
86
 
92
87
  # Then read all stderr
93
88
  for line in self.process.stderr:
Env/shell.py CHANGED
@@ -114,21 +114,16 @@ class ShellExecutor(BaseEnv):
114
114
  stderr_data = []
115
115
  start_time = time.time()
116
116
 
117
- # First read all stdout
118
- for line in self.process.stdout:
119
- # Check for timeout
120
- if time.time() - start_time > 30:
121
- self.process.kill()
122
- return {
123
- 'success': False,
124
- 'output': 'Execution timed out after 30 seconds',
125
- 'error': 'Timeout error'
126
- }
127
-
128
- stdout_data.append(line)
129
- print(line, end='', flush=True) # Print in real-time
117
+ # First read all stdout character by character
118
+ while True:
119
+ char = self.process.stdout.read(1)
120
+ if char == '' and self.process.poll() is not None:
121
+ break # Process ended and no more output
122
+ if char:
123
+ stdout_data.append(char)
124
+ print(char, end='', flush=True) # Print in real-time, no extra newline
130
125
 
131
- # Then read all stderr
126
+ # Then read all stderr (can keep line-by-line or do char-by-char similarly)
132
127
  for line in self.process.stderr:
133
128
  # Check for timeout
134
129
  if time.time() - start_time > 30:
Utils/ter_interface.py CHANGED
@@ -51,72 +51,32 @@ class TerminalInterface:
51
51
 
52
52
  def process_markdown_chunk(self, chunk):
53
53
  """
54
- Process a chunk of markdown text, handling code blocks, shell commands, tool calls, and regular markdown.
54
+ Process a chunk of markdown text, handling tool calls and regular markdown.
55
55
  Args:
56
56
  chunk (str): A piece of markdown text to process
57
57
  """
58
- # Initialize tracking attributes if they don't exist yet
59
-
60
-
61
58
  self.buffer += chunk
62
59
  while "\n" in self.buffer:
63
60
  line, self.buffer = self.buffer.split("\n", 1)
64
61
  line_stripped = line.strip()
65
-
66
- # Handle code blocks
67
- if line_stripped.startswith("<<CODE>>"):
68
- if self.inside_code_block:
69
- # Closing code block
70
- self.console.print(Syntax(self.code_buffer, "python", theme="bw", line_numbers=False))
71
- self.inside_code_block = False
72
- self.code_buffer = ""
73
- else:
74
- # Opening code block
75
- self.inside_code_block = True
76
- self.code_lang = line_stripped[8:].strip() or "python" # default lang
77
-
78
- # Handle shell command blocks
79
- elif line_stripped.startswith("<<SHELL_COMMAND>>"):
80
- self.inside_shell_command = True
81
- self.shell_command_buffer = ""
82
- # Print a styled header for shell commands
83
- self.console.print("[bold yellow]Shell Command:[/bold yellow]")
84
-
85
- elif line_stripped.startswith("<<END_SHELL_COMMAND>>"):
86
- if self.inside_shell_command:
87
- # Closing shell command block
88
- self.console.print(Syntax(self.shell_command_buffer.strip(), "bash", theme="monokai", line_numbers=False))
89
- self.inside_shell_command = False
90
- self.shell_command_buffer = ""
91
-
62
+
92
63
  # Handle tool call opening delimiter - be more flexible with whitespace
93
- elif "<<TOOL_CALL>>" in line_stripped:
64
+ if "<<TOOL_CALL>>" in line_stripped:
94
65
  self.inside_tool_call = True
95
66
  self.tool_call_buffer = ""
96
- # Print a styled header for tool calls
97
67
  self.console.print("[bold cyan]Tool Call:[/bold cyan]")
98
-
68
+
99
69
  # Handle tool call closing delimiter - be more flexible with whitespace
100
70
  elif "<<END_TOOL_CALL>>" in line_stripped:
101
71
  self.console.print(Syntax('{"status": "end_tool_call"}', "json", theme="monokai", line_numbers=False))
102
72
  self.console.print("[bold cyan]--------------------------------[/bold cyan]")
103
73
  self.inside_tool_call = False
104
74
  self.tool_call_buffer = ""
105
-
106
- # Handle content inside code blocks
107
- elif self.inside_code_block:
108
- self.code_buffer += line + "\n"
109
-
110
- # Handle content inside shell command blocks
111
- elif self.inside_shell_command:
112
- self.shell_command_buffer += line + "\n"
113
-
75
+
114
76
  # Handle content inside tool calls
115
77
  elif self.inside_tool_call:
116
78
  self.tool_call_buffer += line + "\n"
117
- # Print the line with styling as it comes in
118
79
 
119
-
120
80
  # Regular markdown content
121
81
  else:
122
82
  self.console.print(Markdown(line))
@@ -125,14 +85,7 @@ class TerminalInterface:
125
85
  """
126
86
  Flush any remaining markdown content in the buffer.
127
87
  """
128
- if self.inside_code_block:
129
- self.console.print(Syntax(self.code_buffer, "python", theme="bw", line_numbers=False))
130
- self.inside_code_block = False
131
- elif self.inside_shell_command:
132
- self.console.print(Syntax(self.shell_command_buffer.strip(), "bash", theme="monokai", line_numbers=False))
133
-
134
- self.inside_shell_command = False
135
- elif hasattr(self, 'inside_tool_call') and self.inside_tool_call:
88
+ if hasattr(self, 'inside_tool_call') and self.inside_tool_call:
136
89
  # Handle case where tool call is not properly terminated
137
90
  self.console.print(Syntax(self.tool_call_buffer.strip(), "json", theme="monokai", line_numbers=False))
138
91
  self.console.print("[bold cyan]End Tool Call (forced)[/bold cyan]")
@@ -142,10 +95,7 @@ class TerminalInterface:
142
95
  self.console.print("━" * 80) # Print a solid line
143
96
  else:
144
97
  self.console.print(Markdown(self.buffer))
145
-
146
98
  self.buffer = ""
147
- self.code_buffer = ""
148
- self.shell_command_buffer = ""
149
99
  if hasattr(self, 'tool_call_buffer'):
150
100
  self.tool_call_buffer = ""
151
101
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PikoAi
3
- Version: 0.1.12
3
+ Version: 0.1.13
4
4
  Summary: An AI-powered task automation tool
5
5
  Home-page: https://github.com/nihaaaar22/OS-Assistant
6
6
  Author: Nihar S
@@ -2,15 +2,15 @@ OpenCopilot.py,sha256=vBAuU6MNhYdnyIIrDWOBSlxa0iyjADJLq5eCxUhlffw,12240
2
2
  cli.py,sha256=hY6KUxvKvJOFThZT--r6m2nzOEMIOVtiVptewsi9Z9w,13868
3
3
  Agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  Agents/Executor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- Agents/Executor/executor.py,sha256=RGYh4bmG5-cvsQPrlCTGNYzQbsnZcQt7eoIpEH9g6OY,8808
6
- Agents/Executor/prompts.py,sha256=bcVxBBCEda7JZtnA1KoMM8KayKAqFeQCP4lY6EbodzQ,3607
5
+ Agents/Executor/executor.py,sha256=-HvywqfroHd0QYNt5AN8vV7wjR-91hWPbSuvNzIVMMU,8191
6
+ Agents/Executor/prompts.py,sha256=dWmUiAloNN_NKwWgaG_IqHDhCX1O-VhwbadUL-16gZw,2903
7
7
  Env/__init__.py,sha256=KLe7UcNV5L395SxhMwbYGyu7KPrSNaoV_9QJo3mLop0,196
8
8
  Env/base_env.py,sha256=K4PoWwPXn3pKeu7_-JOlUuyNbyYQ9itMhQybFOm-3K4,1563
9
9
  Env/base_executor.py,sha256=awTwJ44CKWV4JO2KUHfHDX0p1Ujw55hlaL5oNYTEW9M,893
10
10
  Env/env.py,sha256=I3lOoyBJR5QNq3tWk_HVH6ncRx1vnilRYmj7b7h4jic,114
11
11
  Env/js_executor.py,sha256=tEAg5ho8Pa8LzxUbS1Idau8XuJWZZqPiNlvFPDwGkgc,2690
12
- Env/python_executor.py,sha256=1PIWL3Q8cgkQ4tvarf3d75dUTZoMF_dx_HoDho_zPEQ,4811
13
- Env/shell.py,sha256=kcWwaJwA2rbKqViAkRPTHaCKIGht9Yhjf2p4S57dHTs,8060
12
+ Env/python_executor.py,sha256=siiR-BivXKlCHoL6Jyb3aSQkHdZXCFMNo3c3rspHllA,4664
13
+ Env/shell.py,sha256=DuttZymCUM7QNRxIOPBB81bSBcgzH-wQdUADYridRTo,7987
14
14
  Env/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  Env/tests/test_python_executor.py,sha256=5kfs0cOf-RgWTOers_1wB0yvYSF-HrHPsraJ-PxgR50,3156
16
16
  Env/tests/test_shell_executor.py,sha256=-RcCdSUMoRAXHISIh0IR5MCutco80fX2S3sQBcinc_Q,1034
@@ -24,12 +24,12 @@ Tools/web_loader.py,sha256=PyZk2g7WngZT0tCLs9Danx20dYspnaZwy4rlVE9Sx_4,5054
24
24
  Tools/web_search.py,sha256=4EGq1VZqfDgG-_yXTd4_Ha1iEUcR-szdlgRV7oFPru4,1259
25
25
  Utils/__init__.py,sha256=oukU0ufroPRd8_N8d2xiFes9CTxSaw4NA6p2nS1kkSg,16
26
26
  Utils/executor_utils.py,sha256=WwK3TKgw_hG_crg7ijRaqfidYnnNXYbbs37vKZRYK-0,491
27
- Utils/ter_interface.py,sha256=Zay9mwyAyKYTNQAKOWXHAa3upo9TWprSf26STiHXk0g,6255
27
+ Utils/ter_interface.py,sha256=2k32kVxcxVBewXnjSGSPbx25ZLhKindEMtL6wSC_wL4,3829
28
28
  llm_interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  llm_interface/llm.py,sha256=tI_KDOW14QLWowA7bB3GPe2qjlk0sjS5fBavs9XD1fo,5185
30
- pikoai-0.1.12.dist-info/licenses/LICENSE,sha256=cELUVOboOAderKFp8bdtcM5VyJi61YH1oDbRhOuoQZw,1067
31
- pikoai-0.1.12.dist-info/METADATA,sha256=4wGQkBNIjYCR9di2BrQ4Jwj1k8lQogqnE8JPmua-uCo,2962
32
- pikoai-0.1.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
- pikoai-0.1.12.dist-info/entry_points.txt,sha256=xjZnheDymNDnQ0o84R0jZKEITrhNbzQWN-AhqfA_d6s,50
34
- pikoai-0.1.12.dist-info/top_level.txt,sha256=hWzBNE7UQsuNcENIOksGcJED08k3ZGRRn2X5jnStICU,53
35
- pikoai-0.1.12.dist-info/RECORD,,
30
+ pikoai-0.1.13.dist-info/licenses/LICENSE,sha256=cELUVOboOAderKFp8bdtcM5VyJi61YH1oDbRhOuoQZw,1067
31
+ pikoai-0.1.13.dist-info/METADATA,sha256=mjc1I8aWnP9tMaG0Mlvme1AX-dgDIul3ugC5C5yxbXc,2962
32
+ pikoai-0.1.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
+ pikoai-0.1.13.dist-info/entry_points.txt,sha256=xjZnheDymNDnQ0o84R0jZKEITrhNbzQWN-AhqfA_d6s,50
34
+ pikoai-0.1.13.dist-info/top_level.txt,sha256=hWzBNE7UQsuNcENIOksGcJED08k3ZGRRn2X5jnStICU,53
35
+ pikoai-0.1.13.dist-info/RECORD,,