mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
fix(wiki): preserve agent id tool inputs
This commit is contained in:
parent
b1f3332ae1
commit
7bf18e6af8
@ -154,9 +154,10 @@ public class WikiTool {
|
||||
- boundToAgent — true if the KB is explicitly bound to this agent
|
||||
""")
|
||||
public String wiki_list_kbs(
|
||||
@ToolParam(description = "Agent ID") Long agentId) {
|
||||
List<WikiKnowledgeBaseEntity> kbs = kbService.listByAgentId(agentId);
|
||||
WikiKnowledgeBaseEntity primary = kbService.resolvePrimaryKb(agentId);
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId) {
|
||||
Long parsedAgentId = parseAgentId(agentId);
|
||||
List<WikiKnowledgeBaseEntity> kbs = kbService.listByAgentId(parsedAgentId);
|
||||
WikiKnowledgeBaseEntity primary = kbService.resolvePrimaryKb(parsedAgentId);
|
||||
Long primaryId = primary == null ? null : primary.getId();
|
||||
|
||||
JSONArray arr = new JSONArray();
|
||||
@ -195,7 +196,7 @@ public class WikiTool {
|
||||
consult that page first — call this tool with the bare slug before answering.
|
||||
""")
|
||||
public String wiki_read_page(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Page slug") String slug,
|
||||
@ToolParam(description = "Max characters to return (null = full page)", required = false) Integer maxChars,
|
||||
@ToolParam(description = "Section heading to extract (null = all sections)", required = false) String sectionHeading,
|
||||
@ -247,7 +248,7 @@ public class WikiTool {
|
||||
Without query returns all pages (use only for small KBs).
|
||||
""")
|
||||
public String wiki_list_pages(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Title keyword filter (optional)", required = false) String query,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ToolParam(description = "Numeric KB id from wiki_list_kbs. Use when `kbName` returns an ambiguous-name error.", required = false) Long kbId) {
|
||||
@ -307,7 +308,7 @@ public class WikiTool {
|
||||
When using wiki information in your answer, always cite the source page title.
|
||||
""")
|
||||
public String wiki_search_pages(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Search query") String query,
|
||||
@ToolParam(description = "Mode: keyword|semantic|hybrid (default: hybrid)", required = false) String mode,
|
||||
@ToolParam(description = "Max results (default 5, max 20)", required = false) Integer topK,
|
||||
@ -374,7 +375,7 @@ public class WikiTool {
|
||||
When using retrieved content in your answer, cite the source page title shown in each result.
|
||||
""")
|
||||
public String wiki_semantic_search(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Natural language query") String query,
|
||||
@ToolParam(description = "Max results (default 5)", required = false) Integer topK,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ -441,7 +442,7 @@ public class WikiTool {
|
||||
Returns file names, types, and paths of the original documents.
|
||||
""")
|
||||
public String wiki_trace_source(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Page slug") String slug,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ToolParam(description = "Numeric KB id from wiki_list_kbs. Use when `kbName` returns an ambiguous-name error.", required = false) Long kbId) {
|
||||
@ -474,7 +475,7 @@ public class WikiTool {
|
||||
Content should be Markdown. Slug is auto-generated from title.
|
||||
""")
|
||||
public String wiki_create_page(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Page title") String title,
|
||||
@ToolParam(description = "Page content (Markdown)") String content,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ -561,7 +562,7 @@ public class WikiTool {
|
||||
Set slug to control the page slug; otherwise it's derived from the topic.
|
||||
""")
|
||||
public String wiki_compile_page(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Topic to compile a page about (natural language)") String topic,
|
||||
@ToolParam(description = "Optional explicit slug for the page", required = false) String slug,
|
||||
@ToolParam(description = "Max evidence chunks (default 8, max 20)", required = false) Integer maxEvidenceChunks,
|
||||
@ -618,7 +619,7 @@ public class WikiTool {
|
||||
page; protected/system pages can still be read explicitly here.
|
||||
""")
|
||||
public String wiki_read_many(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Comma-separated slugs (max 10)") String slugs,
|
||||
@ToolParam(description = "Max chars returned per page (default 2000, max 8000)", required = false) Integer maxCharsPerPage,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ -670,7 +671,7 @@ public class WikiTool {
|
||||
System pages (overview / log) cannot be archived.
|
||||
""")
|
||||
public String wiki_archive_page(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Page slug to archive") String slug,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ToolParam(description = "Numeric KB id from wiki_list_kbs. Use when `kbName` returns an ambiguous-name error.", required = false) Long kbId) {
|
||||
@ -682,14 +683,14 @@ public class WikiTool {
|
||||
list / search / related results again. No-op when the page wasn't archived.
|
||||
""")
|
||||
public String wiki_unarchive_page(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Page slug to unarchive") String slug,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ToolParam(description = "Numeric KB id from wiki_list_kbs. Use when `kbName` returns an ambiguous-name error.", required = false) Long kbId) {
|
||||
return setArchivedTool(agentId, slug, false, "unarchived", kbName, kbId);
|
||||
}
|
||||
|
||||
private String setArchivedTool(Long agentId, String slug, boolean archive, String verb, String kbName, Long kbId) {
|
||||
private String setArchivedTool(String agentId, String slug, boolean archive, String verb, String kbName, Long kbId) {
|
||||
if (slug == null || slug.isBlank()) return error("slug is required");
|
||||
KbResolution kbRes = resolveKb(agentId, kbName, kbId);
|
||||
if (kbRes.hasError()) return kbRes.errorJson();
|
||||
@ -725,7 +726,7 @@ public class WikiTool {
|
||||
Delete an AI-generated wiki page. Cannot delete manually curated pages.
|
||||
""")
|
||||
public String wiki_delete_page(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Page slug to delete") String slug,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ToolParam(description = "Numeric KB id from wiki_list_kbs. Use when `kbName` returns an ambiguous-name error.", required = false) Long kbId) {
|
||||
@ -781,7 +782,7 @@ public class WikiTool {
|
||||
semantic similarity). More reliable than keyword search for discovering connected knowledge.
|
||||
""")
|
||||
public String wiki_related_pages(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Page slug") String slug,
|
||||
@ToolParam(description = "Max results (default 5, max 10)", required = false) Integer topK,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ -819,7 +820,7 @@ public class WikiTool {
|
||||
Explain why two wiki pages are related. Returns signal breakdown with scores.
|
||||
""")
|
||||
public String wiki_explain_relation(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "First page slug") String slugA,
|
||||
@ToolParam(description = "Second page slug") String slugB,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ -854,7 +855,7 @@ public class WikiTool {
|
||||
Does NOT regenerate content — only adds [[wikilink]] cross-references.
|
||||
""")
|
||||
public String wiki_enrich_page(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Page slug") String slug,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ToolParam(description = "Numeric KB id from wiki_list_kbs. Use when `kbName` returns an ambiguous-name error.", required = false) Long kbId) {
|
||||
@ -898,7 +899,7 @@ public class WikiTool {
|
||||
is re-derived from the new content unless you pass one explicitly.
|
||||
""")
|
||||
public String wiki_update_page(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Slug of the page to update (from wiki_list_pages / wiki_read_page)") String slug,
|
||||
@ToolParam(description = "New full Markdown content for the page body") String content,
|
||||
@ToolParam(description = "New one-line summary (optional; omit to auto-derive from content)", required = false) String summary,
|
||||
@ -944,7 +945,7 @@ public class WikiTool {
|
||||
relying on experience/analysis pages.
|
||||
""")
|
||||
public String wiki_stale_pages(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ToolParam(description = "Numeric KB id from wiki_list_kbs. Use when `kbName` returns an ambiguous-name error.", required = false) Long kbId) {
|
||||
|
||||
@ -980,7 +981,7 @@ public class WikiTool {
|
||||
human title, and a description of what the prompt produces.
|
||||
""")
|
||||
public String wiki_list_transformations(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ToolParam(description = "Numeric KB id from wiki_list_kbs. Use when `kbName` returns an ambiguous-name error.", required = false) Long kbId) {
|
||||
KbResolution kbRes = resolveKb(agentId, kbName, kbId);
|
||||
@ -1010,7 +1011,7 @@ public class WikiTool {
|
||||
The run is also persisted so the result is visible in the wiki UI.
|
||||
""")
|
||||
public String wiki_apply_transformation(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Transformation name (from wiki_list_transformations)") String name,
|
||||
@ToolParam(description = "Raw material ID to run the transformation against") Long rawId,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ -1065,7 +1066,7 @@ public class WikiTool {
|
||||
is persisted in the wiki UI; pass slug (not page id) for convenience.
|
||||
""")
|
||||
public String wiki_apply_transformation_to_page(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Transformation name (from wiki_list_transformations)") String name,
|
||||
@ToolParam(description = "Source wiki page slug to run the transformation against") String slug,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ -1127,7 +1128,7 @@ public class WikiTool {
|
||||
account). Idempotent — re-running upserts the same slug.
|
||||
""")
|
||||
public String wiki_aggregate_transformation(
|
||||
@ToolParam(description = "Agent ID") Long agentId,
|
||||
@ToolParam(description = "Agent ID. Must be passed as a string to preserve large integer precision") String agentId,
|
||||
@ToolParam(description = "Transformation name (from wiki_list_transformations)") String name,
|
||||
@ToolParam(description = "Target knowledge base name (from wiki_list_kbs). Omit to use the agent's primary KB; switch to `kbId` when two KBs share the name.", required = false) String kbName,
|
||||
@ToolParam(description = "Numeric KB id from wiki_list_kbs. Use when `kbName` returns an ambiguous-name error.", required = false) Long kbId) {
|
||||
@ -1183,6 +1184,18 @@ public class WikiTool {
|
||||
return resolveKbId(agentId, null, null);
|
||||
}
|
||||
|
||||
private Long parseAgentId(String agentId) {
|
||||
String trimmed = agentId != null ? agentId.trim() : "";
|
||||
if (trimmed.isEmpty()) {
|
||||
throw new IllegalArgumentException("agentId is required");
|
||||
}
|
||||
try {
|
||||
return Long.parseLong(trimmed);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException("agentId must be a numeric string");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outcome of resolving a KB for a tool call. Exactly one of
|
||||
* {@code kbId} / {@code errorJson} is non-null:
|
||||
@ -1210,6 +1223,10 @@ public class WikiTool {
|
||||
return pageTypePermissionService.resolve(agentId, kbId);
|
||||
}
|
||||
|
||||
private WikiPageTypePermissionService.Access pageTypeAccess(String agentId, Long kbId) {
|
||||
return pageTypeAccess(parseAgentId(agentId), kbId);
|
||||
}
|
||||
|
||||
/** Whether the resolved access permits reading {@code page}. Null-safe. */
|
||||
private boolean canRead(WikiPageTypePermissionService.Access access, WikiPageEntity page) {
|
||||
return access == null || page == null || access.canRead(page.getPageType());
|
||||
@ -1273,6 +1290,11 @@ public class WikiTool {
|
||||
};
|
||||
}
|
||||
|
||||
private String checkWrite(String agentId, Long kbId, String pageType,
|
||||
WikiPageTypePermissionService.WriteOp op) {
|
||||
return checkWrite(parseAgentId(agentId), kbId, pageType, op);
|
||||
}
|
||||
|
||||
/**
|
||||
* Record a pending approval for an {@code APPROVAL_REQUIRED} wiki write,
|
||||
* keyed to the current conversation via {@link ChatOriginHolder}. Best-effort:
|
||||
@ -1390,6 +1412,10 @@ public class WikiTool {
|
||||
return KbResolution.ok(primary.getId());
|
||||
}
|
||||
|
||||
private KbResolution resolveKb(String agentId, String kbName, Long kbId) {
|
||||
return resolveKb(parseAgentId(agentId), kbName, kbId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy 2-arg routing kept for the tool methods that haven't been
|
||||
* widened to accept {@code kbId} yet. Always returns null when the
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
package vip.mate.wiki.tool;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.ai.support.ToolCallbacks;
|
||||
import org.springframework.ai.tool.ToolCallback;
|
||||
import vip.mate.wiki.service.HybridRetriever;
|
||||
import vip.mate.wiki.service.WikiKnowledgeBaseService;
|
||||
import vip.mate.wiki.service.WikiPageService;
|
||||
import vip.mate.wiki.service.WikiPageTypePermissionService;
|
||||
import vip.mate.wiki.service.WikiRawMaterialService;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
class WikiToolIdSchemaTest {
|
||||
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
@DisplayName("wiki tools publish agentId as a string parameter so LLM tool calls preserve precision")
|
||||
void wikiToolAgentIdSchemasAreString() throws Exception {
|
||||
WikiTool tool = new WikiTool(
|
||||
mock(WikiPageService.class),
|
||||
mock(WikiKnowledgeBaseService.class),
|
||||
mock(WikiRawMaterialService.class),
|
||||
mock(HybridRetriever.class),
|
||||
new ObjectMapper(),
|
||||
mock(WikiPageTypePermissionService.class));
|
||||
|
||||
int checked = 0;
|
||||
for (ToolCallback callback : ToolCallbacks.from(tool)) {
|
||||
JsonNode root = MAPPER.readTree(callback.getToolDefinition().inputSchema());
|
||||
JsonNode agentId = root.at("/properties/agentId/type");
|
||||
if (!agentId.isMissingNode()) {
|
||||
assertThat(agentId.asText())
|
||||
.as(callback.getToolDefinition().name())
|
||||
.isEqualTo("string");
|
||||
checked++;
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(checked).isGreaterThan(0);
|
||||
}
|
||||
}
|
||||
@ -51,6 +51,7 @@ import static org.mockito.Mockito.when;
|
||||
class WikiToolKbNameRoutingTest {
|
||||
|
||||
private static final Long AGENT = 7L;
|
||||
private static final String AGENT_PARAM = String.valueOf(AGENT);
|
||||
private static final long PRIMARY_KB = 100L;
|
||||
private static final long OTHER_KB = 200L;
|
||||
private static final long DUP_BOUND_KB = 300L;
|
||||
@ -109,7 +110,7 @@ class WikiToolKbNameRoutingTest {
|
||||
wirePages();
|
||||
when(kbService.resolvePrimaryKb(AGENT)).thenReturn(kb(PRIMARY_KB, "Primary", AGENT));
|
||||
|
||||
String json = tool.wiki_list_pages(AGENT, null, null, null);
|
||||
String json = tool.wiki_list_pages(AGENT_PARAM, null, null, null);
|
||||
JSONObject obj = JSONUtil.parseObj(json);
|
||||
|
||||
JSONArray pages = obj.getJSONArray("pages");
|
||||
@ -126,7 +127,7 @@ class WikiToolKbNameRoutingTest {
|
||||
when(kbService.resolvePrimaryKb(AGENT)).thenReturn(kb(PRIMARY_KB, "Primary", AGENT));
|
||||
when(kbService.findAllByName(AGENT, "Other")).thenReturn(List.of(kb(OTHER_KB, "Other", null)));
|
||||
|
||||
String json = tool.wiki_list_pages(AGENT, null, "Other", null);
|
||||
String json = tool.wiki_list_pages(AGENT_PARAM, null, "Other", null);
|
||||
JSONObject obj = JSONUtil.parseObj(json);
|
||||
|
||||
JSONArray pages = obj.getJSONArray("pages");
|
||||
@ -141,7 +142,7 @@ class WikiToolKbNameRoutingTest {
|
||||
when(kbService.resolvePrimaryKb(AGENT)).thenReturn(kb(PRIMARY_KB, "Primary", AGENT));
|
||||
when(kbService.findVisibleById(AGENT, OTHER_KB)).thenReturn(kb(OTHER_KB, "Other", null));
|
||||
|
||||
String json = tool.wiki_list_pages(AGENT, null, null, OTHER_KB);
|
||||
String json = tool.wiki_list_pages(AGENT_PARAM, null, null, OTHER_KB);
|
||||
JSONObject obj = JSONUtil.parseObj(json);
|
||||
|
||||
assertThat(obj.getJSONArray("pages").getJSONObject(0).getStr("slug"))
|
||||
@ -156,7 +157,7 @@ class WikiToolKbNameRoutingTest {
|
||||
// Deliberately do NOT stub findAllByName — if the tool consulted
|
||||
// kbName at all (or fell back to primary), the call would NPE.
|
||||
|
||||
String json = tool.wiki_list_pages(AGENT, null, "anything", OTHER_KB);
|
||||
String json = tool.wiki_list_pages(AGENT_PARAM, null, "anything", OTHER_KB);
|
||||
JSONObject obj = JSONUtil.parseObj(json);
|
||||
assertThat(obj.getJSONArray("pages").getJSONObject(0).getStr("slug"))
|
||||
.isEqualTo("other-only-slug");
|
||||
@ -171,7 +172,7 @@ class WikiToolKbNameRoutingTest {
|
||||
// Primary still mockable; the routing must NOT silently fall through.
|
||||
when(kbService.resolvePrimaryKb(AGENT)).thenReturn(kb(PRIMARY_KB, "Primary", AGENT));
|
||||
|
||||
String json = tool.wiki_list_pages(AGENT, null, "Bogus", null);
|
||||
String json = tool.wiki_list_pages(AGENT_PARAM, null, "Bogus", null);
|
||||
JSONObject obj = JSONUtil.parseObj(json);
|
||||
|
||||
assertThat(obj.getStr("error"))
|
||||
@ -188,7 +189,7 @@ class WikiToolKbNameRoutingTest {
|
||||
kb(DUP_SHARED_KB, "Docs", null)));
|
||||
when(kbService.resolvePrimaryKb(AGENT)).thenReturn(kb(PRIMARY_KB, "Primary", AGENT));
|
||||
|
||||
String json = tool.wiki_list_pages(AGENT, null, "Docs", null);
|
||||
String json = tool.wiki_list_pages(AGENT_PARAM, null, "Docs", null);
|
||||
JSONObject obj = JSONUtil.parseObj(json);
|
||||
|
||||
// Error must be ambiguity-flavoured so the LLM knows to retry with kbId.
|
||||
@ -217,7 +218,7 @@ class WikiToolKbNameRoutingTest {
|
||||
// would return null and surface a spurious "kbId=0 not visible" error,
|
||||
// which is exactly the production regression this test prevents.
|
||||
|
||||
String json = tool.wiki_list_pages(AGENT, null, null, 0L);
|
||||
String json = tool.wiki_list_pages(AGENT_PARAM, null, null, 0L);
|
||||
JSONObject obj = JSONUtil.parseObj(json);
|
||||
|
||||
assertThat(obj.getStr("error"))
|
||||
@ -234,7 +235,7 @@ class WikiToolKbNameRoutingTest {
|
||||
when(kbService.findVisibleById(AGENT, 99999L)).thenReturn(null);
|
||||
when(kbService.resolvePrimaryKb(AGENT)).thenReturn(kb(PRIMARY_KB, "Primary", AGENT));
|
||||
|
||||
String json = tool.wiki_list_pages(AGENT, null, null, 99999L);
|
||||
String json = tool.wiki_list_pages(AGENT_PARAM, null, null, 99999L);
|
||||
JSONObject obj = JSONUtil.parseObj(json);
|
||||
|
||||
assertThat(obj.getStr("error"))
|
||||
@ -248,7 +249,7 @@ class WikiToolKbNameRoutingTest {
|
||||
void noResolvableKbReturnsLegacyError() {
|
||||
when(kbService.resolvePrimaryKb(AGENT)).thenReturn(null);
|
||||
|
||||
String json = tool.wiki_list_pages(AGENT, null, null, null);
|
||||
String json = tool.wiki_list_pages(AGENT_PARAM, null, null, null);
|
||||
JSONObject obj = JSONUtil.parseObj(json);
|
||||
|
||||
assertThat(obj.getStr("error")).contains("No wiki knowledge base found");
|
||||
@ -264,7 +265,7 @@ class WikiToolKbNameRoutingTest {
|
||||
kb(PRIMARY_KB, "Primary", AGENT)));
|
||||
when(kbService.resolvePrimaryKb(AGENT)).thenReturn(kb(PRIMARY_KB, "Primary", AGENT));
|
||||
|
||||
String json = tool.wiki_list_kbs(AGENT);
|
||||
String json = tool.wiki_list_kbs(AGENT_PARAM);
|
||||
JSONObject obj = JSONUtil.parseObj(json);
|
||||
|
||||
assertThat(obj.getInt("kbCount")).isEqualTo(2);
|
||||
|
||||
@ -33,6 +33,7 @@ import static org.mockito.Mockito.when;
|
||||
class WikiToolPermissionTest {
|
||||
|
||||
private static final long AGENT = 11L;
|
||||
private static final String AGENT_PARAM = String.valueOf(AGENT);
|
||||
private static final long KB = 7L;
|
||||
|
||||
private record Harness(WikiTool tool, WikiPageService pageService,
|
||||
@ -90,7 +91,7 @@ class WikiToolPermissionTest {
|
||||
Harness h = harness(List.of(row("*", 0, 0, 0, 0, "deny")));
|
||||
when(h.pageService().getBySlug(KB, "secret")).thenReturn(page("secret", "analysis"));
|
||||
|
||||
String out = h.tool().wiki_read_page(AGENT, "secret", null, null, null, KB);
|
||||
String out = h.tool().wiki_read_page(AGENT_PARAM, "secret", null, null, null, KB);
|
||||
|
||||
assertTrue(out.contains("Page not found"), out);
|
||||
}
|
||||
@ -100,7 +101,7 @@ class WikiToolPermissionTest {
|
||||
Harness h = harness(List.of(row("*", 1, 0, 0, 0, "deny")));
|
||||
when(h.pageService().getBySlug(KB, "ok")).thenReturn(page("ok", "concept"));
|
||||
|
||||
String out = h.tool().wiki_read_page(AGENT, "ok", null, null, null, KB);
|
||||
String out = h.tool().wiki_read_page(AGENT_PARAM, "ok", null, null, null, KB);
|
||||
|
||||
assertTrue(out.contains("\"content\""), out);
|
||||
assertFalse(out.contains("Page not found"), out);
|
||||
@ -112,7 +113,7 @@ class WikiToolPermissionTest {
|
||||
Harness h = harness(List.of(row("concept", 1, 0, 0, 0, "deny")));
|
||||
when(h.pageService().getBySlug(KB, "p")).thenReturn(page("p", "concept"));
|
||||
|
||||
String out = h.tool().wiki_delete_page(AGENT, "p", null, KB);
|
||||
String out = h.tool().wiki_delete_page(AGENT_PARAM, "p", null, KB);
|
||||
|
||||
assertTrue(out.contains("Not permitted"), out);
|
||||
verify(h.pageService(), never()).delete(anyLong(), any());
|
||||
@ -123,7 +124,7 @@ class WikiToolPermissionTest {
|
||||
Harness h = harness(List.of(row("concept", 1, 0, 0, 1, "approval_required")));
|
||||
when(h.pageService().getBySlug(KB, "p")).thenReturn(page("p", "concept"));
|
||||
|
||||
String out = h.tool().wiki_delete_page(AGENT, "p", null, KB);
|
||||
String out = h.tool().wiki_delete_page(AGENT_PARAM, "p", null, KB);
|
||||
|
||||
assertTrue(out.contains("Approval required"), out);
|
||||
verify(h.pageService(), never()).delete(anyLong(), any());
|
||||
@ -134,7 +135,7 @@ class WikiToolPermissionTest {
|
||||
Harness h = harness(List.of(row("concept", 1, 1, 1, 1, "allow")));
|
||||
when(h.pageService().getBySlug(KB, "p")).thenReturn(page("p", "concept"));
|
||||
|
||||
String out = h.tool().wiki_delete_page(AGENT, "p", null, KB);
|
||||
String out = h.tool().wiki_delete_page(AGENT_PARAM, "p", null, KB);
|
||||
|
||||
assertTrue(out.contains("\"ok\":true"), out);
|
||||
verify(h.pageService(), times(1)).delete(eq(KB), eq("p"));
|
||||
@ -145,7 +146,7 @@ class WikiToolPermissionTest {
|
||||
// a row exists for 'episode' only → KB is gated, wildcard create not granted
|
||||
Harness h = harness(List.of(row("episode", 1, 1, 1, 1, "allow")));
|
||||
|
||||
String out = h.tool().wiki_create_page(AGENT, "New Page", "content here", null, KB);
|
||||
String out = h.tool().wiki_create_page(AGENT_PARAM, "New Page", "content here", null, KB);
|
||||
|
||||
assertTrue(out.contains("Not permitted"), out);
|
||||
verify(h.pageService(), never()).createPage(anyLong(), any(), any(), any(), any(), any());
|
||||
@ -161,7 +162,7 @@ class WikiToolPermissionTest {
|
||||
updated.setVersion(2);
|
||||
when(h.pageService().updatePageManually(eq(KB), eq("p"), any(), any())).thenReturn(updated);
|
||||
|
||||
String out = h.tool().wiki_update_page(AGENT, "p", "new body", null, null, KB);
|
||||
String out = h.tool().wiki_update_page(AGENT_PARAM, "p", "new body", null, null, KB);
|
||||
|
||||
assertTrue(out.contains("\"ok\":true"), out);
|
||||
assertTrue(out.contains("updated in place"), out);
|
||||
@ -177,7 +178,7 @@ class WikiToolPermissionTest {
|
||||
Harness h = harness(List.of(row("concept", 1, 1, 0, 0, "allow")));
|
||||
when(h.pageService().getBySlug(KB, "p")).thenReturn(page("p", "concept"));
|
||||
|
||||
String out = h.tool().wiki_update_page(AGENT, "p", "new body", null, null, KB);
|
||||
String out = h.tool().wiki_update_page(AGENT_PARAM, "p", "new body", null, null, KB);
|
||||
|
||||
assertTrue(out.contains("Not permitted"), out);
|
||||
verify(h.pageService(), never()).updatePageManually(anyLong(), any(), any(), any());
|
||||
@ -188,7 +189,7 @@ class WikiToolPermissionTest {
|
||||
Harness h = harness(List.of(row("*", 1, 1, 1, 1, "allow")));
|
||||
when(h.pageService().getBySlug(KB, "ghost")).thenReturn(null);
|
||||
|
||||
String out = h.tool().wiki_update_page(AGENT, "ghost", "body", null, null, KB);
|
||||
String out = h.tool().wiki_update_page(AGENT_PARAM, "ghost", "body", null, null, KB);
|
||||
|
||||
assertTrue(out.contains("Page not found"), out);
|
||||
verify(h.pageService(), never()).updatePageManually(anyLong(), any(), any(), any());
|
||||
@ -212,7 +213,7 @@ class WikiToolPermissionTest {
|
||||
WikiPageEntity staleHidden = stalePage("classified", "secret", "{\"reason\":\"x\"}");
|
||||
when(h.pageService().listByKbId(KB)).thenReturn(List.of(fresh, staleOk, staleHidden));
|
||||
|
||||
String out = h.tool().wiki_stale_pages(AGENT, null, KB);
|
||||
String out = h.tool().wiki_stale_pages(AGENT_PARAM, null, KB);
|
||||
|
||||
assertTrue(out.contains("\"staleCount\":1"), out);
|
||||
assertTrue(out.contains("aged"), out);
|
||||
@ -225,7 +226,7 @@ class WikiToolPermissionTest {
|
||||
Harness h = harness(List.of());
|
||||
when(h.pageService().listByKbId(KB)).thenReturn(List.of(page("a", "concept"), page("b", "episode")));
|
||||
|
||||
String out = h.tool().wiki_stale_pages(AGENT, null, KB);
|
||||
String out = h.tool().wiki_stale_pages(AGENT_PARAM, null, KB);
|
||||
|
||||
assertTrue(out.contains("\"staleCount\":0"), out);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user