patchpal 0.25.1__tar.gz → 0.25.3__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 (70) hide show
  1. {patchpal-0.25.1/patchpal.egg-info → patchpal-0.25.3}/PKG-INFO +1 -1
  2. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/__init__.py +1 -1
  3. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/agent/function_calling.py +27 -3
  4. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/cli/sandbox.py +21 -1
  5. {patchpal-0.25.1 → patchpal-0.25.3/patchpal.egg-info}/PKG-INFO +1 -1
  6. {patchpal-0.25.1 → patchpal-0.25.3}/LICENSE +0 -0
  7. {patchpal-0.25.1 → patchpal-0.25.3}/MANIFEST.in +0 -0
  8. {patchpal-0.25.1 → patchpal-0.25.3}/README.md +0 -0
  9. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/agent/__init__.py +0 -0
  10. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/agent/bedrock_profile_utils.py +0 -0
  11. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/agent/react.py +0 -0
  12. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/cli/__init__.py +0 -0
  13. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/cli/autopilot.py +0 -0
  14. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/cli/interactive.py +0 -0
  15. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/cli/mcp.py +0 -0
  16. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/cli/streaming.py +0 -0
  17. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/config.py +0 -0
  18. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/context.py +0 -0
  19. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/permissions.py +0 -0
  20. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/prompts/react_prompt.md +0 -0
  21. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/prompts/system_prompt.md +0 -0
  22. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/skills.py +0 -0
  23. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/__init__.py +0 -0
  24. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/audit.py +0 -0
  25. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/browser_tools.py +0 -0
  26. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/code_analysis.py +0 -0
  27. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/common.py +0 -0
  28. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/definitions.py +0 -0
  29. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/file_reading.py +0 -0
  30. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/file_writing.py +0 -0
  31. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/find_tool.py +0 -0
  32. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/grep_tool.py +0 -0
  33. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/image_handler.py +0 -0
  34. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/mcp.py +0 -0
  35. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/repo_map.py +0 -0
  36. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/shell_tools.py +0 -0
  37. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/todo_tools.py +0 -0
  38. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/tool_schema.py +0 -0
  39. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/user_interaction.py +0 -0
  40. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal/tools/web_tools.py +0 -0
  41. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal.egg-info/SOURCES.txt +0 -0
  42. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal.egg-info/dependency_links.txt +0 -0
  43. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal.egg-info/entry_points.txt +0 -0
  44. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal.egg-info/requires.txt +0 -0
  45. {patchpal-0.25.1 → patchpal-0.25.3}/patchpal.egg-info/top_level.txt +0 -0
  46. {patchpal-0.25.1 → patchpal-0.25.3}/pyproject.toml +0 -0
  47. {patchpal-0.25.1 → patchpal-0.25.3}/setup.cfg +0 -0
  48. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_agent.py +0 -0
  49. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_cli.py +0 -0
  50. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_config_dynamic.py +0 -0
  51. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_context.py +0 -0
  52. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_custom_tools.py +0 -0
  53. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_enabled_tools.py +0 -0
  54. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_find_tool.py +0 -0
  55. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_guardrails.py +0 -0
  56. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_image_blocking.py +0 -0
  57. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_maximum_security.py +0 -0
  58. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_mcp_config.py +0 -0
  59. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_memory.py +0 -0
  60. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_memory_locations.py +0 -0
  61. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_operational_safety.py +0 -0
  62. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_optional_tools.py +0 -0
  63. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_permissions.py +0 -0
  64. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_react.py +0 -0
  65. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_reasoning_content.py +0 -0
  66. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_repo_map.py +0 -0
  67. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_simplified_prompt.py +0 -0
  68. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_skills.py +0 -0
  69. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_streaming.py +0 -0
  70. {patchpal-0.25.1 → patchpal-0.25.3}/tests/test_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: patchpal
3
- Version: 0.25.1
3
+ Version: 0.25.3
4
4
  Summary: An agentic coding and automation assistant, supporting both local and cloud LLMs
5
5
  Author: PatchPal Contributors
6
6
  License-Expression: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  """PatchPal - An open-source Claude Code clone implemented purely in Python."""
2
2
 
3
- __version__ = "0.25.1"
3
+ __version__ = "0.25.3"
4
4
 
5
5
  from patchpal.agent import create_agent, create_react_agent
6
6
  from patchpal.cli.autopilot import autopilot_loop
@@ -1161,6 +1161,12 @@ Repository root takes priority if both exist."""
1161
1161
  The agent's final response
1162
1162
  """
1163
1163
  # Agent loop
1164
+ # Track consecutive empty responses (no content + no tool calls).
1165
+ # Common with some local models (e.g., GPT-OSS-120B on vLLM) due to
1166
+ # intermittent harmony-format parsing hiccups. A bounded retry usually
1167
+ # recovers since the failure is probabilistic.
1168
+ empty_response_retries = 0
1169
+ empty_response_max_retries = int(os.environ.get("PATCHPAL_EMPTY_RETRY_MAX", "2"))
1164
1170
  for iteration in range(max_iterations):
1165
1171
  # Clear any stale pending images from previous iteration (safety check)
1166
1172
  # Images should already be injected, but this prevents accumulation on error
@@ -1335,6 +1341,8 @@ Repository root takes priority if both exist."""
1335
1341
 
1336
1342
  # Check if there are tool calls
1337
1343
  if hasattr(assistant_message, "tool_calls") and assistant_message.tool_calls:
1344
+ # A non-empty turn succeeded; reset the empty-response retry budget
1345
+ empty_response_retries = 0
1338
1346
  # Print explanation text before executing tools (render as markdown)
1339
1347
  if assistant_message.content and assistant_message.content.strip():
1340
1348
  console = Console()
@@ -1834,9 +1842,25 @@ Repository root takes priority if both exist."""
1834
1842
  if assistant_message.content:
1835
1843
  return assistant_message.content
1836
1844
  else:
1837
- # Model returned no content and no tool calls
1838
- # This can happen with some local models (e.g., GPT-OSS-120B)
1839
- # Using "NO_RESPONSE:" prefix for programmatic detection
1845
+ # Model returned no content and no tool calls.
1846
+ # This happens intermittently with some local models
1847
+ # (e.g., GPT-OSS-120B on vLLM) due to harmony-format parsing
1848
+ # hiccups. Because the failure is probabilistic, retry the turn
1849
+ # a bounded number of times before giving up.
1850
+ if empty_response_retries < empty_response_max_retries:
1851
+ empty_response_retries += 1
1852
+ # Drop the empty assistant message so it doesn't pollute history
1853
+ if self.messages and self.messages[-1] is assistant_msg:
1854
+ self.messages.pop()
1855
+ print(
1856
+ f"\033[2m↻ Empty response from model; retrying "
1857
+ f"({empty_response_retries}/{empty_response_max_retries})...\033[0m",
1858
+ flush=True,
1859
+ )
1860
+ continue
1861
+
1862
+ # Retries exhausted: surface the honest failure.
1863
+ # Using "NO_RESPONSE:" prefix for programmatic detection.
1840
1864
  return "NO_RESPONSE: Model returned empty response. Try rephrasing your request or type 'continue' to prompt again."
1841
1865
 
1842
1866
  # Max iterations reached
@@ -198,7 +198,14 @@ def detect_llm_endpoints_from_env():
198
198
  or os.environ.get("AWS_REGION_NAME") # LiteLLM-specific
199
199
  )
200
200
  if aws_region and (
201
- os.environ.get("AWS_ACCESS_KEY_ID") or os.environ.get("AWS_SECRET_ACCESS_KEY")
201
+ os.environ.get("AWS_ACCESS_KEY_ID")
202
+ or os.environ.get("AWS_SECRET_ACCESS_KEY")
203
+ # SSO/ADFS profiles (created via `aws configure sso`) authenticate via a
204
+ # named profile and a cached SSO token instead of static access keys.
205
+ # In that case AWS_PROFILE is set but AWS_ACCESS_KEY_ID is not, so detect
206
+ # it here too — otherwise Bedrock endpoints would be omitted from the
207
+ # firewall allowlist and traffic would be blocked.
208
+ or os.environ.get("AWS_PROFILE")
202
209
  ):
203
210
  # Add Bedrock endpoints for the region
204
211
  # Support both GovCloud and standard regions
@@ -659,6 +666,19 @@ def build_container_args(sandbox_args, patchpal_args, env_file_keys=None):
659
666
  container_args.extend(["-v", f"{patchpal_dir}:/root/.patchpal"])
660
667
  mounted_paths.add(patchpal_dir)
661
668
 
669
+ # Mount ~/.aws if it exists (read-only).
670
+ # Required for AWS SSO/ADFS authentication: credentials for a named profile
671
+ # (created via `aws configure sso`) are resolved from ~/.aws/config, and the
672
+ # short-lived SSO token is cached under ~/.aws/sso/cache/. Mounting this
673
+ # directory lets boto3/LiteLLM inside the container resolve AWS_PROFILE just
674
+ # as it would on the host. It also covers static shared-credential setups
675
+ # (~/.aws/credentials). Mounted read-only; refresh the token on the host with
676
+ # `aws sso login --profile <name>` when it expires.
677
+ aws_dir = os.path.expanduser("~/.aws")
678
+ if os.path.isdir(aws_dir) and aws_dir not in mounted_paths:
679
+ container_args.extend(["-v", f"{aws_dir}:/root/.aws:ro"])
680
+ mounted_paths.add(aws_dir)
681
+
662
682
  # Development mode: mount local patchpal source code
663
683
  dev_mode = False
664
684
  if sandbox_args.dev:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: patchpal
3
- Version: 0.25.1
3
+ Version: 0.25.3
4
4
  Summary: An agentic coding and automation assistant, supporting both local and cloud LLMs
5
5
  Author: PatchPal Contributors
6
6
  License-Expression: Apache-2.0
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