flue-eve

Client Guide

The flue-eve/client package wraps the Eve HTTP contract: health checks, session creation, follow-up turns, NDJSON streams, reconnects, and result extraction.

Client configuration

import { Client } from 'flue-eve/client'

const client = new Client({
  host: 'https://agent.example.com',
  auth: {
    bearer: async () => await getAccessToken(),
  },
  headers: async () => ({
    'x-client-version': '1.0.0',
  }),
  maxReconnectAttempts: 3,
})

Use host: '' for same-origin browser calls. Use a full origin for scripts, tests, or split-origin deployments.

Session lifecycle

Create a session object, then send the first turn:

const session = client.session()

const response = await session.send({
  message: 'Hello',
  agent: 'assistant',
  outputSchema: {
    type: 'object',
    properties: {
      answer: { type: 'string' },
      confidence: { type: 'number' },
    },
    required: ['answer'],
  },
  clientContext: {
    userId: 'user-123',
    locale: 'en-US',
  },
})

Follow-up turns reuse the same ClientSession:

await response.result()
await (await session.send({ message: 'Tell me more' })).result()

Streaming events

MessageResponse is an async iterable of Eve events:

const response = await session.send('Plan the migration')

for await (const event of response) {
  switch (event.type) {
    case 'message.received':
      console.log('User message accepted')
      break
    case 'message.appended':
      process.stdout.write(String(event.data.messageDelta ?? ''))
      break
    case 'actions.requested':
      console.log('Actions:', event.data.actions)
      break
    case 'action.result':
      console.log('Action result:', event.data.result)
      break
    case 'result.completed':
      console.log('Structured result:', event.data.result)
      break
    case 'session.waiting':
      console.log('Ready for the next turn')
      break
    case 'session.failed':
      console.error('Session failed:', event.data)
      break
  }
}

Reconnecting

The session state advances as events are consumed. Persist it and restore it later:

import { loadSessionState, saveSessionState } from 'flue-eve/client'

saveSessionState(localStorage, session.state)

const saved = loadSessionState(localStorage)
const restored = client.session(saved)

for await (const event of restored.stream()) {
  console.log(event.type)
}

The server-side journal owns streamIndex, so replay starts at the same Eve event boundary the client last consumed.

Result extraction

Use result() when you want a turn summary:

const response = await session.send('Return a JSON summary')
const result = await response.result()

console.log(result.status)
console.log(result.message)
console.log(result.data)
console.log(result.inputRequests)

result.status is "completed", "failed", or "waiting". result.data is populated when the stream includes a result.completed event.

Multi-agent sessions

Specify the agent per turn:

const session = client.session()

await (await session.send({
  message: 'Research quantum computing',
  agent: 'researcher',
})).result()

await (await session.send({
  message: 'Review this implementation',
  agent: 'code-reviewer',
})).result()

The Eve session ID remains shared while each turn routes to the requested Flue agent.

Error handling

import { ClientError } from 'flue-eve/client'

try {
  await (await session.send('Hello')).result()
} catch (err) {
  if (err instanceof ClientError && err.status === 401) {
    console.error('Invalid or missing authentication')
  } else if (err instanceof ClientError && err.status === 409) {
    console.error('Session conflict; wait for session.waiting and retry')
  } else if (err instanceof ClientError && err.status === 410) {
    console.error('Session has ended; create a new session')
  } else {
    throw err
  }
}

See event types reference for the full event catalog.