Commit graph

31 commits

Author SHA1 Message Date
Peter Steinberger
0bec93e364 Apply SwiftFormat changes for v1.0.0 release
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 20:35:27 +01:00
Peter Steinberger
1084050f18 Improve error handling 2025-06-08 20:24:46 +01:00
Peter Steinberger
17e73f12f2 Revert to AsyncParsableCommand with parse-as-library
- Remove problematic AsyncAdapter that was causing continuation leaks
- Use AsyncParsableCommand directly with @main attribute
- Add -parse-as-library flag to Package.swift to enable @main
- This fixes the Swift continuation leak issue

Note: Integration tests still timeout in CI environment, likely due to
screen capture permissions or environment differences. The CLI works
correctly when run directly.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 12:09:43 +01:00
Peter Steinberger
559349f198 Fix Swift 6 async execution with synchronous adapter
- Add AsyncAdapter.swift to bridge async/sync execution
- Change AsyncParsableCommand back to ParsableCommand
- Implement AsyncRunnable protocol for async execution
- Use DispatchSemaphore pattern for synchronous blocking
- Make ErrorBox thread-safe with @unchecked Sendable

This fixes the CLI execution issue where commands were showing help
instead of executing, by properly bridging the async/sync worlds
as required by ArgumentParser.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 11:34:53 +01:00
Peter Steinberger
c04b8e7af0 Migrate to Swift 6 with strict concurrency
- Update to swift-tools-version 6.0 and enable StrictConcurrency
- Make all data models and types Sendable for concurrency safety
- Migrate commands from ParsableCommand to AsyncParsableCommand
- Remove AsyncUtils.swift and synchronous bridging patterns
- Update WindowBounds property names to snake_case for consistency
- Ensure all error types conform to Sendable protocol
- Add comprehensive Swift 6 migration documentation

This migration enables full Swift 6 concurrency checking and data race
safety while maintaining backward compatibility with the existing API.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 11:23:10 +01:00
Peter Steinberger
50984f8dc2 Fix async concurrency issues without semaphores
- Replace problematic DispatchSemaphore usage with NSCondition-based async bridge
- Revert to ParsableCommand for compatibility while maintaining async operations
- Use CGWindowListCopyWindowInfo for sync permission checking instead of async ScreenCaptureKit
- Remove all RunLoop workarounds in favor of proper Task.runBlocking pattern
- Eliminate all deadlock sources while preserving async capture functionality
2025-06-08 10:10:04 +01:00
Peter Steinberger
40acc9669b Fix deadlock in ImageCommand by replacing semaphore with RunLoop
- Remove DispatchSemaphore usage that violated Swift concurrency rules
- Implement RunLoop-based async-to-sync bridging in runAsyncCapture()
- Convert all capture methods to async/await patterns
- Replace Thread.sleep with Task.sleep in async contexts
- Keep ParsableCommand for compatibility, avoid AsyncParsableCommand issues
- Add comprehensive tests and documentation
- Improve error handling and browser helper filtering

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 09:41:50 +01:00
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
dd680eb638 feat: Improve window title matching and error messages for URLs with ports
When users search for windows with URLs containing ports (e.g., 'http://example.com:8080'),
the system now provides much better debugging information when the window isn't found.

Key improvements:
- Enhanced window not found errors now list all available window titles
- Added specific guidance for URL-based searches (try without protocol)
- New CaptureError.windowTitleNotFound with detailed debugging info
- Comprehensive test coverage for colon parsing in app targets
- Better error messages help users understand why matching failed

Example improved error:
"Window with title containing 'http://example.com:8080' not found in Google Chrome.
Available windows: 'example.com:8080 - Google Chrome', 'New Tab - Google Chrome'.
Note: For URLs, try without the protocol (e.g., 'example.com:8080' instead of 'http://example.com:8080')."

This addresses the common issue where browsers display simplified URLs in window titles
without the protocol, making it easier for users to find the correct matching pattern.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 08:09:47 +01:00
Peter Steinberger
4afd15279c feat: Capture all windows from multiple exact app matches instead of erroring
When multiple applications have exact matches (e.g., "claude" and "Claude"), the system now:
- Captures all windows from all matching applications instead of throwing an ambiguous match error
- Maintains sequential window indices across all matched applications
- Preserves original application names in saved file metadata
- Only returns errors for truly ambiguous fuzzy matches

This provides more useful behavior for common scenarios where users have multiple apps with
similar names (different case, etc.) and want to capture windows from all of them.

Updates:
- Added `captureWindowsFromMultipleApps` method to handle multi-app capture logic
- Modified error handling in both single window and multi-window capture modes
- Updated documentation (spec.md, CHANGELOG.md) to reflect new behavior
- Comprehensive test suite covering various multiple match scenarios

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 08:00:44 +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
9837e7bea8 style: Apply SwiftFormat formatting
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:29:37 +01:00
Peter Steinberger
c6148849f8 feat: Hide window count for single-window apps (PR #6)
- Only show window count when it's not 1 in list apps output
- Extract formatApplicationList method for better testability
- Fix Swift test compatibility with new CaptureError signatures
- Add comprehensive test coverage for window count display logic

This improves readability by reducing visual clutter for the common
case of apps with single windows.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 07:07:53 +01:00
Peter Steinberger
e6b8931d91 refactor: Improve screen recording permission error detection
- Extract permission error detection into a dedicated method
- Add specific error code checks for ScreenCaptureKit and CoreGraphics
- Improve directory existence check in saveImage method
- More reliable detection of screen recording permission denials

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 06:50:38 +01:00
Peter Steinberger
e85f0c81b8 Apply SwiftFormat changes for release preparation
🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 04:37:52 +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
0c4706393e Improve output path handling 2025-06-08 03:48:33 +01:00
Peter Steinberger
c9ac341e08 style: apply SwiftFormat final formatting 2025-06-08 02:02:37 +01:00
Peter Steinberger
fbf32f8e21 Prepare for beta.14 release: comprehensive test improvements and code cleanup
- Fixed all Swift test compilation errors and SwiftLint violations
- Enhanced test host app with permission status display and CLI availability checking
- Refactored ImageCommand.swift to improve readability and reduce function length
- Updated all tests to use proper Swift Testing patterns
- Added comprehensive local testing framework for screenshot functionality
- Updated documentation with proper test execution instructions
- Applied SwiftFormat to all Swift files and achieved zero serious linting issues

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-08 02:00:44 +01:00
Peter Steinberger
94c09b1c7a Apply SwiftFormat changes 2025-06-07 22:58:07 +01:00
Peter Steinberger
de5a0cb97e Fix Screen Recording permission detection and improve error reporting
- Replace broken CGDisplayBounds check with ScreenCaptureKit API
- Add proper error handling to detect permission-related failures
- Add server_status subcommand to expose permission status via JSON
- Ensure users get clear error messages when permissions are missing

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-07 22:51: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
a1505f3469 Fix SwiftFormat trailing whitespace 2025-05-27 01:23:39 +02:00
Peter Steinberger
f6e9cbc7b9 Migrate to ScreenCaptureKit 2025-05-27 01:22:52 +02:00
Peter Steinberger
7895e1765f Add Swift 6.0 version to SwiftFormat config and apply formatting
- Specify Swift 6.0 in .swiftformat to enable all formatting features
- Apply Swift 6 formatting improvements:
  - Use shorthand optional unwrapping syntax
  - Use implicit returns in computed properties
  - Use modern Swift 6 syntax throughout

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-05-25 18:45:20 +02:00
Peter Steinberger
d07bb0fd37 swiftformat 2025-05-25 18:43:55 +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
Peter Steinberger
53ec5ef9a4 Add Swift linting and enhance image capture features
- Add SwiftLint and SwiftFormat configuration with npm scripts
- Refactor Swift code to comply with linting rules:
  - Fix identifier naming (x/y → xCoordinate/yCoordinate)
  - Extract long functions into smaller methods
  - Fix code style violations
- Enhance image capture tool:
  - Add blur detection parameter
  - Support custom image formats and quality
  - Add flexible naming patterns for saved files
- Add comprehensive integration tests for image tool
- Update documentation with new linting commands

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-05-25 18:02:39 +02:00
Peter Steinberger
6396e299be Prepare for v1.0.0-beta.3 release 2025-05-25 14:07:21 +02:00
Peter Steinberger
670e1c485a Add GitHub Actions CI workflow for Node.js builds
- Configure CI to run on macOS-latest
- Test with Node.js 20.x and 22.x
- Run npm build and tests on push/PR

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-05-25 01:25:35 +02:00
Renamed from swift-cli/Sources/peekaboo/ImageCommand.swift (Browse further)