hyperforge-http 1.0.0.post47__tar.gz → 1.0.0.post58__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperforge_http
3
- Version: 1.0.0.post47
3
+ Version: 1.0.0.post58
4
4
  Summary: HTTP Hyperforge agent
5
5
  Author-email: Nuclia <nucliadb@nuclia.com>
6
6
  License-Expression: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "hyperforge_http"
7
- version = "1.0.0.post47"
7
+ version = "1.0.0.post58"
8
8
  license = "Apache-2.0"
9
9
  description = "HTTP Hyperforge agent"
10
10
  authors = [{ name = "Nuclia", email = "nucliadb@nuclia.com" }]
@@ -7,8 +7,7 @@ from hyperforge.configure import agent
7
7
  from hyperforge.context.agent import ContextAgent
8
8
  from hyperforge.manager import Manager
9
9
  from hyperforge.memory import Chunk, Context, QuestionMemory
10
- from hyperforge.utils import check_dns
11
- from hyperforge.utils.http import safe_http_client
10
+ from hyperforge.utils.http import read_limited_response, safe_http_client
12
11
 
13
12
  from hyperforge_http.config import HTTPStaticAgentConfig
14
13
 
@@ -33,24 +32,22 @@ class HTTPStaticAgent(ContextAgent, Agent[HTTPStaticAgentConfig]):
33
32
  t0 = time()
34
33
  error = None
35
34
 
36
- url = await check_dns(self.config.url)
37
-
38
35
  async with safe_http_client() as client:
39
36
  if self.config.method == "GET":
40
- response = await client.get(
41
- url,
37
+ request = client.build_request(
38
+ "GET",
39
+ self.config.url,
42
40
  headers=self.config.headers,
43
- timeout=self.config.timeout,
44
41
  params={self.config.question_query_param: question}
45
42
  if self.config.question_query_param
46
43
  else None,
47
44
  )
48
45
 
49
46
  elif self.config.method == "POST":
50
- response = await client.post(
51
- url,
47
+ request = client.build_request(
48
+ "POST",
49
+ self.config.url,
52
50
  headers=self.config.headers,
53
- timeout=self.config.timeout,
54
51
  params={self.config.question_query_param: question}
55
52
  if self.config.question_query_param
56
53
  else None,
@@ -61,11 +58,19 @@ class HTTPStaticAgent(ContextAgent, Agent[HTTPStaticAgentConfig]):
61
58
  else:
62
59
  raise ValueError(f"Unsupported HTTP method: {self.config.method}")
63
60
 
61
+ response = await client.send(request, stream=True)
62
+ try:
63
+ response_content = await read_limited_response(
64
+ response, self.config.max_response_bytes
65
+ )
66
+ finally:
67
+ await response.aclose()
68
+
64
69
  if response.status_code != 200:
65
70
  error = f"HTTP request failed with status code {response.status_code}"
66
71
  context_text = ""
67
72
  else:
68
- context_text = response.content.decode("utf-8")
73
+ context_text = response_content.decode("utf-8", errors="replace")
69
74
 
70
75
  context = Context(
71
76
  agent_id=self.config.id if self.config.id else "http",
@@ -88,7 +93,7 @@ class HTTPStaticAgent(ContextAgent, Agent[HTTPStaticAgentConfig]):
88
93
  step_module=self.config.module,
89
94
  step_title=self.step_title("HTTP request"),
90
95
  step_agent_path=f"/context/{self.config.id if self.config.id else 'default'}",
91
- step_value=f" HTTP {self.config.method} to {url}",
96
+ step_value=f" HTTP {self.config.method} to {self.config.url}",
92
97
  timeit=time() - t0,
93
98
  input_nuclia_tokens=0,
94
99
  output_nuclia_tokens=0,
@@ -28,7 +28,13 @@ class HTTPStaticAgentConfig(ContextAgentConfig):
28
28
  description="Optional POST field id to include the question in the request body",
29
29
  )
30
30
  timeout: int = Field(
31
- default=10, description="Timeout for the HTTP request in seconds"
31
+ default=10, ge=1, le=300, description="Timeout for the HTTP request in seconds"
32
+ )
33
+ max_response_bytes: int = Field(
34
+ default=1024 * 1024,
35
+ ge=1,
36
+ le=10 * 1024 * 1024,
37
+ description="Maximum accepted HTTP response size in bytes",
32
38
  )
33
39
 
34
40
  @field_validator("url")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperforge_http
3
- Version: 1.0.0.post47
3
+ Version: 1.0.0.post58
4
4
  Summary: HTTP Hyperforge agent
5
5
  Author-email: Nuclia <nucliadb@nuclia.com>
6
6
  License-Expression: Apache-2.0
@@ -1,6 +1,7 @@
1
1
  import os
2
- from unittest.mock import AsyncMock, MagicMock
2
+ from unittest.mock import AsyncMock
3
3
 
4
+ import httpx
4
5
  import pytest
5
6
  from hyperforge.engine import main as arag_main
6
7
  from hyperforge.interaction import AragAnswer
@@ -46,12 +47,16 @@ CONFIG = {
46
47
  async def test_http_static_get(mocker):
47
48
  answers = []
48
49
 
49
- mock_response = MagicMock()
50
- mock_response.status_code = 200
51
- mock_response.content = b"Experts from the University of Nuclia have found that waking up relaxed can be achieved by following a consistent sleep schedule, creating a calming bedtime routine, and ensuring a comfortable sleep environment. Also, if your alarm is a an BetterStack call, it will help you clear your mind"
50
+ request = httpx.Request("GET", "https://example.com/context")
51
+ mock_response = httpx.Response(
52
+ 200,
53
+ content=b"Experts from the University of Nuclia have found that waking up relaxed can be achieved by following a consistent sleep schedule, creating a calming bedtime routine, and ensuring a comfortable sleep environment. Also, if your alarm is a an BetterStack call, it will help you clear your mind",
54
+ request=request,
55
+ )
52
56
 
53
57
  mock_client = AsyncMock()
54
- mock_client.get = AsyncMock(return_value=mock_response)
58
+ mock_client.build_request.return_value = request
59
+ mock_client.send = AsyncMock(return_value=mock_response)
55
60
  mock_client.__aenter__ = AsyncMock(return_value=mock_client)
56
61
  mock_client.__aexit__ = AsyncMock(return_value=None)
57
62