fix: update system prompt to include today's date and refactor related functions (#43)
This commit is contained in:
@@ -43,7 +43,6 @@ SKILLS_DIR = str(Path(__file__).parent / "skills")
|
||||
|
||||
_config = None
|
||||
_chat_model = None
|
||||
_system_prompt = None
|
||||
|
||||
# Cache MCP tools by the effective config signature to avoid reconnecting
|
||||
# to MCP servers on every `/new` when config is unchanged.
|
||||
@@ -84,14 +83,6 @@ def _ensure_chat_model():
|
||||
return _chat_model
|
||||
|
||||
|
||||
def _ensure_system_prompt():
|
||||
"""Return cached system prompt, creating it on first call."""
|
||||
global _system_prompt
|
||||
if _system_prompt is None:
|
||||
_system_prompt = get_system_prompt()
|
||||
return _system_prompt
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# MCP caching
|
||||
# =============================================================================
|
||||
@@ -180,7 +171,7 @@ def _build_base_kwargs(base_backend, base_middleware):
|
||||
backend=base_backend,
|
||||
subagents=subs,
|
||||
middleware=base_middleware,
|
||||
system_prompt=_ensure_system_prompt(),
|
||||
system_prompt=get_system_prompt(),
|
||||
skills=["/skills/"],
|
||||
)
|
||||
|
||||
@@ -229,7 +220,7 @@ def load_mcp_and_build_kwargs(base_backend, base_middleware):
|
||||
backend=base_backend,
|
||||
subagents=subs,
|
||||
middleware=base_middleware,
|
||||
system_prompt=_ensure_system_prompt(),
|
||||
system_prompt=get_system_prompt(),
|
||||
skills=["/skills/"],
|
||||
)
|
||||
|
||||
@@ -310,7 +301,7 @@ def __getattr__(name: str):
|
||||
if name == "chat_model":
|
||||
return _ensure_chat_model()
|
||||
if name == "SYSTEM_PROMPT":
|
||||
return _ensure_system_prompt()
|
||||
return get_system_prompt()
|
||||
if name == "backend":
|
||||
return _get_default_backend()
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||
|
||||
@@ -41,6 +41,7 @@ def _ccproxy_exe() -> str | None:
|
||||
if found:
|
||||
return found
|
||||
import sys as _sys
|
||||
|
||||
candidate = os.path.join(os.path.dirname(_sys.executable), "ccproxy")
|
||||
if os.path.isfile(candidate) and os.access(candidate, os.X_OK):
|
||||
return candidate
|
||||
@@ -108,7 +109,8 @@ def check_ccproxy_auth(provider: str = "claude_api") -> tuple[bool, str]:
|
||||
|
||||
# Filter out structlog warning/noise lines, keep only status lines
|
||||
status_lines = [
|
||||
line for line in clean.splitlines()
|
||||
line
|
||||
for line in clean.splitlines()
|
||||
if line.strip()
|
||||
and not _re.match(r"\d{4}-\d{2}-\d{2}", line.strip())
|
||||
and "warning" not in line.lower()
|
||||
|
||||
@@ -776,7 +776,11 @@ def _step_anthropic_auth_mode(config: EvoScientistConfig) -> str:
|
||||
Choice(title="API Key (direct Anthropic access)", value="api_key"),
|
||||
Choice(
|
||||
title="Claude Code OAuth (via ccproxy — no API key needed)"
|
||||
+ ("" if ccproxy_available else " [requires: pip install evoscientist[oauth]]"),
|
||||
+ (
|
||||
""
|
||||
if ccproxy_available
|
||||
else " [requires: pip install evoscientist[oauth]]"
|
||||
),
|
||||
value="oauth",
|
||||
),
|
||||
]
|
||||
@@ -878,7 +882,11 @@ def _step_openai_auth_mode(config: EvoScientistConfig) -> str:
|
||||
Choice(title="API Key (direct OpenAI access)", value="api_key"),
|
||||
Choice(
|
||||
title="Codex OAuth (via ccproxy — no API key needed)"
|
||||
+ ("" if ccproxy_available else " [requires: pip install evoscientist[oauth]]"),
|
||||
+ (
|
||||
""
|
||||
if ccproxy_available
|
||||
else " [requires: pip install evoscientist[oauth]]"
|
||||
),
|
||||
value="oauth",
|
||||
),
|
||||
]
|
||||
@@ -2457,10 +2465,10 @@ def run_onboard(skip_validation: bool = False) -> bool:
|
||||
"custom-openai": "custom_openai_api_key",
|
||||
"custom-anthropic": "custom_anthropic_api_key",
|
||||
}
|
||||
_skip_api_key = provider == "ollama" or (
|
||||
provider == "anthropic" and config.anthropic_auth_mode == "oauth"
|
||||
) or (
|
||||
provider == "openai" and config.openai_auth_mode == "oauth"
|
||||
_skip_api_key = (
|
||||
provider == "ollama"
|
||||
or (provider == "anthropic" and config.anthropic_auth_mode == "oauth")
|
||||
or (provider == "openai" and config.openai_auth_mode == "oauth")
|
||||
)
|
||||
if not _skip_api_key:
|
||||
new_key = _step_provider_api_key(config, provider, skip_validation)
|
||||
|
||||
@@ -306,8 +306,12 @@ def get_chat_model(
|
||||
kwargs["base_url"] = base_url
|
||||
_is_openai_proxy = "127.0.0.1" in base_url or "localhost" in base_url
|
||||
if _is_openai_proxy:
|
||||
kwargs.setdefault("streaming", False) # ccproxy streaming format incompatible with langchain-openai
|
||||
kwargs.setdefault("use_responses_api", True) # ccproxy Chat Completions does not support tool calling; Responses API does
|
||||
kwargs.setdefault(
|
||||
"streaming", False
|
||||
) # ccproxy streaming format incompatible with langchain-openai
|
||||
kwargs.setdefault(
|
||||
"use_responses_api", True
|
||||
) # ccproxy Chat Completions does not support tool calling; Responses API does
|
||||
api_key = os.environ.get("OPENAI_API_KEY", "")
|
||||
if api_key:
|
||||
kwargs["api_key"] = api_key
|
||||
|
||||
+10
-2
@@ -332,9 +332,17 @@ Finding one with context [1]. Another insight [2].
|
||||
|
||||
|
||||
def get_system_prompt() -> str:
|
||||
"""Generate the complete system prompt.
|
||||
"""Generate the complete system prompt with today's date.
|
||||
|
||||
Returns:
|
||||
Combined system prompt string.
|
||||
"""
|
||||
return EXPERIMENT_WORKFLOW + "\n" + DELEGATION_STRATEGY
|
||||
from datetime import datetime
|
||||
|
||||
date = datetime.now().strftime("%Y-%m-%d")
|
||||
return (
|
||||
f"Today's date is {date}.\n\n"
|
||||
+ EXPERIMENT_WORKFLOW
|
||||
+ "\n"
|
||||
+ DELEGATION_STRATEGY
|
||||
)
|
||||
|
||||
@@ -277,7 +277,9 @@ class TestMaybeStartCcproxy:
|
||||
@patch("EvoScientist.ccproxy_manager.ensure_ccproxy")
|
||||
@patch("EvoScientist.ccproxy_manager.check_ccproxy_auth", return_value=(True, "OK"))
|
||||
@patch("EvoScientist.ccproxy_manager.is_ccproxy_available", return_value=True)
|
||||
def test_openai_oauth_mode_starts(self, mock_avail, mock_auth, mock_ensure, mock_env):
|
||||
def test_openai_oauth_mode_starts(
|
||||
self, mock_avail, mock_auth, mock_ensure, mock_env
|
||||
):
|
||||
proc = MagicMock()
|
||||
mock_ensure.return_value = proc
|
||||
config = MagicMock()
|
||||
@@ -294,7 +296,9 @@ class TestMaybeStartCcproxy:
|
||||
@patch("EvoScientist.ccproxy_manager.ensure_ccproxy")
|
||||
@patch("EvoScientist.ccproxy_manager.check_ccproxy_auth", return_value=(True, "OK"))
|
||||
@patch("EvoScientist.ccproxy_manager.is_ccproxy_available", return_value=True)
|
||||
def test_both_oauth_starts_both(self, mock_avail, mock_auth, mock_ensure, mock_anthropic_env, mock_codex_env):
|
||||
def test_both_oauth_starts_both(
|
||||
self, mock_avail, mock_auth, mock_ensure, mock_anthropic_env, mock_codex_env
|
||||
):
|
||||
proc = MagicMock()
|
||||
mock_ensure.return_value = proc
|
||||
config = MagicMock()
|
||||
|
||||
+4
-1
@@ -472,7 +472,10 @@ class TestThirdPartyRouting:
|
||||
|
||||
call_kwargs = mock_init.call_args[1]
|
||||
assert call_kwargs["model_provider"] == "openai"
|
||||
assert call_kwargs["base_url"] == "https://dashscope.aliyuncs.com/compatible-mode/v1"
|
||||
assert (
|
||||
call_kwargs["base_url"]
|
||||
== "https://dashscope.aliyuncs.com/compatible-mode/v1"
|
||||
)
|
||||
assert call_kwargs["api_key"] == "ds-key-456"
|
||||
|
||||
|
||||
|
||||
@@ -39,3 +39,9 @@ class TestGetSystemPrompt:
|
||||
|
||||
def test_shell_guidelines_mention_background(self):
|
||||
assert "background" in EXPERIMENT_WORKFLOW.lower()
|
||||
|
||||
def test_contains_todays_date(self):
|
||||
from datetime import datetime
|
||||
|
||||
expected = datetime.now().strftime("%Y-%m-%d")
|
||||
assert expected in get_system_prompt()
|
||||
|
||||
Reference in New Issue
Block a user