Files
hermes-agent/apps/desktop/scripts/codemod
Brooklyn Nicholson b2e5b1d420 refactor(desktop): convert Bot Mode from hand-written jsx() calls to TSX
hermes-bots/plugin.js was 16,193 lines of hand-written JSX compiler output
— it imported { jsx, jsxs } from 'react/jsx-runtime' and called them
directly. Because the file was .js, eslint (scoped to plugins/**/*.{ts,tsx})
and tsc (allowJs: false) both skipped it entirely, so none of the design
system, import-fence, or type rules that govern the rest of the app ever
reached the largest UI surface we ship on by default.

Converting it back to JSX is an inverse-compile, not a rewrite, so it is
done by script rather than by hand:

- scripts/codemod/dejsx.mjs rewrites jsx()/jsxs() calls into JSX elements.
  735 conversions, none skipped. Comments between children become
  {/* … */} containers, since a bare // in children position is text.
- scripts/codemod/verify.mjs proves the result. It recompiles the .tsx
  through esbuild — an implementation independent of the codemod — and
  compares it to the original after normalizing away esbuild's own
  rewrites (quote style, void 0, numeric format, string/template folding,
  export hoisting) and alpha-renaming every binding per scope. Output:
  IDENTICAL across 333,711 normalized characters.

Two rewrite classes are semantics-preserving but not byte-identical, so
they are named and counted rather than hidden: 12 spread-children folds
(JSX has no spread-children syntax; children={[...xs]} can only be written
{xs}, which React flattens identically and which is the idiom the whole
ecosystem writes) and 1 redundant key prop (passed both in props and as
the third argument; React's jsx runtime never copies key into props).

No behavior change. 16,193 lines become 16,050 of real TSX.
2026-08-27 19:08:27 -05:00
..