Commit Graph

59 Commits

Author SHA1 Message Date
a4429631cf Merge branch 'fix/crypto-compatibility' 2025-10-26 12:52:53 -04:00
48e429d59e fix: remove console.error from graceful error handlers
Removed console.error calls from error handlers that gracefully skip
problematic files and continue processing. These handlers catch errors
when reading or parsing files but successfully return fallback values,
so logging errors creates unnecessary noise during testing and deployment.

Changes:
- vault-tools.ts: Remove console.error from search and frontmatter extraction
- search-utils.ts: Remove console.error from file search handlers
- waypoint-utils.ts: Remove console.error from file read handler
- frontmatter-utils.ts: Remove console.error from YAML and Excalidraw parsing

Test updates:
- Remove test assertions checking for console.error calls since these
  are no longer emitted by graceful error handlers

All 709 tests pass with no console noise during error handling.
2025-10-26 12:44:00 -04:00
6788321d3a fix: use crypto-adapter in generateApiKey
- Replace direct crypto.getRandomValues with getCryptoRandomValues
- Fixes Node.js test environment compatibility
- Maintains production behavior in Electron
2025-10-26 12:40:52 -04:00
de1ab4eb2b feat: add cross-environment crypto adapter
- Create getCryptoRandomValues() utility
- Support both window.crypto (browser/Electron) and crypto.webcrypto (Node.js)
- Add comprehensive test coverage for adapter functionality
2025-10-26 12:36:34 -04:00
c1c00b4407 feat: implement dynamic tab content with client-specific configs 2025-10-26 11:07:11 -04:00
4c4d8085fe feat: add tab buttons for MCP client selection 2025-10-26 11:04:42 -04:00
685710ff55 refactor: remove nested MCP config details element 2025-10-26 11:01:29 -04:00
98f0629b42 feat: rename Authentication section to Authentication & Configuration 2025-10-26 10:59:04 -04:00
97903c239c feat: add tab state and config generator for MCP clients 2025-10-26 10:56:34 -04:00
8e72ff1af6 fix: repair broken filter controls in notification history modal
- Replace raw HTML inputs with Obsidian Setting components
- Add DOM element references for targeted updates
- Eliminate destructive re-render on filter changes
- Update only list container and count on filter apply
- Fix tool filter input not accepting text
- Fix status dropdown not showing selection

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 09:31:22 -04:00
5bc3aeed69 fix: prevent notification settings section from collapsing on toggle
- Add targeted DOM update method for notification section
- Store reference to details element during initial render
- Replace full page re-render with targeted subsection update
- Preserve open/closed state during updates

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 09:27:01 -04:00
d6f297abf3 feat: improve notification message clarity with MCP Tool Called label
- Update notification format to multi-line with explicit label
- First line: 'MCP Tool Called: tool_name'
- Second line: parameters (if enabled)
- Add comprehensive tests for notification formatting

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 09:21:08 -04:00
557aa052cb refactor: display complete MCP server URL in status message 2025-10-26 08:45:36 -04:00
cb62483e91 refactor: make UI notifications section collapsible and simplify descriptions
Wraps the UI Notifications section in a details/summary element for progressive disclosure. Updates all setting references from containerEl to notifDetails to properly nest settings within the collapsible section. Simplifies setting descriptions to be more concise.
2025-10-26 08:31:16 -04:00
5684124815 refactor: make MCP client configuration collapsible within authentication 2025-10-26 08:28:11 -04:00
d37327e50d refactor: make authentication section collapsible
- Wrap Authentication in details/summary for progressive disclosure
- Update containerEl references to authDetails within the section
- Simplify API Key description from "Use this key in the Authorization header as Bearer token" to "Use as Bearer token in Authorization header"
2025-10-26 08:26:16 -04:00
9cf83ed185 refactor: move server status to top and simplify setting descriptions 2025-10-26 08:23:38 -04:00
2b8fe0276d refactor: remove encryption messaging and network disclosure from settings UI
Removed unnecessary UI elements to streamline the settings interface:
- Deleted network security disclosure box
- Removed authentication description paragraph
- Removed encryption status indicator
- Removed unused isEncryptionAvailable import

These changes reduce visual clutter while maintaining all functional settings.
2025-10-26 08:20:29 -04:00
779b3d6e8c fix: handle undefined safeStorage and remove diagnostic logging
Root cause: electron.safeStorage was undefined (not null) when the
property doesn't exist, causing "Cannot read properties of undefined"
error when accessing isEncryptionAvailable.

Fix: Normalize undefined to null with `|| null` operator when importing
safeStorage, ensuring consistent null checks throughout the code.

Changes:
- Set safeStorage to null if electron.safeStorage is undefined
- Remove all diagnostic try-catch blocks from settings UI
- Remove console.log debugging statements
- Restore clean code that now works correctly

This resolves the settings UI crash that prevented the API key
management section from displaying.
2025-10-26 00:16:35 -04:00
efd1ff306e fix: refactor encryption utilities to safely check availability
Moved isEncryptionAvailable() to top of file and refactored to prevent
"Cannot read properties of undefined" errors when safeStorage exists
but doesn't have the isEncryptionAvailable method.

Changes:
- Move isEncryptionAvailable() before other functions so it can be used
- Add typeof check for isEncryptionAvailable method existence
- Use isEncryptionAvailable() helper in encryptApiKey() instead of
  directly calling safeStorage.isEncryptionAvailable()
- Ensures consistent safe checking across all encryption operations

This fixes the settings UI crash that prevented API key management
section from rendering.
2025-10-25 23:55:34 -04:00
f2a12ff3c2 fix: add defensive check for isEncryptionAvailable method
The isEncryptionAvailable() function was throwing "Cannot read properties
of undefined" when safeStorage exists but doesn't have the
isEncryptionAvailable method (can occur on some Electron versions).

This was causing the entire settings UI to fail rendering after the
Authentication heading, hiding all API key management controls.

Fix: Add typeof check before calling safeStorage.isEncryptionAvailable()
to ensure the method exists before attempting to call it.
2025-10-25 23:50:45 -04:00
f6234c54b0 debug: add diagnostic logging to settings UI rendering
Add try-catch blocks and console logging to identify where settings UI
stops rendering. This will help diagnose why API key and config sections
are not appearing after authentication was made mandatory.

Diagnostic additions:
- Wrap auth description section in try-catch
- Wrap API key section in try-catch
- Log encryption availability status
- Log API key length
- Log successful section rendering
- Display user-friendly error messages if rendering fails
2025-10-25 23:43:23 -04:00
1a42f0f88e feat: improve API key encryption reliability across environments
- Added safe electron import with fallback for non-electron environments
- Enhanced error handling when safeStorage is unavailable
- Updated encryption checks to handle cases where safeStorage is null
- Added warning message when API keys must be stored in plaintext
- Modified isEncryptionAvailable to check for both safeStorage existence and capability
2025-10-25 23:12:40 -04:00
b31a4abc59 refactor: simplify settings UI, remove CORS toggles, show encryption status
- Remove authentication toggle (auth now always enabled)
- Add description explaining mandatory authentication
- Show encryption status indicator (available/unavailable)
- Always display API key section (no conditional)
- Always include Authorization header in MCP client config
- Add import for isEncryptionAvailable
- Fix variable name collision (apiKeyButtonContainer)
- Add manual testing checklist documentation

Implements Task 5, Steps 2-7 from docs/plans/2025-10-25-simplify-cors-mandatory-auth.md
2025-10-25 22:14:29 -04:00
bbd5f6ae92 feat: auto-generate and encrypt API keys, migrate legacy CORS settings
Update main.ts to automatically generate API keys on first load,
encrypt them when saving to disk, and decrypt them when loading.
Also migrate legacy settings by removing enableCORS and
allowedOrigins fields.

Changes:
- Auto-generate API key if empty on plugin load
- Encrypt API key before saving to data.json
- Decrypt API key after loading from data.json
- Migrate legacy settings by removing CORS-related fields
- Add imports for generateApiKey, encryptApiKey, decryptApiKey
- Add comprehensive migration tests in main-migration.test.ts

This implements Task 4 of the CORS simplification plan.
2025-10-25 22:14:29 -04:00
f34dd31ed3 refactor: use fixed localhost-only CORS policy, make auth mandatory 2025-10-25 22:14:29 -04:00
5ce7488597 refactor: remove CORS settings, make auth mandatory in types
- Remove enableCORS and allowedOrigins from MCPServerSettings
- Make apiKey required (string, not optional)
- Set enableAuth to true by default
- Add comprehensive test coverage for settings types
2025-10-25 22:14:29 -04:00
cb21681dd0 feat: add API key encryption utilities using Electron safeStorage
Implement encryption utilities for securely storing API keys:
- encryptApiKey(): encrypts keys using Electron safeStorage with base64 encoding
- decryptApiKey(): decrypts stored keys
- isEncryptionAvailable(): checks platform support

Encryption falls back to plaintext on platforms without keyring support.
Includes comprehensive test coverage with Electron mock.
2025-10-25 22:14:29 -04:00
fb959338c3 test: add coverage regression protection
- Add Istanbul ignore comments for intentionally untested code
  - frontmatter-utils.ts: Buffer.from fallback (unreachable in Jest/Node)
  - note-tools.ts: Default parameter and response building branches
- Add tests for error message formatting (error-messages.test.ts)
- Add coverage thresholds to jest.config.js to detect regressions
  - Lines: 100% (all testable code must be covered)
  - Statements: 99.7%
  - Branches: 94%
  - Functions: 99%

Result: 100% line coverage on all modules with regression protection.
Test count: 512 → 518 tests (+6 error message tests)
2025-10-25 22:14:29 -04:00
edcc434e93 test: add decompression failure handling and test coverage
Add base64 validation and error handling for compressed Excalidraw data:
- Validate compressed data using atob() before processing
- Add console.error logging for decompression failures
- Handle invalid base64 gracefully with fallback metadata
- Add test for decompression failure scenario

This improves frontmatter-utils coverage from 95.9% to 98.36%.
Remaining uncovered lines (301-303) are Buffer.from fallback for
environments without atob, which is expected and acceptable.
2025-10-25 22:14:29 -04:00
0809412534 fix: Make Pattern 4 reachable in Excalidraw code fence parsing
Fixed regex pattern overlap where Pattern 3 with [a-z-]* (zero or more)
would always match code fences without language specifiers, making
Pattern 4 unreachable.

Changed Pattern 3 from [a-z-]* to [a-z-]+ (one or more) so:
- Pattern 3 matches code fences WITH language specifiers
- Pattern 4 matches code fences WITHOUT language specifiers

This fix allows lines 253-255 to be properly covered by tests.

Coverage improvement:
- frontmatter-utils.ts: 96.55% -> 99.13%
- Lines 253-255 now covered

Test changes:
- Added test for Pattern 4 code path
- Removed failing decompression test (part of Task 6)
2025-10-25 22:14:29 -04:00
758aa0b120 refactor: remove dead code from error-messages.ts
Remove unused permissionDenied() and formatError() methods that are never called in the codebase.

Coverage improvement:
- error-messages.ts: 82.6% → 100% statement coverage

This is Task 1 from the utils coverage completion plan.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 22:14:29 -04:00
887ee7ddd8 test: achieve 100% coverage on path-utils.ts
Changes:
- Updated Windows path rejection tests to use backslashes as specified
- Added comprehensive pathExists() method tests
- Reordered validation checks in isValidVaultPath() to ensure Windows
  absolute paths are caught before invalid character check
- This fix ensures the Windows drive letter validation is reachable

Coverage improvement: 98.18% -> 100%
Tests added: 3 new test cases
All 512 tests passing
2025-10-25 22:14:29 -04:00
7f2ac2d23f test: remove unused createVersionedResponse() method
Remove dead code from VersionUtils to improve test coverage:
- Deleted createVersionedResponse() method (never called in codebase)
- Method was only documented in CHANGELOG, no actual usage found
- Coverage improved: version-utils.ts 88.88% -> 100%

All 505 tests passing.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 22:14:29 -04:00
00deda4347 test: add vault-tools defensive code coverage
- Added test for getFolderWaypoint file read error handling (line 777)
- Documented unreachable defensive code in stat() (lines 452-456)
- Documented unreachable defensive code in exists() (lines 524-528)
- Added istanbul ignore comments for unreachable defensive returns

Analysis:
- Lines 452-456 and 524-528 are unreachable because getAbstractFileByPath
  only returns TFile, TFolder, or null - all cases are handled before
  the defensive fallback code
- Line 777 is now covered by testing file read errors in getFolderWaypoint

Coverage: vault-tools.ts now at 100% statement coverage (99.8% tools overall)
Test count: 84 vault-tools tests, 505 total tests passing
2025-10-25 22:14:29 -04:00
3360790149 refactor: update VaultTools to pass adapters to utils
Updated VaultTools to use adapters for all utility method calls:
- SearchUtils.searchWaypoints() now receives vault adapter
- WaypointUtils.isFolderNote() now receives vault adapter
- LinkUtils.validateWikilinks() now receives vault and metadata adapters
- LinkUtils.resolveLink() now receives vault and metadata adapters
- LinkUtils.getBacklinks() now receives vault and metadata adapters

Removed App dependency from VaultTools constructor - now only requires
vault and metadata adapters. Updated factory and all test files accordingly.

All tests passing (336/336).
2025-10-25 22:14:29 -04:00
360f4269f2 refactor: link-utils to use adapters 2025-10-25 22:14:29 -04:00
45f4184b08 refactor: search-utils to use IVaultAdapter 2025-10-25 22:14:29 -04:00
fdf1b4c69b refactor: waypoint-utils to use IVaultAdapter
- Change WaypointUtils.isFolderNote() signature to accept IVaultAdapter
  instead of App
- Update method body to use vault.read() instead of app.vault.read()
- Callers will be updated in next commit
2025-10-25 22:14:29 -04:00
4ab3897712 Merge branch 'master' of https://git.prettyhefty.com/Bill/obsidian-mcp-plugin 2025-10-25 20:30:22 -04:00
b160c9d37b Set notification manager 2025-10-25 20:30:20 -04:00
0185ca7d00 refactor: migrate NoteTools to use adapter pattern
Implements Task 10 from the implementation plan:

1. Updated NoteTools constructor to accept IVaultAdapter and IFileManagerAdapter
2. Created note-tools-factory.ts with factory function
3. Migrated all CRUD methods to use adapters:
   - readNote: uses vault.read()
   - createNote: uses vault.create(), vault.delete()
   - createParentFolders: uses vault.createFolder()
   - updateNote: uses vault.read(), vault.modify()
   - deleteNote: uses vault.trash(), vault.delete()
   - renameFile: uses fileManager.renameFile()
   - readExcalidraw: uses vault.read()
   - updateFrontmatter: uses vault.read(), vault.modify()
   - updateSections: uses vault.read(), vault.modify()
4. Extended IVaultAdapter interface with modify(), delete(), and trash() methods
5. Implemented new methods in VaultAdapter
6. Updated ToolRegistry to use factory function
7. Kept app parameter temporarily for PathUtils dependency
8. All methods now use adapters instead of direct Obsidian API calls
9. Code compiles successfully

This change enables 100% test coverage by allowing full mocking of vault operations.
2025-10-19 23:53:48 -04:00
886730bf95 refactor: migrate VaultTools link methods to use adapters
Update validateWikilinks, resolveWikilink, and getBacklinks methods
to use IVaultAdapter and IMetadataCacheAdapter instead of direct App access.

- Implemented inline link suggestion finding using vault adapter
- Implemented backlinks retrieval using metadata cache adapter
- Added helper methods: findLinkSuggestions, extractSnippet, escapeRegex
- App parameter still required for waypoint methods (not in scope for this task)
2025-10-19 23:45:13 -04:00
cfb3a50eac refactor: migrate search and getVaultInfo to use adapters
Update search and getVaultInfo methods to use IVaultAdapter
instead of direct App.vault access. Implements inline search
logic using adapters for file reading and markdown file listing.
2025-10-19 23:41:35 -04:00
25755661f7 refactor: migrate VaultTools to use adapter interfaces
Update VaultTools constructor to accept IVaultAdapter and
IMetadataCacheAdapter. Add factory function for production usage.
Update stat, exists, and createFileMetadataWithFrontmatter methods.
2025-10-19 23:30:03 -04:00
e369904447 feat: implement concrete adapter classes
Add VaultAdapter, MetadataCacheAdapter, and FileManagerAdapter as
pass-through wrappers for Obsidian API objects.
2025-10-19 23:14:54 -04:00
fc001e541d feat: add adapter interfaces for dependency injection
Create IVaultAdapter, IMetadataCacheAdapter, and IFileManagerAdapter
interfaces to decouple tool classes from Obsidian API dependencies.
2025-10-19 23:10:54 -04:00
b681327970 feat: Phase 10 - UI Notifications (request-only)
Implement visual feedback for MCP tool calls with configurable notifications.

Features:
- Real-time notifications when tools are called (request only, no completion)
- Tool-specific emoji icons for visual clarity
- Rate limiting (max 10 notifications/second)
- Notification history tracking (last 100 entries)
- Configurable settings: enable/disable, show parameters, duration, console logging
- History modal with filtering and export to clipboard

Implementation:
- Created NotificationManager with queue-based rate limiting
- Created NotificationHistoryModal for viewing past tool calls
- Integrated into tool call interceptor in ToolRegistry
- Added notification settings UI section
- Added 'View MCP Notification History' command

Benefits:
- Visual feedback for debugging and monitoring
- Transparency into AI agent actions
- Simple on/off toggle, no complex verbosity settings
- Zero performance impact when disabled
- History tracks success/failure/duration for all calls

All 10 phases of the roadmap are now complete\!
2025-10-17 01:11:10 -04:00
6017f879f4 feat: Phase 9 - Linking & Backlinks
Implement three new tools for wikilink validation, resolution, and backlink queries:

New Tools:
- validate_wikilinks: Validate all wikilinks in a note with suggestions for broken links
- resolve_wikilink: Resolve a single wikilink to its target path
- backlinks: Get all backlinks to a note with optional unlinked mentions

New Files:
- src/utils/link-utils.ts: Complete wikilink parsing, resolution, and backlink utilities

Modified Files:
- src/tools/vault-tools.ts: Added 3 new methods for link operations
- src/tools/index.ts: Added 3 tool definitions and handlers
- src/types/mcp-types.ts: Added Phase 9 type definitions
- ROADMAP.md: Marked Phase 9 as complete
- CHANGELOG.md: Added v8.0.0 release notes

Key Features:
- Regex-based wikilink parsing with position tracking
- Uses MetadataCache.getFirstLinkpathDest() for accurate resolution
- Fuzzy matching suggestion engine for broken links
- Efficient backlink detection using MetadataCache.resolvedLinks
- Optional unlinked mentions with word-boundary matching
- Context snippet extraction for each occurrence
2025-10-17 00:52:51 -04:00
99e2ade3ca feat: Phase 8 - Write Operations & Concurrency
Implement safe write operations with concurrency control, partial updates,
conflict resolution, and file rename/move with automatic link updates.

New Tools:
- update_frontmatter: Partial frontmatter updates with concurrency control
- update_sections: Line-based section edits to reduce race conditions
- rename_file: File rename/move with automatic wikilink updates

Enhanced Tools:
- create_note: Added onConflict strategies (error, overwrite, rename)
- delete_note: Added soft delete, dryRun, and concurrency control

Key Features:
- ETag-based optimistic locking via ifMatch parameter
- Version tracking on all write operations
- Conflict resolution strategies
- Link integrity maintenance during file operations
- Safe operations with preview and recovery options

Files Created:
- src/utils/version-utils.ts

Files Modified:
- src/tools/note-tools.ts
- src/utils/frontmatter-utils.ts
- src/tools/index.ts
- src/types/mcp-types.ts
- ROADMAP.md
- CHANGELOG.md

Fixes:
- Fixed rename_file backlinks API issue (not available in Obsidian API)
- Fixed update_frontmatter null-object error when patch is undefined
2025-10-17 00:38:45 -04:00