npm package: @foruai/gatekeeper-client
Description: TypeScript client for the ForU Gatekeeper AI API — badges, Discord, profiles, and AI chat
Latest version: 0.2.0

# @foruai/gatekeeper-client

Full-featured TypeScript client for the [ForU Gatekeeper AI API](https://gatekeeper.foruai.io/swagger). Badge verification, Discord membership checks, user profiles, and AI chat — with built-in HMAC and Bearer authentication.

## Installation

```bash
npm install @foruai/gatekeeper-client
# or
pnpm add @foruai/gatekeeper-client
# or
bun add @foruai/gatekeeper-client
```

## Quick Start

### Server-side (with HMAC secret)

```typescript
import { GatekeeperClient } from '@foruai/gatekeeper-client'

const client = new GatekeeperClient({
  baseUrl: 'https://gatekeeper.foruai.io',
  secret: process.env.HMAC_SECRET!, // auto-signs every request
})

// Chat with the AI agent
const reply = await client.chat('check badges for @user123')
console.log(reply)

// Verify badges
const badges = await client.verifyBadges({ user_address: '0x...' })
console.log(badges.badges)

// Check Discord membership
const discord = await client.checkDiscord({ username: 'user123' })
console.log(discord.servers)
```

### Server-side (with Bearer token)

```typescript
const client = new GatekeeperClient({
  baseUrl: 'https://gatekeeper.foruai.io',
  bearerToken: process.env.API_KEY!,
})

const profile = await client.getProfile({ user_address: '0x...' })
```

### Browser (with pre-signed HMAC token)

Your backend generates the token, frontend uses it:

```typescript
// 1. Get token from your backend
const tokenRes = await fetch('/api/gatekeeper-token')
const token = await tokenRes.json() // HmacToken

// 2. Use it with the client
import { GatekeeperClient } from '@foruai/gatekeeper-client'

const client = new GatekeeperClient({
  baseUrl: 'https://gatekeeper.foruai.io',
})

const reply = await client.chat('check badges for @user123', { token })
```

## API Reference

### Constructor

```typescript
new GatekeeperClient(options: GatekeeperClientOptions)
```

| Option | Type | Required | Description |
|--------|------|----------|-------------|
| `baseUrl` | `string` | Yes | API base URL (e.g. `https://gatekeeper.foruai.io`) |
| `secret` | `string` | No | HMAC secret — auto-signs all requests |
| `bearerToken` | `string` | No | API key for Bearer authentication |
| `sessionId` | `string` | No | Default chat session ID for conversation continuity |

Auth priority: per-request token > HMAC secret > Bearer token.

---

### Chat

#### `client.chat(message, options?): Promise<string>`

Send a message and get the AI reply.

```typescript
const reply = await client.chat('does @user123 have the OG badge?')
// => "Yes! @user123 holds the OG Badge (verified, 100% confidence)..."
```

#### `client.chatWithSession(message, options?): Promise<ChatResult>`

Same as `chat()` but returns the full response including session ID and routing info.

```typescript
const result = await client.chatWithSession('check badges for @user123', {
  mode: 'hybrid', // 'hybrid' | 'fast' | 'agent'
})
console.log(result.reply)     // AI-formatted response
console.log(result.sessionId) // session ID for follow-ups
console.log(result.routed)    // matched intent (e.g. 'verify_badge')
```

**Chat options:**

| Option | Type | Description |
|--------|------|-------------|
| `token` | `HmacToken` | Per-request HMAC token (overrides client auth) |
| `mode` | `'hybrid' \| 'fast' \| 'agent'` | `hybrid` (default): intent routing + AI formatting. `fast`: intent routing only. `agent`: full AI agent. |
| `sessionId` | `string` | Session ID for conversation continuity |

---

### Badge Verification

#### `client.verifyBadges(params): Promise<VerifyBadgeResponse>`

Verify badge ownership with confidence scoring, on-chain proofs, and rule breakdowns.

```typescript
const result = await client.verifyBadges({
  user_address: '0x1234...',
  // or: username: 'user123'
  // or: discord_username: 'user#1234'
  badge_id: 5, // optional: filter to specific badge
})

for (const badge of result.badges) {
  console.log(`${badge.name}: ${badge.status} (${badge.confidence * 100}%)`)
  console.log(`  Type: ${badge.badge_type}`)
  console.log(`  Rules: ${badge.rules_breakdown.total} total`)
  if (badge.onchain_proof) {
    console.log(`  On-chain: ${badge.onchain_proof.verified_onchain}`)
  }
  if (badge.awarded_via) {
    console.log(`  From: ${badge.awarded_via.campaign_name || badge.awarded_via.quest_name}`)
  }
  if (badge.minting?.is_minted) {
    console.log(`  Minted: ${badge.minting.chain_name} tx ${badge.minting.mint_hash}`)
  }
}
```

---

### Badge Catalog

#### `client.listBadges(): Promise<{ badges: BadgeInfo[] }>`

List all available badges (no auth required).

```typescript
const { badges } = await client.listBadges()
for (const badge of badges) {
  console.log(`#${badge.id} ${badge.name} — ${badge.description}`)
}
```

---

### Discord

#### `client.checkDiscord(params): Promise<DiscordCheckResponse>`

Check Discord server membership and roles.

```typescript
const result = await client.checkDiscord({
  username: 'user123',
  server_id: '123456789', // optional: filter to specific server
})

console.log(`Discord linked: ${result.linked}`)
console.log(`Username: ${result.discord_username}`)

for (const server of result.servers) {
  console.log(`${server.server_name}: ${server.is_member ? 'Member' : 'Not member'}`)
  if (server.roles?.length) {
    console.log(`  Roles: ${server.roles.join(', ')}`)
  }
}
```

---

### Profile

#### `client.getProfile(params): Promise<ProfileResponse>`

Get a user's linked accounts and badge summary.

```typescript
const profile = await client.getProfile({ user_address: '0x...' })

console.log('Wallets:', profile.wallets.map(w => w.address))
console.log('Twitter:', profile.twitter.username)
console.log('Discord:', profile.discord.username)
console.log(`Badges: ${profile.badges.total} total, ${profile.badges.minted} minted`)
```

---

### Discovery

#### `client.getServices(): Promise<ServicesCatalog>`

Get the API service catalog (no auth required).

```typescript
const catalog = await client.getServices()
for (const service of catalog.services) {
  console.log(`${service.name}: ${service.endpoint}`)
}
```

#### `client.health(): Promise<HealthResponse>`

Health check (no auth required).

```typescript
const health = await client.health()
console.log(health.status) // 'ok'
console.log(health.db)     // 'connected'
```

---

### Session Management

The client tracks `sessionId` automatically for chat conversations:

```typescript
const client = new GatekeeperClient({ baseUrl: '...', secret: '...' })

await client.chat('check badges for @user123')
// client.sessionId is now set

await client.chat('what about their Discord?')
// uses same session — AI remembers context

// Reset session
client.sessionId = null
```

## Authentication Modes

| Mode | Use Case | Setup |
|------|----------|-------|
| **HMAC (auto)** | Server-side apps | Pass `secret` to constructor |
| **Bearer** | Server-to-server | Pass `bearerToken` to constructor |
| **HMAC (per-request)** | Browser apps | Pass `token` to each method call |

### HMAC Flow for Browser Apps

```
Browser  →  Your Backend  →  GatekeeperSigner.createToken()  →  token
Browser  →  client.chat(msg, { token })  →  Gatekeeper API  →  reply
```

Use [`@foruai/gatekeeper-server`](https://www.npmjs.com/package/@foruai/gatekeeper-server) on your backend to generate tokens.

## Error Handling

All methods throw on HTTP errors with the server's error message:

```typescript
try {
  await client.verifyBadges({ user_address: '0xinvalid' })
} catch (err) {
  console.error(err.message) // e.g. "User not found"
}
```

## Runtime Compatibility

| Runtime | Status |
|---------|--------|
| Node.js 18+ | Supported (native `fetch`) |
| Bun | Supported |
| Deno | Supported |
| Browsers | Supported |
| Edge (Cloudflare Workers, Vercel Edge) | Supported |

Zero dependencies beyond `@foruai/shared` and `@foruai/gatekeeper-server`.

## Companion Packages

- [`@foruai/shared`](https://www.npmjs.com/package/@foruai/shared) — Shared types and constants
- [`@foruai/gatekeeper-server`](https://www.npmjs.com/package/@foruai/gatekeeper-server) — Server-side HMAC token signing

## License

MIT