') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); align query tool name by rejojer · Pull Request #1 · VectifyAI/OpenKB · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions openkb/agent/query.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,7 @@
"""


def pageindex_retrieve(doc_id: str, question: str, okb_dir: str, model: str) -> str:
def _pageindex_retrieve_impl(doc_id: str, question: str, okb_dir: str, model: str) -> str:
"""Retrieve relevant content from a long document via PageIndex.

Args:
Expand DownExpand Up@@ -148,7 +148,7 @@ def read_file(path: str) -> str:
return read_wiki_file(path, wiki_root)

@function_tool
def retrieve(doc_id: str, question: str) -> str:
def pageindex_retrieve(doc_id: str, question: str) -> str:
"""Retrieve relevant content from a long document via PageIndex.

Use this when you need detailed content from a document that was
Expand All@@ -158,12 +158,12 @@ def retrieve(doc_id: str, question: str) -> str:
doc_id: PageIndex document identifier (found in index.md).
question: The question you are trying to answer.
"""
return pageindex_retrieve(doc_id, question, okb_dir, model)
return _pageindex_retrieve_impl(doc_id, question, okb_dir, model)

return Agent(
name="wiki-query",
instructions=instructions,
tools=[list_files, read_file, retrieve],
tools=[list_files, read_file, pageindex_retrieve],
model=model,
)

Expand Down
16 changes: 11 additions & 5 deletions tests/test_query.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,7 +6,7 @@

import pytest

from openkb.agent.query import build_query_agent, pageindex_retrieve, run_query
from openkb.agent.query import _pageindex_retrieve_impl, build_query_agent, run_query
from openkb.schema import SCHEMA_MD


Expand All@@ -24,7 +24,13 @@ def test_agent_tool_names(self, tmp_path):
names = {t.name for t in agent.tools}
assert "list_files" in names
assert "read_file" in names
assert "retrieve" in names
assert "pageindex_retrieve" in names

def test_instructions_reference_registered_pageindex_tool(self, tmp_path):
agent = build_query_agent(str(tmp_path), str(tmp_path / "pi"), "gpt-4o-mini")
tool_names = {t.name for t in agent.tools}
assert "pageindex_retrieve" in agent.instructions
assert "pageindex_retrieve" in tool_names

def test_schema_in_instructions(self, tmp_path):
agent = build_query_agent(str(tmp_path), str(tmp_path / "pi"), "gpt-4o-mini")
Expand DownExpand Up@@ -63,7 +69,7 @@ def test_returns_page_content(self, tmp_path):
mock_llm.return_value = MagicMock(
choices=[MagicMock(message=MagicMock(content="1-2"))]
)
result = pageindex_retrieve("doc123", "What is the intro?", "/db", "gpt-4o-mini")
result = _pageindex_retrieve_impl("doc123", "What is the intro?", "/db", "gpt-4o-mini")

assert "Introduction text here." in result
assert "More intro content." in result
Expand All@@ -76,7 +82,7 @@ def test_handles_empty_structure(self, tmp_path):
mock_client.collection.return_value = mock_col

with patch("openkb.agent.query.PageIndexClient", return_value=mock_client):
result = pageindex_retrieve("doc456", "What?", "/db", "gpt-4o-mini")
result = _pageindex_retrieve_impl("doc456", "What?", "/db", "gpt-4o-mini")

assert "No structure found" in result

Expand All@@ -88,7 +94,7 @@ def test_handles_structure_error(self, tmp_path):
mock_client.collection.return_value = mock_col

with patch("openkb.agent.query.PageIndexClient", return_value=mock_client):
result = pageindex_retrieve("doc789", "What?", "/db", "gpt-4o-mini")
result = _pageindex_retrieve_impl("doc789", "What?", "/db", "gpt-4o-mini")

assert "Error" in result

Expand Down