hyperforge-static 1.0.0.post20__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.
@@ -0,0 +1,19 @@
1
+ Metadata-Version: 2.4
2
+ Name: hyperforge_static
3
+ Version: 1.0.0.post20
4
+ Summary: Static Context Hyperforge agent
5
+ Author-email: Nuclia <nucliadb@nuclia.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://progress.com
8
+ Project-URL: Repository, https://github.com/nuclia/forge
9
+ Classifier: Programming Language :: Python
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Requires-Python: <4,>=3.10
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: hyperforge
18
+
19
+ # Advanced Generation Hyperforge agents
@@ -0,0 +1 @@
1
+ # Advanced Generation Hyperforge agents
@@ -0,0 +1,38 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "hyperforge_static"
7
+ version = "1.0.0.post20"
8
+ license = "Apache-2.0"
9
+ description = "Static Context Hyperforge agent"
10
+ authors = [{ name = "Nuclia", email = "nucliadb@nuclia.com" }]
11
+ readme = "README.md"
12
+ classifiers = [
13
+ "Programming Language :: Python",
14
+ "Programming Language :: Python :: 3.10",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3 :: Only",
18
+ "Topic :: Software Development :: Libraries :: Python Modules",
19
+ ]
20
+ requires-python = ">=3.10, <4"
21
+ dependencies = ["hyperforge"]
22
+
23
+ [dependency-groups]
24
+ # these dependencies are actually in the src/ folder (under
25
+ # src/nucliadb_utils/tests/), but only used when the module is imported
26
+ dev = [
27
+ "pytest",
28
+ "pytest-benchmark",
29
+ "pytest-docker-fixtures>=1.4.2",
30
+ "pytest-lazy-fixtures",
31
+ ]
32
+
33
+ [project.urls]
34
+ Homepage = "https://progress.com"
35
+ Repository = "https://github.com/nuclia/forge"
36
+
37
+ [tool.pytest.ini_options]
38
+ asyncio_mode = "auto"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ from .agent import StaticAgent
2
+
3
+ __all__ = ["StaticAgent"]
@@ -0,0 +1,96 @@
1
+ from time import time
2
+ from typing import Any, ClassVar, Dict, List, Optional, Tuple
3
+ from uuid import uuid4
4
+
5
+ from hyperforge.agent import Agent
6
+ from hyperforge.configure import agent
7
+ from hyperforge.context.agent import ContextAgent
8
+ from hyperforge.definition import FunctionDefinition
9
+ from hyperforge.manager import Manager
10
+ from hyperforge.memory.memory import Chunk, Context, QuestionMemory
11
+
12
+ from hyperforge_static.config import StaticAgentConfig
13
+
14
+
15
+ @agent(
16
+ id="static",
17
+ agent_type="context",
18
+ title="Static Context",
19
+ description="Provide static context to answer questions.",
20
+ config_schema=StaticAgentConfig,
21
+ )
22
+ class StaticAgent(ContextAgent, Agent[StaticAgentConfig]):
23
+ __published_functions__: ClassVar[Dict[str, FunctionDefinition]] = {
24
+ "static_context": FunctionDefinition(
25
+ name="static_context",
26
+ description="Provide static context to answer questions.",
27
+ parameters={},
28
+ )
29
+ }
30
+
31
+ async def static_context(
32
+ self,
33
+ memory: QuestionMemory,
34
+ manager: Manager,
35
+ question: Optional[str] = "",
36
+ question_uuid: Optional[str] = None,
37
+ ) -> Context:
38
+ if question_uuid is None:
39
+ question_uuid = uuid4().hex
40
+
41
+ context = Context(
42
+ agent_id=self.config.id if self.config.id else "static_context",
43
+ original_question_uuid=memory.original_question_uuid,
44
+ actual_question_uuid=question_uuid,
45
+ question=question,
46
+ source="static_context",
47
+ agent="static_context",
48
+ title=self.config.title if self.config.title else "Static Context",
49
+ )
50
+ if self.config.context:
51
+ context.chunks.append(
52
+ Chunk(
53
+ chunk_id=uuid4().hex,
54
+ text=self.config.context,
55
+ origin_agent=self.config.module,
56
+ )
57
+ )
58
+ if self.config.structured:
59
+ context.structured.append(self.config.structured)
60
+ return context
61
+
62
+ async def _get_question_context(
63
+ self,
64
+ memory: QuestionMemory,
65
+ manager: Manager,
66
+ question_uuid: str,
67
+ question: str,
68
+ flow_id: str,
69
+ extra_context: Optional[Dict[str, Any]] = None,
70
+ ) -> List[Tuple[str, str]]:
71
+ t0 = time()
72
+ error = None
73
+
74
+ context = await self.static_context(
75
+ memory=memory,
76
+ manager=manager,
77
+ )
78
+
79
+ await memory.add_step(
80
+ step_module=self.config.module,
81
+ step_title=self.step_title("Static context"),
82
+ step_agent_path=f"/context/{self.config.id if self.config.id else 'default'}",
83
+ step_value=" Static context retrieval",
84
+ timeit=time() - t0,
85
+ input_nuclia_tokens=0,
86
+ output_nuclia_tokens=0,
87
+ error=error,
88
+ )
89
+ missing = await self.save_ctx_and_return_missing(
90
+ context=context,
91
+ question=question,
92
+ memory=memory,
93
+ manager=manager,
94
+ flow_id=flow_id,
95
+ )
96
+ return [missing] if missing is not None else []
@@ -0,0 +1,33 @@
1
+ from typing import Literal, Optional, Tuple
2
+
3
+ from hyperforge.context.config import ContextAgentConfig
4
+ from hyperforge.utils import WidgetType
5
+ from pydantic import Field
6
+ from pydantic.config import ConfigDict
7
+
8
+
9
+ class StaticAgentConfig(ContextAgentConfig):
10
+ model_config = ConfigDict(title="Static data")
11
+ module: Literal["static"] = "static"
12
+ published_functions: Optional[Tuple[str, ...]] = Field(
13
+ default=("static_context",),
14
+ title="Published functions",
15
+ description="List of functions published by this agent to be used by other agents in the chain",
16
+ json_schema_extra={
17
+ "widget": WidgetType.NOT_SHOWN,
18
+ },
19
+ )
20
+ context: Optional[str] = Field(
21
+ None,
22
+ description="Static context to be used by the agent",
23
+ json_schema_extra={
24
+ "widget": WidgetType.EXPANDABLE_TEXTAREA,
25
+ },
26
+ )
27
+ structured: Optional[str] = Field(
28
+ None,
29
+ description="Structured data in JSON format to be used by the agent",
30
+ json_schema_extra={
31
+ "widget": WidgetType.EXPANDABLE_TEXTAREA,
32
+ },
33
+ )
@@ -0,0 +1,19 @@
1
+ Metadata-Version: 2.4
2
+ Name: hyperforge_static
3
+ Version: 1.0.0.post20
4
+ Summary: Static Context Hyperforge agent
5
+ Author-email: Nuclia <nucliadb@nuclia.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://progress.com
8
+ Project-URL: Repository, https://github.com/nuclia/forge
9
+ Classifier: Programming Language :: Python
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Requires-Python: <4,>=3.10
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: hyperforge
18
+
19
+ # Advanced Generation Hyperforge agents
@@ -0,0 +1,11 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/hyperforge_static/__init__.py
4
+ src/hyperforge_static/agent.py
5
+ src/hyperforge_static/config.py
6
+ src/hyperforge_static.egg-info/PKG-INFO
7
+ src/hyperforge_static.egg-info/SOURCES.txt
8
+ src/hyperforge_static.egg-info/dependency_links.txt
9
+ src/hyperforge_static.egg-info/requires.txt
10
+ src/hyperforge_static.egg-info/top_level.txt
11
+ tests/test_static.py
@@ -0,0 +1,79 @@
1
+ from unittest.mock import MagicMock
2
+ from uuid import uuid4
3
+
4
+ import pytest
5
+ from hyperforge.manager import Manager
6
+ from hyperforge.memory.memory import EphemeralSessionMemory
7
+ from hyperforge.models import MemoryConfig, Rules
8
+ from hyperforge_static.agent import StaticAgent
9
+ from hyperforge_static.config import StaticAgentConfig
10
+
11
+ pytestmark = pytest.mark.asyncio
12
+
13
+
14
+ async def test_static_agent():
15
+ # 1. Create a mocked manager
16
+ manager = MagicMock(spec=Manager)
17
+
18
+ # 2. Create the configuration for StaticAgent
19
+ config = StaticAgentConfig(
20
+ id="test-static",
21
+ title="Static Context",
22
+ context="This is a test static context text.",
23
+ structured="{'key': 'value'}",
24
+ prune_context=False,
25
+ )
26
+
27
+ # 3. Create the StaticAgent instance
28
+ agent = StaticAgent(config=config)
29
+
30
+ # 4. Set up EphemeralSessionMemory and QuestionMemory
31
+ session = EphemeralSessionMemory.from_config(
32
+ config=MemoryConfig(), agent_id="test", workflow_id="test", rules=Rules()
33
+ )
34
+ session.init("test-session")
35
+ memory = session.start_question("What is the static context?")
36
+ flow_id = uuid4().hex
37
+
38
+ # 5. Call static_context directly
39
+ context = await agent.static_context(
40
+ memory=memory,
41
+ manager=manager,
42
+ question="What is the static context?",
43
+ )
44
+
45
+ # 6. Assert static_context returns Context with correct values
46
+ assert context is not None
47
+ assert context.agent_id == "test-static"
48
+ assert context.title == "Static Context"
49
+ assert len(context.chunks) == 1
50
+ assert context.chunks[0].text == "This is a test static context text."
51
+ assert len(context.structured) == 1
52
+ assert context.structured[0] == "{'key': 'value'}"
53
+
54
+ # 7. Call _get_question_context
55
+ missing = await agent._get_question_context(
56
+ memory=memory,
57
+ manager=manager,
58
+ question_uuid=memory.original_question_uuid,
59
+ question="What is the static context?",
60
+ flow_id=flow_id,
61
+ )
62
+
63
+ # 8. Assertions on the memory state and missing questions
64
+ assert (
65
+ missing == []
66
+ ) # Since no validation/fallback model is used, should return empty list
67
+
68
+ # Check that context is saved to memory under the given flow_id
69
+ saved_contexts = memory.get_agent_contexts(flow_id=flow_id, agent_id="test-static")
70
+ assert len(saved_contexts) == 1
71
+ assert saved_contexts[0].chunks[0].text == "This is a test static context text."
72
+ assert saved_contexts[0].structured[0] == "{'key': 'value'}"
73
+
74
+ # Verify step was added to memory
75
+ assert len(memory.steps) == 1
76
+ step = memory.steps[0]
77
+ assert step.module == "static"
78
+ assert "Static context" in step.title
79
+ assert step.value == " Static context retrieval"