Natives media + system utilities
This document covers the media/system/conversion exports currently present in @oh-my-pi/pi-natives: terminal SIXEL image encoding, HTML conversion, clipboard access, token counting, macOS appearance/power helpers, and work profiling.
Implementation files
crates/pi-natives/src/sixel.rscrates/pi-natives/src/html.rscrates/pi-natives/src/clipboard.rscrates/pi-natives/src/tokens.rscrates/pi-natives/src/appearance.rscrates/pi-natives/src/power.rscrates/pi-natives/src/prof.rscrates/pi-natives/src/task.rspackages/natives/native/index.d.ts
There is no native PhotonImage class, image.rs, or ProjFS overlay helper module in the current pi-natives addon. General-purpose image decode/resize/encode is expected to live outside this native surface; the native image export here is only terminal SIXEL encoding.
JS API ↔ Rust export/module mapping
| JS export | Rust N-API export | Rust module |
|---|---|---|
encodeSixel(bytes, width, height) |
encode_sixel |
sixel.rs |
htmlToMarkdown(html, options?) |
html_to_markdown |
html.rs |
copyToClipboard(text) |
copy_to_clipboard |
clipboard.rs |
readImageFromClipboard() |
read_image_from_clipboard |
clipboard.rs |
countTokens(input, encoding?) |
count_tokens |
tokens.rs |
detectMacOSAppearance() |
detect_mac_os_appearance |
appearance.rs |
MacAppearanceObserver.start(cb) |
MacAppearanceObserver::start |
appearance.rs |
MacOSPowerAssertion.start(options?) |
MacOSPowerAssertion::start |
power.rs |
getWorkProfile(lastSeconds) |
get_work_profile |
prof.rs |
Data format boundaries and conversions
SIXEL image encoding (sixel)
- JS input boundary:
Uint8Arraycontaining encoded image bytes. - Rust decode boundary: format is guessed with
ImageReader::with_guessed_format(), then decoded toDynamicImage. - Resize boundary: image is resized with
resize_exact(..., FilterType::Lanczos3)only when source dimensions differ fromtargetWidthPx/targetHeightPx. - Output boundary:
encodeSixel(...)returns a SIXEL escape string synchronously.
Supported decode formats are whatever the compiled image crate supports for ImageReader in this build (commonly PNG/JPEG/WebP/GIF). Invalid target dimensions (0 width or height) fail with Target SIXEL dimensions must be greater than zero.
HTML conversion (html)
- JS input boundary: HTML
string+ optional{ cleanContent?: boolean; skipImages?: boolean }. - Rust conversion boundary: conversion is scheduled through
task::blocking("html_to_markdown", (), ...); there is no timeout/abort option on this export. - Output boundary: Markdown
stringpromise.
Conversion behavior:
cleanContentdefaults tofalse.- When
cleanContent=true, preprocessing is enabled withPreprocessingPreset::Aggressive,remove_navigation=true, andremove_forms=true. skipImagesdefaults tofalseand is passed tohtml_to_markdown_rs::ConversionOptions.
Clipboard (clipboard)
copyToClipboard(text)is a synchronous native call usingarboard::Clipboard::set_text.readImageFromClipboard()runs intask::blocking("clipboard.read_image", (), ...).- Image read returns
null/undefinedwhenarboardreportsContentNotAvailable. - Successful image read converts clipboard RGBA data into PNG bytes and returns
{ data: Uint8Array, mimeType: "image/png" }. - Clipboard access or image encoding failures reject/throw as native errors.
There is no current packages/natives TS wrapper that emits OSC52, handles Termux, or suppresses native clipboard failures. Any best-effort clipboard policy must live in consumers.
Tokens (tokens)
countTokens(input, encoding?)accepts a single string or an array of strings.- Arrays return one aggregate token count; array elements are encoded in parallel via rayon.
- Default encoding is
O200kBase;Cl100kBaseis also exported. - The implementation uses
encode_ordinary, not special-token handling. - BPE tables are initialized once through
LazyLockand reused.
macOS appearance and power helpers
detectMacOSAppearance()returns"dark","light", ornullon non-macOS.MacAppearanceObserver.start(callback)returns a handle withstop(); on macOS it uses distributed notifications plus a 2-second polling fallback, and on non-macOS it is a no-op observer.MacOSPowerAssertion.start(options?)returns a handle withstop(); on macOS it acquires one or more IOKit assertions, and on other platforms it is a no-op handle.- Power assertion options are
{ reason?, idle?, system?, user?, display? }. If every boolean is unset or omitted,idlebehavior is used by default.
Work profiling (prof)
- Collection boundary: profiling samples are produced by
profile_region(tag)guards intask::blockingandtask::future. - Storage format: fixed-size circular buffer (
MAX_SAMPLES = 10_000) storing stack path, duration, and timestamp. - Output boundary:
getWorkProfile(lastSeconds)returns:folded: folded-stack text (flamegraph input)summary: markdown table summarysvg: optional flamegraph SVGtotalMs,sampleCount
Lifecycle and state transitions
SIXEL lifecycle
encodeSixel(bytes, targetWidthPx, targetHeightPx)validates target dimensions.- Rust guesses and decodes the encoded image.
- Image is resized exactly to the target dimensions when needed.
- Pixels are converted to RGBA8 and encoded with
icy_sixel::sixel_encode. - The SIXEL escape string is returned synchronously.
Failure transitions:
- Format detection/decode failure throws.
- Invalid target dimensions throw.
- SIXEL encoding failure throws with
Failed to encode SIXEL: ....
HTML lifecycle
htmlToMarkdown(html, options)schedules a blocking conversion task.- Conversion runs with defaulted options (
cleanContent=false,skipImages=false) unless specified. - Returns markdown string or rejects with
Conversion error: ....
Clipboard lifecycle
- Text copy constructs an
arboard::Clipboardand callsset_textsynchronously. - Image read constructs an
arboard::Clipboard, callsget_image, encodes PNG on success, mapsContentNotAvailabletoNone, and rejects other errors.
Work profiling lifecycle
- No explicit start: profiling is active when task helpers execute.
- Every instrumented task scope records one sample on guard drop.
- Samples overwrite oldest entries after buffer capacity is reached.
getWorkProfile(lastSeconds)reads a time window and derives folded/summary/svg artifacts.
Failure transitions:
- SVG generation failure is soft (
svgomitted/undefined), while folded and summary still return. - Empty sample windows return empty folded data and no SVG, not an error.
Unsupported operations and error propagation
SIXEL
- Unsupported or corrupted image input is a strict failure.
- Invalid SIXEL target dimensions are a strict failure.
- No JS fallback path is exposed by the natives package.
HTML
- Conversion errors are strict failures.
- Option omission is defaulting, not failure.
Clipboard
- Text copy is strict at the native API surface.
- Image read distinguishes "no image" (
null/undefined) from operational failure (rejection).
Work profiling
- Retrieval is strict for the function call itself.
- Flamegraph SVG generation is nullable/optional.
- Buffer truncation is expected ring-buffer behavior.
Platform caveats
- Clipboard access depends on OS/session support exposed through
arboard. - macOS appearance and power helpers intentionally return no-op/null behavior on unsupported platforms.
- ProjFS is not exposed by this media/system native utility surface. Isolation backend selection, including any ProjFS support, lives in the separate
isosubsystem.