refactor(natives): migrated native bindings to NAPI-RS with auto-generated types
- Migrated native bindings from TypeScript wrappers to NAPI-RS generated modules with auto-generated type definitions and runtime enums. - Replaced chunk tree API with stateful ChunkState class supporting render, edit, and resolve operations with improved error handling. - Converted callback signatures to error-first pattern (error, result) for shell, PTY, glob, and grep operations. - Introduced type-safe enums for MacOSAppearance, GrepOutputMode, KeyEventType, ImageFormat, and AstMatchStrictness replacing string literals. - Refactored chunk tree implementation with dedicated modules for edit, indent, resolve, and state management with comprehensive validation. - Moved clipboard utilities from native bindings to coding-agent package with improved OSC 52 and Termux compatibility.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import { execSync } from "node:child_process";
|
||||
import type { ClipboardImage } from "@oh-my-pi/pi-natives";
|
||||
import * as native from "@oh-my-pi/pi-natives";
|
||||
|
||||
const hasDisplay = process.platform !== "linux" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
|
||||
|
||||
/**
|
||||
* Copy text to the system clipboard.
|
||||
*
|
||||
* Emits OSC 52 first when running in a real terminal (works over SSH/mosh),
|
||||
* then attempts native clipboard copy as best-effort for local sessions.
|
||||
* On Termux, tries `termux-clipboard-set` before native.
|
||||
*
|
||||
* @param text - UTF-8 text to place on the clipboard.
|
||||
*/
|
||||
export async function copyToClipboard(text: string): Promise<void> {
|
||||
if (process.stdout.isTTY) {
|
||||
const onError = (err: unknown) => {
|
||||
process.stdout.off("error", onError);
|
||||
// Prevent unhandled 'error' from crashing the process when stdout is a closed pipe.
|
||||
if ((err as NodeJS.ErrnoException | null | undefined)?.code === "EPIPE") {
|
||||
return;
|
||||
}
|
||||
};
|
||||
try {
|
||||
const encoded = Buffer.from(text).toString("base64");
|
||||
const osc52 = `\x1b]52;c;${encoded}\x07`;
|
||||
process.stdout.on("error", onError);
|
||||
process.stdout.write(osc52, err => {
|
||||
process.stdout.off("error", onError);
|
||||
// If stdout is closed (e.g. piped to a process that exits early),
|
||||
// ignore EPIPE and proceed with native clipboard best-effort.
|
||||
if ((err as NodeJS.ErrnoException | null | undefined)?.code === "EPIPE") {
|
||||
return;
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
process.stdout.off("error", onError);
|
||||
if ((err as NodeJS.ErrnoException | null | undefined)?.code !== "EPIPE") {
|
||||
// Ignore all write failures (OSC 52 is best-effort).
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also try native tools (best effort for local sessions)
|
||||
try {
|
||||
if (process.env.TERMUX_VERSION) {
|
||||
try {
|
||||
execSync("termux-clipboard-set", { input: text, timeout: 5000 });
|
||||
return;
|
||||
} catch {
|
||||
// Fall through to native
|
||||
}
|
||||
}
|
||||
|
||||
await native.copyToClipboard(text);
|
||||
} catch {
|
||||
// Ignore — clipboard copy is best-effort
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an image from the system clipboard.
|
||||
*
|
||||
* Returns null on Termux (no image clipboard support) or when no display
|
||||
* server is available (headless/SSH without forwarding).
|
||||
*
|
||||
* @returns PNG payload or null when no image is available.
|
||||
*/
|
||||
export async function readImageFromClipboard(): Promise<ClipboardImage | null> {
|
||||
if (process.env.TERMUX_VERSION) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!hasDisplay) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (await native.readImageFromClipboard()) ?? null;
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { resolveEditMode } from "./edit-mode";
|
||||
export interface FileDisplayMode {
|
||||
lineNumbers: boolean;
|
||||
hashLines: boolean;
|
||||
chunked: boolean;
|
||||
}
|
||||
|
||||
/** Session-like object providing settings and tool availability for display mode resolution. */
|
||||
@@ -27,8 +28,10 @@ export function resolveFileDisplayMode(session: FileDisplayModeSession): FileDis
|
||||
const { settings } = session;
|
||||
const hasEditTool = session.hasEditTool ?? true;
|
||||
const hashLines = hasEditTool && resolveEditMode(session) === "hashline" && settings.get("readHashLines") !== false;
|
||||
const chunked = hasEditTool && resolveEditMode(session) === "chunk";
|
||||
return {
|
||||
hashLines,
|
||||
lineNumbers: hashLines || settings.get("readLineNumbers") === true,
|
||||
chunked,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user