mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-17 13:55:50 +00:00
claude-code with OpenAI mode fix
This commit is contained in:
125
packages/image-processor-napi/src/index.ts
Normal file
125
packages/image-processor-napi/src/index.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import sharpModule from 'sharp'
|
||||
|
||||
export const sharp = sharpModule
|
||||
|
||||
interface NativeModule {
|
||||
hasClipboardImage(): boolean
|
||||
readClipboardImage(
|
||||
maxWidth?: number,
|
||||
maxHeight?: number,
|
||||
): {
|
||||
png: Buffer
|
||||
width: number
|
||||
height: number
|
||||
originalWidth: number
|
||||
originalHeight: number
|
||||
} | null
|
||||
}
|
||||
|
||||
function createDarwinNativeModule(): NativeModule {
|
||||
return {
|
||||
hasClipboardImage(): boolean {
|
||||
try {
|
||||
const result = Bun.spawnSync({
|
||||
cmd: [
|
||||
'osascript',
|
||||
'-e',
|
||||
'try\nthe clipboard as «class PNGf»\nreturn "yes"\non error\nreturn "no"\nend try',
|
||||
],
|
||||
stdout: 'pipe',
|
||||
stderr: 'pipe',
|
||||
})
|
||||
const output = result.stdout.toString().trim()
|
||||
return output === 'yes'
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
},
|
||||
|
||||
readClipboardImage(
|
||||
maxWidth?: number,
|
||||
maxHeight?: number,
|
||||
) {
|
||||
try {
|
||||
// Use osascript to read clipboard image as PNG data and write to a temp file,
|
||||
// then read the temp file back
|
||||
const tmpPath = `/tmp/claude_clipboard_native_${Date.now()}.png`
|
||||
const script = `
|
||||
set png_data to (the clipboard as «class PNGf»)
|
||||
set fp to open for access POSIX file "${tmpPath}" with write permission
|
||||
write png_data to fp
|
||||
close access fp
|
||||
return "${tmpPath}"
|
||||
`
|
||||
const result = Bun.spawnSync({
|
||||
cmd: ['osascript', '-e', script],
|
||||
stdout: 'pipe',
|
||||
stderr: 'pipe',
|
||||
})
|
||||
|
||||
if (result.exitCode !== 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
const file = Bun.file(tmpPath)
|
||||
// Use synchronous read via Node compat
|
||||
const fs = require('fs')
|
||||
const buffer: Buffer = fs.readFileSync(tmpPath)
|
||||
|
||||
// Clean up temp file
|
||||
try {
|
||||
fs.unlinkSync(tmpPath)
|
||||
} catch {
|
||||
// ignore cleanup errors
|
||||
}
|
||||
|
||||
if (buffer.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Read PNG dimensions from IHDR chunk
|
||||
// PNG header: 8 bytes signature, then IHDR chunk
|
||||
// IHDR starts at offset 8 (4 bytes length) + 4 bytes "IHDR" + 4 bytes width + 4 bytes height
|
||||
let width = 0
|
||||
let height = 0
|
||||
if (buffer.length > 24 && buffer[12] === 0x49 && buffer[13] === 0x48 && buffer[14] === 0x44 && buffer[15] === 0x52) {
|
||||
width = buffer.readUInt32BE(16)
|
||||
height = buffer.readUInt32BE(20)
|
||||
}
|
||||
|
||||
const originalWidth = width
|
||||
const originalHeight = height
|
||||
|
||||
// If maxWidth/maxHeight are specified and the image exceeds them,
|
||||
// we still return the full PNG - the caller handles resizing via sharp
|
||||
// But we report the capped dimensions
|
||||
if (maxWidth && maxHeight) {
|
||||
if (width > maxWidth || height > maxHeight) {
|
||||
const scale = Math.min(maxWidth / width, maxHeight / height)
|
||||
width = Math.round(width * scale)
|
||||
height = Math.round(height * scale)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
png: buffer,
|
||||
width,
|
||||
height,
|
||||
originalWidth,
|
||||
originalHeight,
|
||||
}
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export function getNativeModule(): NativeModule | null {
|
||||
if (process.platform === 'darwin') {
|
||||
return createDarwinNativeModule()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export default sharp
|
||||
Reference in New Issue
Block a user