feat: prepare GoodBuddy 0.8.0
This commit is contained in:
@@ -1,15 +1,23 @@
|
||||
import { mkdtemp, rm, writeFile } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { basename, join } from 'node:path'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
const { showOpenDialog } = vi.hoisted(() => ({
|
||||
const { createFromBuffer, getSources, showOpenDialog } = vi.hoisted(() => ({
|
||||
createFromBuffer: vi.fn(),
|
||||
getSources: vi.fn(),
|
||||
showOpenDialog: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('electron', () => ({
|
||||
desktopCapturer: {
|
||||
getSources
|
||||
},
|
||||
dialog: {
|
||||
showOpenDialog
|
||||
},
|
||||
nativeImage: {
|
||||
createFromBuffer
|
||||
}
|
||||
}))
|
||||
|
||||
@@ -19,7 +27,9 @@ import { ContextManager } from './context-manager'
|
||||
const temporaryDirectories: string[] = []
|
||||
|
||||
afterEach(async () => {
|
||||
getSources.mockReset()
|
||||
showOpenDialog.mockReset()
|
||||
createFromBuffer.mockReset()
|
||||
await Promise.all(
|
||||
temporaryDirectories.splice(0).map((directory) =>
|
||||
rm(directory, { recursive: true, force: true })
|
||||
@@ -67,4 +77,136 @@ describe('ContextManager', () => {
|
||||
}).prompt
|
||||
).toBe('summarize')
|
||||
})
|
||||
|
||||
it('lists windows for a renderer picker and captures only the selected source as JPEG', async () => {
|
||||
const thumbnail = {
|
||||
isEmpty: () => false,
|
||||
getSize: () => ({ width: 1_280, height: 800 }),
|
||||
resize: vi.fn(),
|
||||
toDataURL: () =>
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB',
|
||||
toJPEG: () => Buffer.from([0xff, 0xd8, 0xff, 0xd9])
|
||||
}
|
||||
thumbnail.resize.mockReturnValue(thumbnail)
|
||||
getSources.mockResolvedValue([
|
||||
{
|
||||
id: 'window-1',
|
||||
name: 'GoodBuddy',
|
||||
thumbnail
|
||||
},
|
||||
{
|
||||
id: 'window-2',
|
||||
name: 'Browser',
|
||||
thumbnail
|
||||
},
|
||||
{
|
||||
id: 'window-3',
|
||||
name: 'Terminal',
|
||||
thumbnail
|
||||
}
|
||||
])
|
||||
const window = {
|
||||
getTitle: () => 'GoodBuddy'
|
||||
} as BrowserWindow
|
||||
const manager = new ContextManager()
|
||||
|
||||
await expect(manager.listWindows(window)).resolves.toEqual([
|
||||
{ id: 'window-2', name: 'Browser' },
|
||||
{ id: 'window-3', name: 'Terminal' }
|
||||
])
|
||||
const captured = await manager.captureWindow(window, 'window-2')
|
||||
|
||||
expect(captured).toMatchObject({
|
||||
name: expect.stringMatching(/^窗口-Browser-.+\.jpg$/u),
|
||||
kind: 'image',
|
||||
size: 4,
|
||||
contentUrl: 'data:image/jpeg;base64,/9j/2Q=='
|
||||
})
|
||||
expect(
|
||||
manager.enrichRequest({
|
||||
requestId: '1f6a37b6-e0a3-449f-8878-b10d353fbfb4',
|
||||
conversationId: 'conversation-1',
|
||||
prompt: 'inspect',
|
||||
contextIds: [captured.id]
|
||||
}).images
|
||||
).toEqual([
|
||||
expect.objectContaining({
|
||||
name: captured.name,
|
||||
mediaType: 'image/jpeg',
|
||||
data: '/9j/2Q=='
|
||||
})
|
||||
])
|
||||
})
|
||||
|
||||
it('accepts explicitly selected images and exposes bounded conversation content', async () => {
|
||||
const directory = await mkdtemp(join(tmpdir(), 'goodbuddy-context-'))
|
||||
temporaryDirectories.push(directory)
|
||||
const filePath = join(directory, 'reference.png')
|
||||
await writeFile(filePath, Buffer.from('synthetic image bytes'))
|
||||
showOpenDialog.mockResolvedValue({
|
||||
canceled: false,
|
||||
filePaths: [filePath]
|
||||
})
|
||||
const image = {
|
||||
isEmpty: () => false,
|
||||
getSize: () => ({ width: 640, height: 480 }),
|
||||
resize: vi.fn(),
|
||||
toJPEG: () => Buffer.from([0xff, 0xd8, 0xff, 0xd9])
|
||||
}
|
||||
image.resize.mockReturnValue(image)
|
||||
createFromBuffer.mockReturnValue(image)
|
||||
|
||||
const manager = new ContextManager()
|
||||
const [attachment] = await manager.selectFiles({} as BrowserWindow)
|
||||
|
||||
expect(attachment).toMatchObject({
|
||||
name: 'reference.png',
|
||||
kind: 'image',
|
||||
preview: '640 × 480',
|
||||
contentUrl: 'data:image/jpeg;base64,/9j/2Q=='
|
||||
})
|
||||
expect(showOpenDialog).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
expect.objectContaining({
|
||||
filters: expect.arrayContaining([
|
||||
expect.objectContaining({ name: '图片' })
|
||||
])
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('keeps all five explicitly selected images', async () => {
|
||||
const directory = await mkdtemp(join(tmpdir(), 'goodbuddy-context-'))
|
||||
temporaryDirectories.push(directory)
|
||||
const filePaths = await Promise.all(
|
||||
Array.from({ length: 5 }, async (_, index) => {
|
||||
const filePath = join(directory, `reference-${index + 1}.png`)
|
||||
await writeFile(filePath, Buffer.from(`image-${index + 1}`))
|
||||
return filePath
|
||||
})
|
||||
)
|
||||
showOpenDialog.mockResolvedValue({
|
||||
canceled: false,
|
||||
filePaths
|
||||
})
|
||||
const image = {
|
||||
isEmpty: () => false,
|
||||
getSize: () => ({ width: 640, height: 480 }),
|
||||
resize: vi.fn(),
|
||||
toJPEG: () => Buffer.from([0xff, 0xd8, 0xff, 0xd9])
|
||||
}
|
||||
image.resize.mockReturnValue(image)
|
||||
createFromBuffer.mockReturnValue(image)
|
||||
|
||||
const manager = new ContextManager()
|
||||
const attachments = await manager.selectFiles({} as BrowserWindow)
|
||||
|
||||
expect(attachments).toHaveLength(5)
|
||||
expect(attachments.map((attachment) => attachment.name)).toEqual(
|
||||
filePaths.map((filePath) => basename(filePath))
|
||||
)
|
||||
expect(attachments.every((attachment) => attachment.kind === 'image')).toBe(
|
||||
true
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user