hyperforge-static-string 1.0.0.post22__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.
- hyperforge_static_string-1.0.0.post22/PKG-INFO +11 -0
- hyperforge_static_string-1.0.0.post22/pyproject.toml +33 -0
- hyperforge_static_string-1.0.0.post22/setup.cfg +4 -0
- hyperforge_static_string-1.0.0.post22/src/hyperforge_static_string/__init__.py +3 -0
- hyperforge_static_string-1.0.0.post22/src/hyperforge_static_string/agent.py +78 -0
- hyperforge_static_string-1.0.0.post22/src/hyperforge_static_string/py.typed +0 -0
- hyperforge_static_string-1.0.0.post22/src/hyperforge_static_string.egg-info/PKG-INFO +11 -0
- hyperforge_static_string-1.0.0.post22/src/hyperforge_static_string.egg-info/SOURCES.txt +10 -0
- hyperforge_static_string-1.0.0.post22/src/hyperforge_static_string.egg-info/dependency_links.txt +1 -0
- hyperforge_static_string-1.0.0.post22/src/hyperforge_static_string.egg-info/requires.txt +1 -0
- hyperforge_static_string-1.0.0.post22/src/hyperforge_static_string.egg-info/top_level.txt +1 -0
- hyperforge_static_string-1.0.0.post22/tests/test_static_string.py +115 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hyperforge_static_string
|
|
3
|
+
Version: 1.0.0.post22
|
|
4
|
+
Summary: A Hyperforge agent that always returns a fixed string
|
|
5
|
+
License: MIT License
|
|
6
|
+
Project-URL: Homepage, https://progress.com
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Requires-Dist: hyperforge
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
dependencies = ["hyperforge"]
|
|
3
|
+
|
|
4
|
+
name = "hyperforge_static_string"
|
|
5
|
+
version = "1.0.0.post22"
|
|
6
|
+
authors = []
|
|
7
|
+
description = "A Hyperforge agent that always returns a fixed string"
|
|
8
|
+
requires-python = ">=3.10"
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Programming Language :: Python :: 3",
|
|
11
|
+
"License :: OSI Approved :: MIT License",
|
|
12
|
+
"Operating System :: OS Independent",
|
|
13
|
+
]
|
|
14
|
+
license = { text = "MIT License" }
|
|
15
|
+
|
|
16
|
+
[tool.uv]
|
|
17
|
+
required-version = ">=0.10"
|
|
18
|
+
managed = true
|
|
19
|
+
default-groups = "all"
|
|
20
|
+
keyring-provider = "subprocess"
|
|
21
|
+
package = true
|
|
22
|
+
|
|
23
|
+
[project.urls]
|
|
24
|
+
Homepage = "https://progress.com"
|
|
25
|
+
|
|
26
|
+
[tool.pytest.ini_options]
|
|
27
|
+
asyncio_mode = "auto"
|
|
28
|
+
|
|
29
|
+
[dependency-groups]
|
|
30
|
+
dev = [
|
|
31
|
+
"pytest",
|
|
32
|
+
"pytest-asyncio",
|
|
33
|
+
]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from time import time
|
|
2
|
+
from typing import Any, ClassVar, Dict, Optional
|
|
3
|
+
|
|
4
|
+
from hyperforge.agent import Agent
|
|
5
|
+
from hyperforge.configure import agent
|
|
6
|
+
from hyperforge.context.agent import ContextAgent
|
|
7
|
+
from hyperforge.context.config import ContextAgentConfig
|
|
8
|
+
from hyperforge.definition import FunctionDefinition
|
|
9
|
+
from hyperforge.manager import Manager
|
|
10
|
+
from hyperforge.memory import Chunk, Context, QuestionMemory
|
|
11
|
+
from pydantic import Field
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class StaticStringAgentConfig(ContextAgentConfig):
|
|
15
|
+
context: str = Field(description="Data to add to the context")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@agent(
|
|
19
|
+
id="static_string",
|
|
20
|
+
agent_type="context",
|
|
21
|
+
title="Static String",
|
|
22
|
+
description="Use a static string to provide context for answering questions.",
|
|
23
|
+
config_schema=StaticStringAgentConfig,
|
|
24
|
+
)
|
|
25
|
+
class StaticStringAgent(ContextAgent, Agent[StaticStringAgentConfig]):
|
|
26
|
+
__published_functions__: ClassVar[Dict[str, FunctionDefinition]] = {
|
|
27
|
+
"static_string": FunctionDefinition(
|
|
28
|
+
name="static_string",
|
|
29
|
+
description="Returns a static string to provide context for answering questions.",
|
|
30
|
+
parameters={},
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
def static_string(self) -> str:
|
|
35
|
+
return self.config.context
|
|
36
|
+
|
|
37
|
+
async def _get_question_context(
|
|
38
|
+
self,
|
|
39
|
+
memory: QuestionMemory,
|
|
40
|
+
manager: Manager,
|
|
41
|
+
question_uuid: str,
|
|
42
|
+
question: str,
|
|
43
|
+
flow_id: str,
|
|
44
|
+
extra_context: Optional[Dict[str, Any]] = None,
|
|
45
|
+
) -> list[tuple[str, str]]:
|
|
46
|
+
error = None
|
|
47
|
+
t0 = time()
|
|
48
|
+
missing = await self.save_ctx_and_return_missing(
|
|
49
|
+
memory=memory,
|
|
50
|
+
context=Context(
|
|
51
|
+
original_question_uuid=memory.original_question_uuid,
|
|
52
|
+
actual_question_uuid=question_uuid,
|
|
53
|
+
question=question,
|
|
54
|
+
chunks=[
|
|
55
|
+
Chunk(
|
|
56
|
+
chunk_id="static_string",
|
|
57
|
+
text=self.static_string(),
|
|
58
|
+
origin_agent=self.config.module,
|
|
59
|
+
)
|
|
60
|
+
],
|
|
61
|
+
source=f"/context/{self.agent_id}",
|
|
62
|
+
agent=self.config.module,
|
|
63
|
+
),
|
|
64
|
+
question=question,
|
|
65
|
+
manager=manager,
|
|
66
|
+
flow_id=flow_id,
|
|
67
|
+
)
|
|
68
|
+
await memory.add_step(
|
|
69
|
+
step_module=self.config.module,
|
|
70
|
+
step_title=self.step_title("Search results"),
|
|
71
|
+
step_agent_path=f"/context/{self.agent_id}",
|
|
72
|
+
step_value="String done",
|
|
73
|
+
timeit=time() - t0,
|
|
74
|
+
input_nuclia_tokens=0.5,
|
|
75
|
+
output_nuclia_tokens=0.5,
|
|
76
|
+
error=error,
|
|
77
|
+
)
|
|
78
|
+
return [missing] if missing is not None else []
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hyperforge_static_string
|
|
3
|
+
Version: 1.0.0.post22
|
|
4
|
+
Summary: A Hyperforge agent that always returns a fixed string
|
|
5
|
+
License: MIT License
|
|
6
|
+
Project-URL: Homepage, https://progress.com
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Requires-Dist: hyperforge
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
pyproject.toml
|
|
2
|
+
src/hyperforge_static_string/__init__.py
|
|
3
|
+
src/hyperforge_static_string/agent.py
|
|
4
|
+
src/hyperforge_static_string/py.typed
|
|
5
|
+
src/hyperforge_static_string.egg-info/PKG-INFO
|
|
6
|
+
src/hyperforge_static_string.egg-info/SOURCES.txt
|
|
7
|
+
src/hyperforge_static_string.egg-info/dependency_links.txt
|
|
8
|
+
src/hyperforge_static_string.egg-info/requires.txt
|
|
9
|
+
src/hyperforge_static_string.egg-info/top_level.txt
|
|
10
|
+
tests/test_static_string.py
|
hyperforge_static_string-1.0.0.post22/src/hyperforge_static_string.egg-info/dependency_links.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hyperforge
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
hyperforge_static_string
|
|
@@ -0,0 +1,115 @@
|
|
|
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_string.agent import StaticStringAgent, StaticStringAgentConfig
|
|
9
|
+
|
|
10
|
+
pytestmark = pytest.mark.asyncio
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def make_config(**kwargs) -> StaticStringAgentConfig:
|
|
14
|
+
"""Helper to create a StaticStringAgentConfig with sensible test defaults."""
|
|
15
|
+
defaults = dict(
|
|
16
|
+
id="test-static-string",
|
|
17
|
+
title="Static String",
|
|
18
|
+
module="static_string",
|
|
19
|
+
prune_context=False, # Disable validation so no LLM calls are needed
|
|
20
|
+
)
|
|
21
|
+
defaults.update(kwargs)
|
|
22
|
+
return StaticStringAgentConfig(**defaults)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def make_session() -> EphemeralSessionMemory:
|
|
26
|
+
session = EphemeralSessionMemory.from_config(
|
|
27
|
+
config=MemoryConfig(), agent_id="test", workflow_id="test", rules=Rules()
|
|
28
|
+
)
|
|
29
|
+
session.init("test-session")
|
|
30
|
+
return session
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def test_static_string_returns_context_string():
|
|
34
|
+
"""static_string() returns exactly the configured context string."""
|
|
35
|
+
config = make_config(context="Hello, world!")
|
|
36
|
+
agent = StaticStringAgent(config=config)
|
|
37
|
+
assert agent.static_string() == "Hello, world!"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
async def test_get_question_context_saves_context_to_memory():
|
|
41
|
+
"""_get_question_context saves a Context with the correct chunk to memory."""
|
|
42
|
+
manager = MagicMock(spec=Manager)
|
|
43
|
+
config = make_config(context="Some static context text.")
|
|
44
|
+
agent = StaticStringAgent(config=config)
|
|
45
|
+
|
|
46
|
+
memory = make_session().start_question("What is the answer?")
|
|
47
|
+
flow_id = uuid4().hex
|
|
48
|
+
|
|
49
|
+
missing = await agent._get_question_context(
|
|
50
|
+
memory=memory,
|
|
51
|
+
manager=manager,
|
|
52
|
+
question_uuid=memory.original_question_uuid,
|
|
53
|
+
question="What is the answer?",
|
|
54
|
+
flow_id=flow_id,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# No missing context — everything was provided
|
|
58
|
+
assert missing == []
|
|
59
|
+
|
|
60
|
+
# Context was saved with the correct chunk.
|
|
61
|
+
# Note: StaticStringAgent does not set agent_id on the Context object,
|
|
62
|
+
# so contexts are stored under the empty-string key.
|
|
63
|
+
saved = memory.get_agent_contexts(flow_id=flow_id, agent_id="")
|
|
64
|
+
assert len(saved) == 1
|
|
65
|
+
assert saved[0].chunks[0].chunk_id == "static_string"
|
|
66
|
+
assert saved[0].chunks[0].text == "Some static context text."
|
|
67
|
+
assert saved[0].chunks[0].origin_agent == config.module
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
async def test_get_question_context_records_step():
|
|
71
|
+
"""_get_question_context adds exactly one step with correct metadata."""
|
|
72
|
+
manager = MagicMock(spec=Manager)
|
|
73
|
+
config = make_config(context="Step test context.")
|
|
74
|
+
agent = StaticStringAgent(config=config)
|
|
75
|
+
|
|
76
|
+
memory = make_session().start_question("Any question?")
|
|
77
|
+
flow_id = uuid4().hex
|
|
78
|
+
|
|
79
|
+
await agent._get_question_context(
|
|
80
|
+
memory=memory,
|
|
81
|
+
manager=manager,
|
|
82
|
+
question_uuid=memory.original_question_uuid,
|
|
83
|
+
question="Any question?",
|
|
84
|
+
flow_id=flow_id,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
assert len(memory.steps) == 1
|
|
88
|
+
step = memory.steps[0]
|
|
89
|
+
assert step.module == "static_string"
|
|
90
|
+
assert "Search results" in step.title
|
|
91
|
+
assert step.value == "String done"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
async def test_get_question_context_different_flow_ids():
|
|
95
|
+
"""Contexts are scoped to their flow_id and do not bleed across flows."""
|
|
96
|
+
manager = MagicMock(spec=Manager)
|
|
97
|
+
config = make_config(context="Flow-isolated context.")
|
|
98
|
+
agent = StaticStringAgent(config=config)
|
|
99
|
+
|
|
100
|
+
memory = make_session().start_question("Question?")
|
|
101
|
+
flow_id_a = uuid4().hex
|
|
102
|
+
flow_id_b = uuid4().hex
|
|
103
|
+
|
|
104
|
+
await agent._get_question_context(
|
|
105
|
+
memory=memory,
|
|
106
|
+
manager=manager,
|
|
107
|
+
question_uuid=memory.original_question_uuid,
|
|
108
|
+
question="Question?",
|
|
109
|
+
flow_id=flow_id_a,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
saved_a = memory.get_agent_contexts(flow_id=flow_id_a, agent_id="")
|
|
113
|
+
saved_b = memory.get_agent_contexts(flow_id=flow_id_b, agent_id="")
|
|
114
|
+
assert len(saved_a) == 1
|
|
115
|
+
assert len(saved_b) == 0
|