Fix run cancellation and live activity stability
This commit is contained in:
+23
-4
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from typing import Any, Iterator
|
||||
from urllib import error, request
|
||||
|
||||
@@ -31,6 +32,7 @@ ANTHROPIC_MESSAGES_MODEL_PREFIXES = (
|
||||
|
||||
ANTHROPIC_VERSION = '2023-06-01'
|
||||
ANTHROPIC_MAX_TOKENS = 4096
|
||||
DEFAULT_MODEL_IDLE_TIMEOUT_SECONDS = 60.0
|
||||
|
||||
|
||||
def _join_url(base_url: str, suffix: str) -> str:
|
||||
@@ -274,6 +276,23 @@ class OpenAICompatClient:
|
||||
def __init__(self, config: ModelConfig) -> None:
|
||||
self.config = config
|
||||
|
||||
def _request_timeout_seconds(self) -> float:
|
||||
"""Return per-socket model timeout.
|
||||
|
||||
`ModelConfig.timeout_seconds` is the whole request budget used by the
|
||||
product, but urllib applies it as an idle socket timeout. Keeping it at
|
||||
one hour makes a bad upstream stream hold a session lock for an hour.
|
||||
Use a shorter idle timeout by default; any normally streaming response
|
||||
keeps extending this naturally because bytes continue to arrive.
|
||||
"""
|
||||
raw = os.environ.get('CLAW_MODEL_IDLE_TIMEOUT_SECONDS', '').strip()
|
||||
try:
|
||||
configured = float(raw) if raw else DEFAULT_MODEL_IDLE_TIMEOUT_SECONDS
|
||||
except ValueError:
|
||||
configured = DEFAULT_MODEL_IDLE_TIMEOUT_SECONDS
|
||||
configured = max(5.0, configured)
|
||||
return min(float(self.config.timeout_seconds), configured)
|
||||
|
||||
def complete(
|
||||
self,
|
||||
messages: list[dict[str, Any]],
|
||||
@@ -351,7 +370,7 @@ class OpenAICompatClient:
|
||||
method='POST',
|
||||
)
|
||||
try:
|
||||
with request.urlopen(req, timeout=self.config.timeout_seconds) as response:
|
||||
with request.urlopen(req, timeout=self._request_timeout_seconds()) as response:
|
||||
yield StreamEvent(type='message_start')
|
||||
for event_payload in self._iter_sse_payloads(response):
|
||||
yield from self._parse_stream_payload(event_payload)
|
||||
@@ -380,7 +399,7 @@ class OpenAICompatClient:
|
||||
method='POST',
|
||||
)
|
||||
try:
|
||||
with request.urlopen(req, timeout=self.config.timeout_seconds) as response:
|
||||
with request.urlopen(req, timeout=self._request_timeout_seconds()) as response:
|
||||
raw = response.read()
|
||||
except error.HTTPError as exc:
|
||||
detail = exc.read().decode('utf-8', errors='replace')
|
||||
@@ -521,7 +540,7 @@ class OpenAICompatClient:
|
||||
method='POST',
|
||||
)
|
||||
try:
|
||||
with request.urlopen(req, timeout=self.config.timeout_seconds) as response:
|
||||
with request.urlopen(req, timeout=self._request_timeout_seconds()) as response:
|
||||
raw = response.read()
|
||||
except error.HTTPError as exc:
|
||||
detail = exc.read().decode('utf-8', errors='replace')
|
||||
@@ -561,7 +580,7 @@ class OpenAICompatClient:
|
||||
method='POST',
|
||||
)
|
||||
try:
|
||||
with request.urlopen(req, timeout=self.config.timeout_seconds) as response:
|
||||
with request.urlopen(req, timeout=self._request_timeout_seconds()) as response:
|
||||
yield StreamEvent(type='message_start')
|
||||
tool_block_indexes: dict[int, int] = {}
|
||||
next_tool_index = 0
|
||||
|
||||
Reference in New Issue
Block a user