Skip to content

fix(cli): make native modules (sharp, onnxruntime) optional + soften inspect overlap#1476

Merged
miguel-heygen merged 1 commit into
mainfrom
fix/cli-capture-sharp-p0
Jun 16, 2026
Merged

fix(cli): make native modules (sharp, onnxruntime) optional + soften inspect overlap#1476
miguel-heygen merged 1 commit into
mainfrom
fix/cli-capture-sharp-p0

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Make npx hyperframes robust for end users — standalone and inside monorepos — where the native modules sharp and onnxruntime-node can't install or load. Plus a small inspect change.

Root fix: native modules are optional, and never abort the CLI

sharp and onnxruntime-node are native modules. Their platform binaries ship as optional sub-dependencies that can fail to land on end-user installs — --omit=optional, musl/glibc, monorepo hoisting, cross-platform lockfiles, a broken npx cache. Both powered only optional commands, but both were wired as hard dependencies, so on any platform where a binary can't install, the whole CLI failed to install. Moved both to optionalDependencies (same bucket as @google/genai) so the core CLI always installs; native-accelerated paths light up only when present.

Runtime handling so a missing/unloadable binary degrades instead of crashing:

  • capture (contentExtractor.ts): sharp was imported statically (import sharp from "sharp" at module top), so a load failure threw on module import — before the inner try/catch — aborting the entire command. Now a guarded lazy await import("sharp") that degrades to skipping SVG captioning with an actionable warning. Also marked external in tsup so esbuild never bundles the native module.
  • remove-background (inference.ts): both onnxruntime-node and sharp load here and are genuinely required. The dynamic imports are now guarded to throw an actionable "install / reinstall with optional deps" error (surfaced cleanly by the command's existing try/catch) instead of a raw "Cannot find module". New unit tests assert createSession rejects with that guidance — before touching the model download — when either module is unavailable.

contactSheet.ts also uses sharp but is already behind a dynamic-import boundary wrapped in try { } catch { /* non-critical */ }, so it was never a hard-fatal path.

Net effect for npx hyperframes users: the CLI always installs; capture never aborts on sharp; remove-background fails with clear guidance when its native deps are missing; native-accelerated features work whenever the binaries are available.

inspect: content-overlap as a warning, not a blocking error

The content_overlap layout-audit check shipped as severity: "error", and the audit exits non-zero when errorCount > 0, so inspect failed for compositions that intentionally layer text. Downgraded to severity: "warning" so it still reports (and prints the data-layout-allow-overlap opt-out hint) without breaking exit codes. Reversible.

Verification

  • tsc --noEmit clean
  • full monorepo build succeeds; sharp and onnxruntime-node still resolve in-repo (optional deps install by default)
  • vitest — 116 tests pass across background-removal, capture, commands/capture, layout-audit.browser, including 2 new tests for the missing-native-module error paths
  • lint + format clean; pre-commit hooks (lint/format/typecheck/fallow/commitlint) green

@miguel-heygen miguel-heygen changed the title fix(cli): P0 regressions in 0.6.99 — capture sharp crash + inspect overlap severity fix(cli): make capture resilient to sharp load failures + soften inspect overlap to warning Jun 15, 2026
@miguel-heygen miguel-heygen force-pushed the fix/cli-capture-sharp-p0 branch 2 times, most recently from cdc70c1 to aa9fb31 Compare June 15, 2026 23:33
@miguel-heygen miguel-heygen changed the title fix(cli): make capture resilient to sharp load failures + soften inspect overlap to warning fix(cli): make native modules (sharp, onnxruntime) optional + soften inspect overlap Jun 15, 2026
…inspect overlap

Aimed at `npx hyperframes` users (standalone and inside monorepos), where the
native modules `sharp` and `onnxruntime-node` can't install or load.

## Native modules are now optional, and never abort the CLI

`sharp` and `onnxruntime-node` are native modules: their platform binaries ship
as optional sub-dependencies that can fail to land on end-user installs
(--omit=optional, musl/glibc, monorepo hoisting, cross-platform lockfiles,
broken npx cache). Both powered only optional commands, yet both were wired as
hard `dependencies`, so on any platform where a binary can't install the whole
CLI failed to install. Moved both to `optionalDependencies` (alongside
@google/genai) so the core CLI always installs; the native-accelerated paths
light up only when present.

Runtime handling so a missing/unloadable binary degrades instead of crashing:

- `capture` (`contentExtractor.ts`): sharp was a static top-level
  `import sharp from "sharp"`, so a load failure threw on module import —
  before the inner try/catch — aborting the whole command. Now a guarded lazy
  `await import("sharp")` that skips SVG captioning with an actionable warning.
  Marked `external` in tsup so esbuild never bundles the native module.

- `remove-background` (`inference.ts`): both `onnxruntime-node` and `sharp`
  are loaded here and genuinely required. The dynamic imports are now guarded
  to throw an actionable "install / reinstall with optional deps" error
  (surfaced cleanly by the command's existing try/catch) instead of a raw
  "Cannot find module". New tests assert createSession rejects with that
  guidance — before touching the model download — when either module is
  unavailable.

`contactSheet.ts` also uses sharp but is already behind a dynamic-import
boundary wrapped in try/catch, so it was never a hard-fatal path.

## inspect: content-overlap as a warning, not a blocking error

The `content_overlap` layout-audit check shipped as `severity: "error"`, and
the audit exits non-zero when `errorCount > 0`, so `inspect` failed for
compositions that intentionally layer text. Downgraded to `severity: "warning"`
so it still reports (and prints the `data-layout-allow-overlap` opt-out hint)
without breaking exit codes. Reversible.
@miguel-heygen miguel-heygen force-pushed the fix/cli-capture-sharp-p0 branch from aa9fb31 to c31a7b0 Compare June 16, 2026 00:07
@miguel-heygen miguel-heygen merged commit 8f71378 into main Jun 16, 2026
36 checks passed
@miguel-heygen miguel-heygen deleted the fix/cli-capture-sharp-p0 branch June 16, 2026 00:15
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