hyperforge-nucliadb 1.0.0.post108__tar.gz → 1.0.0.post111__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_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/PKG-INFO +11 -1
- hyperforge_nucliadb-1.0.0.post111/README.md +16 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/pyproject.toml +1 -1
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/driver.py +8 -2
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb.egg-info/PKG-INFO +11 -1
- hyperforge_nucliadb-1.0.0.post111/tests/test_driver.py +99 -0
- hyperforge_nucliadb-1.0.0.post108/README.md +0 -6
- hyperforge_nucliadb-1.0.0.post108/tests/test_driver.py +0 -34
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/setup.cfg +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/__init__.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/advanced_ask_agent.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/advanced_ask_config.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/__init__.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/analysis.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/ask.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/config.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/hydrate.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/kb_analysis.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/knowledge_scan.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/models.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/multi.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/nucliadb.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/prompt_analysis.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/query_analysis.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/rerank.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask/utils.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/ask_utils.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/basic_ask_agent.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/basic_ask_config.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/driver_config.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/py.typed +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/sync/__init__.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/sync/agent.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/sync/config.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/sync/config_driver.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb/sync/driver.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb.egg-info/SOURCES.txt +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb.egg-info/dependency_links.txt +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb.egg-info/requires.txt +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/src/hyperforge_nucliadb.egg-info/top_level.txt +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/tests/test_ask_utils.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/tests/test_nucliadb.py +0 -0
- {hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/tests/test_sync.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hyperforge_nucliadb
|
|
3
|
-
Version: 1.0.0.
|
|
3
|
+
Version: 1.0.0.post111
|
|
4
4
|
Summary: NucliaDB Hyperforge agent
|
|
5
5
|
Author-email: Nuclia <nucliadb@nuclia.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -25,3 +25,13 @@ Basic ASK - Basic initial agent
|
|
|
25
25
|
Advanced ASK (deprecated)
|
|
26
26
|
ASK (experimental)
|
|
27
27
|
Sync (Sync Service oauth linked)
|
|
28
|
+
|
|
29
|
+
## Client identification
|
|
30
|
+
|
|
31
|
+
NucliaDB `/ask` and `/find` requests made by these agents use
|
|
32
|
+
`X-NDB-Client: agentic`, including when invoked as tools by a smart agent in a
|
|
33
|
+
RAO workflow. The Sync driver inherits the same behavior. Other request headers
|
|
34
|
+
are preserved, and caller-provided headers are not modified.
|
|
35
|
+
|
|
36
|
+
Workflow memory searches through `/find` also use the `agentic` client type.
|
|
37
|
+
The receiving NucliaDB API must support the `agentic` client type.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# NucliaDB Hyperforge agents
|
|
2
|
+
|
|
3
|
+
Basic ASK - Basic initial agent
|
|
4
|
+
Advanced ASK (deprecated)
|
|
5
|
+
ASK (experimental)
|
|
6
|
+
Sync (Sync Service oauth linked)
|
|
7
|
+
|
|
8
|
+
## Client identification
|
|
9
|
+
|
|
10
|
+
NucliaDB `/ask` and `/find` requests made by these agents use
|
|
11
|
+
`X-NDB-Client: agentic`, including when invoked as tools by a smart agent in a
|
|
12
|
+
RAO workflow. The Sync driver inherits the same behavior. Other request headers
|
|
13
|
+
are preserved, and caller-provided headers are not modified.
|
|
14
|
+
|
|
15
|
+
Workflow memory searches through `/find` also use the `agentic` client type.
|
|
16
|
+
The receiving NucliaDB API must support the `agentic` client type.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hyperforge_nucliadb"
|
|
7
|
-
version = "1.0.0.
|
|
7
|
+
version = "1.0.0.post111"
|
|
8
8
|
license = "Apache-2.0"
|
|
9
9
|
description = "NucliaDB Hyperforge agent"
|
|
10
10
|
authors = [{ name = "Nuclia", email = "nucliadb@nuclia.com" }]
|
|
@@ -303,9 +303,13 @@ class NucliaDBDriver(Driver):
|
|
|
303
303
|
result.append(word)
|
|
304
304
|
return " ".join(result)
|
|
305
305
|
|
|
306
|
-
async def ask(
|
|
306
|
+
async def ask(
|
|
307
|
+
self, item: AskRequest, headers: dict[str, str] | None = None
|
|
308
|
+
) -> SyncAskResponse:
|
|
309
|
+
request_headers = httpx.Headers(headers)
|
|
310
|
+
request_headers["X-NDB-Client"] = "agentic"
|
|
307
311
|
return await self.driver.ask(
|
|
308
|
-
kbid=self.config.kbid, content=item, headers=
|
|
312
|
+
kbid=self.config.kbid, content=item, headers=dict(request_headers)
|
|
309
313
|
)
|
|
310
314
|
|
|
311
315
|
async def find(
|
|
@@ -313,6 +317,7 @@ class NucliaDBDriver(Driver):
|
|
|
313
317
|
) -> KnowledgeboxFindResults:
|
|
314
318
|
return await self.driver.find(
|
|
315
319
|
kbid=self.config.kbid,
|
|
320
|
+
headers={"X-NDB-Client": "agentic"},
|
|
316
321
|
content=FindRequest(
|
|
317
322
|
query=q,
|
|
318
323
|
resource_filters=rids,
|
|
@@ -326,6 +331,7 @@ class NucliaDBDriver(Driver):
|
|
|
326
331
|
return await self.driver.find(
|
|
327
332
|
kbid=self.config.kbid,
|
|
328
333
|
content=q,
|
|
334
|
+
headers={"X-NDB-Client": "agentic"},
|
|
329
335
|
)
|
|
330
336
|
|
|
331
337
|
async def graph_relations(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hyperforge_nucliadb
|
|
3
|
-
Version: 1.0.0.
|
|
3
|
+
Version: 1.0.0.post111
|
|
4
4
|
Summary: NucliaDB Hyperforge agent
|
|
5
5
|
Author-email: Nuclia <nucliadb@nuclia.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -25,3 +25,13 @@ Basic ASK - Basic initial agent
|
|
|
25
25
|
Advanced ASK (deprecated)
|
|
26
26
|
ASK (experimental)
|
|
27
27
|
Sync (Sync Service oauth linked)
|
|
28
|
+
|
|
29
|
+
## Client identification
|
|
30
|
+
|
|
31
|
+
NucliaDB `/ask` and `/find` requests made by these agents use
|
|
32
|
+
`X-NDB-Client: agentic`, including when invoked as tools by a smart agent in a
|
|
33
|
+
RAO workflow. The Sync driver inherits the same behavior. Other request headers
|
|
34
|
+
are preserved, and caller-provided headers are not modified.
|
|
35
|
+
|
|
36
|
+
Workflow memory searches through `/find` also use the `agentic` client type.
|
|
37
|
+
The receiving NucliaDB API must support the `agentic` client type.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from types import SimpleNamespace
|
|
3
|
+
from unittest.mock import AsyncMock
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
import pytest
|
|
7
|
+
from nucliadb_models.search import AskRequest, FindRequest
|
|
8
|
+
from nucliadb_sdk.v2 import NucliaDBAsync
|
|
9
|
+
|
|
10
|
+
from hyperforge_nucliadb.driver import NucliaDBDriver
|
|
11
|
+
from hyperforge_nucliadb.sync.driver import SyncDriver
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def make_driver(client, driver_type=NucliaDBDriver):
|
|
15
|
+
return driver_type.model_construct(
|
|
16
|
+
provider="nucliadb",
|
|
17
|
+
name="test",
|
|
18
|
+
config=SimpleNamespace(kbid="test-kb", filters=[]),
|
|
19
|
+
driver=client,
|
|
20
|
+
manager=SimpleNamespace(),
|
|
21
|
+
_synonyms=None,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@pytest.mark.asyncio
|
|
26
|
+
async def test_labels_uses_complete_labelsets_response():
|
|
27
|
+
client = AsyncMock()
|
|
28
|
+
client.get_labelsets.return_value = SimpleNamespace(
|
|
29
|
+
labelsets={
|
|
30
|
+
"type": SimpleNamespace(labels=[SimpleNamespace(title="report")]),
|
|
31
|
+
"topic": SimpleNamespace(labels=[SimpleNamespace(title="science")]),
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
driver = make_driver(client)
|
|
35
|
+
|
|
36
|
+
assert await driver.labels() == {"type": ["report"], "topic": ["science"]}
|
|
37
|
+
|
|
38
|
+
client.get_labelsets.assert_awaited_once_with(kbid="test-kb")
|
|
39
|
+
client.get_labelset.assert_not_awaited()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@pytest.mark.asyncio
|
|
43
|
+
@pytest.mark.parametrize("driver_type", [NucliaDBDriver, SyncDriver])
|
|
44
|
+
@pytest.mark.parametrize("operation", ["ask", "find", "find_raw"])
|
|
45
|
+
async def test_search_requests_use_agentic_client_type(driver_type, operation):
|
|
46
|
+
def handle(request: httpx.Request) -> httpx.Response:
|
|
47
|
+
endpoint = "ask" if operation == "ask" else "find"
|
|
48
|
+
assert request.url.path.endswith(f"/kb/test-kb/{endpoint}")
|
|
49
|
+
assert request.headers.get_list("x-ndb-client") == ["agentic"]
|
|
50
|
+
assert request.headers["x-test-header"] == "preserved"
|
|
51
|
+
assert json.loads(request.content)["query"] == "question"
|
|
52
|
+
result = {"resources": {}, "total": 0}
|
|
53
|
+
if operation == "ask":
|
|
54
|
+
result = {
|
|
55
|
+
"status": "success",
|
|
56
|
+
"answer": "answer",
|
|
57
|
+
"retrieval_results": result,
|
|
58
|
+
}
|
|
59
|
+
return httpx.Response(200, json=result)
|
|
60
|
+
|
|
61
|
+
client = NucliaDBAsync(
|
|
62
|
+
url="http://nucliadb.test/api",
|
|
63
|
+
headers={"X-NDB-Client": "api", "x-test-header": "preserved"},
|
|
64
|
+
_httpx_transport=httpx.MockTransport(handle),
|
|
65
|
+
)
|
|
66
|
+
driver = make_driver(client, driver_type)
|
|
67
|
+
|
|
68
|
+
async with client.session:
|
|
69
|
+
if operation == "ask":
|
|
70
|
+
result = await driver.ask(AskRequest(query="question"))
|
|
71
|
+
assert result.answer == "answer"
|
|
72
|
+
elif operation == "find":
|
|
73
|
+
result = await driver.find("question")
|
|
74
|
+
assert result.total == 0
|
|
75
|
+
else:
|
|
76
|
+
result = await driver.find_raw(FindRequest(query="question"))
|
|
77
|
+
assert result.total == 0
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@pytest.mark.asyncio
|
|
81
|
+
@pytest.mark.parametrize(
|
|
82
|
+
"client_header", ["X-NDB-Client", "x-ndb-client", "X-NdB-ClIeNt"]
|
|
83
|
+
)
|
|
84
|
+
async def test_ask_preserves_caller_headers_without_mutating_them(client_header):
|
|
85
|
+
client = AsyncMock()
|
|
86
|
+
driver = make_driver(client)
|
|
87
|
+
headers = {client_header: "widget", "X-Synchronous": "true"}
|
|
88
|
+
original_headers = headers.copy()
|
|
89
|
+
request = AskRequest(query="question")
|
|
90
|
+
|
|
91
|
+
await driver.ask(request, headers=headers)
|
|
92
|
+
|
|
93
|
+
kwargs = client.ask.await_args.kwargs
|
|
94
|
+
sent_headers = httpx.Headers(kwargs["headers"])
|
|
95
|
+
assert sent_headers.get_list("x-ndb-client") == ["agentic"]
|
|
96
|
+
assert sent_headers["X-Synchronous"] == "true"
|
|
97
|
+
assert kwargs["kbid"] == "test-kb"
|
|
98
|
+
assert kwargs["content"] is request
|
|
99
|
+
assert headers == original_headers
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
from types import SimpleNamespace
|
|
2
|
-
from unittest.mock import AsyncMock
|
|
3
|
-
|
|
4
|
-
import pytest
|
|
5
|
-
|
|
6
|
-
from hyperforge_nucliadb.driver import NucliaDBDriver
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def make_driver(client):
|
|
10
|
-
return NucliaDBDriver.model_construct(
|
|
11
|
-
provider="nucliadb",
|
|
12
|
-
name="test",
|
|
13
|
-
config=SimpleNamespace(kbid="test-kb"),
|
|
14
|
-
driver=client,
|
|
15
|
-
manager=SimpleNamespace(),
|
|
16
|
-
_synonyms=None,
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@pytest.mark.asyncio
|
|
21
|
-
async def test_labels_uses_complete_labelsets_response():
|
|
22
|
-
client = AsyncMock()
|
|
23
|
-
client.get_labelsets.return_value = SimpleNamespace(
|
|
24
|
-
labelsets={
|
|
25
|
-
"type": SimpleNamespace(labels=[SimpleNamespace(title="report")]),
|
|
26
|
-
"topic": SimpleNamespace(labels=[SimpleNamespace(title="science")]),
|
|
27
|
-
}
|
|
28
|
-
)
|
|
29
|
-
driver = make_driver(client)
|
|
30
|
-
|
|
31
|
-
assert await driver.labels() == {"type": ["report"], "topic": ["science"]}
|
|
32
|
-
|
|
33
|
-
client.get_labelsets.assert_awaited_once_with(kbid="test-kb")
|
|
34
|
-
client.get_labelset.assert_not_awaited()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/tests/test_ask_utils.py
RENAMED
|
File without changes
|
{hyperforge_nucliadb-1.0.0.post108 → hyperforge_nucliadb-1.0.0.post111}/tests/test_nucliadb.py
RENAMED
|
File without changes
|
|
File without changes
|