feat: register isphere group search tool

This commit is contained in:
zhaoyilun
2026-07-10 00:29:49 +08:00
parent 4502a05bb4
commit 444c0d8ff1
9 changed files with 272 additions and 27 deletions

View File

@@ -8,7 +8,8 @@ $expectedTools = @(
"win_helper_scan_windows",
"win_helper_dump_uia",
"isphere_receive_messages",
"isphere_search_contacts"
"isphere_search_contacts",
"isphere_search_groups"
)
$tempRoot = Join-Path ([System.IO.Path]::GetTempPath()) ("isphere-go-mcp-verify-" + [guid]::NewGuid().ToString("N"))
@@ -81,6 +82,7 @@ var expectedTools = []string{
"win_helper_dump_uia",
"isphere_receive_messages",
"isphere_search_contacts",
"isphere_search_groups",
}
var forbiddenTerms = []string{"send", "file", "login", "conversation", "upload", "download", "autologin"}
@@ -136,7 +138,7 @@ func main() {
sort.Strings(toolNames)
want := append([]string(nil), expectedTools...)
sort.Strings(want)
if len(toolNames) != 6 || !reflect.DeepEqual(toolNames, want) {
if len(toolNames) != 7 || !reflect.DeepEqual(toolNames, want) {
fail("tools/list", fmt.Errorf("tool names = %#v, want %#v", toolNames, want))
}
@@ -187,7 +189,8 @@ func main() {
fail("tools/call isphere_receive_messages", fmt.Errorf("default empty source returned %d messages, want 0", len(messagesValue)))
}
defaultContactCount := verifySearchContacts(ctx, session, "sender", "tools/call isphere_search_contacts default", 0)
configuredReceiveCount, configuredContactCount := verifyConfiguredReceiveSource(ctx)
defaultGroupCount := verifySearchGroups(ctx, session, "project", "tools/call isphere_search_groups default", 0)
configuredReceiveCount, configuredContactCount, configuredGroupCount := verifyConfiguredReceiveSource(ctx)
result := map[string]any{
"ok": true,
@@ -198,8 +201,10 @@ func main() {
"helper_name": helperName,
"receive_message_count": len(messagesValue),
"contact_count": defaultContactCount,
"group_count": defaultGroupCount,
"configured_receive_message_count": configuredReceiveCount,
"configured_contact_count": configuredContactCount,
"configured_group_count": configuredGroupCount,
"packet_log_file_configured": os.Getenv("ISPHERE_PACKET_LOG_FILE") != "",
"real_isphere_login_required": false,
"python_runtime_required": false,
@@ -210,10 +215,10 @@ func main() {
}
func verifyConfiguredReceiveSource(ctx context.Context) (int, int) {
func verifyConfiguredReceiveSource(ctx context.Context) (int, int, int) {
plaintext := "--------------------------------------------------------------------------------------------------------------------------------------------\n" +
"2026/7/7 15:30:07\n" +
"<message id=\"msg-fixture-1\" from=\"sender@imopenfire1-lanzhou/imp_pc_4.1.2.6842\" to=\"receiver@imopenfire1-lanzhou\" type=\"chat\">\n" +
"<message id=\"msg-fixture-1\" from=\"project-room@conference.imopenfire1-lanzhou/imp_pc_4.1.2.6842\" to=\"sender@imopenfire1-lanzhou\" type=\"groupchat\">\n" +
" <body>redacted fixture</body>\n" +
" <received xmlns=\"urn:xmpp:receipts\" id=\"receipt-fixture-1\" type=\"1\" stamp=\"\" />\n" +
" <subject>VERIFY_FIXTURE</subject>\n" +
@@ -304,11 +309,12 @@ func verifyConfiguredReceiveSource(ctx context.Context) (int, int) {
if message["id"] != "msg-fixture-1" || message["text"] != "redacted fixture" || message["subject"] != "VERIFY_FIXTURE" {
fail("fixture/assert", fmt.Errorf("unexpected message: %#v", message))
}
if message["conversation_id"] != "sender@imopenfire1-lanzhou|receiver@imopenfire1-lanzhou" {
if message["conversation_id"] != "project-room@conference.imopenfire1-lanzhou|sender@imopenfire1-lanzhou" {
fail("fixture/assert", fmt.Errorf("conversation_id = %#v", message["conversation_id"]))
}
contactCount := verifySearchContacts(ctx, session, "sender", "fixture/call isphere_search_contacts", 1)
return len(messagesValue), contactCount
groupCount := verifySearchGroups(ctx, session, "project", "fixture/call isphere_search_groups", 1)
return len(messagesValue), contactCount, groupCount
}
func verifySearchContacts(ctx context.Context, session *mcp.ClientSession, query string, step string, wantCount int) int {
@@ -346,6 +352,42 @@ func verifySearchContacts(ctx context.Context, session *mcp.ClientSession, query
return len(contactsValue)
}
func verifySearchGroups(ctx context.Context, session *mcp.ClientSession, query string, step string, wantCount int) int {
callResult, err := session.CallTool(ctx, &mcp.CallToolParams{Name: "isphere_search_groups", Arguments: map[string]any{"query": query, "limit": 5}})
if err != nil {
fail(step, err)
}
if callResult.IsError {
fail(step, fmt.Errorf("tool returned isError=true: %#v", callResult.Content))
}
var groupsPayload map[string]any
encoded, _ := json.Marshal(callResult.StructuredContent)
if err := json.Unmarshal(encoded, &groupsPayload); err != nil {
fail(step, fmt.Errorf("decode structuredContent %s: %w", encoded, err))
}
if groupsPayload["ok"] != true {
fail(step, fmt.Errorf("ok = %#v, want true", groupsPayload["ok"]))
}
groupsValue, ok := groupsPayload["groups"].([]any)
if !ok {
fail(step, fmt.Errorf("groups missing or not array: %s", encoded))
}
if len(groupsValue) != wantCount {
fail(step, fmt.Errorf("groups count = %d, want %d: %s", len(groupsValue), wantCount, encoded))
}
if wantCount > 0 {
group, ok := groupsValue[0].(map[string]any)
if !ok {
fail(step, fmt.Errorf("group was not object: %#v", groupsValue[0]))
}
if group["group_id"] != "project-room@conference.imopenfire1-lanzhou" || group["source"] != "local_readonly" {
fail(step, fmt.Errorf("unexpected group: %#v", group))
}
}
return len(groupsValue)
}
func encryptPacketLogLineForHarness(plaintext string) (string, error) {
block, err := des.NewCipher([]byte("hyhccdtm"))
if err != nil {
@@ -394,11 +436,13 @@ func fail(step string, err error) {
Assert-True ($script:harnessJson.ok -eq $true) "SDK harness did not return ok=true"
Assert-True ($script:harnessJson.helper_name -eq "ISphereWinHelper") "SDK harness helper_name mismatch: $($script:harnessJson.helper_name)"
Assert-True ($script:harnessJson.tool_count -eq 6) "SDK harness tool_count mismatch: $($script:harnessJson.tool_count)"
Assert-True ($script:harnessJson.tool_count -eq 7) "SDK harness tool_count mismatch: $($script:harnessJson.tool_count)"
Assert-True ($script:harnessJson.receive_message_count -eq 0) "SDK harness receive_message_count mismatch: $($script:harnessJson.receive_message_count)"
Assert-True ($script:harnessJson.contact_count -eq 0) "SDK harness contact_count mismatch: $($script:harnessJson.contact_count)"
Assert-True ($script:harnessJson.group_count -eq 0) "SDK harness group_count mismatch: $($script:harnessJson.group_count)"
Assert-True ($script:harnessJson.configured_receive_message_count -eq 1) "SDK harness configured_receive_message_count mismatch: $($script:harnessJson.configured_receive_message_count)"
Assert-True ($script:harnessJson.configured_contact_count -eq 1) "SDK harness configured_contact_count mismatch: $($script:harnessJson.configured_contact_count)"
Assert-True ($script:harnessJson.configured_group_count -eq 1) "SDK harness configured_group_count mismatch: $($script:harnessJson.configured_group_count)"
[ordered]@{
ok = $true
@@ -409,8 +453,10 @@ func fail(step string, err error) {
tools = $script:harnessJson.tools
receive_message_count = $script:harnessJson.receive_message_count
contact_count = $script:harnessJson.contact_count
group_count = $script:harnessJson.group_count
configured_receive_message_count = $script:harnessJson.configured_receive_message_count
configured_contact_count = $script:harnessJson.configured_contact_count
configured_group_count = $script:harnessJson.configured_group_count
packet_log_file_configured = $script:harnessJson.packet_log_file_configured
python_runtime_required = $false
real_isphere_login_required = $false