Skip to content

fix(file-preview): attribute events to source tools#479

Open
edgarsskore wants to merge 2 commits into
mainfrom
chore/event-adjustments
Open

fix(file-preview): attribute events to source tools#479
edgarsskore wants to merge 2 commits into
mainfrom
chore/event-adjustments

Conversation

@edgarsskore
Copy link
Copy Markdown
Collaborator

@edgarsskore edgarsskore commented May 24, 2026

File preview UI events were always reported as read_file, which hid whether the preview came from write_file or edit_block. Carry sourceTool through structured content so analytics reflects the initiating tool.

Move default editor detection out of the browser UI and onto the server as a lazy cached lookup. This avoids repeated hidden start_process/osascript calls from the preview and keeps command execution in server code.

Summary by CodeRabbit

  • New Features

    • Automatic detection of the system default editor on macOS.
    • File operations now record their source (read, write, edit) in previews.
  • Improvements

    • Event telemetry now includes source operation information for better analytics.
    • File preview app preserves and uses incoming editor metadata when present.
  • Tests

    • Updated tests to assert source and editor metadata in file previews.

Review Change Stack

File preview UI events were always reported as read_file, which hid whether the preview came from write_file or edit_block. Carry sourceTool through structured content so analytics reflects the initiating tool.

Move default editor detection out of the browser UI and onto the server as a lazy macOS-only cached lookup. This avoids repeated hidden start_process/osascript calls from the preview and keeps command execution in server code.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 24, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 740382f7-2420-4fd0-8a3e-466023c6ff90

📥 Commits

Reviewing files that changed from the base of the PR and between 8c8f612 and 644ab1c.

📒 Files selected for processing (2)
  • src/tools/filesystem.ts
  • src/types.ts

📝 Walkthrough

Walkthrough

This PR adds sourceTool and default-editor metadata to file preview and edit responses, implements getDefaultEditorMetadata(...) (macOS osascript + cache), and updates UI wiring and telemetry to consume payload-provided editor metadata instead of performing client-side detection.

Changes

Editor metadata enrichment and refactoring

Layer / File(s) Summary
Type contract for editor metadata
src/types.ts
FilePreviewStructuredContent now includes optional sourceTool, defaultEditorName, and defaultEditorPath fields.
Default editor detection service
src/tools/filesystem.ts
Adds getDefaultEditorMetadata(filePath) (macOS osascript probe, parsing, TTL cache) and necessary Node imports.
Filesystem handler enrichment
src/handlers/filesystem-handlers.ts
handleReadFile and handleWriteFile set sourceTool (read_file/write_file) and merge getDefaultEditorMetadata(...) into structuredContent across PDF, image, and generic branches.
Edit tool enrichment
src/tools/edit.ts
performSearchReplace() and handleEditBlock() set sourceTool: 'edit_block' and merge getDefaultEditorMetadata(...) into successful edit structuredContent returns.
UI wiring refactoring and telemetry update
src/ui/file-preview/src/app.ts, src/ui/file-preview/src/host/external-actions.ts
Removes detectDefaultMarkdownEditor; seeds markdownEditorAppCache from payload defaultEditorName/defaultEditorPath, preserves incoming payload.sourceTool during resolution, and derives telemetry tool_name from payload source tool.
Test coverage for editor metadata
test/test-file-handlers.js
Adds assertions that previews set structuredContent.sourceTool (read_file/write_file) and that successful edits set edit_block; imports handleWriteFile for write-preview tests.

Sequence Diagram

sequenceDiagram
  participant Client
  participant ServerHandler
  participant getDefaultEditorMetadata
  participant StructuredContent
  participant UI
  Client->>ServerHandler: request file preview / edit
  ServerHandler->>getDefaultEditorMetadata: getDefaultEditorMetadata(filePath)
  getDefaultEditorMetadata-->>ServerHandler: { defaultEditorName?, defaultEditorPath? } or {}
  ServerHandler->>StructuredContent: set sourceTool + merge editor metadata
  StructuredContent-->>Client: return enriched payload
  Client->>UI: render payload (UI seeds cache from payload, uses sourceTool for telemetry)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

size:L

Suggested reviewers

  • wonderwhy-er
  • dmitry-ottic-ai
  • serg33v

Poem

🐰 I hopped through code with whiskers bright,
Adding where editors hid in night.
Previews now tell which tool they saw,
Edits report their editor law.
Payloads bring the answer home—no more guess-flight. 🎩

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: attributing file preview events to their source tools (read_file, write_file, edit_block) for accurate telemetry, which is the primary objective throughout the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/event-adjustments

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
src/types.ts (1)

79-79: ⚡ Quick win

Narrow sourceTool to a literal union to prevent telemetry drift.

FilePreviewStructuredContent.sourceTool is currently string, but all in-repo producers assign only 'read_file', 'write_file', or 'edit_block', so tightening the type prevents silent typos at compile time.

Proposed diff
 export interface FilePreviewStructuredContent {
   fileName: string;
   filePath: string;
   fileType: PreviewFileType;
-  sourceTool?: string;
+  sourceTool?: 'read_file' | 'write_file' | 'edit_block';
   defaultEditorName?: string;
   defaultEditorPath?: string;
   content?: string;
   imageData?: string;
   mimeType?: string;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/types.ts` at line 79, Change the FilePreviewStructuredContent.sourceTool
property from a generic string to a literal union of the allowed values to avoid
telemetry drift: replace the type of sourceTool with 'read_file' | 'write_file'
| 'edit_block' (i.e., FilePreviewStructuredContent.sourceTool?: 'read_file' |
'write_file' | 'edit_block';) so any future mistyped values fail at compile
time.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/handlers/filesystem-handlers.ts`:
- Around line 141-142: The call to getDefaultEditorMetadata currently can throw
and turn successful writeFile/append operations into failures; change enrichment
to be best-effort by wrapping each await
getDefaultEditorMetadata(resolvedFilePath) in a try/catch inside the filesystem
handler functions (e.g., where sourceTool: 'read_file' is assembled), so that on
error you log/debug the metadata error and continue returning the successful
operation result without throwing; merge metadata only if the call succeeds.
Apply this pattern to all occurrences (the blocks around the existing
getDefaultEditorMetadata calls).

In `@src/tools/edit.ts`:
- Around line 230-231: The code currently awaits
getDefaultEditorMetadata(resolvedEditPath) and if that throws the entire edit
tool returns an error even though the edit completed; wrap the metadata lookup
in a try/catch around calls that populate metadata (e.g., where sourceTool:
'edit_block' and the other two occurrences at the same pattern), and on error
log a warning and set metadata to null/{} (or omit it) so the function returns
the successful edit result; ensure you only catch errors from
getDefaultEditorMetadata and do not change the edit/mutation result handling.

In `@src/tools/filesystem.ts`:
- Around line 1062-1083: The code only writes to defaultEditorCache on
successful osascript detection, so repeated failures keep spawning
execFileAsync('osascript', ...) on every call; modify the get-default-editor
flow (use symbols defaultEditorCache, cacheKey, execFileAsync,
escapeAppleScriptString) to record and return a cached negative result when
detection fails (e.g., cache an empty metadata object or a sentinel value with
appropriate TTL) inside the try/catch path so subsequent lookups short-circuit
and avoid repeated process spawns; ensure the same cached shape is used by
callers and that successful detections continue to overwrite the negative cache
when appropriate.

---

Nitpick comments:
In `@src/types.ts`:
- Line 79: Change the FilePreviewStructuredContent.sourceTool property from a
generic string to a literal union of the allowed values to avoid telemetry
drift: replace the type of sourceTool with 'read_file' | 'write_file' |
'edit_block' (i.e., FilePreviewStructuredContent.sourceTool?: 'read_file' |
'write_file' | 'edit_block';) so any future mistyped values fail at compile
time.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 19bffc2e-d823-4a3a-82a6-cf055ede2d1b

📥 Commits

Reviewing files that changed from the base of the PR and between 9c44119 and 8c8f612.

📒 Files selected for processing (7)
  • src/handlers/filesystem-handlers.ts
  • src/tools/edit.ts
  • src/tools/filesystem.ts
  • src/types.ts
  • src/ui/file-preview/src/app.ts
  • src/ui/file-preview/src/host/external-actions.ts
  • test/test-file-handlers.js
💤 Files with no reviewable changes (1)
  • src/ui/file-preview/src/host/external-actions.ts

Comment on lines +141 to +142
sourceTool: 'read_file',
...await getDefaultEditorMetadata(resolvedFilePath),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Make editor metadata enrichment best-effort so it never flip-flops successful operations into errors.

getDefaultEditorMetadata() is optional enrichment, but it currently gates the full response. If it throws after writeFile succeeds, callers can receive an error and retry non-idempotent writes (notably append), causing duplicate content.

Proposed fix
+const safeDefaultEditorMetadata = async (filePath: string) => {
+    try {
+        return await getDefaultEditorMetadata(filePath);
+    } catch {
+        return {};
+    }
+};
...
-                    ...await getDefaultEditorMetadata(resolvedFilePath),
+                    ...await safeDefaultEditorMetadata(resolvedFilePath),
...
-                    ...await getDefaultEditorMetadata(resolvedFilePath),
+                    ...await safeDefaultEditorMetadata(resolvedFilePath),
...
-                    ...await getDefaultEditorMetadata(resolvedFilePath),
+                    ...await safeDefaultEditorMetadata(resolvedFilePath),
...
-                ...await getDefaultEditorMetadata(resolvedWritePath),
+                ...await safeDefaultEditorMetadata(resolvedWritePath),

Also applies to: 170-171, 191-192, 313-314

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/handlers/filesystem-handlers.ts` around lines 141 - 142, The call to
getDefaultEditorMetadata currently can throw and turn successful
writeFile/append operations into failures; change enrichment to be best-effort
by wrapping each await getDefaultEditorMetadata(resolvedFilePath) in a try/catch
inside the filesystem handler functions (e.g., where sourceTool: 'read_file' is
assembled), so that on error you log/debug the metadata error and continue
returning the successful operation result without throwing; merge metadata only
if the call succeeds. Apply this pattern to all occurrences (the blocks around
the existing getDefaultEditorMetadata calls).

Comment thread src/tools/edit.ts
Comment on lines +230 to +231
sourceTool: 'edit_block',
...await getDefaultEditorMetadata(resolvedEditPath),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Don’t let optional editor-metadata lookup fail successful edit operations.

These success paths perform the edit first, then await metadata. If metadata lookup fails, the tool returns an error despite a completed mutation, which can trigger duplicate retries.

Proposed fix
+const safeDefaultEditorMetadata = async (filePath: string) => {
+    try {
+        return await getDefaultEditorMetadata(filePath);
+    } catch {
+        return {};
+    }
+};
...
-                ...await getDefaultEditorMetadata(resolvedEditPath),
+                ...await safeDefaultEditorMetadata(resolvedEditPath),
...
-                        ...await getDefaultEditorMetadata(resolvedRangePath),
+                        ...await safeDefaultEditorMetadata(resolvedRangePath),
...
-                        ...await getDefaultEditorMetadata(resolvedEditRangePath),
+                        ...await safeDefaultEditorMetadata(resolvedEditRangePath),

Also applies to: 443-444, 483-484

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tools/edit.ts` around lines 230 - 231, The code currently awaits
getDefaultEditorMetadata(resolvedEditPath) and if that throws the entire edit
tool returns an error even though the edit completed; wrap the metadata lookup
in a try/catch around calls that populate metadata (e.g., where sourceTool:
'edit_block' and the other two occurrences at the same pattern), and on error
log a warning and set metadata to null/{} (or omit it) so the function returns
the successful edit result; ensure you only catch errors from
getDefaultEditorMetadata and do not change the edit/mutation result handling.

Comment thread src/tools/filesystem.ts Outdated
Narrow sourceTool to the known file-preview tool names so telemetry attribution cannot drift silently.

Cache failed default-editor detections briefly and keep getDefaultEditorMetadata best-effort so editor metadata lookup cannot repeatedly spawn osascript or break successful file operations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant