Commit graph

66 commits

Author SHA1 Message Date
Peter Steinberger
d5b40c1550 feat: Implement proper frontmost window capture
Adds support for capturing the frontmost window of the frontmost application
instead of falling back to screen capture mode.

Changes:
- Added 'frontmost' case to CaptureMode enum in Swift CLI
- Implemented captureFrontmostWindow() method using NSWorkspace.shared.frontmostApplication
- Updated TypeScript to use --mode frontmost instead of defaulting to screen mode
- Added comprehensive test coverage for frontmost functionality
- Updated existing tests to reflect new behavior

The frontmost mode now:
1. Detects the currently active application
2. Captures only its frontmost window (index 0)
3. Returns a single image file with proper metadata

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 08:42:43 +01:00
Peter Steinberger
34dac65d2a fix: Handle empty string item_type parameter in list tool
Fixes issue where item_type: '' was not properly defaulting to the correct operation.
Empty strings and whitespace-only strings now fall back to the proper default logic:
- If app is provided: defaults to 'application_windows'
- If no app: defaults to 'running_applications'

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 08:33:44 +01:00
Peter Steinberger
4a2d802977 fix: Handle empty provider_config gracefully and improve case-insensitive targets
- Fix "Cannot convert undefined or null to object" error when provider_config is empty
- Make frontmost target case-insensitive (frontmost, FRONTMOST, Frontmost)
- Make window specifiers case-insensitive (WINDOW_TITLE, window_title, Window_Title)
- Add comprehensive test coverage for empty/null provider_config scenarios
- Improve error handling to prevent spread operator failures on undefined _meta

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 08:20:30 +01:00
Peter Steinberger
17dea6ad79 fix: Prevent security vulnerability from malformed app targets
Addresses critical edge case where malformed app targets with multiple leading colons
(e.g., "::::::::::::::::Finder") created empty app names that would match ALL system
processes. This could potentially expose sensitive information or cause unintended
system-wide captures.

Key improvements:
- Enhanced app target parsing to validate non-empty app names
- Added fallback logic to extract valid app names from malformed inputs
- Default to screen mode when all parts are empty (security-first approach)
- Comprehensive test coverage for edge cases
- Improved backward compatibility with hidden path parameters

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 08:16:39 +01:00
Peter Steinberger
089d96ce22 fix: Handle edge cases for invalid screen index and JSON null paths
- Invalid screen index (e.g., screen:99) now properly falls back to capturing all screens with unique filenames
- String "null" in path parameter is now correctly treated as undefined instead of literal path
- Added fallback-aware filename generation to prevent file overwrites when screen index is out of bounds
- Comprehensive test coverage for both edge cases

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:53:21 +01:00
Peter Steinberger
000da1e2c1 Fix file extension correction when format is changed
- Automatically correct file extensions when format gets preprocessed/corrected
- When invalid format like 'bmp' is provided with path ending in .bmp,
  the path is corrected to end in .png to match the actual output format
- Add Swift CLI path initialization to invalid-format-integration.test.ts
- Add conditional skipping for non-macOS platforms
- Integration tests now pass: files are created with correct .png extensions

This fixes the issue where providing format: "bmp" with path: "test.bmp"
would create a PNG file named "test.bmp", which was confusing for users.
Now it creates "test.png" to match the actual file format.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:46:32 +01:00
Peter Steinberger
ab882069b4 fix: Add defensive validation for invalid image formats with automatic PNG fallback
Implements robust handling for invalid image formats (like 'bmp', 'gif', 'webp') that bypass schema validation:

- Added defensive format validation in image tool handler
- Automatic path correction to ensure file extensions match actual format used
- Warning messages in response when format fallback occurs
- Comprehensive unit and integration test coverage for edge cases

This ensures invalid formats automatically fall back to PNG as requested, preventing
Swift CLI rejection and incorrect file extensions in output paths.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:44:17 +01:00
Peter Steinberger
977c22d37a Fix array parameter parsing for include_window_details
- Add preprocessing to handle JSON string arrays from MCP clients
- Support multiple input formats: JSON string, comma-separated, single value
- Handle empty strings and null/undefined values gracefully
- Add comprehensive test coverage for all parsing scenarios
- Fixes "Expected array, received string" error when MCP clients send JSON string arrays

This resolves the issue shown in the test screenshot where include_window_details
was sent as '["ids", "bounds", "off_screen"]' (JSON string) instead of a proper array.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:40:14 +01:00
Peter Steinberger
141502d668 style: Fix linting errors
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:29:11 +01:00
Peter Steinberger
b10253ea2e Fix tests to match new executeSwiftCli signature with timeout parameter
- Update all test assertions to expect the new three-parameter signature
- Add expect.objectContaining({ timeout: expect.any(Number) }) to all executeSwiftCli assertions
- Fixed 37 test assertions across image.test.ts, image-edge-cases.test.ts, and image-tool.test.ts
- All tests now pass (297 tests passed, 17 skipped)

This completes the integration of PR #2's timeout functionality by ensuring all tests match the new function signature.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:24:02 +01:00
Peter Steinberger
4e20e9adbd Merge PR #2: Add timeout handling to prevent test hangs
- Adds configurable timeout support via PEEKABOO_CLI_TIMEOUT env var
- Implements proper SIGTERM/SIGKILL handling for stuck processes
- Updates tests for Linux compatibility
- Fixes hanging issues when permission dialogs appear

Co-authored-by: codegen-sh[bot] <131295404+codegen-sh[bot]@users.noreply.github.com>
2025-06-08 07:13:21 +01:00
Peter Steinberger
f72799803b refactor: Remove multi-JSON parsing workaround from TypeScript
The complex JSON parsing logic that handled multiple JSON objects was only
needed because ApplicationFinder was incorrectly outputting errors directly.
Now that the root cause is fixed (ApplicationFinder only throws errors),
we can simplify the TypeScript code to just parse single JSON responses.

This makes the codebase cleaner and error handling more predictable.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:10:34 +01:00
codegen-sh[bot]
7b8b7f5fe1 Fix syntax error in peekaboo-cli.ts
- Removed duplicate catch block that was causing compilation errors
- Fixed missing closing brace in timeout handler
- Verified TypeScript tests now run correctly on Linux with Swift tests skipped
2025-06-08 06:03:49 +00:00
codegen-sh[bot]
fe9599819c Fix SIGKILL fallback bug in timeout handling
- Replace unreliable process.killed check with signal 0 test
- Use try-catch around all process.kill() calls
- Properly detect if process is still running before SIGKILL
- Fixes bug where SIGKILL was never sent to stuck processes

The process.killed property is set immediately when process.kill()
is called, regardless of actual process termination. Using signal 0
to test process existence is the correct approach.
2025-06-08 06:03:29 +00:00
codegen-sh[bot]
b80cceb541 Add timeout handling to prevent test hangs
- Add configurable timeout to executeSwiftCli (default 30s)
- Add timeout support to execPeekaboo (default 15s)
- Support PEEKABOO_CLI_TIMEOUT environment variable
- Graceful process termination with SIGTERM then SIGKILL
- Skip E2E tests in CI environments and non-macOS platforms
- Add test timeouts to vitest config (60s tests, 30s hooks)
- Update tool handlers to use appropriate timeouts
- Prevent multiple promise resolutions with isResolved flag
- Enhanced error messages for timeout scenarios
2025-06-08 06:03:29 +00:00
Peter Steinberger
e74796f7e3 fix: Handle case-insensitive format parameter and add jpeg alias
The image tool now properly handles:
- Case-insensitive format values (e.g., "PNG", "Png", "png" all work)
- "jpeg" as an alias for "jpg" format
- Invalid format values gracefully fall back to "png"

This is implemented through Zod schema preprocessing that normalizes
the format parameter before it reaches the Swift CLI, which only
accepts lowercase "png" and "jpg".

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 06:49:49 +01:00
Peter Steinberger
0301df2608 fix: Trim whitespace from app_target parameter
- Add .trim() to app_target when passing to Swift CLI
- Handles cases like "   Spotify   " correctly matching "Spotify"
- Applies to all app name formats including window specifiers

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 06:47:56 +01:00
Peter Steinberger
a10cbb59d5 style: Fix linting errors
- Removed trailing spaces
- Added curly braces for if statement

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 06:18:48 +01:00
Peter Steinberger
2676decf51 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>
2025-06-08 06:16:15 +01:00
Peter Steinberger
dbb68e4294 feat: Auto-fallback to PNG for invalid format values and screen captures
- Screen captures with format 'data' now auto-fallback to PNG to prevent stack overflow
- Invalid format values (empty strings, null, unrecognized) gracefully fall back to PNG
- Added comprehensive tests for format validation
- Updated documentation to reflect the new behavior

This provides a better user experience by handling edge cases gracefully instead of returning errors.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 06:04:09 +01:00
Peter Steinberger
2e65e000f0 fallback to png for full screen captures. 2025-06-08 06:04:09 +01:00
Peter Steinberger
30277bbf6c fix: Prevent format 'data' for screen captures to avoid stack overflow
- Screen captures now reject format: 'data' with clear error message
- Large screen images cause JavaScript stack overflow when base64 encoded
- Application window captures can still use format: 'data'
- Update tests and documentation to reflect this limitation
2025-06-08 06:04:09 +01:00
Peter Steinberger
94e966fa98 feat: Add fuzzy matching for application names
- Implement Levenshtein distance algorithm for fuzzy app name matching
- Handle common typos like "Chromee" → "Google Chrome"
- Add window-specific labels in analysis results
- Improve error messages with app name suggestions
- Fix TypeScript JSON parsing for error responses
- Update tests for new error message formats

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 05:22:58 +01:00
Peter Steinberger
b3ec918363 Improve analyze description for multiple windows 2025-06-08 05:22:58 +01:00
Peter Steinberger
57c277f4da Fix ESLint violations for release preparation
- Remove unused imports and variables
- Fix quote consistency and trailing commas
- Remove non-null assertions

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 04:37:35 +01:00
Peter Steinberger
282d00f5d9 Add auto capture focus mode and fix list tool validation
- Added new "auto" capture focus mode that intelligently brings windows to foreground only when needed
- Changed default capture_focus from "background" to "auto" for better screenshot success rates
- Fixed list tool server_status validation to allow empty include_window_details arrays
- Added comprehensive tests for new auto mode functionality
- Enhanced error messages for better user experience

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 04:31:28 +01:00
Peter Steinberger
e9e2cdb6cb Improve error handling when no windows are available 2025-06-08 04:05:52 +01:00
Peter Steinberger
17b74b4f1f accept path as silent fallback parameter 2025-06-08 04:05:13 +01:00
Peter Steinberger
76d0faef42 image + analyze keeps the temp files 2025-06-08 04:02:04 +01:00
Peter Steinberger
b8fd8870dd more lenient tool handling 2025-06-08 03:49:46 +01:00
Peter Steinberger
bc834f977a better path handling 2025-06-08 03:49:23 +01:00
Peter Steinberger
3ce1d38050 improve path resolve logic 2025-06-08 03:49:04 +01:00
Peter Steinberger
10672e57c0 Prepare v1.0.0-beta.15: Improved list tool usability and robustness
### Improved
- The list tool is now more lenient and user-friendly
- item_type parameter is now optional (defaults to 'running_applications')
- Intelligent auto-detection when app parameter is provided
- Enhanced error handling and validation

### Fixed
- Fixed crash when list tool called with empty item_type
- Improved image tool path handling for temporary files
- Better error messages and validation throughout

### Tests
- Added comprehensive test coverage for new list tool features
- Enhanced integration tests for improved scenarios
- Total test count increased from 223 to 228 tests

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 02:36:13 +01:00
Peter Steinberger
f5ad072bc8 chore: bump version to 1.0.0-beta.13 2025-06-08 01:28:12 +01:00
Peter Steinberger
b1ddf6f1b6 Enhance Swift testing framework and test coverage
- Update CI configuration to use macOS-15 runner with Xcode 16.3
- Expand test coverage with comprehensive new test suites:
  * JSONOutputTests.swift - JSON encoding/decoding and MCP compliance
  * LoggerTests.swift - Thread-safe logging functionality
  * ImageCaptureLogicTests.swift - Image capture command logic
  * TestTags.swift - Centralized test tagging system
- Improve existing tests with Swift Testing patterns and async support
- Make Logger thread-safe with concurrent dispatch queue
- Add performance, concurrency, and edge case testing
- Fix compilation issues and optimize test performance

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-07 23:57:26 +01:00
Peter Steinberger
27f229e802 Fix linting issues in peekaboo-cli.ts 2025-06-07 22:57:49 +01:00
Peter Steinberger
a491adbdf1 Enhance error handling with specific exit codes and user-friendly messages
- Add distinct exit codes for different error conditions in Swift CLI
- Map exit codes to clear, actionable error messages in Node.js server
- Replace generic "Swift CLI execution failed" with specific guidance
- Improve permission error messages to guide users to System Settings

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-07 22:44:07 +01:00
Peter Steinberger
4be8c69e77 Fix TypeScript compilation errors
- Added missing imports for ToolResponse and z in index.ts
- Added missing imports for WindowInfo and TargetApplicationInfo in list.ts
- Fixed type casting for ImageCaptureData in image.ts
- Added proper return type annotations to handlers
- Fixed content array metadata type to Record<string, unknown>
- Added const assertions for all 'text' type literals
- Fixed return types for helper functions in list.ts
- Added minItems and maxItems to JSONSchema interface

All TypeScript compilation errors resolved

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-05-27 01:10:35 +02:00
Peter Steinberger
cbecd6181d Fix all ESLint warnings
- Fixed long lines by splitting template literals
- Replaced all 'any' types with proper types:
  - Used ToolResponse type instead of any
  - Used z.ZodError for Zod validation errors
  - Created JSONSchema interface for zod-to-json-schema
  - Added ServerStatusData interface
  - Used Record<string, unknown> for metadata
  - Created ZodDefAny type for internal Zod properties
- Fixed quote style to use double quotes
- Removed trailing spaces

All ESLint issues resolved (0 errors, 0 warnings)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-05-27 01:03:36 +02:00
Peter Steinberger
b640074c33 Fix ESLint errors in image-summary.ts
- Remove unused variables target and mode
- Fix quote style to use double quotes

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-05-27 00:43:34 +02:00
Peter Steinberger
c6abc9d168 Fix test failures after refactoring
- Fix buildSwiftCliArgs import in image tests
- Update buildSwiftCliArgs to match expected behavior (capture-focus default, warning messages)
- Fix image summary builder logic to properly generate summaries
- Update server status test to match new implementation that doesn't use executeSwiftCli

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-05-27 00:42:46 +02:00
Peter Steinberger
44364221d6 Complete MCP best practices compliance and code cleanup
- Fix all critical ESLint errors (unused variables, wrong types)
- Split image.ts into smaller modules for better maintainability:
  - image-analysis.ts: AI provider analysis logic
  - image-summary.ts: Summary text generation
  - image-cli-args.ts: Swift CLI argument building
- Reduce image.ts from 472 to 246 lines
- Add proper TypeScript types throughout (reduce 'any' usage)
- Fix logger type imports and use proper Pino Logger type
- Update ESLint to ignore test files (handled by vitest)
- Clean up all trailing spaces and formatting issues
- Export buildSwiftCliArgs for test compatibility

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-05-27 00:32:54 +02:00
Peter Steinberger
54a01ecc46 Fix remaining MCP best practices compliance issues
- Add LICENSE and README.md to npm package files array
- Enhance list tool's server_status as comprehensive info command:
  - Shows MCP version, Swift CLI status and version
  - Displays system permissions (screen recording, accessibility)
  - Lists environment configuration and potential issues
  - Checks log file accessibility
- Implement dynamic version injection for Swift CLI via build script
- Add ESLint configuration (.eslintrc.json) and npm scripts
- Fix critical ESLint issues (console.error, unused imports, prefer-const)
- Add Pino fallback logic when log directory is not writable
- Update default log path to ~/Library/Logs/peekaboo-mcp.log (macOS system log directory)
- Update README to document new log path
- Add Version.swift to .gitignore (auto-generated file)
- Create Version.swift.development for local development
- Add execPeekaboo utility function for simple CLI execution

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-05-27 00:25:21 +02:00
Peter Steinberger
731b89b779 Prepare release 2025-05-27 00:21:29 +02:00
Peter Steinberger
7bf63a225c Implement missing best practices
- Add npm run inspector script for MCP inspector tool
- Synchronize Swift CLI version with package.json (1.0.0-beta.9)
- Update macOS version requirement to v14 (Sonoma) for n-1 support
- Add Swift compiler warnings check in prepare-release script
- Convert tests/setup.ts from Jest to Vitest syntax
- Update server status tests to match new format

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-05-26 23:46:03 +02:00
Peter Steinberger
eeabb3eb20 Tweak tool text 2025-05-25 22:15:13 +02:00
Peter Steinberger
cfc236153a Fix server description 2025-05-25 22:06:50 +02:00
Peter Steinberger
2ac01774b2 Tweak server status 2025-05-25 21:59:03 +02:00
Peter Steinberger
d0cdd645d3 Better tool formatting 2025-05-25 21:50:38 +02:00
Peter Steinberger
72819798ff feat: Simplify image tool API and add screen index support\n\n- MCP image tool API simplified with app_target, new format:data behavior, and automatic AI provider selection.\n- Swift CLI image command now supports --screen-index for specific display capture.\n- Updated image.ts, relevant documentation, and tests accordingly.\n- Version bumped to 1.0.0-beta.4. 2025-05-25 18:31:50 +02:00