code-puppy 0.0.164__tar.gz → 0.0.165__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.
- {code_puppy-0.0.164 → code_puppy-0.0.165}/PKG-INFO +1 -1
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/message_history_processor.py +123 -13
- {code_puppy-0.0.164 → code_puppy-0.0.165}/pyproject.toml +1 -1
- {code_puppy-0.0.164 → code_puppy-0.0.165}/.gitignore +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/LICENSE +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/README.md +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/agent.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/agents/agent_orchestrator.json +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/agents/base_agent.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/agents/runtime_manager.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/add_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/test_command.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/meta_command_handler.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/motd.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/config.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/main.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/async_lifecycle.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/blocking_startup.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/captured_stdio_server.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/circuit_breaker.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/config_wizard.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/dashboard.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/error_isolation.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/examples/retry_example.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/health_monitor.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/managed_server.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/manager.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/registry.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/retry_manager.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/server_registry_catalog.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/status_tracker.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/mcp/system_tools.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/messaging/spinner/textual_spinner.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/models.json +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/state_management.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tools/command_runner.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/app.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/components/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/components/chat_view.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/components/command_history_modal.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/components/copy_button.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/components/custom_widgets.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/components/human_input_modal.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/components/input_area.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/components/sidebar.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/components/status_bar.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/messages.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/models/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/models/chat_message.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/models/command_history.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/models/enums.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/screens/__init__.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/screens/help.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/screens/mcp_install_wizard.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/screens/settings.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/screens/tools.py +0 -0
- {code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/version_checker.py +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import queue
|
|
3
|
-
from typing import Any, List, Set, Tuple
|
|
3
|
+
from typing import Any, Dict, List, Set, Tuple
|
|
4
4
|
|
|
5
5
|
import pydantic
|
|
6
6
|
from pydantic_ai.messages import ModelMessage, ModelRequest, TextPart, ToolCallPart
|
|
7
7
|
|
|
8
8
|
from code_puppy.config import (
|
|
9
|
+
get_compaction_strategy,
|
|
10
|
+
get_compaction_threshold,
|
|
9
11
|
get_model_name,
|
|
10
12
|
get_protected_token_count,
|
|
11
|
-
get_compaction_threshold,
|
|
12
|
-
get_compaction_strategy,
|
|
13
13
|
)
|
|
14
14
|
from code_puppy.messaging import emit_error, emit_info, emit_warning
|
|
15
15
|
from code_puppy.model_factory import ModelFactory
|
|
@@ -82,7 +82,9 @@ def estimate_tokens_for_message(message: ModelMessage) -> int:
|
|
|
82
82
|
|
|
83
83
|
|
|
84
84
|
def filter_huge_messages(messages: List[ModelMessage]) -> List[ModelMessage]:
|
|
85
|
-
|
|
85
|
+
# First deduplicate tool returns to clean up any duplicates
|
|
86
|
+
deduplicated = deduplicate_tool_returns(messages)
|
|
87
|
+
filtered = [m for m in deduplicated if estimate_tokens_for_message(m) < 50000]
|
|
86
88
|
pruned = prune_interrupted_tool_calls(filtered)
|
|
87
89
|
return pruned
|
|
88
90
|
|
|
@@ -234,21 +236,100 @@ def get_model_context_length() -> int:
|
|
|
234
236
|
return int(context_length)
|
|
235
237
|
|
|
236
238
|
|
|
239
|
+
def deduplicate_tool_returns(messages: List[ModelMessage]) -> List[ModelMessage]:
|
|
240
|
+
"""
|
|
241
|
+
Remove duplicate tool returns while preserving the first occurrence for each tool_call_id.
|
|
242
|
+
|
|
243
|
+
This function identifies tool-return parts that share the same tool_call_id and
|
|
244
|
+
removes duplicates, keeping only the first return for each id. This prevents
|
|
245
|
+
conversation corruption from duplicate tool_result blocks.
|
|
246
|
+
"""
|
|
247
|
+
if not messages:
|
|
248
|
+
return messages
|
|
249
|
+
|
|
250
|
+
seen_tool_returns: Set[str] = set()
|
|
251
|
+
deduplicated: List[ModelMessage] = []
|
|
252
|
+
removed_count = 0
|
|
253
|
+
|
|
254
|
+
for msg in messages:
|
|
255
|
+
# Check if this message has any parts we need to filter
|
|
256
|
+
if not hasattr(msg, "parts") or not msg.parts:
|
|
257
|
+
deduplicated.append(msg)
|
|
258
|
+
continue
|
|
259
|
+
|
|
260
|
+
# Filter parts within this message
|
|
261
|
+
filtered_parts = []
|
|
262
|
+
msg_had_duplicates = False
|
|
263
|
+
|
|
264
|
+
for part in msg.parts:
|
|
265
|
+
tool_call_id = getattr(part, "tool_call_id", None)
|
|
266
|
+
part_kind = getattr(part, "part_kind", None)
|
|
267
|
+
|
|
268
|
+
# Check if this is a tool-return part
|
|
269
|
+
if tool_call_id and part_kind in {
|
|
270
|
+
"tool-return",
|
|
271
|
+
"tool-result",
|
|
272
|
+
"tool_result",
|
|
273
|
+
}:
|
|
274
|
+
if tool_call_id in seen_tool_returns:
|
|
275
|
+
# This is a duplicate return, skip it
|
|
276
|
+
msg_had_duplicates = True
|
|
277
|
+
removed_count += 1
|
|
278
|
+
continue
|
|
279
|
+
else:
|
|
280
|
+
# First occurrence of this return, keep it
|
|
281
|
+
seen_tool_returns.add(tool_call_id)
|
|
282
|
+
filtered_parts.append(part)
|
|
283
|
+
else:
|
|
284
|
+
# Not a tool return, always keep
|
|
285
|
+
filtered_parts.append(part)
|
|
286
|
+
|
|
287
|
+
# If we filtered out parts, create a new message with filtered parts
|
|
288
|
+
if msg_had_duplicates and filtered_parts:
|
|
289
|
+
# Create a new message with the same attributes but filtered parts
|
|
290
|
+
new_msg = type(msg)(parts=filtered_parts)
|
|
291
|
+
# Copy over other attributes if they exist
|
|
292
|
+
for attr_name in dir(msg):
|
|
293
|
+
if (
|
|
294
|
+
not attr_name.startswith("_")
|
|
295
|
+
and attr_name != "parts"
|
|
296
|
+
and hasattr(msg, attr_name)
|
|
297
|
+
):
|
|
298
|
+
try:
|
|
299
|
+
setattr(new_msg, attr_name, getattr(msg, attr_name))
|
|
300
|
+
except (AttributeError, TypeError):
|
|
301
|
+
# Skip attributes that can't be set
|
|
302
|
+
pass
|
|
303
|
+
deduplicated.append(new_msg)
|
|
304
|
+
elif filtered_parts: # No duplicates but has parts
|
|
305
|
+
deduplicated.append(msg)
|
|
306
|
+
# If no parts remain after filtering, drop the entire message
|
|
307
|
+
|
|
308
|
+
if removed_count > 0:
|
|
309
|
+
emit_warning(f"Removed {removed_count} duplicate tool-return part(s)")
|
|
310
|
+
|
|
311
|
+
return deduplicated
|
|
312
|
+
|
|
313
|
+
|
|
237
314
|
def prune_interrupted_tool_calls(messages: List[ModelMessage]) -> List[ModelMessage]:
|
|
238
315
|
"""
|
|
239
316
|
Remove any messages that participate in mismatched tool call sequences.
|
|
240
317
|
|
|
241
318
|
A mismatched tool call id is one that appears in a ToolCall (model/tool request)
|
|
242
|
-
without a corresponding tool return, or vice versa. We
|
|
243
|
-
and
|
|
319
|
+
without a corresponding tool return, or vice versa. We enforce a strict 1:1 ratio
|
|
320
|
+
between tool calls and tool returns. We preserve original order and only drop
|
|
321
|
+
messages that contain parts referencing mismatched tool_call_ids.
|
|
244
322
|
"""
|
|
245
323
|
if not messages:
|
|
246
324
|
return messages
|
|
247
325
|
|
|
248
|
-
|
|
249
|
-
|
|
326
|
+
# First deduplicate tool returns to clean up any duplicate returns
|
|
327
|
+
messages = deduplicate_tool_returns(messages)
|
|
250
328
|
|
|
251
|
-
|
|
329
|
+
tool_call_counts: Dict[str, int] = {}
|
|
330
|
+
tool_return_counts: Dict[str, int] = {}
|
|
331
|
+
|
|
332
|
+
# First pass: count occurrences of each tool_call_id for calls vs returns
|
|
252
333
|
for msg in messages:
|
|
253
334
|
for part in getattr(msg, "parts", []) or []:
|
|
254
335
|
tool_call_id = getattr(part, "tool_call_id", None)
|
|
@@ -257,11 +338,25 @@ def prune_interrupted_tool_calls(messages: List[ModelMessage]) -> List[ModelMess
|
|
|
257
338
|
# Heuristic: if it's an explicit ToolCallPart or has a tool_name/args,
|
|
258
339
|
# consider it a call; otherwise it's a return/result.
|
|
259
340
|
if part.part_kind == "tool-call":
|
|
260
|
-
|
|
341
|
+
tool_call_counts[tool_call_id] = (
|
|
342
|
+
tool_call_counts.get(tool_call_id, 0) + 1
|
|
343
|
+
)
|
|
261
344
|
else:
|
|
262
|
-
|
|
345
|
+
tool_return_counts[tool_call_id] = (
|
|
346
|
+
tool_return_counts.get(tool_call_id, 0) + 1
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
# Find mismatched tool_call_ids (not exactly 1:1 ratio)
|
|
350
|
+
all_tool_ids = set(tool_call_counts.keys()) | set(tool_return_counts.keys())
|
|
351
|
+
mismatched: Set[str] = set()
|
|
352
|
+
|
|
353
|
+
for tool_id in all_tool_ids:
|
|
354
|
+
call_count = tool_call_counts.get(tool_id, 0)
|
|
355
|
+
return_count = tool_return_counts.get(tool_id, 0)
|
|
356
|
+
# Enforce strict 1:1 ratio - both must be exactly 1
|
|
357
|
+
if call_count != 1 or return_count != 1:
|
|
358
|
+
mismatched.add(tool_id)
|
|
263
359
|
|
|
264
|
-
mismatched: Set[str] = tool_call_ids.symmetric_difference(tool_return_ids)
|
|
265
360
|
if not mismatched:
|
|
266
361
|
return messages
|
|
267
362
|
|
|
@@ -287,7 +382,10 @@ def prune_interrupted_tool_calls(messages: List[ModelMessage]) -> List[ModelMess
|
|
|
287
382
|
|
|
288
383
|
|
|
289
384
|
def message_history_processor(messages: List[ModelMessage]) -> List[ModelMessage]:
|
|
290
|
-
# First,
|
|
385
|
+
# First, deduplicate tool returns to clean up any duplicates
|
|
386
|
+
messages = deduplicate_tool_returns(messages)
|
|
387
|
+
|
|
388
|
+
# Then, prune any interrupted/mismatched tool-call conversations
|
|
291
389
|
total_current_tokens = sum(estimate_tokens_for_message(msg) for msg in messages)
|
|
292
390
|
|
|
293
391
|
model_max = get_model_context_length()
|
|
@@ -379,6 +477,8 @@ def truncation(
|
|
|
379
477
|
messages: List[ModelMessage], protected_tokens: int
|
|
380
478
|
) -> List[ModelMessage]:
|
|
381
479
|
emit_info("Truncating message history to manage token usage")
|
|
480
|
+
# First deduplicate tool returns to clean up any duplicates
|
|
481
|
+
messages = deduplicate_tool_returns(messages)
|
|
382
482
|
result = [messages[0]] # Always keep the first message (system prompt)
|
|
383
483
|
num_tokens = 0
|
|
384
484
|
stack = queue.LifoQueue()
|
|
@@ -401,6 +501,10 @@ def truncation(
|
|
|
401
501
|
|
|
402
502
|
def message_history_accumulator(messages: List[Any]):
|
|
403
503
|
_message_history = get_message_history()
|
|
504
|
+
|
|
505
|
+
# Deduplicate tool returns in current history before processing new messages
|
|
506
|
+
_message_history = deduplicate_tool_returns(_message_history)
|
|
507
|
+
|
|
404
508
|
message_history_hashes = set([hash_message(m) for m in _message_history])
|
|
405
509
|
for msg in messages:
|
|
406
510
|
if (
|
|
@@ -409,6 +513,12 @@ def message_history_accumulator(messages: List[Any]):
|
|
|
409
513
|
):
|
|
410
514
|
_message_history.append(msg)
|
|
411
515
|
|
|
516
|
+
# Deduplicate tool returns again after adding new messages to ensure no duplicates
|
|
517
|
+
_message_history = deduplicate_tool_returns(_message_history)
|
|
518
|
+
|
|
519
|
+
# Update the message history with deduplicated messages
|
|
520
|
+
set_message_history(_message_history)
|
|
521
|
+
|
|
412
522
|
# Apply message history trimming using the main processor
|
|
413
523
|
# This ensures we maintain global state while still managing context limits
|
|
414
524
|
message_history_processor(_message_history)
|
|
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
|
{code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/load_context_completion.py
RENAMED
|
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
|
{code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/model_picker_completion.py
RENAMED
|
File without changes
|
|
File without changes
|
{code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/command_line/prompt_toolkit_completion.py
RENAMED
|
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
|
{code_puppy-0.0.164 → code_puppy-0.0.165}/code_puppy/tui/components/command_history_modal.py
RENAMED
|
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
|