npm package: @layerscale/layerscale
Description: Client for the LayerScale inference server
Latest version: 0.1.9

# @layerscale/layerscale

TypeScript client for the LayerScale inference server.

## Install

```bash
npm install @layerscale/layerscale
```

## Usage

```typescript
import { LayerScale } from '@layerscale/layerscale';

const client = new LayerScale('http://localhost:8080', {
  apiKey: 'your-api-key', // or set LAYERSCALE_API_KEY env var
});
```

### OpenAI-compatible chat

```typescript
const chat = await client.chat({
  messages: [{ role: 'user', content: 'Hello' }],
});
```

### Anthropic-compatible messages

```typescript
const msg = await client.message({
  messages: [{ role: 'user', content: 'Hello' }],
  max_tokens: 256,
});
```

### Streaming

All streaming methods return async generators:

```typescript
for await (const chunk of client.chatStream({ messages })) {
  process.stdout.write(chunk.choices[0]?.delta.content ?? '');
}

for await (const chunk of client.messageStream({ messages, max_tokens: 256 })) {
  if (chunk.type === 'content_block_delta') {
    process.stdout.write(chunk.delta.text);
  }
}
```

### Sessions

```typescript
const session = await client.createSession({
  prompt: 'You are a trading analyst.',
  flash: ['Is the trend bullish?', 'Is volume increasing?'],
});

await client.markPrefix(session.session_id);

const answer = await client.generate(session.session_id, {
  prompt: 'What is the trend?',
  max_tokens: 256,
});

// Stream generation token-by-token
for await (const chunk of client.generateStream(session.session_id, { max_tokens: 256 })) {
  if (chunk.token) process.stdout.write(chunk.token);
}
```

### Session management

```typescript
const sessions = await client.listSessions();
const state = await client.getSession(session.session_id);
await client.deleteSession(session.session_id);
```

### Continuous streaming

Push OHLCV data into the lock-free ring buffer for background processing:

```typescript
await client.streamPush(session.session_id, [
  { o: 150.5, h: 151.0, l: 150.0, c: 150.75, v: 1_000_000, timestamp: 1704067200, sym: 'AAPL' },
]);

const status = await client.streamStatus(session.session_id);
```

### Flash queries

Register questions that are automatically evaluated in the background after each data update. Answers are cached for near-instant retrieval:

```typescript
const registered = await client.flash(session.session_id, 'Is the trend bullish?');
const queries = await client.listFlash(session.session_id);
await client.unflash(session.session_id, registered.query_id);
```

### Session events

Subscribe to real-time session events via SSE:

```typescript
for await (const event of client.events(session.session_id)) {
  if (event.type === 'flash_ready') {
    console.log(event.query, event.answer, event.confidence);
  }
}
```

### Error handling

```typescript
import { LayerScaleError } from '@layerscale/layerscale';

try {
  await client.generate(sessionId, { max_tokens: 256 });
} catch (err) {
  if (err instanceof LayerScaleError) {
    console.error(err.status, err.body.error.message);
  }
}
```

## API

| Method | Endpoint |
|--------|----------|
| `health()` | `GET /v1/health` |
| `models()` | `GET /v1/models` |
| `chat(params)` | `POST /v1/chat/completions` |
| `chatStream(params)` | `POST /v1/chat/completions` (streaming) |
| `complete(params)` | `POST /v1/completions` |
| `message(params)` | `POST /v1/messages` |
| `messageStream(params)` | `POST /v1/messages` (streaming) |
| `createSession(params)` | `POST /v1/sessions/init` |
| `listSessions()` | `GET /v1/sessions` |
| `getSession(id)` | `GET /v1/sessions/:id/state` |
| `deleteSession(id)` | `DELETE /v1/sessions/:id` |
| `append(id, text)` | `POST /v1/sessions/:id/append` |
| `listSlots(id)` | `GET /v1/sessions/:id/slots` |
| `generate(id, params)` | `POST /v1/sessions/:id/generate` |
| `generateStream(id, params)` | `POST /v1/sessions/:id/generate` (streaming) |
| `markPrefix(id)` | `POST /v1/sessions/:id/mark_prefix` |
| `streamPush(id, data)` | `POST /v1/sessions/:id/stream/push` |
| `streamStatus(id)` | `GET /v1/sessions/:id/stream/status` |
| `flash(id, query)` | `POST /v1/sessions/:id/flash` |
| `listFlash(id)` | `GET /v1/sessions/:id/flash` |
| `unflash(id, queryId)` | `DELETE /v1/sessions/:id/flash/:queryId` |
| `events(id)` | `GET /v1/sessions/:id/events` (SSE) |