patchpal 0.22.2__tar.gz → 0.22.4__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.
- {patchpal-0.22.2/patchpal.egg-info → patchpal-0.22.4}/PKG-INFO +2 -2
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/__init__.py +1 -1
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/agent/function_calling.py +8 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/cli/interactive.py +3 -1
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/cli/sandbox.py +0 -3
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/context.py +41 -18
- {patchpal-0.22.2 → patchpal-0.22.4/patchpal.egg-info}/PKG-INFO +2 -2
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal.egg-info/requires.txt +1 -1
- {patchpal-0.22.2 → patchpal-0.22.4}/pyproject.toml +1 -1
- {patchpal-0.22.2 → patchpal-0.22.4}/LICENSE +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/MANIFEST.in +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/README.md +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/agent/__init__.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/agent/react.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/cli/__init__.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/cli/autopilot.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/cli/mcp.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/cli/streaming.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/config.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/permissions.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/prompts/react_prompt.md +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/prompts/system_prompt.md +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/skills.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/__init__.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/audit.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/code_analysis.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/common.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/definitions.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/file_reading.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/file_writing.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/find_tool.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/grep_tool.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/image_handler.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/mcp.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/repo_map.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/shell_tools.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/todo_tools.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/tool_schema.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/user_interaction.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal/tools/web_tools.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal.egg-info/SOURCES.txt +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal.egg-info/dependency_links.txt +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal.egg-info/entry_points.txt +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/patchpal.egg-info/top_level.txt +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/setup.cfg +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_agent.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_cli.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_config_dynamic.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_context.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_custom_tools.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_enabled_tools.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_find_tool.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_guardrails.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_image_blocking.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_maximum_security.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_mcp_config.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_memory.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_operational_safety.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_optional_tools.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_permissions.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_react.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_reasoning_content.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_repo_map.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_simplified_prompt.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_skills.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_streaming.py +0 -0
- {patchpal-0.22.2 → patchpal-0.22.4}/tests/test_tools.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: patchpal
|
|
3
|
-
Version: 0.22.
|
|
3
|
+
Version: 0.22.4
|
|
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
|
|
@@ -30,7 +30,7 @@ Requires-Dist: boto3
|
|
|
30
30
|
Requires-Dist: pymupdf>=1.23.0
|
|
31
31
|
Requires-Dist: python-docx>=1.0.0
|
|
32
32
|
Requires-Dist: python-pptx>=0.6.0
|
|
33
|
-
Requires-Dist: tree-sitter-language-pack
|
|
33
|
+
Requires-Dist: tree-sitter-language-pack<1.0.0,>=0.3.0
|
|
34
34
|
Provides-Extra: dev
|
|
35
35
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
36
36
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
@@ -479,6 +479,10 @@ class PatchPalAgent:
|
|
|
479
479
|
self.cumulative_input_tokens = 0
|
|
480
480
|
self.cumulative_output_tokens = 0
|
|
481
481
|
|
|
482
|
+
# Track last prompt tokens from most recent API response (includes cache operations)
|
|
483
|
+
# This is the ACTUAL token count sent to the API, used for accurate context management
|
|
484
|
+
self.last_prompt_tokens = None
|
|
485
|
+
|
|
482
486
|
# Track cache-related tokens (for Anthropic/Bedrock models with prompt caching)
|
|
483
487
|
self.cumulative_cache_creation_tokens = 0
|
|
484
488
|
self.cumulative_cache_read_tokens = 0
|
|
@@ -953,6 +957,7 @@ It's currently empty (just the template). The file is automatically loaded at se
|
|
|
953
957
|
|
|
954
958
|
# Check for compaction BEFORE starting work
|
|
955
959
|
# This ensures we never compact mid-execution and lose tool results
|
|
960
|
+
# Always estimates current messages to avoid staleness issues (no actual_prompt_tokens)
|
|
956
961
|
if self.enable_auto_compact and self.context_manager.needs_compaction(self.messages):
|
|
957
962
|
self._perform_auto_compaction()
|
|
958
963
|
|
|
@@ -1100,7 +1105,10 @@ It's currently empty (just the template). The file is automatically loaded at se
|
|
|
1100
1105
|
last_prompt_tokens = None # Track for reactive context management
|
|
1101
1106
|
if hasattr(response, "usage") and response.usage:
|
|
1102
1107
|
if hasattr(response.usage, "prompt_tokens"):
|
|
1108
|
+
# LiteLLM already includes cache operations in prompt_tokens for Anthropic/Bedrock
|
|
1109
|
+
# (see litellm/llms/anthropic/chat/transformation.py)
|
|
1103
1110
|
last_prompt_tokens = response.usage.prompt_tokens
|
|
1111
|
+
self.last_prompt_tokens = last_prompt_tokens # Store for /status command
|
|
1104
1112
|
self.cumulative_input_tokens += response.usage.prompt_tokens
|
|
1105
1113
|
if hasattr(response.usage, "completion_tokens"):
|
|
1106
1114
|
self.cumulative_output_tokens += response.usage.completion_tokens
|
|
@@ -670,7 +670,9 @@ Supported models: Any LiteLLM-supported model
|
|
|
670
670
|
|
|
671
671
|
# Handle /status command - show context window usage
|
|
672
672
|
if user_input.lower() in ["status", "/status"]:
|
|
673
|
-
stats = agent.context_manager.get_usage_stats(
|
|
673
|
+
stats = agent.context_manager.get_usage_stats(
|
|
674
|
+
agent.messages, actual_prompt_tokens=agent.last_prompt_tokens
|
|
675
|
+
)
|
|
674
676
|
|
|
675
677
|
print("\n" + "=" * 70)
|
|
676
678
|
print("\033[1;36mContext Window Status\033[0m")
|
|
@@ -686,9 +686,6 @@ DESCRIPTION:
|
|
|
686
686
|
- Pre-built image with patchpal installed (fast startup)
|
|
687
687
|
- Auto-mounts ~/.patchpal for custom tools, config, and memory
|
|
688
688
|
- Custom tools work automatically (from ~/.patchpal/tools/ and <repo>/.patchpal/tools/)
|
|
689
|
-
- Auto-sets OLLAMA_CONTEXT_LENGTH for Ollama models:
|
|
690
|
-
* 8192 for regular models (agents)
|
|
691
|
-
* 32768 for reasoning models (gpt-oss, deepseek-r1, qwq, qwen)
|
|
692
689
|
|
|
693
690
|
Recommended for autopilot mode and high-risk operations.
|
|
694
691
|
|
|
@@ -321,30 +321,31 @@ Be comprehensive but concise. The goal is to continue work seamlessly without lo
|
|
|
321
321
|
) -> bool:
|
|
322
322
|
"""Check if context window needs compaction.
|
|
323
323
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
324
|
+
ALWAYS estimates current messages to avoid staleness issues when predicting
|
|
325
|
+
whether the NEXT API call will overflow. Using actual_prompt_tokens from a
|
|
326
|
+
previous call can cause false negatives when large messages are added between
|
|
327
|
+
the last API call and the compaction check.
|
|
328
|
+
|
|
329
|
+
Example of staleness bug (fixed):
|
|
330
|
+
- Previous API call: 120K tokens (60% usage)
|
|
331
|
+
- User pastes huge changelog: +90K tokens
|
|
332
|
+
- Total: 210K tokens (exceeds 200K limit)
|
|
333
|
+
- Bug: If we used actual_prompt_tokens=120K, we'd think we're at 60%
|
|
334
|
+
- Fix: Always re-estimate to see the 210K total
|
|
335
|
+
|
|
336
|
+
The actual_prompt_tokens parameter is kept for API compatibility but ignored
|
|
337
|
+
for compaction decisions. Use get_usage_stats() for display purposes where
|
|
338
|
+
actual tokens are appropriate (staleness OK for showing recent stats).
|
|
330
339
|
|
|
331
340
|
Args:
|
|
332
341
|
messages: Current message history
|
|
333
|
-
actual_prompt_tokens:
|
|
342
|
+
actual_prompt_tokens: IGNORED - kept for API compatibility only
|
|
334
343
|
|
|
335
344
|
Returns:
|
|
336
345
|
True if compaction is needed
|
|
337
346
|
"""
|
|
338
|
-
#
|
|
339
|
-
|
|
340
|
-
# Add output reserve to account for response tokens
|
|
341
|
-
total_tokens = actual_prompt_tokens + self.output_reserve
|
|
342
|
-
usage_ratio = total_tokens / self.context_limit
|
|
343
|
-
return usage_ratio >= self.COMPACT_THRESHOLD
|
|
344
|
-
|
|
345
|
-
# Proactive approach (fallback): estimate tokens when API data not available
|
|
346
|
-
# This uses character-based estimation (3 chars per token) which works
|
|
347
|
-
# reliably without requiring tiktoken or network access
|
|
347
|
+
# ALWAYS estimate current messages - never use stale actual_prompt_tokens
|
|
348
|
+
# This ensures we detect large message additions that happen between API calls
|
|
348
349
|
# Note: Dynamic date/time message adds ~30 tokens on each LLM call
|
|
349
350
|
system_tokens = self.estimator.estimate_tokens(self.system_prompt)
|
|
350
351
|
datetime_tokens = 30 # Approximate size of dynamic date/time message
|
|
@@ -355,15 +356,37 @@ Be comprehensive but concise. The goal is to continue work seamlessly without lo
|
|
|
355
356
|
usage_ratio = total_tokens / self.context_limit
|
|
356
357
|
return usage_ratio >= self.COMPACT_THRESHOLD
|
|
357
358
|
|
|
358
|
-
def get_usage_stats(
|
|
359
|
+
def get_usage_stats(
|
|
360
|
+
self, messages: List[Dict[str, Any]], actual_prompt_tokens: int = None
|
|
361
|
+
) -> Dict[str, Any]:
|
|
359
362
|
"""Get current context usage statistics.
|
|
360
363
|
|
|
361
364
|
Args:
|
|
362
365
|
messages: Current message history
|
|
366
|
+
actual_prompt_tokens: Optional actual prompt tokens from latest API response (includes cache operations)
|
|
363
367
|
|
|
364
368
|
Returns:
|
|
365
369
|
Dict with usage statistics
|
|
366
370
|
"""
|
|
371
|
+
# If we have actual prompt tokens from API (includes cache writes/reads), use those
|
|
372
|
+
if actual_prompt_tokens is not None:
|
|
373
|
+
total_tokens = actual_prompt_tokens + self.output_reserve
|
|
374
|
+
# For display purposes, estimate system vs message breakdown
|
|
375
|
+
system_tokens = self.estimator.estimate_tokens(self.system_prompt)
|
|
376
|
+
datetime_tokens = 30
|
|
377
|
+
message_tokens = actual_prompt_tokens - system_tokens - datetime_tokens
|
|
378
|
+
|
|
379
|
+
return {
|
|
380
|
+
"system_tokens": system_tokens + datetime_tokens,
|
|
381
|
+
"message_tokens": max(0, message_tokens), # Ensure non-negative
|
|
382
|
+
"output_reserve": self.output_reserve,
|
|
383
|
+
"total_tokens": total_tokens,
|
|
384
|
+
"context_limit": self.context_limit,
|
|
385
|
+
"usage_ratio": total_tokens / self.context_limit,
|
|
386
|
+
"usage_percent": int((total_tokens / self.context_limit) * 100),
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
# Fallback to estimation when actual tokens not available
|
|
367
390
|
system_tokens = self.estimator.estimate_tokens(self.system_prompt)
|
|
368
391
|
datetime_tokens = 30 # Approximate size of dynamic date/time message
|
|
369
392
|
message_tokens = self.estimator.estimate_messages_tokens(messages)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: patchpal
|
|
3
|
-
Version: 0.22.
|
|
3
|
+
Version: 0.22.4
|
|
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
|
|
@@ -30,7 +30,7 @@ Requires-Dist: boto3
|
|
|
30
30
|
Requires-Dist: pymupdf>=1.23.0
|
|
31
31
|
Requires-Dist: python-docx>=1.0.0
|
|
32
32
|
Requires-Dist: python-pptx>=0.6.0
|
|
33
|
-
Requires-Dist: tree-sitter-language-pack
|
|
33
|
+
Requires-Dist: tree-sitter-language-pack<1.0.0,>=0.3.0
|
|
34
34
|
Provides-Extra: dev
|
|
35
35
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
36
36
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
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
|
|
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
|