initialize Electron desktop app and remove unused files
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import { EventEmitter } from 'events'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
const ioMock = vi.hoisted(() => vi.fn())
|
||||
const scenarioMock = vi.hoisted(() => ({
|
||||
emitRunEvents: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('socket.io-client', () => ({
|
||||
io: ioMock,
|
||||
}))
|
||||
|
||||
function makeSocket() {
|
||||
const emitter = new EventEmitter() as EventEmitter & {
|
||||
emit: ReturnType<typeof vi.fn>
|
||||
disconnect: ReturnType<typeof vi.fn>
|
||||
emitNative: (event: string, payload?: unknown) => boolean
|
||||
}
|
||||
const nativeEmit = EventEmitter.prototype.emit.bind(emitter)
|
||||
emitter.emitNative = nativeEmit
|
||||
emitter.emit = vi.fn((event: string, payload?: unknown) => {
|
||||
if (event === 'run') {
|
||||
process.nextTick(() => scenarioMock.emitRunEvents(nativeEmit, payload))
|
||||
}
|
||||
return true
|
||||
}) as any
|
||||
emitter.disconnect = vi.fn()
|
||||
return emitter
|
||||
}
|
||||
|
||||
function makeCtx(body: Record<string, unknown>) {
|
||||
return {
|
||||
get: vi.fn((name: string) => name.toLowerCase() === 'authorization' ? 'Bearer token-1' : ''),
|
||||
state: { profile: { name: 'default' } },
|
||||
request: { body },
|
||||
status: 200,
|
||||
body: undefined as any,
|
||||
}
|
||||
}
|
||||
|
||||
describe('chat-run action/event baseline', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('returns requires_action when approval is requested', async () => {
|
||||
const socket = makeSocket()
|
||||
ioMock.mockReturnValue(socket)
|
||||
scenarioMock.emitRunEvents.mockImplementation((emitNative: Function) => {
|
||||
emitNative('run.started', { run_id: 'run-1' })
|
||||
emitNative('approval.requested', { run_id: 'run-1', approval_id: 'approval-1', command: 'touch file' })
|
||||
})
|
||||
|
||||
const { runOnce } = await import('../../packages/server/src/controllers/chat-run')
|
||||
const ctx = makeCtx({ session_id: 'session-1', input: 'needs approval', include_events: true })
|
||||
const pending = runOnce(ctx as any)
|
||||
socket.emitNative('connect')
|
||||
await pending
|
||||
|
||||
expect(ctx.status).toBe(409)
|
||||
expect(ctx.body).toMatchObject({
|
||||
ok: false,
|
||||
status: 'requires_action',
|
||||
event: 'approval.requested',
|
||||
session_id: 'session-1',
|
||||
run_id: 'run-1',
|
||||
action: { event: 'approval.requested', approval_id: 'approval-1' },
|
||||
})
|
||||
expect(ctx.body.events.map((event: any) => event.event)).toEqual(['run.started', 'approval.requested'])
|
||||
})
|
||||
|
||||
it('returns requires_action when clarification is requested', async () => {
|
||||
const socket = makeSocket()
|
||||
ioMock.mockReturnValue(socket)
|
||||
scenarioMock.emitRunEvents.mockImplementation((emitNative: Function) => {
|
||||
emitNative('run.started', { run_id: 'run-1' })
|
||||
emitNative('clarify.requested', { run_id: 'run-1', question: 'Which room?' })
|
||||
})
|
||||
|
||||
const { runOnce } = await import('../../packages/server/src/controllers/chat-run')
|
||||
const ctx = makeCtx({ session_id: 'session-1', input: 'needs clarify', include_events: true })
|
||||
const pending = runOnce(ctx as any)
|
||||
socket.emitNative('connect')
|
||||
await pending
|
||||
|
||||
expect(ctx.status).toBe(409)
|
||||
expect(ctx.body).toMatchObject({
|
||||
ok: false,
|
||||
status: 'requires_action',
|
||||
event: 'clarify.requested',
|
||||
action: { event: 'clarify.requested', question: 'Which room?' },
|
||||
})
|
||||
})
|
||||
|
||||
it('records bounded event history and accumulates output/reasoning when include_events is true', async () => {
|
||||
const socket = makeSocket()
|
||||
ioMock.mockReturnValue(socket)
|
||||
scenarioMock.emitRunEvents.mockImplementation((emitNative: Function) => {
|
||||
emitNative('run.started', { run_id: 'run-1' })
|
||||
emitNative('reasoning.delta', { run_id: 'run-1', delta: 'thought' })
|
||||
emitNative('tool.started', { run_id: 'run-1', name: 'lookup' })
|
||||
emitNative('tool.completed', { run_id: 'run-1', name: 'lookup' })
|
||||
emitNative('message.delta', { run_id: 'run-1', delta: 'hello' })
|
||||
emitNative('run.completed', { run_id: 'run-1' })
|
||||
})
|
||||
|
||||
const { runOnce } = await import('../../packages/server/src/controllers/chat-run')
|
||||
const ctx = makeCtx({ session_id: 'session-1', input: 'hello', include_events: true })
|
||||
const pending = runOnce(ctx as any)
|
||||
socket.emitNative('connect')
|
||||
await pending
|
||||
|
||||
expect(ctx.status).toBe(200)
|
||||
expect(ctx.body).toMatchObject({
|
||||
ok: true,
|
||||
status: 'completed',
|
||||
output: 'hello',
|
||||
reasoning: 'thought',
|
||||
run_id: 'run-1',
|
||||
})
|
||||
expect(ctx.body.events.map((event: any) => event.event)).toEqual([
|
||||
'run.started',
|
||||
'reasoning.delta',
|
||||
'tool.started',
|
||||
'tool.completed',
|
||||
'message.delta',
|
||||
'run.completed',
|
||||
])
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user