Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7acd6c902c | ||
|
|
0cb42c10a4 | ||
|
|
169bfe20e4 |
+46
-46
@@ -275,71 +275,71 @@ def _merge_custom_provider_extra_body(agent, custom_providers: List[Dict[str, An
|
||||
|
||||
def init_agent(
|
||||
agent,
|
||||
base_url: str = None,
|
||||
api_key: str = None,
|
||||
provider: str = None,
|
||||
api_mode: str = None,
|
||||
acp_command: str = None,
|
||||
base_url: str | None = None,
|
||||
api_key: str | None = None,
|
||||
provider: str | None = None,
|
||||
api_mode: str | None = None,
|
||||
acp_command: str | None = None,
|
||||
acp_args: list[str] | None = None,
|
||||
command: str = None,
|
||||
command: str | None = None,
|
||||
args: list[str] | None = None,
|
||||
model: str = "",
|
||||
max_iterations: int = 90, # Default tool-calling iterations (shared with subagents)
|
||||
tool_delay: float = 1.0,
|
||||
enabled_toolsets: List[str] = None,
|
||||
disabled_toolsets: List[str] = None,
|
||||
enabled_toolsets: List[str] | None = None,
|
||||
disabled_toolsets: List[str] | None = None,
|
||||
save_trajectories: bool = False,
|
||||
verbose_logging: bool = False,
|
||||
quiet_mode: bool = False,
|
||||
tool_progress_mode: str = "all",
|
||||
ephemeral_system_prompt: str = None,
|
||||
ephemeral_system_prompt: str | None = None,
|
||||
log_prefix_chars: int = 100,
|
||||
log_prefix: str = "",
|
||||
providers_allowed: List[str] = None,
|
||||
providers_ignored: List[str] = None,
|
||||
providers_order: List[str] = None,
|
||||
provider_sort: str = None,
|
||||
providers_allowed: List[str] | None = None,
|
||||
providers_ignored: List[str] | None = None,
|
||||
providers_order: List[str] | None = None,
|
||||
provider_sort: str | None = None,
|
||||
provider_require_parameters: bool = False,
|
||||
provider_data_collection: str = None,
|
||||
provider_data_collection: str | None = None,
|
||||
openrouter_min_coding_score: Optional[float] = None,
|
||||
session_id: str = None,
|
||||
tool_progress_callback: callable = None,
|
||||
tool_start_callback: callable = None,
|
||||
tool_complete_callback: callable = None,
|
||||
thinking_callback: callable = None,
|
||||
reasoning_callback: callable = None,
|
||||
clarify_callback: callable = None,
|
||||
read_terminal_callback: callable = None,
|
||||
step_callback: callable = None,
|
||||
stream_delta_callback: callable = None,
|
||||
interim_assistant_callback: callable = None,
|
||||
tool_gen_callback: callable = None,
|
||||
status_callback: callable = None,
|
||||
notice_callback: callable = None,
|
||||
notice_clear_callback: callable = None,
|
||||
session_id: str | None = None,
|
||||
tool_progress_callback: Callable | None = None,
|
||||
tool_start_callback: Callable | None = None,
|
||||
tool_complete_callback: Callable | None = None,
|
||||
thinking_callback: Callable | None = None,
|
||||
reasoning_callback: Callable | None = None,
|
||||
clarify_callback: Callable | None = None,
|
||||
read_terminal_callback: Callable | None = None,
|
||||
step_callback: Callable | None = None,
|
||||
stream_delta_callback: Callable | None = None,
|
||||
interim_assistant_callback: Callable | None = None,
|
||||
tool_gen_callback: Callable | None = None,
|
||||
status_callback: Callable | None = None,
|
||||
notice_callback: Callable | None = None,
|
||||
notice_clear_callback: Callable | None = None,
|
||||
event_callback: Optional[Callable[[str, dict], None]] = None,
|
||||
reaction_callback: Optional[Callable[[str], None]] = None,
|
||||
max_tokens: int = None,
|
||||
reasoning_config: Dict[str, Any] = None,
|
||||
service_tier: str = None,
|
||||
request_overrides: Dict[str, Any] = None,
|
||||
prefill_messages: List[Dict[str, Any]] = None,
|
||||
platform: str = None,
|
||||
user_id: str = None,
|
||||
user_id_alt: str = None,
|
||||
user_name: str = None,
|
||||
chat_id: str = None,
|
||||
chat_name: str = None,
|
||||
chat_type: str = None,
|
||||
thread_id: str = None,
|
||||
gateway_session_key: str = None,
|
||||
max_tokens: int | None = None,
|
||||
reasoning_config: Dict[str, Any] | None = None,
|
||||
service_tier: str | None = None,
|
||||
request_overrides: Dict[str, Any] | None = None,
|
||||
prefill_messages: List[Dict[str, Any]] | None = None,
|
||||
platform: str | None = None,
|
||||
user_id: str | None = None,
|
||||
user_id_alt: str | None = None,
|
||||
user_name: str | None = None,
|
||||
chat_id: str | None = None,
|
||||
chat_name: str | None = None,
|
||||
chat_type: str | None = None,
|
||||
thread_id: str | None = None,
|
||||
gateway_session_key: str | None = None,
|
||||
skip_context_files: bool = False,
|
||||
load_soul_identity: bool = False,
|
||||
skip_memory: bool = False,
|
||||
session_db=None,
|
||||
parent_session_id: str = None,
|
||||
iteration_budget: "IterationBudget" = None,
|
||||
fallback_model: Dict[str, Any] = None,
|
||||
parent_session_id: str | None = None,
|
||||
iteration_budget: Optional["IterationBudget"] = None,
|
||||
fallback_model: Dict[str, Any] | None = None,
|
||||
credential_pool=None,
|
||||
checkpoints_enabled: bool = False,
|
||||
checkpoint_max_snapshots: int = 20,
|
||||
|
||||
@@ -246,7 +246,7 @@ def sanitize_tool_call_arguments(
|
||||
messages: list,
|
||||
*,
|
||||
logger=None,
|
||||
session_id: str = None,
|
||||
session_id: str | None = None,
|
||||
) -> int:
|
||||
"""Repair corrupted assistant tool-call argument JSON in-place."""
|
||||
log = logger or logging.getLogger(__name__)
|
||||
|
||||
@@ -633,8 +633,8 @@ def _common_betas_for_base_url(
|
||||
|
||||
def _build_anthropic_client_with_bearer_hook(
|
||||
token_provider,
|
||||
base_url: str = None,
|
||||
timeout: float = None,
|
||||
base_url: str | None = None,
|
||||
timeout: float | None = None,
|
||||
*,
|
||||
drop_context_1m_beta: bool = False,
|
||||
):
|
||||
@@ -709,8 +709,8 @@ def _build_anthropic_client_with_bearer_hook(
|
||||
|
||||
def build_anthropic_client(
|
||||
api_key,
|
||||
base_url: str = None,
|
||||
timeout: float = None,
|
||||
base_url: str | None = None,
|
||||
timeout: float | None = None,
|
||||
*,
|
||||
drop_context_1m_beta: bool = False,
|
||||
):
|
||||
|
||||
+35
-35
@@ -3972,7 +3972,7 @@ async def _call_fallback_candidate_async(
|
||||
|
||||
def _try_payment_fallback(
|
||||
failed_provider: str,
|
||||
task: str = None,
|
||||
task: str | None = None,
|
||||
reason: str = "payment error",
|
||||
) -> Tuple[Optional[Any], Optional[str], str]:
|
||||
"""Try alternative providers after a payment/credit or connection error.
|
||||
@@ -4023,7 +4023,7 @@ def _try_payment_fallback(
|
||||
|
||||
def _try_main_agent_model_fallback(
|
||||
failed_provider: str,
|
||||
task: str = None,
|
||||
task: str | None = None,
|
||||
reason: str = "error",
|
||||
) -> Tuple[Optional[Any], Optional[str], str]:
|
||||
"""Last-resort fallback to the user's main agent provider + model.
|
||||
@@ -4665,12 +4665,12 @@ def _normalize_resolved_model(model_name: Optional[str], provider: str) -> Optio
|
||||
|
||||
def resolve_provider_client(
|
||||
provider: str,
|
||||
model: str = None,
|
||||
model: str | None = None,
|
||||
async_mode: bool = False,
|
||||
raw_codex: bool = False,
|
||||
explicit_base_url: str = None,
|
||||
explicit_api_key: str = None,
|
||||
api_mode: str = None,
|
||||
explicit_base_url: str | None = None,
|
||||
explicit_api_key: str | None = None,
|
||||
api_mode: str | None = None,
|
||||
main_runtime: Optional[Dict[str, Any]] = None,
|
||||
is_vision: bool = False,
|
||||
task: Optional[str] = None,
|
||||
@@ -6086,11 +6086,11 @@ def _compat_model(client: Any, model: Optional[str], cached_default: Optional[st
|
||||
|
||||
def _get_cached_client(
|
||||
provider: str,
|
||||
model: str = None,
|
||||
model: str | None = None,
|
||||
async_mode: bool = False,
|
||||
base_url: str = None,
|
||||
api_key: str = None,
|
||||
api_mode: str = None,
|
||||
base_url: str | None = None,
|
||||
api_key: str | None = None,
|
||||
api_mode: str | None = None,
|
||||
main_runtime: Optional[Dict[str, Any]] = None,
|
||||
is_vision: bool = False,
|
||||
task: Optional[str] = None,
|
||||
@@ -6222,11 +6222,11 @@ _AUX_DIRECT_API_BASE_URLS: Dict[str, str] = {
|
||||
|
||||
|
||||
def _resolve_task_provider_model(
|
||||
task: str = None,
|
||||
provider: str = None,
|
||||
model: str = None,
|
||||
base_url: str = None,
|
||||
api_key: str = None,
|
||||
task: str | None = None,
|
||||
provider: str | None = None,
|
||||
model: str | None = None,
|
||||
base_url: str | None = None,
|
||||
api_key: str | None = None,
|
||||
) -> Tuple[str, Optional[str], Optional[str], Optional[str], Optional[str]]:
|
||||
"""Determine provider + model for a call.
|
||||
|
||||
@@ -6900,23 +6900,23 @@ def _obj_get(obj: Any, key: str, default: Any = None) -> Any:
|
||||
|
||||
|
||||
def call_llm(
|
||||
task: str = None,
|
||||
task: str | None = None,
|
||||
*,
|
||||
provider: str = None,
|
||||
model: str = None,
|
||||
base_url: str = None,
|
||||
api_key: str = None,
|
||||
provider: str | None = None,
|
||||
model: str | None = None,
|
||||
base_url: str | None = None,
|
||||
api_key: str | None = None,
|
||||
main_runtime: Optional[Dict[str, Any]] = None,
|
||||
messages: list,
|
||||
temperature: Optional[float] = None,
|
||||
max_tokens: int = None,
|
||||
tools: list = None,
|
||||
timeout: float = None,
|
||||
extra_body: dict = None,
|
||||
max_tokens: int | None = None,
|
||||
tools: list | None = None,
|
||||
timeout: float | None = None,
|
||||
extra_body: dict | None = None,
|
||||
reasoning_config: Optional[dict] = None,
|
||||
api_mode: str = None,
|
||||
api_mode: str | None = None,
|
||||
stream: bool = False,
|
||||
stream_options: dict = None,
|
||||
stream_options: dict | None = None,
|
||||
) -> Any:
|
||||
"""Centralized synchronous LLM call.
|
||||
|
||||
@@ -7567,19 +7567,19 @@ def extract_content_or_reasoning(response) -> str:
|
||||
|
||||
|
||||
async def async_call_llm(
|
||||
task: str = None,
|
||||
task: str | None = None,
|
||||
*,
|
||||
provider: str = None,
|
||||
model: str = None,
|
||||
base_url: str = None,
|
||||
api_key: str = None,
|
||||
provider: str | None = None,
|
||||
model: str | None = None,
|
||||
base_url: str | None = None,
|
||||
api_key: str | None = None,
|
||||
main_runtime: Optional[Dict[str, Any]] = None,
|
||||
messages: list,
|
||||
temperature: Optional[float] = None,
|
||||
max_tokens: int = None,
|
||||
tools: list = None,
|
||||
timeout: float = None,
|
||||
extra_body: dict = None,
|
||||
max_tokens: int | None = None,
|
||||
tools: list | None = None,
|
||||
timeout: float | None = None,
|
||||
extra_body: dict | None = None,
|
||||
reasoning_config: Optional[dict] = None,
|
||||
) -> Any:
|
||||
"""Centralized asynchronous LLM call.
|
||||
|
||||
+24
-24
@@ -536,22 +536,22 @@ class BatchRunner:
|
||||
run_name: str,
|
||||
distribution: str = "default",
|
||||
max_iterations: int = 10,
|
||||
base_url: str = None,
|
||||
api_key: str = None,
|
||||
base_url: str | None = None,
|
||||
api_key: str | None = None,
|
||||
model: str = "claude-opus-4-20250514",
|
||||
num_workers: int = 4,
|
||||
verbose: bool = False,
|
||||
ephemeral_system_prompt: str = None,
|
||||
ephemeral_system_prompt: str | None = None,
|
||||
log_prefix_chars: int = 100,
|
||||
providers_allowed: List[str] = None,
|
||||
providers_ignored: List[str] = None,
|
||||
providers_order: List[str] = None,
|
||||
provider_sort: str = None,
|
||||
providers_allowed: List[str] | None = None,
|
||||
providers_ignored: List[str] | None = None,
|
||||
providers_order: List[str] | None = None,
|
||||
provider_sort: str | None = None,
|
||||
openrouter_min_coding_score: Optional[float] = None,
|
||||
max_tokens: int = None,
|
||||
reasoning_config: Dict[str, Any] = None,
|
||||
prefill_messages: List[Dict[str, Any]] = None,
|
||||
max_samples: int = None,
|
||||
max_tokens: int | None = None,
|
||||
reasoning_config: Dict[str, Any] | None = None,
|
||||
prefill_messages: List[Dict[str, Any]] | None = None,
|
||||
max_samples: int | None = None,
|
||||
):
|
||||
"""
|
||||
Initialize the batch runner.
|
||||
@@ -1145,29 +1145,29 @@ class BatchRunner:
|
||||
|
||||
|
||||
def main(
|
||||
dataset_file: str = None,
|
||||
batch_size: int = None,
|
||||
run_name: str = None,
|
||||
dataset_file: str | None = None,
|
||||
batch_size: int | None = None,
|
||||
run_name: str | None = None,
|
||||
distribution: str = "default",
|
||||
model: str = "anthropic/claude-sonnet-4.6",
|
||||
api_key: str = None,
|
||||
api_key: str | None = None,
|
||||
base_url: str = "https://openrouter.ai/api/v1",
|
||||
max_turns: int = 10,
|
||||
num_workers: int = 4,
|
||||
resume: bool = False,
|
||||
verbose: bool = False,
|
||||
list_distributions: bool = False,
|
||||
ephemeral_system_prompt: str = None,
|
||||
ephemeral_system_prompt: str | None = None,
|
||||
log_prefix_chars: int = 100,
|
||||
providers_allowed: str = None,
|
||||
providers_ignored: str = None,
|
||||
providers_order: str = None,
|
||||
provider_sort: str = None,
|
||||
max_tokens: int = None,
|
||||
reasoning_effort: str = None,
|
||||
providers_allowed: str | None = None,
|
||||
providers_ignored: str | None = None,
|
||||
providers_order: str | None = None,
|
||||
provider_sort: str | None = None,
|
||||
max_tokens: int | None = None,
|
||||
reasoning_effort: str | None = None,
|
||||
reasoning_disabled: bool = False,
|
||||
prefill_messages_file: str = None,
|
||||
max_samples: int = None,
|
||||
prefill_messages_file: str | None = None,
|
||||
max_samples: int | None = None,
|
||||
):
|
||||
"""
|
||||
Run batch processing of agent prompts from a dataset.
|
||||
|
||||
@@ -3708,15 +3708,15 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
model: str = None,
|
||||
toolsets: List[str] = None,
|
||||
provider: str = None,
|
||||
api_key: str = None,
|
||||
base_url: str = None,
|
||||
max_turns: int = None,
|
||||
model: str | None = None,
|
||||
toolsets: List[str] | None = None,
|
||||
provider: str | None = None,
|
||||
api_key: str | None = None,
|
||||
base_url: str | None = None,
|
||||
max_turns: int | None = None,
|
||||
verbose: Optional[bool] = None,
|
||||
compact: bool = False,
|
||||
resume: str = None,
|
||||
resume: str | None = None,
|
||||
checkpoints: bool = False,
|
||||
pass_session_id: bool = False,
|
||||
ignore_rules: bool = False,
|
||||
@@ -15999,23 +15999,23 @@ def _run_kanban_goal_loop_q(cli: "HermesCLI", first_response: str) -> None:
|
||||
|
||||
|
||||
def main(
|
||||
query: str = None,
|
||||
q: str = None,
|
||||
image: str = None,
|
||||
toolsets: str = None,
|
||||
skills: str | list[str] | tuple[str, ...] = None,
|
||||
model: str = None,
|
||||
provider: str = None,
|
||||
api_key: str = None,
|
||||
base_url: str = None,
|
||||
max_turns: int = None,
|
||||
query: str | None = None,
|
||||
q: str | None = None,
|
||||
image: str | None = None,
|
||||
toolsets: str | None = None,
|
||||
skills: str | list[str] | tuple[str, ...] | None = None,
|
||||
model: str | None = None,
|
||||
provider: str | None = None,
|
||||
api_key: str | None = None,
|
||||
base_url: str | None = None,
|
||||
max_turns: int | None = None,
|
||||
verbose: Optional[bool] = None,
|
||||
quiet: bool = False,
|
||||
compact: bool = False,
|
||||
list_tools: bool = False,
|
||||
list_toolsets: bool = False,
|
||||
gateway: bool = False,
|
||||
resume: str = None,
|
||||
resume: str | None = None,
|
||||
worktree: bool = False,
|
||||
w: bool = False,
|
||||
checkpoints: bool = False,
|
||||
|
||||
@@ -2891,8 +2891,8 @@ class APIServerAdapter(BasePlatformAdapter):
|
||||
|
||||
async def _write_sse_chat_completion(
|
||||
self, request: "web.Request", completion_id: str, model: str,
|
||||
created: int, stream_q, agent_task, agent_ref=None, session_id: str = None,
|
||||
gateway_session_key: str = None,
|
||||
created: int, stream_q, agent_task, agent_ref | None = None, session_id: str = None,
|
||||
gateway_session_key: str | None = None,
|
||||
) -> "web.StreamResponse":
|
||||
"""Write real streaming SSE from agent's stream_delta_callback queue.
|
||||
|
||||
|
||||
+5
-5
@@ -219,7 +219,7 @@ def _gateway_platform_value(platform: Any) -> str:
|
||||
def _non_conversational_metadata(
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
*,
|
||||
platform: Any = None,
|
||||
platform: Any | None = None,
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
"""Mark Discord lifecycle/status sends without changing other platforms."""
|
||||
if _gateway_platform_value(platform) != "discord":
|
||||
@@ -542,7 +542,7 @@ def _resolve_gateway_display_bool(
|
||||
setting: str,
|
||||
*,
|
||||
default: bool = False,
|
||||
platform: Any = None,
|
||||
platform: Any | None = None,
|
||||
require_platform_override_for: set[Any] | None = None,
|
||||
) -> bool:
|
||||
"""Resolve a boolean display setting with optional platform-only opt-in.
|
||||
@@ -17311,7 +17311,7 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
|
||||
history: List[Dict[str, Any]],
|
||||
source: "SessionSource",
|
||||
session_id: str,
|
||||
session_key: str = None,
|
||||
session_key: str | None = None,
|
||||
run_generation: Optional[int] = None,
|
||||
event_message_id: Optional[str] = None,
|
||||
) -> Dict[str, Any]:
|
||||
@@ -17610,7 +17610,7 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
|
||||
history: List[Dict[str, Any]],
|
||||
source: SessionSource,
|
||||
session_id: str,
|
||||
session_key: str = None,
|
||||
session_key: str | None = None,
|
||||
run_generation: Optional[int] = None,
|
||||
_interrupt_depth: int = 0,
|
||||
event_message_id: Optional[str] = None,
|
||||
@@ -17760,7 +17760,7 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
|
||||
history: List[Dict[str, Any]],
|
||||
source: SessionSource,
|
||||
session_id: str,
|
||||
session_key: str = None,
|
||||
session_key: str | None = None,
|
||||
run_generation: Optional[int] = None,
|
||||
_interrupt_depth: int = 0,
|
||||
event_message_id: Optional[str] = None,
|
||||
|
||||
+6
-6
@@ -2132,8 +2132,8 @@ def _scope_values(raw_scope: Any) -> set[str]:
|
||||
def _nous_invoke_jwt_status(
|
||||
token: Any,
|
||||
*,
|
||||
scope: Any = None,
|
||||
expires_at: Any = None,
|
||||
scope: Any | None = None,
|
||||
expires_at: Any | None = None,
|
||||
min_ttl_seconds: int = NOUS_INVOKE_JWT_MIN_TTL_SECONDS,
|
||||
) -> Optional[str]:
|
||||
"""Return None when the token can be used for inference, else a reason."""
|
||||
@@ -2161,8 +2161,8 @@ def _nous_invoke_jwt_status(
|
||||
def _nous_invoke_jwt_is_usable(
|
||||
token: Any,
|
||||
*,
|
||||
scope: Any = None,
|
||||
expires_at: Any = None,
|
||||
scope: Any | None = None,
|
||||
expires_at: Any | None = None,
|
||||
min_ttl_seconds: int = NOUS_INVOKE_JWT_MIN_TTL_SECONDS,
|
||||
) -> bool:
|
||||
return (
|
||||
@@ -2179,7 +2179,7 @@ def _nous_invoke_jwt_is_usable(
|
||||
def _assert_nous_inference_jwt_usable(
|
||||
state: Dict[str, Any],
|
||||
*,
|
||||
access_token: Any = None,
|
||||
access_token: Any | None = None,
|
||||
) -> None:
|
||||
token = state.get("access_token") if access_token is None else access_token
|
||||
reason = _nous_invoke_jwt_status(
|
||||
@@ -2263,7 +2263,7 @@ def _set_nous_agent_key_from_invoke_jwt(
|
||||
def _select_nous_invoke_jwt(
|
||||
state: Dict[str, Any],
|
||||
*,
|
||||
access_token: Any = None,
|
||||
access_token: Any | None = None,
|
||||
sequence_id: Optional[str] = None,
|
||||
) -> None:
|
||||
if isinstance(access_token, str) and access_token.strip():
|
||||
|
||||
@@ -578,12 +578,12 @@ def _display_toolset_name(toolset_name: str) -> str:
|
||||
|
||||
|
||||
def build_welcome_banner(console: "Console", model: str, cwd: str,
|
||||
tools: List[dict] = None,
|
||||
enabled_toolsets: List[str] = None,
|
||||
session_id: str = None,
|
||||
tools: List[dict] | None = None,
|
||||
enabled_toolsets: List[str] | None = None,
|
||||
session_id: str | None = None,
|
||||
get_toolset_for_tool=None,
|
||||
context_length: int = None,
|
||||
provider: str = None):
|
||||
context_length: int | None = None,
|
||||
provider: str | None = None):
|
||||
"""Build and print a welcome banner with caduceus on left and info on right.
|
||||
|
||||
Args:
|
||||
|
||||
@@ -3391,7 +3391,7 @@ def _has_sticky_block(conn: sqlite3.Connection, task_id: str) -> bool:
|
||||
|
||||
|
||||
def recompute_ready(
|
||||
conn: sqlite3.Connection, failure_limit: int = None,
|
||||
conn: sqlite3.Connection, failure_limit: int | None = None,
|
||||
) -> int:
|
||||
"""Promote ``todo`` tasks to ``ready`` when all parents are ``done`` or ``archived``.
|
||||
|
||||
@@ -7025,7 +7025,7 @@ def _record_task_failure(
|
||||
error: str,
|
||||
*,
|
||||
outcome: str,
|
||||
failure_limit: int = None,
|
||||
failure_limit: int | None = None,
|
||||
force_trip: bool = False,
|
||||
release_claim: bool = False,
|
||||
end_run: bool = False,
|
||||
@@ -7190,7 +7190,7 @@ def _record_spawn_failure(
|
||||
task_id: str,
|
||||
error: str,
|
||||
*,
|
||||
failure_limit: int = None,
|
||||
failure_limit: int | None = None,
|
||||
) -> bool:
|
||||
return _record_task_failure(
|
||||
conn, task_id, error,
|
||||
|
||||
+2
-2
@@ -2008,8 +2008,8 @@ def _launch_tui(
|
||||
tui_dev: bool = False,
|
||||
model: Optional[str] = None,
|
||||
provider: Optional[str] = None,
|
||||
toolsets: object = None,
|
||||
skills: object = None,
|
||||
toolsets: object | None = None,
|
||||
skills: object | None = None,
|
||||
verbose: Optional[bool] = None,
|
||||
quiet: bool = False,
|
||||
query: Optional[str] = None,
|
||||
|
||||
@@ -638,7 +638,7 @@ def resolve_alias(
|
||||
|
||||
def get_authenticated_provider_slugs(
|
||||
current_provider: str = "",
|
||||
user_providers: dict = None,
|
||||
user_providers: dict | None = None,
|
||||
custom_providers: list | None = None,
|
||||
) -> list[str]:
|
||||
"""Return slugs of providers that have credentials.
|
||||
@@ -801,7 +801,7 @@ def switch_model(
|
||||
current_api_key: str = "",
|
||||
is_global: bool = False,
|
||||
explicit_provider: str = "",
|
||||
user_providers: dict = None,
|
||||
user_providers: dict | None = None,
|
||||
custom_providers: list | None = None,
|
||||
) -> ModelSwitchResult:
|
||||
"""Core model-switching pipeline shared between CLI and gateway.
|
||||
@@ -1471,7 +1471,7 @@ def prewarm_picker_cache_async() -> Optional["_threading.Thread"]:
|
||||
def list_authenticated_providers(
|
||||
current_provider: str = "",
|
||||
current_base_url: str = "",
|
||||
user_providers: dict = None,
|
||||
user_providers: dict | None = None,
|
||||
custom_providers: list | None = None,
|
||||
*,
|
||||
force_fresh_nous_tier: bool = False,
|
||||
@@ -2438,7 +2438,7 @@ def _prepend_moa_picker_provider(providers: List[dict], current_provider: str =
|
||||
def list_picker_providers(
|
||||
current_provider: str = "",
|
||||
current_base_url: str = "",
|
||||
user_providers: dict = None,
|
||||
user_providers: dict | None = None,
|
||||
custom_providers: list | None = None,
|
||||
max_models: int | None = None,
|
||||
current_model: str = "",
|
||||
|
||||
@@ -4042,9 +4042,9 @@ def get_sessions(
|
||||
min_messages: int = 0,
|
||||
archived: str = "exclude",
|
||||
order: str = "created",
|
||||
source: str = None,
|
||||
exclude_sources: str = None,
|
||||
cwd_prefix: str = None,
|
||||
source: str | None = None,
|
||||
exclude_sources: str | None = None,
|
||||
cwd_prefix: str | None = None,
|
||||
full: bool = False,
|
||||
profile: Optional[str] = None,
|
||||
):
|
||||
@@ -4142,8 +4142,8 @@ def get_profiles_sessions(
|
||||
archived: str = "exclude",
|
||||
order: str = "recent",
|
||||
profile: str = "all",
|
||||
source: str = None,
|
||||
exclude_sources: str = None,
|
||||
source: str | None = None,
|
||||
exclude_sources: str | None = None,
|
||||
full: bool = False,
|
||||
):
|
||||
"""Unified, read-only session list aggregated across ALL profiles.
|
||||
|
||||
+49
-49
@@ -1928,17 +1928,17 @@ class SessionDB:
|
||||
self,
|
||||
session_id: str,
|
||||
source: str,
|
||||
model: str = None,
|
||||
model_config: Dict[str, Any] = None,
|
||||
system_prompt: str = None,
|
||||
user_id: str = None,
|
||||
session_key: str = None,
|
||||
chat_id: str = None,
|
||||
chat_type: str = None,
|
||||
thread_id: str = None,
|
||||
parent_session_id: str = None,
|
||||
cwd: str = None,
|
||||
profile_name: str = None,
|
||||
model: str | None = None,
|
||||
model_config: Dict[str, Any] | None = None,
|
||||
system_prompt: str | None = None,
|
||||
user_id: str | None = None,
|
||||
session_key: str | None = None,
|
||||
chat_id: str | None = None,
|
||||
chat_type: str | None = None,
|
||||
thread_id: str | None = None,
|
||||
parent_session_id: str | None = None,
|
||||
cwd: str | None = None,
|
||||
profile_name: str | None = None,
|
||||
) -> None:
|
||||
"""Insert a session row, enriching NULL metadata on conflict.
|
||||
|
||||
@@ -2005,13 +2005,13 @@ class SessionDB:
|
||||
session_id: str,
|
||||
*,
|
||||
source: str,
|
||||
user_id: str = None,
|
||||
session_key: str = None,
|
||||
chat_id: str = None,
|
||||
chat_type: str = None,
|
||||
thread_id: str = None,
|
||||
display_name: str = None,
|
||||
origin_json: str = None,
|
||||
user_id: str | None = None,
|
||||
session_key: str | None = None,
|
||||
chat_id: str | None = None,
|
||||
chat_type: str | None = None,
|
||||
thread_id: str | None = None,
|
||||
display_name: str | None = None,
|
||||
origin_json: str | None = None,
|
||||
) -> None:
|
||||
"""Persist the gateway routing peer for an existing session row.
|
||||
|
||||
@@ -2830,7 +2830,7 @@ class SessionDB:
|
||||
session_id: str,
|
||||
input_tokens: int = 0,
|
||||
output_tokens: int = 0,
|
||||
model: str = None,
|
||||
model: str | None = None,
|
||||
cache_read_tokens: int = 0,
|
||||
cache_write_tokens: int = 0,
|
||||
reasoning_tokens: int = 0,
|
||||
@@ -3100,7 +3100,7 @@ class SessionDB:
|
||||
self,
|
||||
session_id: str,
|
||||
source: str = "unknown",
|
||||
model: str = None,
|
||||
model: str | None = None,
|
||||
**kwargs,
|
||||
) -> str:
|
||||
"""Ensure a session row exists (INSERT OR IGNORE). Accepts optional kwargs."""
|
||||
@@ -3678,9 +3678,9 @@ class SessionDB:
|
||||
|
||||
def list_sessions_rich(
|
||||
self,
|
||||
source: str = None,
|
||||
exclude_sources: List[str] = None,
|
||||
cwd_prefix: str = None,
|
||||
source: str | None = None,
|
||||
exclude_sources: List[str] | None = None,
|
||||
cwd_prefix: str | None = None,
|
||||
limit: int = 20,
|
||||
offset: int = 0,
|
||||
include_children: bool = False,
|
||||
@@ -3689,8 +3689,8 @@ class SessionDB:
|
||||
order_by_last_active: bool = False,
|
||||
include_archived: bool = False,
|
||||
archived_only: bool = False,
|
||||
id_query: str = None,
|
||||
search_query: str = None,
|
||||
id_query: str | None = None,
|
||||
search_query: str | None = None,
|
||||
compact_rows: bool = False,
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""List sessions with preview (first user message) and last active timestamp.
|
||||
@@ -4123,21 +4123,21 @@ class SessionDB:
|
||||
self,
|
||||
session_id: str,
|
||||
role: str,
|
||||
content: str = None,
|
||||
tool_name: str = None,
|
||||
tool_calls: Any = None,
|
||||
tool_call_id: str = None,
|
||||
token_count: int = None,
|
||||
finish_reason: str = None,
|
||||
reasoning: str = None,
|
||||
reasoning_content: str = None,
|
||||
reasoning_details: Any = None,
|
||||
codex_reasoning_items: Any = None,
|
||||
codex_message_items: Any = None,
|
||||
platform_message_id: str = None,
|
||||
content: str | None = None,
|
||||
tool_name: str | None = None,
|
||||
tool_calls: Any | None = None,
|
||||
tool_call_id: str | None = None,
|
||||
token_count: int | None = None,
|
||||
finish_reason: str | None = None,
|
||||
reasoning: str | None = None,
|
||||
reasoning_content: str | None = None,
|
||||
reasoning_details: Any | None = None,
|
||||
codex_reasoning_items: Any | None = None,
|
||||
codex_message_items: Any | None = None,
|
||||
platform_message_id: str | None = None,
|
||||
observed: bool = False,
|
||||
effect_disposition: Optional[str] = None,
|
||||
timestamp: Any = None,
|
||||
timestamp: Any | None = None,
|
||||
) -> int:
|
||||
"""
|
||||
Append a message to a session. Returns the message row ID.
|
||||
@@ -5238,12 +5238,12 @@ class SessionDB:
|
||||
def search_messages(
|
||||
self,
|
||||
query: str,
|
||||
source_filter: List[str] = None,
|
||||
exclude_sources: List[str] = None,
|
||||
role_filter: List[str] = None,
|
||||
source_filter: List[str] | None = None,
|
||||
exclude_sources: List[str] | None = None,
|
||||
role_filter: List[str] | None = None,
|
||||
limit: int = 20,
|
||||
offset: int = 0,
|
||||
sort: str = None,
|
||||
sort: str | None = None,
|
||||
include_inactive: bool = False,
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
@@ -5605,7 +5605,7 @@ class SessionDB:
|
||||
|
||||
def search_sessions(
|
||||
self,
|
||||
source: str = None,
|
||||
source: str | None = None,
|
||||
limit: int = 20,
|
||||
offset: int = 0,
|
||||
) -> List[Dict[str, Any]]:
|
||||
@@ -5645,13 +5645,13 @@ class SessionDB:
|
||||
|
||||
def session_count(
|
||||
self,
|
||||
source: str = None,
|
||||
cwd_prefix: str = None,
|
||||
source: str | None = None,
|
||||
cwd_prefix: str | None = None,
|
||||
min_message_count: int = 0,
|
||||
include_archived: bool = False,
|
||||
archived_only: bool = False,
|
||||
exclude_children: bool = False,
|
||||
exclude_sources: List[str] = None,
|
||||
exclude_sources: List[str] | None = None,
|
||||
) -> int:
|
||||
"""Count sessions, optionally filtered by source.
|
||||
|
||||
@@ -6653,7 +6653,7 @@ class SessionDB:
|
||||
def list_prune_candidates(
|
||||
self,
|
||||
older_than_days: Optional[float] = None,
|
||||
source: str = None,
|
||||
source: str | None = None,
|
||||
**filters,
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Return the sessions a matching :meth:`prune_sessions` /
|
||||
@@ -6681,7 +6681,7 @@ class SessionDB:
|
||||
def archive_sessions(
|
||||
self,
|
||||
older_than_days: Optional[float] = None,
|
||||
source: str = None,
|
||||
source: str | None = None,
|
||||
**filters,
|
||||
) -> int:
|
||||
"""Bulk-archive (soft-hide) every session matching the filters.
|
||||
@@ -6707,7 +6707,7 @@ class SessionDB:
|
||||
def prune_sessions(
|
||||
self,
|
||||
older_than_days: Optional[float] = 90,
|
||||
source: str = None,
|
||||
source: str | None = None,
|
||||
sessions_dir: Optional[Path] = None,
|
||||
**filters,
|
||||
) -> int:
|
||||
|
||||
+6
-6
@@ -163,8 +163,8 @@ class MiniSWERunner:
|
||||
def __init__(
|
||||
self,
|
||||
model: str = "anthropic/claude-sonnet-4.6",
|
||||
base_url: str = None,
|
||||
api_key: str = None,
|
||||
base_url: str | None = None,
|
||||
api_key: str | None = None,
|
||||
env_type: str = "local",
|
||||
image: str = "python:3.11-slim",
|
||||
cwd: str = "/tmp",
|
||||
@@ -628,12 +628,12 @@ Complete the user's task step by step."""
|
||||
# ============================================================================
|
||||
|
||||
def main(
|
||||
task: str = None,
|
||||
prompts_file: str = None,
|
||||
task: str | None = None,
|
||||
prompts_file: str | None = None,
|
||||
output_file: str = "swe-runner-test1.jsonl",
|
||||
model: str = "claude-sonnet-4-20250514",
|
||||
base_url: str = None,
|
||||
api_key: str = None,
|
||||
base_url: str | None = None,
|
||||
api_key: str | None = None,
|
||||
env: str = "local",
|
||||
image: str = "python:3.11-slim",
|
||||
cwd: str = "/tmp",
|
||||
|
||||
+25
-8
@@ -9,6 +9,7 @@
|
||||
stdenv,
|
||||
makeWrapper,
|
||||
callPackage,
|
||||
python311,
|
||||
python312,
|
||||
nodejs_22,
|
||||
electron,
|
||||
@@ -37,15 +38,28 @@
|
||||
}:
|
||||
let
|
||||
nodejs = nodejs_22;
|
||||
|
||||
mkHermesVenv =
|
||||
extraDependencyGroups:
|
||||
{
|
||||
extraDependencyGroups,
|
||||
python ? null,
|
||||
}:
|
||||
callPackage ./python.nix {
|
||||
inherit uv2nix pyproject-nix pyproject-build-systems;
|
||||
inherit
|
||||
uv2nix
|
||||
pyproject-nix
|
||||
pyproject-build-systems
|
||||
python
|
||||
;
|
||||
pythonSrc = hermesNpmLib.pythonSrc;
|
||||
dependency-groups = [ "all" ] ++ extraDependencyGroups;
|
||||
};
|
||||
|
||||
hermesVenv = (mkHermesVenv extraDependencyGroups).venv;
|
||||
hermesVenv =
|
||||
(mkHermesVenv {
|
||||
inherit extraDependencyGroups;
|
||||
python = python312;
|
||||
}).venv;
|
||||
|
||||
hermesNpmLib = callPackage ./lib.nix {
|
||||
inherit npm-lockfile-fix nodejs;
|
||||
@@ -61,8 +75,7 @@ let
|
||||
|
||||
bundledSkills = lib.cleanSourceWith {
|
||||
src = ../skills;
|
||||
filter =
|
||||
path: _type: !(lib.hasInfix "/index-cache/" path) && !(lib.hasInfix "/__pycache__/" path);
|
||||
filter = path: _type: !(lib.hasInfix "/index-cache/" path) && !(lib.hasInfix "/__pycache__/" path);
|
||||
};
|
||||
|
||||
# Optional skills are NOT in the wheel (pythonSrc excludes them, see
|
||||
@@ -70,8 +83,7 @@ let
|
||||
# same mechanism Homebrew packaging uses.
|
||||
bundledOptionalSkills = lib.cleanSourceWith {
|
||||
src = ../optional-skills;
|
||||
filter =
|
||||
path: _type: !(lib.hasInfix "/index-cache/" path) && !(lib.hasInfix "/__pycache__/" path);
|
||||
filter = path: _type: !(lib.hasInfix "/index-cache/" path) && !(lib.hasInfix "/__pycache__/" path);
|
||||
};
|
||||
|
||||
# Import bundled plugins (memory, context_engine, platforms/*). Keeping
|
||||
@@ -224,8 +236,13 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
'';
|
||||
|
||||
passthru =
|
||||
python:
|
||||
let
|
||||
devPython = (mkHermesVenv (extraDependencyGroups ++ [ "dev" ])).editableVenv;
|
||||
devPython =
|
||||
(mkHermesVenv ({
|
||||
extraDependencyGroups = extraDependencyGroups ++ [ "dev" ];
|
||||
python = python311;
|
||||
})).editableVenv;
|
||||
in
|
||||
{
|
||||
inherit
|
||||
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
# nix/python.nix — uv2nix virtual environment builder
|
||||
{
|
||||
python312,
|
||||
python,
|
||||
lib,
|
||||
callPackage,
|
||||
uv2nix,
|
||||
@@ -65,30 +65,30 @@ let
|
||||
final: _prev:
|
||||
if isAarch64Darwin then
|
||||
{
|
||||
numpy = mkPrebuiltOverride final python312.pkgs.numpy { };
|
||||
numpy = mkPrebuiltOverride final python.pkgs.numpy { };
|
||||
|
||||
pyarrow = mkPrebuiltOverride final python312.pkgs.pyarrow { };
|
||||
pyarrow = mkPrebuiltOverride final python.pkgs.pyarrow { };
|
||||
|
||||
av = mkPrebuiltOverride final python312.pkgs.av { };
|
||||
av = mkPrebuiltOverride final python.pkgs.av { };
|
||||
|
||||
humanfriendly = mkPrebuiltOverride final python312.pkgs.humanfriendly { };
|
||||
humanfriendly = mkPrebuiltOverride final python.pkgs.humanfriendly { };
|
||||
|
||||
coloredlogs = mkPrebuiltOverride final python312.pkgs.coloredlogs {
|
||||
coloredlogs = mkPrebuiltOverride final python.pkgs.coloredlogs {
|
||||
humanfriendly = [ ];
|
||||
};
|
||||
|
||||
onnxruntime = mkPrebuiltOverride final python312.pkgs.onnxruntime {
|
||||
onnxruntime = mkPrebuiltOverride final python.pkgs.onnxruntime {
|
||||
coloredlogs = [ ];
|
||||
numpy = [ ];
|
||||
packaging = [ ];
|
||||
};
|
||||
|
||||
ctranslate2 = mkPrebuiltOverride final python312.pkgs.ctranslate2 {
|
||||
ctranslate2 = mkPrebuiltOverride final python.pkgs.ctranslate2 {
|
||||
numpy = [ ];
|
||||
pyyaml = [ ];
|
||||
};
|
||||
|
||||
faster-whisper = mkPrebuiltOverride final python312.pkgs.faster-whisper {
|
||||
faster-whisper = mkPrebuiltOverride final python.pkgs.faster-whisper {
|
||||
av = [ ];
|
||||
ctranslate2 = [ ];
|
||||
huggingface-hub = [ ];
|
||||
@@ -102,7 +102,7 @@ let
|
||||
|
||||
pythonSet =
|
||||
(callPackage pyproject-nix.build.packages {
|
||||
python = python312;
|
||||
python = python;
|
||||
}).overrideScope
|
||||
(
|
||||
lib.composeManyExtensions [
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
# ty type-checking notes — antipatterns & refactors spotted
|
||||
|
||||
working through the codebase root-to-tip with astral.sh `ty`.
|
||||
logging antipatterns, clean refactors, and observations as we go.
|
||||
|
||||
---
|
||||
|
||||
## tools/registry.py (dependency root, 810 lines)
|
||||
|
||||
### invalid-parameter-default (FIXED)
|
||||
three params in `ToolEntry.register()` were annotated as bare `Callable` / `list`
|
||||
but defaulted to `None`. this is the #1 pattern ty flags across the whole codebase
|
||||
(~423 occurrences). the fix is always the same: add `| None` to the annotation.
|
||||
|
||||
```python
|
||||
# BEFORE
|
||||
check_fn: Callable = None,
|
||||
requires_env: list = None,
|
||||
dynamic_schema_overrides: Callable = None,
|
||||
|
||||
# AFTER
|
||||
check_fn: Callable | None = None,
|
||||
requires_env: list | None = None,
|
||||
dynamic_schema_overrides: Callable | None = None,
|
||||
```
|
||||
|
||||
this is the single highest-leverage fix across the codebase. each one of these
|
||||
cascades: when ty sees `None` as a possible value, every downstream `d["key"]`,
|
||||
`d.get(...)`, `d.pop()` on that variable becomes an `unresolved-attribute` or
|
||||
`not-subscriptable` or `invalid-argument-type` error. fixing the parameter
|
||||
default upstream makes all those downstream errors vanish.
|
||||
|
||||
### antipattern: ToolEntry.__init__ has zero annotations
|
||||
|
||||
```python
|
||||
def __init__(self, name, toolset, schema, handler, check_fn,
|
||||
requires_env, is_async, description, emoji,
|
||||
max_result_size_chars=None, dynamic_schema_overrides=None):
|
||||
```
|
||||
|
||||
this is a core data class (every tool in the system passes through it) but has
|
||||
no type annotations on any parameter. `__slots__` is used so the shape is
|
||||
well-defined — adding annotations would be straightforward and high-value.
|
||||
ty can't infer much here because everything comes through as `Unknown`.
|
||||
|
||||
not fixed yet — would benefit from a proper pass:
|
||||
```python
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
toolset: str,
|
||||
schema: dict,
|
||||
handler: Callable,
|
||||
check_fn: Callable | None,
|
||||
requires_env: list[str],
|
||||
is_async: bool,
|
||||
description: str,
|
||||
emoji: str,
|
||||
max_result_size_chars: int | float | None = None,
|
||||
dynamic_schema_overrides: Callable | None = None,
|
||||
):
|
||||
```
|
||||
|
||||
### antipattern: tool_error / tool_result helpers lack annotations
|
||||
|
||||
```python
|
||||
def tool_error(message, **extra) -> str: # message: str, **extra: Any
|
||||
def tool_result(data=None, **kwargs) -> str: # data: dict | None, **kwargs: Any
|
||||
```
|
||||
|
||||
these are the canonical serialization helpers used by hundreds of tool handlers.
|
||||
low-effort to annotate, high-value since they're the return path for everything.
|
||||
|
||||
### clean pattern: _check_fn_cached TTL + grace window
|
||||
|
||||
this is well-done code. the TTL cache with transient-failure suppression is
|
||||
a correct implementation of a flaky-external-check absorption pattern. the
|
||||
docstrings explain WHY (issue #21658 / #5304 — flaky docker probes stripping
|
||||
tools mid-session). nothing to change here, just noting it as a positive
|
||||
example of defensive caching done right.
|
||||
|
||||
### clean pattern: _snapshot_state() for thread safety
|
||||
|
||||
using `_lock` + snapshot copies for reads is the right pattern for a registry
|
||||
that can be mutated by MCP dynamic refresh while other threads read. the
|
||||
generation counter for cache invalidation is also clean.
|
||||
|
||||
### observation: `from typing import` vs PEP 604 `X | None`
|
||||
|
||||
the file imports `Optional`, `Callable`, `Dict`, `List`, `Set` from `typing`
|
||||
but also uses `int | float | None` (PEP 604) in the same signatures. the
|
||||
codebase targets python >=3.11 so PEP 604 is always available. there's a
|
||||
mix of `Optional[X]` and `X | None` styles across files — not a bug, but
|
||||
worth standardizing on `X | None` (PEP 604) as we type-sweep since it's
|
||||
shorter and the modern idiom.
|
||||
|
||||
---
|
||||
|
||||
## agent/agent_init.py + run_agent.py (AIAgent constructor, 60+ params)
|
||||
|
||||
### invalid-parameter-default (FIXED — 31 + 54 params)
|
||||
same pattern as registry.py but at massive scale. the AIAgent.__init__ in
|
||||
`agent_init.py` and the class `AIAgent.__init__` in `run_agent.py` each take
|
||||
~60 params, nearly all defaulting to None but annotated as bare `str`, `list`,
|
||||
`dict`, `int`, etc.
|
||||
|
||||
### antipattern: lowercase `callable` used as a type annotation
|
||||
|
||||
**this is a real runtime bug, not just a type error.** 14 callback params in
|
||||
both `agent_init.py` and `run_agent.py` were annotated as `callable` (the
|
||||
builtin *function*) instead of `Callable` (from `typing`).
|
||||
|
||||
```python
|
||||
# BEFORE — runtime crash if you try `X | None`
|
||||
tool_progress_callback: callable = None, # callable is the builtin function
|
||||
|
||||
# AFTER
|
||||
tool_progress_callback: Callable | None = None, # Callable is the type
|
||||
```
|
||||
|
||||
when the automated sweep script added `| None` to these, it produced
|
||||
`callable | None` which crashes at *import time* with:
|
||||
```
|
||||
TypeError: unsupported operand type(s) for |: 'builtin_function_or_method' and 'NoneType'
|
||||
```
|
||||
|
||||
this was lurking silently as long as nobody tried to make the annotation
|
||||
nullable — the `callable` builtin is truthy so `callable = None` didn't
|
||||
crash, it just stored a nonsensical annotation. the fix is `Callable` (capital C).
|
||||
|
||||
also spotted in `agent/transports/chat_completions.py` in docstring-like
|
||||
comments (lines 290, 314-315) — not executable code but worth standardizing.
|
||||
|
||||
### antipattern: string forward-ref with `| None` doesn't work
|
||||
|
||||
```python
|
||||
# WRONG — crashes at class-def time
|
||||
iteration_budget: "IterationBudget" | None = None,
|
||||
# TypeError: unsupported operand type(s) for |: 'str' and 'NoneType'
|
||||
|
||||
# RIGHT — wrap the whole thing in Optional
|
||||
iteration_budget: Optional["IterationBudget"] = None,
|
||||
```
|
||||
|
||||
when a type is a forward reference (string-quoted because it's not yet defined),
|
||||
you CANNOT use PEP 604 `| None` on it directly — the `|` operator tries to
|
||||
OR a `str` with `NoneType` and crashes. must use `Optional["ForwardRef"]`.
|
||||
|
||||
this affected both `agent_init.py` and `run_agent.py`.
|
||||
|
||||
---
|
||||
|
||||
## hermes_state.py (49 params fixed)
|
||||
same `X = None` → `X | None = None` sweep. this is the SQLite session store
|
||||
module — heavily imported by cli.py, run_agent.py, gateway/, etc.
|
||||
|
||||
## batch_runner.py (24 params fixed)
|
||||
parallel batch processing entry point.
|
||||
|
||||
## cli.py (18 params fixed)
|
||||
the HermesCLI class constructor + helper methods.
|
||||
|
||||
## tools/*.py (20+ params fixed across file_tools, file_operations,
|
||||
skills_tool, skills_hub, terminal_tool, browser_tool, memory_tool,
|
||||
delegate_tool, process_registry, skill_manager_tool, session_search_tool)
|
||||
|
||||
---
|
||||
|
||||
## summary of the invalid-parameter-default sweep
|
||||
|
||||
total params fixed: ~250 across ~25 core files
|
||||
the pattern is always identical: `param: Type = None` → `param: Type | None = None`
|
||||
|
||||
two runtime-breaking gotchas found during the sweep:
|
||||
1. lowercase `callable` (builtin function) → must be `Callable` (typing)
|
||||
2. string forward-refs can't use `| None` → must use `Optional["Ref"]`
|
||||
|
||||
---
|
||||
|
||||
## run_agent.py — unresolved-attribute analysis (190 errors)
|
||||
|
||||
### category 1: "Self@<method>" — init_agent() cross-module init (186/190)
|
||||
|
||||
these are ALL the same root cause: `AIAgent.__init__` in `run_agent.py` is a
|
||||
thin forwarder that calls `init_agent(self, ...)` from `agent/agent_init.py`.
|
||||
that function sets `self.model`, `self.provider`, `self.session_id`, etc. on
|
||||
the instance — but ty can't see across the module boundary that these
|
||||
attributes are being set. so every method that accesses `self.model`,
|
||||
`self.provider`, etc. gets flagged.
|
||||
|
||||
**these are NOT bugs.** the attributes are correctly set at runtime by
|
||||
`init_agent()`. this is a ty limitation — it can't track attribute assignments
|
||||
made in a function defined in a different module that receives `self` as a
|
||||
regular parameter (not as a method on the class).
|
||||
|
||||
example:
|
||||
```python
|
||||
# run_agent.py
|
||||
class AIAgent:
|
||||
def __init__(self, model: str = "", ...):
|
||||
from agent.agent_init import init_agent
|
||||
init_agent(self, model=model, ...) # sets self.model, self.provider, etc.
|
||||
|
||||
def _resolved_api_call_timeout(self):
|
||||
return self.provider # ty: "Self@_resolved_api_call_timeout has no attribute provider"
|
||||
```
|
||||
|
||||
**fix approach:** this is the single biggest cluster of ty errors in the
|
||||
codebase (186 in run_agent.py alone, plus similar in other files). the cleanest
|
||||
fix would be to declare the attributes as class-level annotations in the
|
||||
`AIAgent` class body so ty knows they exist:
|
||||
|
||||
```python
|
||||
class AIAgent:
|
||||
# Instance attributes — set by init_agent() in agent/agent_init.py
|
||||
model: str
|
||||
provider: str | None
|
||||
session_id: str | None
|
||||
# ... etc
|
||||
```
|
||||
|
||||
this is a one-time declaration that would clear ~186 errors instantly. it's
|
||||
also good documentation — currently there's no single place that lists all
|
||||
instance attributes; they're scattered across the 60-param init_agent() body.
|
||||
|
||||
### category 2: object.function — duck-typed tool_calls access (2 errors)
|
||||
|
||||
line 1968: `tc.function.name` and `tc.function.arguments` on objects typed as
|
||||
`object`. this is because `msg.tool_calls` is checked via `hasattr` +
|
||||
`isinstance(list)` but the list elements are `object` to ty.
|
||||
|
||||
```python
|
||||
if hasattr(msg, "tool_calls") and isinstance(msg.tool_calls, list) and msg.tool_calls:
|
||||
tool_calls_data = [
|
||||
{"name": tc.function.name, "arguments": tc.function.arguments}
|
||||
for tc in msg.tool_calls
|
||||
]
|
||||
```
|
||||
|
||||
**not a bug** — this is duck-typed access to OpenAI SDK objects. the `hasattr`
|
||||
guard makes it safe at runtime. ty just can't infer the element type of a
|
||||
list accessed via `hasattr`. could be fixed with a `type: ignore` or by
|
||||
narrowing `msg` to a proper type.
|
||||
|
||||
### category 3: ~AlwaysFalsy.on_session_end — duck-typed context_compressor (2 errors)
|
||||
|
||||
lines 3416, 3441: `self.context_compressor.on_session_end(...)` after a
|
||||
`hasattr(self, "context_compressor") and self.context_compressor` guard.
|
||||
|
||||
```python
|
||||
if hasattr(self, "context_compressor") and self.context_compressor:
|
||||
self.context_compressor.on_session_end(self.session_id or "", messages or [])
|
||||
```
|
||||
|
||||
ty narrows `self.context_compressor` to `~AlwaysFalsy` (the truthy branch of
|
||||
the `and`) but doesn't know it has `on_session_end`. **not a bug** — the
|
||||
`hasattr` guard makes this safe. again a type-system limitation with
|
||||
duck-typed access.
|
||||
|
||||
### verdict for run_agent.py: 0 real bugs, 190 type-system limitations
|
||||
|
||||
all 190 are ty being unable to track either cross-module attribute init
|
||||
(186) or duck-typed hasattr-guarded access (4). no logic bugs found.
|
||||
|
||||
### remaining 6 unresolved-attribute (post class-level annotation fix)
|
||||
|
||||
1. **line 2162** (`object.function` ×2): duck-typed access to OpenAI SDK
|
||||
`ChatCompletionMessageToolCall` objects. `hasattr` guard makes it safe.
|
||||
ty can't infer the list element type through `hasattr`. not a bug.
|
||||
|
||||
2. **lines 3586-3587** (`iteration_budget.used` / `.max_total`): `iteration_budget`
|
||||
is `Optional[IterationBudget]` but `init_agent` always sets it to a non-None
|
||||
value (`iteration_budget or IterationBudget(max_iterations)`). the annotation
|
||||
says `| None` but the code guarantees non-None at runtime. not a bug — but
|
||||
the annotation could be tightened to just `IterationBudget` (without Optional).
|
||||
|
||||
3. **lines 4677 + 4799** (`_anthropic_client.close()`): `_anthropic_client` is
|
||||
`Any | None` — could be None if the anthropic path was never taken. but both
|
||||
call sites are wrapped in `try/except Exception: pass`, so even if it IS None,
|
||||
the AttributeError is caught. safe.
|
||||
|
||||
---
|
||||
|
||||
## plugins/platforms/discord/adapter.py — unresolved-attribute analysis (269 errors)
|
||||
|
||||
### root cause: ty resolving the wrong Python environment
|
||||
|
||||
the `.venv` directory (created by `uv run` earlier) contained Python 3.13 with
|
||||
NO dependencies installed. ty auto-discovers `.venv` and uses it for module
|
||||
resolution — so it couldn't find `discord.py`, `aiohttp`, etc., producing 254
|
||||
`Module 'discord' has no member X` errors.
|
||||
|
||||
the actual dependencies are installed in the nix develop environment
|
||||
(Python 3.12, all deps in site-packages). removing the empty `.venv` made ty
|
||||
fall back to the system/nix python, resolving all 254 import errors instantly.
|
||||
|
||||
**fix:** `rm -rf .venv` (it was a stray artifact, not a real venv).
|
||||
also set `python-version = "3.12"` in `[tool.ty.environment]` to match the
|
||||
nix env, with a comment explaining why.
|
||||
|
||||
**impact:** 4,422 → 3,385 diagnostics (−1,037) from this single fix.
|
||||
|
||||
### remaining 122 discord errors (post-fix)
|
||||
|
||||
after ty could resolve discord.py:
|
||||
- 17 `not defined on None` — `self._client` (Optional[commands.Bot]) accessed
|
||||
before ty can prove it's non-None. all are in event handlers called after
|
||||
the bot is ready. not bugs, but could benefit from `assert self._client is not None`
|
||||
guards for type narrowing.
|
||||
- ~100 remaining are real type-checking errors from ty now being able to
|
||||
see discord.py's actual types (mismatched args, wrong attribute access, etc.)
|
||||
these need individual triage.
|
||||
@@ -92,12 +92,12 @@ class EvidenceStore:
|
||||
source: str,
|
||||
content: str,
|
||||
evidence_type: str,
|
||||
actor: str = None,
|
||||
url: str = None,
|
||||
timestamp: str = None,
|
||||
ioc_type: str = None,
|
||||
actor: str | None = None,
|
||||
url: str | None = None,
|
||||
timestamp: str | None = None,
|
||||
ioc_type: str | None = None,
|
||||
verification: str = "unverified",
|
||||
notes: str = None,
|
||||
notes: str | None = None,
|
||||
) -> str:
|
||||
evidence_id = self._next_id()
|
||||
entry = {
|
||||
|
||||
+7
-1
@@ -366,12 +366,18 @@ markers = [
|
||||
addopts = "-m 'not integration'"
|
||||
|
||||
[tool.ty.environment]
|
||||
python-version = "3.13"
|
||||
# Match requires-python floor (>=3.11).
|
||||
python-version = "3.11"
|
||||
|
||||
[tool.ty.rules]
|
||||
unknown-argument = "warn"
|
||||
redundant-cast = "ignore"
|
||||
|
||||
# Exclude tests from type-checking — they're the lowest-value typing target
|
||||
# (~57% of diagnostics) and we want to focus ty on the core codebase.
|
||||
[tool.ty.src]
|
||||
exclude = ["tests/"]
|
||||
|
||||
[tool.ruff]
|
||||
preview = true # required for PLW1514 (unspecified-encoding) — preview rule
|
||||
|
||||
|
||||
+248
-54
@@ -400,6 +400,200 @@ class AIAgent:
|
||||
for AI models that support function calling.
|
||||
"""
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Instance attributes — set by init_agent() in agent/agent_init.py.
|
||||
# Ideally, we could refactor this class into smaller parts so that
|
||||
# we don't need to split its __init__ into a separate file.
|
||||
# Declared here so type checkers know they exist (init_agent receives
|
||||
# the instance as a plain `agent` parameter, not as a method receiver,
|
||||
# so cross-module attribute assignment is invisible to static analysis).
|
||||
# -----------------------------------------------------------------------
|
||||
# scalars
|
||||
_anthropic_api_key: str
|
||||
_anthropic_base_url: str | None
|
||||
_budget_exhausted_injected: bool
|
||||
_budget_grace_call: bool
|
||||
_cache_ttl: str
|
||||
_cached_system_prompt: str | None
|
||||
_chat_id: str | None
|
||||
_chat_name: str | None
|
||||
_chat_type: str | None
|
||||
_client_kwargs: dict
|
||||
_codex_reasoning_replay_enabled: bool
|
||||
_compression_feasibility_checked: bool
|
||||
_credits_latch: dict
|
||||
_current_streamed_assistant_text: str
|
||||
_delegate_depth: int
|
||||
_end_session_on_close: bool
|
||||
_executing_tools: bool
|
||||
_fallback_activated: bool
|
||||
_fallback_chain: list
|
||||
_fallback_index: int
|
||||
_force_ascii_payload: bool
|
||||
_interrupt_requested: bool
|
||||
_interrupt_thread_signal_pending: bool
|
||||
_is_anthropic_oauth: bool
|
||||
_is_user_initiated_turn: bool
|
||||
_iters_since_skill: int
|
||||
_last_flushed_db_idx: int
|
||||
_memory_enabled: bool
|
||||
_memory_nudge_interval: int
|
||||
_memory_write_context: str
|
||||
_memory_write_origin: str
|
||||
_parent_session_id: str | None
|
||||
_persist_disabled: bool
|
||||
_primary_runtime: dict
|
||||
_session_db_created: bool
|
||||
_session_init_model_config: dict
|
||||
_session_json_enabled: bool
|
||||
_skill_nudge_interval: int
|
||||
_skip_mcp_refresh: bool
|
||||
_stream_needs_break: bool
|
||||
_stream_writer_dropped: int
|
||||
_stream_writer_token: int
|
||||
_thread_id: str | None
|
||||
_tool_snapshot_generation: int
|
||||
_turns_since_memory: int
|
||||
_user_name: str | None
|
||||
_user_profile_enabled: bool
|
||||
_user_turn_count: int
|
||||
acp_command: str | None
|
||||
api_key: str | None
|
||||
api_mode: str | None
|
||||
ephemeral_system_prompt: str | None
|
||||
lmstudio_load_mode: str
|
||||
load_soul_identity: bool
|
||||
log_prefix: str
|
||||
log_prefix_chars: int
|
||||
max_iterations: int
|
||||
max_tokens: int | None
|
||||
memory_notifications: str
|
||||
model: str
|
||||
pass_session_id: bool
|
||||
platform: str | None
|
||||
provider: str | None
|
||||
provider_data_collection: str | None
|
||||
provider_require_parameters: bool
|
||||
provider_sort: str | None
|
||||
quiet_mode: bool
|
||||
save_trajectories: bool
|
||||
service_tier: str | None
|
||||
session_api_calls: int
|
||||
session_cache_read_tokens: int
|
||||
session_cache_write_tokens: int
|
||||
session_completion_tokens: int
|
||||
session_cost_source: str
|
||||
session_cost_status: str
|
||||
session_estimated_cost_usd: float
|
||||
session_id: str | None
|
||||
session_input_tokens: int
|
||||
session_output_tokens: int
|
||||
session_prompt_tokens: int
|
||||
session_reasoning_tokens: int
|
||||
session_total_tokens: int
|
||||
show_commentary: bool
|
||||
skip_context_files: bool
|
||||
suppress_status_output: bool
|
||||
tool_delay: float
|
||||
tool_progress_mode: str
|
||||
verbose_logging: bool
|
||||
|
||||
# callbacks
|
||||
clarify_callback: Callable | None
|
||||
event_callback: Optional[Callable[[str, dict], None]]
|
||||
interim_assistant_callback: Callable | None
|
||||
notice_callback: Callable | None
|
||||
notice_clear_callback: Callable | None
|
||||
reaction_callback: Optional[Callable[[str], None]]
|
||||
read_terminal_callback: Callable | None
|
||||
reasoning_callback: Callable | None
|
||||
status_callback: Callable | None
|
||||
step_callback: Callable | None
|
||||
stream_delta_callback: Callable | None
|
||||
thinking_callback: Callable | None
|
||||
tool_complete_callback: Callable | None
|
||||
tool_gen_callback: Callable | None
|
||||
tool_progress_callback: Callable | None
|
||||
tool_start_callback: Callable | None
|
||||
|
||||
# collections
|
||||
acp_args: list[str] | None
|
||||
disabled_toolsets: List[str] | None
|
||||
enabled_toolsets: List[str] | None
|
||||
prefill_messages: List[Dict[str, Any]] | None
|
||||
providers_allowed: List[str] | None
|
||||
providers_ignored: List[str] | None
|
||||
providers_order: List[str] | None
|
||||
reasoning_config: Dict[str, Any] | None
|
||||
request_overrides: Dict[str, Any] | None
|
||||
|
||||
# internal / runtime state
|
||||
_active_children: list
|
||||
_active_children_lock: Any
|
||||
_anthropic_client: Any | None
|
||||
_anthropic_image_fallback_cache: Any
|
||||
_api_max_retries: Any
|
||||
_aux_compression_context_length_config: Any | None
|
||||
_base_url_hostname: Any
|
||||
_bedrock_guardrail_config: Any | None
|
||||
_bedrock_region: Any
|
||||
_checkpoint_mgr: Any
|
||||
_client_lock: Any
|
||||
_compression_threshold_autoraised: Any | None
|
||||
_compression_warning: Any | None
|
||||
_config_context_length: Any
|
||||
_credential_pool: Any
|
||||
_credits_session_start_micros: Any | None
|
||||
_credits_state: Any | None
|
||||
_custom_providers: Any
|
||||
_environment_probe: Any
|
||||
_execution_thread_id: Any
|
||||
_fallback_model: Any
|
||||
_gateway_session_key: Any
|
||||
_intent_ack_continuation: Any
|
||||
_interrupt_message: Any
|
||||
_kanban_worker_guidance: Any
|
||||
_memory_manager: Any | None
|
||||
_memory_store: Any | None
|
||||
_ollama_num_ctx: Any
|
||||
_parallel_tool_call_guidance: Any
|
||||
_pending_cli_user_message: Any | None
|
||||
_pending_steer_lock: Any
|
||||
_persist_user_message_idx: Any | None
|
||||
_persist_user_message_override: Any | None
|
||||
_persist_user_message_timestamp: Any | None
|
||||
_platform_hint_overrides: Any
|
||||
_print_fn: Any | None
|
||||
_session_db: Any
|
||||
_session_persist_lock: Any
|
||||
_stream_callback: Any | None
|
||||
_stream_context_scrubber: Any
|
||||
_stream_think_scrubber: Any
|
||||
_stream_writer_lock: Any
|
||||
_stream_writer_tls: Any
|
||||
_subdirectory_hints: Any
|
||||
_task_completion_guidance: Any
|
||||
_todo_store: Any
|
||||
_tool_guardrails: Any
|
||||
_tool_use_enforcement: Any
|
||||
_tool_worker_threads_lock: Any
|
||||
_user_id: Any
|
||||
_user_id_alt: Any
|
||||
background_review_callback: Any
|
||||
client: Any | None
|
||||
codex_app_server_auto_compaction: Any
|
||||
compression_enabled: Any
|
||||
compression_in_place: Any
|
||||
context_compressor: Any
|
||||
iteration_budget: Optional[IterationBudget]
|
||||
logs_dir: Any
|
||||
openrouter_min_coding_score: Optional[float]
|
||||
session_start: Any
|
||||
tools: Any
|
||||
valid_tool_names: Any
|
||||
_current_tool: Any
|
||||
_api_call_count: int
|
||||
|
||||
_TOOL_CALL_ARGUMENTS_CORRUPTION_MARKER = (
|
||||
"[hermes-agent: tool call arguments were corrupted in this session and "
|
||||
"have been dropped to keep the conversation alive. See issue #15236.]"
|
||||
@@ -417,71 +611,71 @@ class AIAgent:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
base_url: str = None,
|
||||
api_key: str = None,
|
||||
provider: str = None,
|
||||
api_mode: str = None,
|
||||
acp_command: str = None,
|
||||
base_url: str | None = None,
|
||||
api_key: str | None = None,
|
||||
provider: str | None = None,
|
||||
api_mode: str | None = None,
|
||||
acp_command: str | None = None,
|
||||
acp_args: list[str] | None = None,
|
||||
command: str = None,
|
||||
command: str | None = None,
|
||||
args: list[str] | None = None,
|
||||
model: str = "",
|
||||
max_iterations: int = 90, # Default tool-calling iterations (shared with subagents)
|
||||
tool_delay: float = 1.0,
|
||||
enabled_toolsets: List[str] = None,
|
||||
disabled_toolsets: List[str] = None,
|
||||
enabled_toolsets: List[str] | None = None,
|
||||
disabled_toolsets: List[str] | None = None,
|
||||
save_trajectories: bool = False,
|
||||
verbose_logging: bool = False,
|
||||
quiet_mode: bool = False,
|
||||
tool_progress_mode: str = "all",
|
||||
ephemeral_system_prompt: str = None,
|
||||
ephemeral_system_prompt: str | None = None,
|
||||
log_prefix_chars: int = 100,
|
||||
log_prefix: str = "",
|
||||
providers_allowed: List[str] = None,
|
||||
providers_ignored: List[str] = None,
|
||||
providers_order: List[str] = None,
|
||||
provider_sort: str = None,
|
||||
providers_allowed: List[str] | None = None,
|
||||
providers_ignored: List[str] | None = None,
|
||||
providers_order: List[str] | None = None,
|
||||
provider_sort: str | None = None,
|
||||
provider_require_parameters: bool = False,
|
||||
provider_data_collection: str = None,
|
||||
provider_data_collection: str | None = None,
|
||||
openrouter_min_coding_score: Optional[float] = None,
|
||||
session_id: str = None,
|
||||
tool_progress_callback: callable = None,
|
||||
tool_start_callback: callable = None,
|
||||
tool_complete_callback: callable = None,
|
||||
thinking_callback: callable = None,
|
||||
reasoning_callback: callable = None,
|
||||
clarify_callback: callable = None,
|
||||
read_terminal_callback: callable = None,
|
||||
step_callback: callable = None,
|
||||
stream_delta_callback: callable = None,
|
||||
interim_assistant_callback: callable = None,
|
||||
tool_gen_callback: callable = None,
|
||||
status_callback: callable = None,
|
||||
notice_callback: callable = None,
|
||||
notice_clear_callback: callable = None,
|
||||
session_id: str | None = None,
|
||||
tool_progress_callback: Callable | None = None,
|
||||
tool_start_callback: Callable | None = None,
|
||||
tool_complete_callback: Callable | None = None,
|
||||
thinking_callback: Callable | None = None,
|
||||
reasoning_callback: Callable | None = None,
|
||||
clarify_callback: Callable | None = None,
|
||||
read_terminal_callback: Callable | None = None,
|
||||
step_callback: Callable | None = None,
|
||||
stream_delta_callback: Callable | None = None,
|
||||
interim_assistant_callback: Callable | None = None,
|
||||
tool_gen_callback: Callable | None = None,
|
||||
status_callback: Callable | None = None,
|
||||
notice_callback: Callable | None = None,
|
||||
notice_clear_callback: Callable | None = None,
|
||||
event_callback: Optional[Callable[[str, dict], None]] = None,
|
||||
reaction_callback: Optional[Callable[[str], None]] = None,
|
||||
max_tokens: int = None,
|
||||
reasoning_config: Dict[str, Any] = None,
|
||||
service_tier: str = None,
|
||||
request_overrides: Dict[str, Any] = None,
|
||||
prefill_messages: List[Dict[str, Any]] = None,
|
||||
platform: str = None,
|
||||
user_id: str = None,
|
||||
user_id_alt: str = None,
|
||||
user_name: str = None,
|
||||
chat_id: str = None,
|
||||
chat_name: str = None,
|
||||
chat_type: str = None,
|
||||
thread_id: str = None,
|
||||
gateway_session_key: str = None,
|
||||
max_tokens: int | None = None,
|
||||
reasoning_config: Dict[str, Any] | None = None,
|
||||
service_tier: str | None = None,
|
||||
request_overrides: Dict[str, Any] | None = None,
|
||||
prefill_messages: List[Dict[str, Any]] | None = None,
|
||||
platform: str | None = None,
|
||||
user_id: str | None = None,
|
||||
user_id_alt: str | None = None,
|
||||
user_name: str | None = None,
|
||||
chat_id: str | None = None,
|
||||
chat_name: str | None = None,
|
||||
chat_type: str | None = None,
|
||||
thread_id: str | None = None,
|
||||
gateway_session_key: str | None = None,
|
||||
skip_context_files: bool = False,
|
||||
load_soul_identity: bool = False,
|
||||
skip_memory: bool = False,
|
||||
session_db=None,
|
||||
parent_session_id: str = None,
|
||||
iteration_budget: "IterationBudget" = None,
|
||||
fallback_model: Dict[str, Any] = None,
|
||||
parent_session_id: str | None = None,
|
||||
iteration_budget: Optional["IterationBudget"] = None,
|
||||
fallback_model: Dict[str, Any] | None = None,
|
||||
credential_pool=None,
|
||||
checkpoints_enabled: bool = False,
|
||||
checkpoint_max_snapshots: int = 20,
|
||||
@@ -5932,7 +6126,7 @@ class AIAgent:
|
||||
messages: list,
|
||||
*,
|
||||
logger=None,
|
||||
session_id: str = None,
|
||||
session_id: str | None = None,
|
||||
) -> int:
|
||||
"""Forwarder — see ``agent.agent_runtime_helpers.sanitize_tool_call_arguments``."""
|
||||
from agent.agent_runtime_helpers import sanitize_tool_call_arguments
|
||||
@@ -6171,9 +6365,9 @@ class AIAgent:
|
||||
def run_conversation(
|
||||
self,
|
||||
user_message: Any,
|
||||
system_message: str = None,
|
||||
conversation_history: List[Dict[str, Any]] = None,
|
||||
task_id: str = None,
|
||||
system_message: str | None = None,
|
||||
conversation_history: List[Dict[str, Any]] | None = None,
|
||||
task_id: str | None = None,
|
||||
stream_callback: Optional[callable] = None,
|
||||
persist_user_message: Optional[Any] = None,
|
||||
persist_user_timestamp: Optional[float] = None,
|
||||
@@ -6253,13 +6447,13 @@ class AIAgent:
|
||||
return run_codex_app_server_turn(self, user_message=user_message, original_user_message=original_user_message, messages=messages, effective_task_id=effective_task_id, should_review_memory=should_review_memory)
|
||||
|
||||
def main(
|
||||
query: str = None,
|
||||
query: str | None = None,
|
||||
model: str = "",
|
||||
api_key: str = None,
|
||||
api_key: str | None = None,
|
||||
base_url: str = "",
|
||||
max_turns: int = 10,
|
||||
enabled_toolsets: str = None,
|
||||
disabled_toolsets: str = None,
|
||||
enabled_toolsets: str | None = None,
|
||||
disabled_toolsets: str | None = None,
|
||||
list_tools: bool = False,
|
||||
save_trajectories: bool = False,
|
||||
save_sample: bool = False,
|
||||
|
||||
@@ -2266,7 +2266,7 @@ def _extract_screenshot_path_from_text(text: str) -> Optional[str]:
|
||||
def _run_browser_command(
|
||||
task_id: str,
|
||||
command: str,
|
||||
args: List[str] = None,
|
||||
args: List[str] | None = None,
|
||||
timeout: Optional[int] = None,
|
||||
_engine_override: Optional[str] = None,
|
||||
) -> Dict[str, Any]:
|
||||
|
||||
@@ -869,7 +869,7 @@ def _build_child_progress_callback(
|
||||
return kw
|
||||
|
||||
def _relay(
|
||||
event_type: str, tool_name: str = None, preview: str = None, args=None, **kwargs
|
||||
event_type: str, tool_name: str | None = None, preview: str = None, args=None, **kwargs
|
||||
):
|
||||
if not parent_cb:
|
||||
return
|
||||
|
||||
@@ -834,7 +834,7 @@ class ShellFileOperations(FileOperations):
|
||||
self._command_cache: Dict[str, bool] = {}
|
||||
|
||||
def _exec(self, command: str, cwd: str = None, timeout: int = None,
|
||||
stdin_data: str = None) -> ExecuteResult:
|
||||
stdin_data: str | None = None) -> ExecuteResult:
|
||||
"""Execute command via terminal backend.
|
||||
|
||||
Args:
|
||||
|
||||
+2
-2
@@ -1653,7 +1653,7 @@ def write_file_tool(path: str, content: str, task_id: str = "default",
|
||||
|
||||
|
||||
def patch_tool(mode: str = "replace", path: str = None, old_string: str = None,
|
||||
new_string: str = None, replace_all: bool = False, patch: str = None,
|
||||
new_string: str | None = None, replace_all: bool = False, patch: str = None,
|
||||
task_id: str = "default", cross_profile: bool = False,
|
||||
session_id: str | None = None) -> str:
|
||||
"""Patch a file using replace mode or V4A patch format.
|
||||
@@ -1847,7 +1847,7 @@ def patch_tool(mode: str = "replace", path: str = None, old_string: str = None,
|
||||
|
||||
|
||||
def search_tool(pattern: str, target: str = "content", path: str = ".",
|
||||
file_glob: str = None, limit: int = 50, offset: int = 0,
|
||||
file_glob: str | None = None, limit: int = 50, offset: int = 0,
|
||||
output_mode: str = "content", context: int = 0,
|
||||
task_id: str = "default") -> str:
|
||||
"""Search for content or files."""
|
||||
|
||||
@@ -957,10 +957,10 @@ def _missing_old_text_error(store: "MemoryStore", target: str, action: str) -> s
|
||||
|
||||
|
||||
def memory_tool(
|
||||
action: str = None,
|
||||
action: str | None = None,
|
||||
target: str = "memory",
|
||||
content: str = None,
|
||||
old_text: str = None,
|
||||
content: str | None = None,
|
||||
old_text: str | None = None,
|
||||
operations: Optional[List[Dict[str, Any]]] = None,
|
||||
store: Optional[MemoryStore] = None,
|
||||
) -> str:
|
||||
|
||||
@@ -689,10 +689,10 @@ class ProcessRegistry:
|
||||
def spawn_local(
|
||||
self,
|
||||
command: str,
|
||||
cwd: str = None,
|
||||
cwd: str | None = None,
|
||||
task_id: str = "",
|
||||
session_key: str = "",
|
||||
env_vars: dict = None,
|
||||
env_vars: dict | None = None,
|
||||
use_pty: bool = False,
|
||||
) -> ProcessSession:
|
||||
"""
|
||||
@@ -829,7 +829,7 @@ class ProcessRegistry:
|
||||
self,
|
||||
env: Any,
|
||||
command: str,
|
||||
cwd: str = None,
|
||||
cwd: str | None = None,
|
||||
task_id: str = "",
|
||||
session_key: str = "",
|
||||
timeout: int = 10,
|
||||
|
||||
+3
-3
@@ -368,13 +368,13 @@ class ToolRegistry:
|
||||
toolset: str,
|
||||
schema: dict,
|
||||
handler: Callable,
|
||||
check_fn: Callable = None,
|
||||
requires_env: list = None,
|
||||
check_fn: Callable | None = None,
|
||||
requires_env: list | None = None,
|
||||
is_async: bool = False,
|
||||
description: str = "",
|
||||
emoji: str = "",
|
||||
max_result_size_chars: int | float | None = None,
|
||||
dynamic_schema_overrides: Callable = None,
|
||||
dynamic_schema_overrides: Callable | None = None,
|
||||
override: bool = False,
|
||||
):
|
||||
"""Register a tool. Called at module-import time by each tool file.
|
||||
|
||||
@@ -305,7 +305,7 @@ def _scroll(
|
||||
session_id: str,
|
||||
around_message_id: int,
|
||||
window: int = 5,
|
||||
current_session_id: str = None,
|
||||
current_session_id: str | None = None,
|
||||
) -> str:
|
||||
"""Scroll shape: return a window of messages centered on an anchor.
|
||||
|
||||
@@ -502,7 +502,7 @@ def _discover(
|
||||
role_filter: Optional[List[str]],
|
||||
limit: int,
|
||||
sort: Optional[str],
|
||||
current_session_id: str = None,
|
||||
current_session_id: str | None = None,
|
||||
) -> str:
|
||||
"""Discovery shape: FTS5 + anchored window + bookends per hit. Single call."""
|
||||
role_list = role_filter if role_filter else ["user", "assistant"]
|
||||
@@ -618,18 +618,18 @@ def _discover(
|
||||
|
||||
def session_search(
|
||||
query: str = "",
|
||||
role_filter: str = None,
|
||||
role_filter: str | None = None,
|
||||
limit: int = 3,
|
||||
db=None,
|
||||
current_session_id: str = None,
|
||||
current_session_id: str | None = None,
|
||||
# Scroll shape
|
||||
session_id: str = None,
|
||||
around_message_id: int = None,
|
||||
session_id: str | None = None,
|
||||
around_message_id: int | None = None,
|
||||
window: int = 5,
|
||||
# Discovery shape
|
||||
sort: str = None,
|
||||
sort: str | None = None,
|
||||
# Cross-profile (any shape)
|
||||
profile: str = None,
|
||||
profile: str | None = None,
|
||||
) -> str:
|
||||
"""Single-shape tool. Mode inferred from which args are set.
|
||||
|
||||
|
||||
@@ -918,7 +918,7 @@ def _patch_skill(
|
||||
name: str,
|
||||
old_string: str,
|
||||
new_string: str,
|
||||
file_path: str = None,
|
||||
file_path: str | None = None,
|
||||
replace_all: bool = False,
|
||||
) -> Dict[str, Any]:
|
||||
"""Targeted find-and-replace within a skill file.
|
||||
@@ -1323,14 +1323,14 @@ def apply_skill_pending(payload: Dict[str, Any]) -> str:
|
||||
def skill_manage(
|
||||
action: str,
|
||||
name: str,
|
||||
content: str = None,
|
||||
category: str = None,
|
||||
file_path: str = None,
|
||||
file_content: str = None,
|
||||
old_string: str = None,
|
||||
new_string: str = None,
|
||||
content: str | None = None,
|
||||
category: str | None = None,
|
||||
file_path: str | None = None,
|
||||
file_content: str | None = None,
|
||||
old_string: str | None = None,
|
||||
new_string: str | None = None,
|
||||
replace_all: bool = False,
|
||||
absorbed_into: str = None,
|
||||
absorbed_into: str | None = None,
|
||||
) -> str:
|
||||
"""
|
||||
Manage user-created skills. Dispatches to the appropriate action handler.
|
||||
|
||||
@@ -960,8 +960,8 @@ def _serve_plugin_skill(
|
||||
|
||||
def skill_view(
|
||||
name: str,
|
||||
file_path: str = None,
|
||||
task_id: str = None,
|
||||
file_path: str | None = None,
|
||||
task_id: str | None = None,
|
||||
preprocess: bool = True,
|
||||
) -> str:
|
||||
"""
|
||||
|
||||
@@ -1482,10 +1482,10 @@ def _get_modal_backend_state(modal_mode: object | None) -> Dict[str, Any]:
|
||||
|
||||
|
||||
def _create_environment(env_type: str, image: str, cwd: str, timeout: int,
|
||||
ssh_config: dict = None, container_config: dict = None,
|
||||
local_config: dict = None,
|
||||
ssh_config: dict | None = None, container_config: dict = None,
|
||||
local_config: dict | None = None,
|
||||
task_id: str = "default",
|
||||
host_cwd: str = None):
|
||||
host_cwd: str | None = None):
|
||||
"""
|
||||
Create an execution environment for sandboxed command execution.
|
||||
|
||||
|
||||
@@ -1355,11 +1355,11 @@ Write only the summary, starting with "[CONTEXT SUMMARY]:" prefix."""
|
||||
|
||||
def main(
|
||||
input: str,
|
||||
output: str = None,
|
||||
output: str | None = None,
|
||||
config: str = "configs/trajectory_compression.yaml",
|
||||
target_max_tokens: int = None,
|
||||
tokenizer: str = None,
|
||||
sample_percent: float = None,
|
||||
target_max_tokens: int | None = None,
|
||||
tokenizer: str | None = None,
|
||||
sample_percent: float | None = None,
|
||||
seed: int = 42,
|
||||
dry_run: bool = False,
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user