mirror of
https://github.com/samsonjs/Peekaboo.git
synced 2026-04-27 15:07:41 +00:00
feat: Enhanced error messages for ambiguous app identifiers
- Error messages now include the list of matching applications when multiple apps match an identifier
- Shows bundle IDs alongside app names to help users disambiguate (e.g., Calendar (com.apple.iCal))
- Applies to both image and list tools for consistent user experience
- Added comprehensive tests for error detail handling
This makes it much easier for users to understand which specific application to target when there are multiple matches.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
dbb68e4294
commit
2676decf51
5 changed files with 105 additions and 3 deletions
|
|
@ -16,6 +16,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Invalid format values now automatically fall back to PNG instead of returning an error
|
- Invalid format values now automatically fall back to PNG instead of returning an error
|
||||||
- Empty strings, null values, and unrecognized format values are converted to PNG
|
- Empty strings, null values, and unrecognized format values are converted to PNG
|
||||||
- This provides a better user experience by gracefully handling invalid inputs
|
- This provides a better user experience by gracefully handling invalid inputs
|
||||||
|
- Enhanced error messages for ambiguous application identifiers
|
||||||
|
- When multiple applications match an identifier (e.g., "C" matches Calendar, Console, and Cursor), the error message now lists all matching applications with their bundle IDs
|
||||||
|
- This helps users quickly identify the correct application name to use
|
||||||
|
- Applies to both `image` and `list` tools
|
||||||
|
|
||||||
## [1.0.0-beta.18] - 2025-06-08
|
## [1.0.0-beta.18] - 2025-06-08
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,11 +63,17 @@ export async function imageToolHandler(
|
||||||
{ error: swiftResponse.error },
|
{ error: swiftResponse.error },
|
||||||
"Swift CLI returned error for image capture",
|
"Swift CLI returned error for image capture",
|
||||||
);
|
);
|
||||||
|
const errorMessage = swiftResponse.error?.message || "Unknown error";
|
||||||
|
const errorDetails = swiftResponse.error?.details;
|
||||||
|
const fullErrorMessage = errorDetails
|
||||||
|
? `${errorMessage}\n${errorDetails}`
|
||||||
|
: errorMessage;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
text: `Image capture failed: ${swiftResponse.error?.message || "Unknown error"}`,
|
text: `Image capture failed: ${fullErrorMessage}`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
isError: true,
|
isError: true,
|
||||||
|
|
|
||||||
|
|
@ -119,11 +119,17 @@ export async function listToolHandler(
|
||||||
|
|
||||||
if (!swiftResponse.success) {
|
if (!swiftResponse.success) {
|
||||||
logger.error({ error: swiftResponse.error }, "Swift CLI returned error");
|
logger.error({ error: swiftResponse.error }, "Swift CLI returned error");
|
||||||
|
const errorMessage = swiftResponse.error?.message || "Unknown error";
|
||||||
|
const errorDetails = swiftResponse.error?.details;
|
||||||
|
const fullErrorMessage = errorDetails
|
||||||
|
? `${errorMessage}\n${errorDetails}`
|
||||||
|
: errorMessage;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: "text" as const,
|
type: "text" as const,
|
||||||
text: `List operation failed: ${swiftResponse.error?.message || "Unknown error"}`,
|
text: `List operation failed: ${fullErrorMessage}`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
isError: true,
|
isError: true,
|
||||||
|
|
|
||||||
|
|
@ -1142,4 +1142,62 @@ describe("Image Tool", () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("imageToolHandler - Error message handling", () => {
|
||||||
|
it("should include error details for ambiguous app identifier", async () => {
|
||||||
|
// Mock resolveImagePath
|
||||||
|
mockResolveImagePath.mockResolvedValue({
|
||||||
|
effectivePath: MOCK_TEMP_IMAGE_DIR,
|
||||||
|
tempDirUsed: MOCK_TEMP_IMAGE_DIR,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mock Swift CLI returning ambiguous app error with details
|
||||||
|
mockExecuteSwiftCli.mockResolvedValue({
|
||||||
|
success: false,
|
||||||
|
error: {
|
||||||
|
message: "Multiple applications match identifier 'C'. Please be more specific.",
|
||||||
|
code: "AMBIGUOUS_APP_IDENTIFIER",
|
||||||
|
details: "Matches found: Calendar (com.apple.iCal), Console (com.apple.Console), Cursor (com.todesktop.230313mzl4w4u92)"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await imageToolHandler(
|
||||||
|
{ app_target: "C" },
|
||||||
|
mockContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.isError).toBe(true);
|
||||||
|
expect(result.content[0].type).toBe("text");
|
||||||
|
// Should include both the main message and the details
|
||||||
|
expect(result.content[0].text).toContain("Multiple applications match identifier 'C'");
|
||||||
|
expect(result.content[0].text).toContain("Matches found: Calendar (com.apple.iCal), Console (com.apple.Console), Cursor (com.todesktop.230313mzl4w4u92)");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should handle errors without details gracefully", async () => {
|
||||||
|
// Mock resolveImagePath
|
||||||
|
mockResolveImagePath.mockResolvedValue({
|
||||||
|
effectivePath: MOCK_TEMP_IMAGE_DIR,
|
||||||
|
tempDirUsed: MOCK_TEMP_IMAGE_DIR,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mock Swift CLI returning error without details
|
||||||
|
mockExecuteSwiftCli.mockResolvedValue({
|
||||||
|
success: false,
|
||||||
|
error: {
|
||||||
|
message: "Application not found",
|
||||||
|
code: "APP_NOT_FOUND"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await imageToolHandler(
|
||||||
|
{ app_target: "NonExistent" },
|
||||||
|
mockContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.isError).toBe(true);
|
||||||
|
expect(result.content[0].type).toBe("text");
|
||||||
|
// Should only include the main message
|
||||||
|
expect(result.content[0].text).toBe("Image capture failed: Application not found");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -288,7 +288,7 @@ describe("List Tool", () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(result.isError).toBe(true);
|
expect(result.isError).toBe(true);
|
||||||
expect(result.content[0].text).toBe(
|
expect(result.content[0].text).toBe(
|
||||||
"List operation failed: The specified application ('Ciursor') is not running or could not be found."
|
"List operation failed: The specified application ('Ciursor') is not running or could not be found.\nError: Application with name 'Ciursor' not found."
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -865,4 +865,32 @@ describe("List Tool", () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("listToolHandler - Error message handling", () => {
|
||||||
|
it("should include error details for ambiguous app identifier", async () => {
|
||||||
|
// Mock Swift CLI returning ambiguous app error with details
|
||||||
|
mockExecuteSwiftCli.mockResolvedValue({
|
||||||
|
success: false,
|
||||||
|
error: {
|
||||||
|
message: "Multiple applications match identifier 'C'. Please be more specific.",
|
||||||
|
code: "AMBIGUOUS_APP_IDENTIFIER",
|
||||||
|
details: "Matches found: Calendar (com.apple.iCal), Console (com.apple.Console), Cursor (com.todesktop.230313mzl4w4u92)"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await listToolHandler(
|
||||||
|
{
|
||||||
|
item_type: "application_windows",
|
||||||
|
app: "C"
|
||||||
|
},
|
||||||
|
mockContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.isError).toBe(true);
|
||||||
|
expect(result.content[0].type).toBe("text");
|
||||||
|
// Should include both the main message and the details
|
||||||
|
expect(result.content[0].text).toContain("Multiple applications match identifier 'C'");
|
||||||
|
expect(result.content[0].text).toContain("Matches found: Calendar (com.apple.iCal), Console (com.apple.Console), Cursor (com.todesktop.230313mzl4w4u92)");
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue