gclm-code 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +1 -1
  2. package/bin/gc.js +53 -25
  3. package/bin/install-runtime.js +253 -0
  4. package/package.json +10 -5
  5. package/vendor/manifest.json +92 -0
  6. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/package.json +9 -0
  7. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/bridgeClient.ts +1126 -0
  8. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/browserTools.ts +546 -0
  9. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/index.ts +15 -0
  10. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/mcpServer.ts +96 -0
  11. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/mcpSocketClient.ts +493 -0
  12. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/mcpSocketPool.ts +327 -0
  13. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/toolCalls.ts +301 -0
  14. package/vendor/modules/node_modules/@ant/claude-for-chrome-mcp/src/types.ts +134 -0
  15. package/vendor/modules/node_modules/@ant/computer-use-input/package.json +9 -0
  16. package/vendor/modules/node_modules/@ant/computer-use-input/src/driver-jxa.js +341 -0
  17. package/vendor/modules/node_modules/@ant/computer-use-input/src/driver-swift.swift +417 -0
  18. package/vendor/modules/node_modules/@ant/computer-use-input/src/implementation.js +204 -0
  19. package/vendor/modules/node_modules/@ant/computer-use-input/src/index.js +5 -0
  20. package/vendor/modules/node_modules/@ant/computer-use-mcp/package.json +11 -0
  21. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/deniedApps.ts +553 -0
  22. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/imageResize.ts +108 -0
  23. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/index.ts +69 -0
  24. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/keyBlocklist.ts +153 -0
  25. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/mcpServer.ts +313 -0
  26. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/pixelCompare.ts +171 -0
  27. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/sentinelApps.ts +43 -0
  28. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/subGates.ts +19 -0
  29. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/toolCalls.ts +3872 -0
  30. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/tools.ts +706 -0
  31. package/vendor/modules/node_modules/@ant/computer-use-mcp/src/types.ts +635 -0
  32. package/vendor/modules/node_modules/@ant/computer-use-swift/package.json +9 -0
  33. package/vendor/modules/node_modules/@ant/computer-use-swift/src/driver-jxa.js +108 -0
  34. package/vendor/modules/node_modules/@ant/computer-use-swift/src/implementation.js +706 -0
  35. package/vendor/modules/node_modules/@ant/computer-use-swift/src/index.js +7 -0
  36. package/vendor/modules/node_modules/audio-capture-napi/package.json +8 -0
  37. package/vendor/modules/node_modules/audio-capture-napi/src/index.ts +226 -0
  38. package/vendor/modules/node_modules/image-processor-napi/package.json +11 -0
  39. package/vendor/modules/node_modules/image-processor-napi/src/index.ts +396 -0
  40. package/vendor/modules/node_modules/modifiers-napi/package.json +8 -0
  41. package/vendor/modules/node_modules/modifiers-napi/src/index.ts +79 -0
  42. package/vendor/modules/node_modules/url-handler-napi/package.json +8 -0
  43. package/vendor/modules/node_modules/url-handler-napi/src/index.ts +62 -0
@@ -0,0 +1,226 @@
1
+ // Pure-JS audio capture module. Replaces the pre-compiled NAPI binary with
2
+ // subprocess backends: SoX (rec/play) as primary, ALSA (arecord/aplay) as
3
+ // Linux fallback. The public API is identical to the former NAPI wrapper so
4
+ // callers (voice.ts) require no changes.
5
+
6
+ import { type ChildProcess, spawn, spawnSync } from 'child_process'
7
+
8
+ const SAMPLE_RATE = 16000
9
+ const CHANNELS = 1
10
+ // SoX silence-detection parameters — mirror the cpal native module's
11
+ // auto-stop-on-silence behaviour.
12
+ const SILENCE_DURATION_SECS = '2.0'
13
+ const SILENCE_THRESHOLD = '3%'
14
+
15
+ // ─── State ─────────────────────────────────────────────────────────────────
16
+
17
+ let isRecording = false
18
+ let recordProcess: ChildProcess | null = null
19
+ // Track explicit stops per child so a late close event from the previous
20
+ // recorder cannot suppress or spuriously trigger callbacks for the next one.
21
+ const explicitlyStoppedRecorders = new WeakSet<ChildProcess>()
22
+
23
+ let isPlaying = false
24
+ let playProcess: ChildProcess | null = null
25
+
26
+ // ─── Helpers ───────────────────────────────────────────────────────────────
27
+
28
+ function hasCommand(cmd: string): boolean {
29
+ const result = spawnSync(cmd, ['--version'], { stdio: 'ignore', timeout: 3000 })
30
+ return result.error === undefined
31
+ }
32
+
33
+ // Prefer SoX because it supports built-in silence detection. Fall back to
34
+ // arecord on Linux when SoX is absent.
35
+ function recordingBackend(): 'sox' | 'arecord' | null {
36
+ if (hasCommand('rec')) return 'sox'
37
+ if (process.platform === 'linux' && hasCommand('arecord')) return 'arecord'
38
+ return null
39
+ }
40
+
41
+ // Prefer SoX play; fall back to aplay on Linux.
42
+ function playbackBackend(): 'sox' | 'aplay' | null {
43
+ if (hasCommand('play')) return 'sox'
44
+ if (process.platform === 'linux' && hasCommand('aplay')) return 'aplay'
45
+ return null
46
+ }
47
+
48
+ // ─── Public API ────────────────────────────────────────────────────────────
49
+
50
+ export function isNativeAudioAvailable(): boolean {
51
+ const platform = process.platform
52
+ if (platform !== 'darwin' && platform !== 'linux' && platform !== 'win32') {
53
+ return false
54
+ }
55
+ return recordingBackend() !== null
56
+ }
57
+
58
+ export function startNativeRecording(
59
+ onData: (data: Buffer) => void,
60
+ onEnd: () => void,
61
+ ): boolean {
62
+ if (isRecording) return false
63
+
64
+ const backend = recordingBackend()
65
+ if (!backend) return false
66
+
67
+ let child: ChildProcess
68
+
69
+ if (backend === 'arecord') {
70
+ // arecord has no built-in silence detection; the caller is responsible
71
+ // for stopping via stopNativeRecording() (push-to-talk usage).
72
+ child = spawn(
73
+ 'arecord',
74
+ [
75
+ '-f', 'S16_LE', // signed 16-bit little-endian
76
+ '-r', String(SAMPLE_RATE),
77
+ '-c', String(CHANNELS),
78
+ '-t', 'raw', // raw PCM, no WAV header
79
+ '-q', // suppress progress output
80
+ '-', // write to stdout
81
+ ],
82
+ { stdio: ['ignore', 'pipe', 'ignore'] },
83
+ )
84
+ } else {
85
+ // SoX with silence detection: process exits naturally after
86
+ // SILENCE_DURATION_SECS of silence, triggering onEnd automatically.
87
+ // --buffer 1024 forces small flushes so onData fires promptly.
88
+ child = spawn(
89
+ 'rec',
90
+ [
91
+ '-q',
92
+ '--buffer', '1024',
93
+ '-t', 'raw',
94
+ '-r', String(SAMPLE_RATE),
95
+ '-e', 'signed',
96
+ '-b', '16',
97
+ '-c', String(CHANNELS),
98
+ '-',
99
+ 'silence', '1', '0.1', SILENCE_THRESHOLD,
100
+ '1', SILENCE_DURATION_SECS, SILENCE_THRESHOLD,
101
+ ],
102
+ { stdio: ['ignore', 'pipe', 'ignore'] },
103
+ )
104
+ }
105
+
106
+ recordProcess = child
107
+ isRecording = true
108
+
109
+ child.stdout?.on('data', (chunk: Buffer) => {
110
+ onData(chunk)
111
+ })
112
+
113
+ const handleClose = () => {
114
+ if (recordProcess === child) {
115
+ recordProcess = null
116
+ isRecording = false
117
+ }
118
+ const wasStoppedExplicitly = explicitlyStoppedRecorders.has(child)
119
+ explicitlyStoppedRecorders.delete(child)
120
+ // Only fire onEnd for natural termination (silence detection).
121
+ // Explicit stopNativeRecording() calls suppress it, matching cpal behaviour.
122
+ if (!wasStoppedExplicitly) {
123
+ onEnd()
124
+ }
125
+ }
126
+
127
+ child.on('close', handleClose)
128
+ child.on('error', handleClose)
129
+
130
+ return true
131
+ }
132
+
133
+ export function stopNativeRecording(): void {
134
+ if (recordProcess) {
135
+ explicitlyStoppedRecorders.add(recordProcess)
136
+ recordProcess.kill('SIGTERM')
137
+ recordProcess = null
138
+ }
139
+ isRecording = false
140
+ }
141
+
142
+ export function isNativeRecordingActive(): boolean {
143
+ return isRecording
144
+ }
145
+
146
+ export function startNativePlayback(sampleRate: number, channels: number): boolean {
147
+ if (isPlaying) stopNativePlayback()
148
+
149
+ const backend = playbackBackend()
150
+ if (!backend) return false
151
+
152
+ let child: ChildProcess
153
+
154
+ if (backend === 'aplay') {
155
+ child = spawn(
156
+ 'aplay',
157
+ [
158
+ '-f', 'S16_LE',
159
+ '-r', String(sampleRate),
160
+ '-c', String(channels),
161
+ '-t', 'raw',
162
+ '-q',
163
+ '-',
164
+ ],
165
+ { stdio: ['pipe', 'ignore', 'ignore'] },
166
+ )
167
+ } else {
168
+ child = spawn(
169
+ 'play',
170
+ [
171
+ '-q',
172
+ '-t', 'raw',
173
+ '-r', String(sampleRate),
174
+ '-e', 'signed',
175
+ '-b', '16',
176
+ '-c', String(channels),
177
+ '-',
178
+ ],
179
+ { stdio: ['pipe', 'ignore', 'ignore'] },
180
+ )
181
+ }
182
+
183
+ playProcess = child
184
+ isPlaying = true
185
+
186
+ const handleClose = () => {
187
+ if (playProcess === child) {
188
+ playProcess = null
189
+ isPlaying = false
190
+ }
191
+ }
192
+
193
+ child.on('close', handleClose)
194
+ child.on('error', handleClose)
195
+
196
+ return true
197
+ }
198
+
199
+ export function writeNativePlaybackData(data: Buffer): void {
200
+ playProcess?.stdin?.write(data)
201
+ }
202
+
203
+ export function stopNativePlayback(): void {
204
+ if (playProcess) {
205
+ playProcess.stdin?.end()
206
+ playProcess.kill('SIGTERM')
207
+ playProcess = null
208
+ }
209
+ isPlaying = false
210
+ }
211
+
212
+ export function isNativePlaying(): boolean {
213
+ return isPlaying
214
+ }
215
+
216
+ // Returns the microphone authorization status.
217
+ // macOS: 0 (notDetermined) — TCC cannot be queried from pure JS; the system
218
+ // permission prompt appears on the first recording attempt.
219
+ // Linux: 3 (authorized) — no system-level microphone permission API.
220
+ // Windows: 3 (authorized) — registry check requires Win32 API; assume OK.
221
+ // Other/unavailable: 0 (notDetermined).
222
+ export function microphoneAuthorizationStatus(): number {
223
+ const platform = process.platform
224
+ if (platform === 'linux' || platform === 'win32') return 3
225
+ return 0 // darwin or unknown — cannot check without native code
226
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "image-processor-napi",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "./src/index.ts",
7
+ "types": "./src/index.ts",
8
+ "dependencies": {
9
+ "sharp": "^0.34.5"
10
+ }
11
+ }
@@ -0,0 +1,396 @@
1
+ import { spawnSync } from 'child_process'
2
+ import { mkdtempSync, readFileSync, rmSync } from 'fs'
3
+ import { createRequire } from 'module'
4
+ import { tmpdir } from 'os'
5
+ import { join } from 'path'
6
+
7
+ const require = createRequire(import.meta.url)
8
+
9
+ export type ClipboardImageResult = {
10
+ png: Buffer
11
+ originalWidth: number
12
+ originalHeight: number
13
+ width: number
14
+ height: number
15
+ }
16
+
17
+ type ImageProcessor = {
18
+ metadata(): Promise<{ width: number; height: number; format: string }>
19
+ resize(
20
+ width: number,
21
+ height: number,
22
+ options?: { fit?: string; withoutEnlargement?: boolean },
23
+ ): ImageProcessor
24
+ jpeg(quality?: number): ImageProcessor
25
+ png(options?: {
26
+ compressionLevel?: number
27
+ palette?: boolean
28
+ colors?: number
29
+ }): ImageProcessor
30
+ webp(quality?: number): ImageProcessor
31
+ toBuffer(): Promise<Buffer>
32
+ }
33
+
34
+ export type NativeModule = {
35
+ processImage: (input: Buffer) => Promise<ImageProcessor>
36
+ readClipboardImage?: (
37
+ maxWidth: number,
38
+ maxHeight: number,
39
+ ) => ClipboardImageResult | null
40
+ hasClipboardImage?: () => boolean
41
+ }
42
+
43
+ type SharpInstance = {
44
+ metadata(): Promise<{ width?: number; height?: number; format?: string }>
45
+ resize(
46
+ width: number,
47
+ height: number,
48
+ options?: { fit?: string; withoutEnlargement?: boolean },
49
+ ): SharpInstance
50
+ jpeg(options?: { quality?: number }): SharpInstance
51
+ png(options?: {
52
+ compressionLevel?: number
53
+ palette?: boolean
54
+ colors?: number
55
+ }): SharpInstance
56
+ webp(options?: { quality?: number }): SharpInstance
57
+ toBuffer(): Promise<Buffer>
58
+ }
59
+
60
+ type SharpFactory = (input: Buffer) => SharpInstance
61
+ type MaybeDefault<T> = T | { default: T }
62
+
63
+ const PNG_SIGNATURE = Buffer.from([
64
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
65
+ ])
66
+
67
+ let cachedSharpFactory: SharpFactory | null = null
68
+
69
+ function getSharpFactory(): SharpFactory {
70
+ if (cachedSharpFactory) {
71
+ return cachedSharpFactory
72
+ }
73
+ const imported = require('sharp') as MaybeDefault<SharpFactory>
74
+ cachedSharpFactory =
75
+ typeof imported === 'function' ? imported : imported.default
76
+ return cachedSharpFactory
77
+ }
78
+
79
+ function createSharpProcessor(input: Buffer): ImageProcessor {
80
+ const sharpFactory = getSharpFactory()
81
+ let pipeline = sharpFactory(input)
82
+
83
+ const processor: ImageProcessor = {
84
+ async metadata() {
85
+ const metadata = await pipeline.metadata()
86
+ return {
87
+ width: metadata.width ?? 0,
88
+ height: metadata.height ?? 0,
89
+ format: metadata.format ?? 'unknown',
90
+ }
91
+ },
92
+ resize(width, height, options) {
93
+ pipeline = pipeline.resize(width, height, options)
94
+ return processor
95
+ },
96
+ jpeg(quality) {
97
+ pipeline = pipeline.jpeg(
98
+ quality === undefined ? undefined : { quality },
99
+ )
100
+ return processor
101
+ },
102
+ png(options) {
103
+ pipeline = pipeline.png(options)
104
+ return processor
105
+ },
106
+ webp(quality) {
107
+ pipeline = pipeline.webp(
108
+ quality === undefined ? undefined : { quality },
109
+ )
110
+ return processor
111
+ },
112
+ toBuffer() {
113
+ return pipeline.toBuffer()
114
+ },
115
+ }
116
+
117
+ return processor
118
+ }
119
+
120
+ function createFallbackModule(): NativeModule {
121
+ return {
122
+ async processImage(input: Buffer) {
123
+ return createSharpProcessor(input)
124
+ },
125
+ hasClipboardImage: process.platform === 'darwin' ? hasClipboardImage : undefined,
126
+ readClipboardImage:
127
+ process.platform === 'darwin' ? readClipboardImage : undefined,
128
+ }
129
+ }
130
+
131
+ // Raw binding accessor. Callers that need optional exports (e.g. clipboard
132
+ // functions) reach through this; keeping the wrappers on the caller side lets
133
+ // feature() tree-shake the property access strings out of external builds.
134
+ export function getNativeModule(): NativeModule | null {
135
+ return createFallbackModule()
136
+ }
137
+
138
+ function escapeAppleScriptString(value: string): string {
139
+ return value.replaceAll('\\', '\\\\').replaceAll('"', '\\"')
140
+ }
141
+
142
+ function readPngDimensions(
143
+ buffer: Buffer,
144
+ ): { width: number; height: number } | null {
145
+ if (buffer.length < 24) {
146
+ return null
147
+ }
148
+ if (!buffer.subarray(0, PNG_SIGNATURE.length).equals(PNG_SIGNATURE)) {
149
+ return null
150
+ }
151
+ if (buffer.toString('ascii', 12, 16) !== 'IHDR') {
152
+ return null
153
+ }
154
+ return {
155
+ width: buffer.readUInt32BE(16),
156
+ height: buffer.readUInt32BE(20),
157
+ }
158
+ }
159
+
160
+ function writeClipboardPng(targetPath: string): Buffer | null {
161
+ const escaped = escapeAppleScriptString(targetPath)
162
+ const result = spawnSync(
163
+ '/usr/bin/osascript',
164
+ [
165
+ '-e',
166
+ 'set png_data to (the clipboard as «class PNGf»)',
167
+ '-e',
168
+ `set fp to open for access POSIX file "${escaped}" with write permission`,
169
+ '-e',
170
+ 'write png_data to fp',
171
+ '-e',
172
+ 'close access fp',
173
+ ],
174
+ { stdio: 'pipe' },
175
+ )
176
+
177
+ if (result.status !== 0) {
178
+ return null
179
+ }
180
+
181
+ try {
182
+ return readFileSync(targetPath)
183
+ } catch {
184
+ return null
185
+ }
186
+ }
187
+
188
+ function resizePngSync(
189
+ inputPath: string,
190
+ outputPath: string,
191
+ width: number,
192
+ height: number,
193
+ ): Buffer | null {
194
+ const result = spawnSync(
195
+ '/usr/bin/sips',
196
+ [
197
+ '-s',
198
+ 'format',
199
+ 'png',
200
+ '-z',
201
+ String(height),
202
+ String(width),
203
+ inputPath,
204
+ '--out',
205
+ outputPath,
206
+ ],
207
+ { stdio: 'pipe' },
208
+ )
209
+
210
+ if (result.status !== 0) {
211
+ return null
212
+ }
213
+
214
+ try {
215
+ return readFileSync(outputPath)
216
+ } catch {
217
+ return null
218
+ }
219
+ }
220
+
221
+ function hasClipboardImage(): boolean {
222
+ const result = spawnSync(
223
+ '/usr/bin/osascript',
224
+ ['-e', 'the clipboard as «class PNGf»'],
225
+ { stdio: 'pipe' },
226
+ )
227
+ return result.status === 0
228
+ }
229
+
230
+ function readClipboardImage(
231
+ maxWidth: number,
232
+ maxHeight: number,
233
+ ): ClipboardImageResult | null {
234
+ const tempDir = mkdtempSync(join(tmpdir(), 'claude-image-processor-'))
235
+ const clipboardPath = join(tempDir, 'clipboard.png')
236
+ const resizedPath = join(tempDir, 'clipboard-resized.png')
237
+
238
+ try {
239
+ const buffer = writeClipboardPng(clipboardPath)
240
+ if (!buffer) {
241
+ return null
242
+ }
243
+
244
+ const original = readPngDimensions(buffer)
245
+ if (!original) {
246
+ return null
247
+ }
248
+
249
+ let png = buffer
250
+ let width = original.width
251
+ let height = original.height
252
+
253
+ const safeMaxWidth = Math.max(1, Math.floor(maxWidth))
254
+ const safeMaxHeight = Math.max(1, Math.floor(maxHeight))
255
+ const scale = Math.min(
256
+ 1,
257
+ safeMaxWidth / Math.max(width, 1),
258
+ safeMaxHeight / Math.max(height, 1),
259
+ )
260
+
261
+ if (scale < 1) {
262
+ const targetWidth = Math.max(1, Math.round(width * scale))
263
+ const targetHeight = Math.max(1, Math.round(height * scale))
264
+ const resized = resizePngSync(
265
+ clipboardPath,
266
+ resizedPath,
267
+ targetWidth,
268
+ targetHeight,
269
+ )
270
+ if (resized) {
271
+ const resizedDimensions = readPngDimensions(resized)
272
+ if (resizedDimensions) {
273
+ png = resized
274
+ width = resizedDimensions.width
275
+ height = resizedDimensions.height
276
+ }
277
+ }
278
+ }
279
+
280
+ return {
281
+ png,
282
+ originalWidth: original.width,
283
+ originalHeight: original.height,
284
+ width,
285
+ height,
286
+ }
287
+ } finally {
288
+ rmSync(tempDir, { recursive: true, force: true })
289
+ }
290
+ }
291
+
292
+ interface SharpInstancePublic {
293
+ metadata(): Promise<{ width: number; height: number; format: string }>
294
+ resize(
295
+ width: number,
296
+ height: number,
297
+ options?: { fit?: string; withoutEnlargement?: boolean },
298
+ ): SharpInstancePublic
299
+ jpeg(options?: { quality?: number }): SharpInstancePublic
300
+ png(options?: {
301
+ compressionLevel?: number
302
+ palette?: boolean
303
+ colors?: number
304
+ }): SharpInstancePublic
305
+ webp(options?: { quality?: number }): SharpInstancePublic
306
+ toBuffer(): Promise<Buffer>
307
+ }
308
+
309
+ // Factory function that matches sharp's API
310
+ export function sharp(input: Buffer): SharpInstancePublic {
311
+ let processorPromise: Promise<ImageProcessor> | null = null
312
+
313
+ // Create a chain of operations
314
+ const operations: Array<(proc: ImageProcessor) => void> = []
315
+
316
+ // Track how many operations have been applied to avoid re-applying
317
+ let appliedOperationsCount = 0
318
+
319
+ // Get or create the processor (without applying operations)
320
+ async function ensureProcessor(): Promise<ImageProcessor> {
321
+ if (!processorPromise) {
322
+ processorPromise = (async () => {
323
+ const mod = getNativeModule()
324
+ if (!mod) {
325
+ throw new Error('Native image processor module not available')
326
+ }
327
+ return mod.processImage(input)
328
+ })()
329
+ }
330
+ return processorPromise
331
+ }
332
+
333
+ // Apply any pending operations to the processor
334
+ function applyPendingOperations(proc: ImageProcessor): void {
335
+ for (let i = appliedOperationsCount; i < operations.length; i++) {
336
+ const op = operations[i]
337
+ if (op) {
338
+ op(proc)
339
+ }
340
+ }
341
+ appliedOperationsCount = operations.length
342
+ }
343
+
344
+ const instance: SharpInstancePublic = {
345
+ async metadata() {
346
+ const proc = await ensureProcessor()
347
+ return proc.metadata()
348
+ },
349
+
350
+ resize(
351
+ width: number,
352
+ height: number,
353
+ options?: { fit?: string; withoutEnlargement?: boolean },
354
+ ) {
355
+ operations.push(proc => {
356
+ proc.resize(width, height, options)
357
+ })
358
+ return instance
359
+ },
360
+
361
+ jpeg(options?: { quality?: number }) {
362
+ operations.push(proc => {
363
+ proc.jpeg(options?.quality)
364
+ })
365
+ return instance
366
+ },
367
+
368
+ png(options?: {
369
+ compressionLevel?: number
370
+ palette?: boolean
371
+ colors?: number
372
+ }) {
373
+ operations.push(proc => {
374
+ proc.png(options)
375
+ })
376
+ return instance
377
+ },
378
+
379
+ webp(options?: { quality?: number }) {
380
+ operations.push(proc => {
381
+ proc.webp(options?.quality)
382
+ })
383
+ return instance
384
+ },
385
+
386
+ async toBuffer() {
387
+ const proc = await ensureProcessor()
388
+ applyPendingOperations(proc)
389
+ return proc.toBuffer()
390
+ },
391
+ }
392
+
393
+ return instance
394
+ }
395
+
396
+ export default sharp
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "modifiers-napi",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "main": "./src/index.ts",
7
+ "types": "./src/index.ts"
8
+ }