Skip to content

Commit e2c5d6e

Browse files
committed
fix: deduplicate tool catalog entries and correct screenshot device matching
- Deduplicate tools in buildToolCatalogFromManifest when the same tool appears in multiple workflows, preventing ambiguous resolution via kebab-case MCP name lookup and non-deterministic Map overwrites - Fix screenshot window title matching to use the actual Simulator title separator (en-dash/hyphen) instead of bare space, preventing false-positives like "iPhone 15" matching "iPhone 15 Pro" - Remove dead tool-visibility.ts superseded by the predicate system
1 parent 78e31b9 commit e2c5d6e

3 files changed

Lines changed: 9 additions & 18 deletions

File tree

src/mcp/tools/ui-automation/screenshot.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ function escapeSwiftStringLiteral(value: string): string {
5959
*/
6060
function getWindowDetectionSwiftCode(deviceName: string): string {
6161
const escapedDeviceName = escapeSwiftStringLiteral(deviceName);
62-
// Use hasPrefix + boundary check to avoid matching "iPhone 15" when looking for "iPhone 15 Pro"
63-
// Window titles are formatted like "iPhone 15 Pro iOS 17.2"
62+
// Match by title separator (en-dash) to avoid "iPhone 15" matching "iPhone 15 Pro"
63+
// Window titles are formatted like "iPhone 15 Pro \u{2013} iOS 17.2"
6464
return `
6565
import Cocoa
6666
import CoreGraphics
@@ -71,8 +71,9 @@ if let wins = CGWindowListCopyWindowInfo(opts, kCGNullWindowID) as? [[String: An
7171
if let o = w[kCGWindowOwnerName as String] as? String, o == "Simulator",
7272
let b = w[kCGWindowBounds as String] as? [String: Any],
7373
let n = w[kCGWindowName as String] as? String {
74-
// Check for exact match: name starts with deviceName followed by separator or end
75-
let isMatch = n == deviceName || n.hasPrefix(deviceName + " ")
74+
// Check for exact match: name equals deviceName or is followed by the title separator
75+
// Window titles use en-dash: "iPhone 15 Pro \u{2013} iOS 17.2"
76+
let isMatch = n == deviceName || n.hasPrefix(deviceName + " \\u{2013}") || n.hasPrefix(deviceName + " -")
7677
if isMatch {
7778
print("\\(b["Width"] as? Int ?? 0),\\(b["Height"] as? Int ?? 0)")
7879
break

src/runtime/tool-catalog.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,12 @@ export async function buildToolCatalogFromManifest(opts: {
130130
// Cache imported modules to avoid re-importing the same tool
131131
const moduleCache = new Map<string, Awaited<ReturnType<typeof importToolModule>>>();
132132
const tools: ToolDefinition[] = [];
133+
const seenToolIds = new Set<string>();
133134

134135
for (const workflow of filteredWorkflows) {
135136
for (const toolId of workflow.tools) {
137+
if (seenToolIds.has(toolId)) continue;
138+
136139
const toolManifest = manifest.tools.get(toolId);
137140
if (!toolManifest) continue;
138141

@@ -154,6 +157,7 @@ export async function buildToolCatalogFromManifest(opts: {
154157
}
155158
}
156159

160+
seenToolIds.add(toolId);
157161
const cliName = getEffectiveCliName(toolManifest);
158162
tools.push({
159163
cliName,

src/utils/tool-visibility.ts

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)