Configurable conversation limit now set to 10 exchanges. This helps when you want to manually continue a thread of thought across different models manually.
This commit is contained in:
@@ -92,6 +92,12 @@ DEFAULT_THINKING_MODE_THINKDEEP=high
|
|||||||
# Defaults to 3 hours if not specified
|
# Defaults to 3 hours if not specified
|
||||||
CONVERSATION_TIMEOUT_HOURS=3
|
CONVERSATION_TIMEOUT_HOURS=3
|
||||||
|
|
||||||
|
# Optional: Max conversation turns
|
||||||
|
# Maximum number of turns allowed in an AI-to-AI conversation thread
|
||||||
|
# Each exchange (Claude asks, Gemini responds) counts as 2 turns
|
||||||
|
# So 20 turns = 10 exchanges. Defaults to 20 if not specified
|
||||||
|
MAX_CONVERSATION_TURNS=20
|
||||||
|
|
||||||
# Optional: Logging level (DEBUG, INFO, WARNING, ERROR)
|
# Optional: Logging level (DEBUG, INFO, WARNING, ERROR)
|
||||||
# DEBUG: Shows detailed operational messages for troubleshooting (default)
|
# DEBUG: Shows detailed operational messages for troubleshooting (default)
|
||||||
# INFO: Shows general operational messages
|
# INFO: Shows general operational messages
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -166,3 +166,6 @@ test_simulation_files/.claude/
|
|||||||
|
|
||||||
# Temporary test directories
|
# Temporary test directories
|
||||||
test-setup/
|
test-setup/
|
||||||
|
|
||||||
|
# Scratch feature documentation files
|
||||||
|
FEATURE_*.md
|
||||||
|
|||||||
@@ -470,7 +470,7 @@ This server enables **true AI collaboration** between Claude and multiple AI mod
|
|||||||
- **Asynchronous workflow**: Conversations don't need to be sequential - Claude can work on tasks between exchanges, then return to Gemini with additional context and progress updates
|
- **Asynchronous workflow**: Conversations don't need to be sequential - Claude can work on tasks between exchanges, then return to Gemini with additional context and progress updates
|
||||||
- **Incremental updates**: Share only new information in each exchange while maintaining full conversation history
|
- **Incremental updates**: Share only new information in each exchange while maintaining full conversation history
|
||||||
- **Automatic 25K limit bypass**: Each exchange sends only incremental context, allowing unlimited total conversation size
|
- **Automatic 25K limit bypass**: Each exchange sends only incremental context, allowing unlimited total conversation size
|
||||||
- Up to 5 exchanges per conversation with 3-hour expiry (configurable)
|
- Up to 10 exchanges per conversation (configurable via `MAX_CONVERSATION_TURNS`) with 3-hour expiry (configurable via `CONVERSATION_TIMEOUT_HOURS`)
|
||||||
- Thread-safe with Redis persistence across all tools
|
- Thread-safe with Redis persistence across all tools
|
||||||
|
|
||||||
**Cross-tool & Cross-Model Continuation Example:**
|
**Cross-tool & Cross-Model Continuation Example:**
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ services:
|
|||||||
- DEFAULT_MODEL=${DEFAULT_MODEL:-auto}
|
- DEFAULT_MODEL=${DEFAULT_MODEL:-auto}
|
||||||
- DEFAULT_THINKING_MODE_THINKDEEP=${DEFAULT_THINKING_MODE_THINKDEEP:-high}
|
- DEFAULT_THINKING_MODE_THINKDEEP=${DEFAULT_THINKING_MODE_THINKDEEP:-high}
|
||||||
- CONVERSATION_TIMEOUT_HOURS=${CONVERSATION_TIMEOUT_HOURS:-3}
|
- CONVERSATION_TIMEOUT_HOURS=${CONVERSATION_TIMEOUT_HOURS:-3}
|
||||||
|
- MAX_CONVERSATION_TURNS=${MAX_CONVERSATION_TURNS:-20}
|
||||||
# Model usage restrictions
|
# Model usage restrictions
|
||||||
- OPENAI_ALLOWED_MODELS=${OPENAI_ALLOWED_MODELS:-}
|
- OPENAI_ALLOWED_MODELS=${OPENAI_ALLOWED_MODELS:-}
|
||||||
- GOOGLE_ALLOWED_MODELS=${GOOGLE_ALLOWED_MODELS:-}
|
- GOOGLE_ALLOWED_MODELS=${GOOGLE_ALLOWED_MODELS:-}
|
||||||
|
|||||||
@@ -146,8 +146,8 @@ class TestClaudeContinuationOffers:
|
|||||||
# Should still offer continuation since turns remain
|
# Should still offer continuation since turns remain
|
||||||
assert response_data["status"] == "continuation_available"
|
assert response_data["status"] == "continuation_available"
|
||||||
assert "continuation_offer" in response_data
|
assert "continuation_offer" in response_data
|
||||||
# 10 max - 2 existing - 1 new = 7 remaining
|
# MAX_CONVERSATION_TURNS - 2 existing - 1 new = remaining
|
||||||
assert response_data["continuation_offer"]["remaining_turns"] == 7
|
assert response_data["continuation_offer"]["remaining_turns"] == MAX_CONVERSATION_TURNS - 3
|
||||||
|
|
||||||
@patch("utils.conversation_memory.get_redis_client")
|
@patch("utils.conversation_memory.get_redis_client")
|
||||||
@patch.dict("os.environ", {"PYTEST_CURRENT_TEST": ""}, clear=False)
|
@patch.dict("os.environ", {"PYTEST_CURRENT_TEST": ""}, clear=False)
|
||||||
@@ -267,10 +267,10 @@ I'd be happy to examine the error handling patterns in more detail if that would
|
|||||||
# Parse response
|
# Parse response
|
||||||
response_data = json.loads(response[0].text)
|
response_data = json.loads(response[0].text)
|
||||||
|
|
||||||
# Should offer continuation since there are remaining turns (9 remaining: 10 max - 0 current - 1)
|
# Should offer continuation since there are remaining turns (MAX - 0 current - 1)
|
||||||
assert response_data["status"] == "continuation_available"
|
assert response_data["status"] == "continuation_available"
|
||||||
assert response_data.get("continuation_offer") is not None
|
assert response_data.get("continuation_offer") is not None
|
||||||
assert response_data["continuation_offer"]["remaining_turns"] == 9
|
assert response_data["continuation_offer"]["remaining_turns"] == MAX_CONVERSATION_TURNS - 1
|
||||||
|
|
||||||
@patch("utils.conversation_memory.get_redis_client")
|
@patch("utils.conversation_memory.get_redis_client")
|
||||||
@patch.dict("os.environ", {"PYTEST_CURRENT_TEST": ""}, clear=False)
|
@patch.dict("os.environ", {"PYTEST_CURRENT_TEST": ""}, clear=False)
|
||||||
@@ -465,8 +465,8 @@ class TestContinuationIntegration:
|
|||||||
# Should still offer continuation if there are remaining turns
|
# Should still offer continuation if there are remaining turns
|
||||||
assert response_data2["status"] == "continuation_available"
|
assert response_data2["status"] == "continuation_available"
|
||||||
assert "continuation_offer" in response_data2
|
assert "continuation_offer" in response_data2
|
||||||
# 10 max - 1 existing - 1 new = 8 remaining
|
# MAX_CONVERSATION_TURNS - 1 existing - 1 new = remaining
|
||||||
assert response_data2["continuation_offer"]["remaining_turns"] == 8
|
assert response_data2["continuation_offer"]["remaining_turns"] == MAX_CONVERSATION_TURNS - 2
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -57,7 +57,17 @@ from pydantic import BaseModel
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Configuration constants
|
# Configuration constants
|
||||||
MAX_CONVERSATION_TURNS = 10 # Maximum turns allowed per conversation thread
|
# Get max conversation turns from environment, default to 20 turns (10 exchanges)
|
||||||
|
try:
|
||||||
|
MAX_CONVERSATION_TURNS = int(os.getenv("MAX_CONVERSATION_TURNS", "20"))
|
||||||
|
if MAX_CONVERSATION_TURNS <= 0:
|
||||||
|
logger.warning(f"Invalid MAX_CONVERSATION_TURNS value ({MAX_CONVERSATION_TURNS}), using default of 20 turns")
|
||||||
|
MAX_CONVERSATION_TURNS = 20
|
||||||
|
except ValueError:
|
||||||
|
logger.warning(
|
||||||
|
f"Invalid MAX_CONVERSATION_TURNS value ('{os.getenv('MAX_CONVERSATION_TURNS')}'), using default of 20 turns"
|
||||||
|
)
|
||||||
|
MAX_CONVERSATION_TURNS = 20
|
||||||
|
|
||||||
# Get conversation timeout from environment (in hours), default to 3 hours
|
# Get conversation timeout from environment (in hours), default to 3 hours
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user