Skip to content

Add fullscreen difit integration#1354

Closed
mulyoved wants to merge 5 commits intopingdotgg:mainfrom
mulyoved:feat/difit-fullscreen
Closed

Add fullscreen difit integration#1354
mulyoved wants to merge 5 commits intopingdotgg:mainfrom
mulyoved:feat/difit-fullscreen

Conversation

@mulyoved
Copy link

@mulyoved mulyoved commented Mar 24, 2026

Summary

  • add fullscreen difit integration backed by an external managed process and same-origin proxy
  • add Alt+G, Escape, and a floating back button for entering and leaving fullscreen diff
  • restore /restart-t3code as a project prompt that rebuilds/restarts the PM2-managed app

Implementation

  • add apps/server/src/difitManager.ts and apps/server/src/difitProxy.ts for process lifecycle and proxying
  • wire difit.open into server/web contracts and websocket/native API handling
  • add apps/web/src/routes/difit.$threadId.tsx for the fullscreen route
  • add the difit.toggle keybinding and browser/unit coverage for the shortcut flow
  • add a PM2-aware rebuild/restart helper script and project prompt

Closes #1353


Note

High Risk
High risk because it introduces new process-spawning/proxying logic (difit) and a dynamic plugin loading/runtime path (server file watchers + web import()), both of which can affect stability, security boundaries, and request handling.

Overview
Adds a new fullscreen diff viewer flow backed by a managed difit subprocess on the server and a same-origin proxy (/__difit/:sessionRevision/...), exposed via a new difit.open websocket/native API and a new web route '/difit/$threadId' with Alt+G/Escape navigation.

Introduces a manifest-driven plugin host (new t3-plugin.json discovery, hot-reload, typed server procedures, and web bundle serving at /__plugins/:id/web.js) plus a web runtime (PluginHostProvider, PluginSlot, composer item providers) to let plugins contribute UI slots and composer commands/skills.

Expands contracts to include plugin, skill, prompt, and difit schemas; wires new plugins.*, skills.list, and prompts.list websocket methods; updates composer/keybinding logic (including alt-key code handling) and adds tests/fixtures; and restores the /restart-t3code project prompt plus a repo-level rebuild:restart script entry.

Written by Cursor Bugbot for commit 21bc4f3. This will update automatically on new commits. Configure here.

Note

Add fullscreen difit integration with plugin host, skills, and composer slash-command support

  • Adds a fullscreen difit route at /difit/$threadId that opens a difit session via a new api.difit.open WebSocket method, displays it in a sandboxed iframe, and supports closing via Escape or the difit.toggle keybinding (Alt+G).
  • Introduces a reverse proxy in difitProxy.ts that forwards /__difit/<sessionRevision>/... requests to a loopback difit server, with on-the-fly HTML/JS/CSS URL rewriting and a client-side fetch shim.
  • Adds a server-side plugin manager (manager.ts) that discovers, loads, validates, and lifecycle-manages plugins; web plugin assets are served at /__plugins/<pluginId>/web.js.
  • Adds a web-side PluginHostProvider (host.tsx) that dynamically imports enabled plugins and registers their composer providers and slot renderers into the app.
  • Extends the composer menu to support plugin-provided items, skills ($ prefix trigger), prompts, and richer slash commands with icons, badges, actions, and a live preview panel.
  • Adds skills.list and prompts.list WebSocket APIs backed by new file-system discovery modules (skills.ts, prompts.ts) that scan .codex/skills and .codex/prompts directories.
  • Risk: The difit proxy and plugin loading introduce new runtime processes and dynamic import() calls; plugin errors are isolated via PluginRenderErrorBoundary but server-side plugin failures may affect procedure routing.

Macroscope summarized 21bc4f3.

@coderabbitai
Copy link

coderabbitai bot commented Mar 24, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 49844b92-12f3-49d3-a9c2-bedecb0ae7a7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@github-actions github-actions bot added size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Mar 24, 2026
@mulyoved mulyoved closed this Mar 24, 2026
Copy link
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

return () => {
cancelled = true;
};
}, [api, iframeSrc, navigate, search.sessionRevision, thread, thread?.worktreePath, threadId]);
Copy link
Contributor

Choose a reason for hiding this comment

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

Effect dependency on iframeSrc causes redundant API call

Medium Severity

The useEffect that calls api.difit.open() includes iframeSrc in its dependency array. When the open call succeeds, it calls setIframeSrc(result.proxyPath) which triggers a re-render. Since iframeSrc changed, the effect re-runs, making a second redundant difit.open() call (which spawns/reuses an external process). The second call is functionally harmless because the server reuses the active process, but it doubles API calls and introduces unnecessary latency on every difit open. The iframeSrc comparison inside the .then() callback captures a stale closure value anyway, so it doesn't need to be a dependency — a ref would avoid the re-trigger.

Fix in Cursor Fix in Web

next.push(value);
}
return next;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Duplicated dedupeBy utility across skills and prompts

Low Severity

The dedupeBy generic helper function is identically defined in both skills.ts and prompts.ts. Similarly, extractFrontmatterValue is duplicated across both files with the same implementation. These are general-purpose utilities that belong in a shared module to avoid inconsistent bug fixes if either copy is updated independently.

Additional Locations (1)
Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add fullscreen difit integration

1 participant