# Ask Client SDK - Examples

This directory contains examples demonstrating how to use the Ask Client SDK in different environments.

## Examples Overview

### 1. Browser Example (`browser/index.html`)
A complete browser-based UI demo with:
- Configuration form for API settings
- Provider and model selection
- Streaming and non-streaming requests
- Beautiful, responsive UI
- Error handling

**How to run:**
```bash
# 1. Build the project
bun run build

# 2. Serve the example (using any static server)
cd examples/browser
python -m http.server 8000

# 3. Open http://localhost:8000 in your browser
```

### 2. Node.js Basic Example (`node/basic.ts`)
Demonstrates fundamental SDK usage:
- Non-streaming requests
- Streaming requests
- Multi-turn conversations
- Using different providers
- Health checks

**How to run:**
```bash
bun run example:basic
# or
bun run examples/node/basic.ts
```

### 3. Node.js Streaming Example (`node/streaming.ts`)
Advanced streaming techniques:
- Stream with visual feedback
- Collecting stream into buffer
- Raw stream access
- Parallel streaming requests
- Timeout handling

**How to run:**
```bash
bun run example:streaming
# or
bun run examples/node/streaming.ts
```

## Setup

### 1. Environment Variables

Create a `.env` file in the project root:

```bash
# Ask API (recommended)
ASK_API_KEY=ask_abc123...
WORKER_API_URL=http://localhost:59898/v1

# Or use provider keys directly
OPENAI_API_KEY=sk-...
CLAUDE_API_KEY=sk-ant-...
GROQ_API_KEY=gsk_...
GOOGLE_AI_API_KEY=...
```

### 2. Start the Worker

```bash
# Start the local worker
bun run worker:dev
```

### 3. Get Ask API Key (Optional)

If you want to use Ask's unified API key management:

```bash
# Sync your provider keys to get an Ask API key
bun run worker:sync-keys

# Your Ask API key will be saved in .env.ask
```

## Integration Examples

### React

```tsx
import { useState } from 'react';
import { AskClient } from '@livx.cc/ask/client';

const client = new AskClient({
  baseUrl: import.meta.env.VITE_ASK_API_URL,
  askApiKey: import.meta.env.VITE_ASK_API_KEY
});

function ChatComponent() {
  const [message, setMessage] = useState('');
  const [response, setResponse] = useState('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setLoading(true);
    setResponse('');

    try {
      const stream = await client.streamCompletion({
        messages: [{ role: 'user', content: message }]
      });

      for await (const chunk of stream) {
        setResponse(prev => prev + chunk);
      }
    } catch (error) {
      console.error('Error:', error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input
          value={message}
          onChange={(e) => setMessage(e.target.value)}
          disabled={loading}
        />
        <button type="submit" disabled={loading}>
          {loading ? 'Thinking...' : 'Send'}
        </button>
      </form>
      <div>{response}</div>
    </div>
  );
}
```

### Vue

```vue
<template>
  <div>
    <form @submit.prevent="handleSubmit">
      <input v-model="message" :disabled="loading" />
      <button type="submit" :disabled="loading">
        {{ loading ? 'Thinking...' : 'Send' }}
      </button>
    </form>
    <div>{{ response }}</div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { AskClient } from '@livx.cc/ask/client';

const client = new AskClient({
  baseUrl: import.meta.env.VITE_ASK_API_URL,
  askApiKey: import.meta.env.VITE_ASK_API_KEY
});

const message = ref('');
const response = ref('');
const loading = ref(false);

async function handleSubmit() {
  loading.value = true;
  response.value = '';

  try {
    const stream = await client.streamCompletion({
      messages: [{ role: 'user', content: message.value }]
    });

    for await (const chunk of stream) {
      response.value += chunk;
    }
  } catch (error) {
    console.error('Error:', error);
  } finally {
    loading.value = false;
  }
}
</script>
```

### Vanilla JavaScript

```html
<!DOCTYPE html>
<html>
<head>
  <title>Ask Client</title>
</head>
<body>
  <input id="message" type="text" placeholder="Ask something...">
  <button id="submit">Send</button>
  <div id="output"></div>

  <script type="module">
    import { AskClient } from './path/to/build/src/client/index.js';

    const client = new AskClient({
      baseUrl: 'http://localhost:59898/v1',
      askApiKey: 'your-key-here'
    });

    document.getElementById('submit').addEventListener('click', async () => {
      const message = document.getElementById('message').value;
      const output = document.getElementById('output');
      output.textContent = '';

      try {
        const stream = await client.streamCompletion({
          messages: [{ role: 'user', content: message }]
        });

        for await (const chunk of stream) {
          output.textContent += chunk;
        }
      } catch (error) {
        output.textContent = 'Error: ' + error.message;
      }
    });
  </script>
</body>
</html>
```

## Troubleshooting

### CORS Errors in Browser

If you get CORS errors, ensure your worker has proper CORS headers. The Ask worker should handle this automatically, but if using a custom server, add:

```typescript
headers: {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET,POST,OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type,Authorization'
}
```

### Module Resolution

If you get module resolution errors in the browser example, ensure you've:
1. Run `bun run build` to compile TypeScript
2. Check the import path in the HTML file matches your build output
3. Serve from a web server (not `file://` protocol)

### Authentication Issues

If requests fail with 401/403 errors:
1. Check your API key is correct
2. Ensure the base URL is correct
3. Verify the worker is running (`bun run worker:dev`)
4. Check provider API keys are configured

## Documentation

- **Main README**: [../README.md](../README.md)
- **Client SDK Docs**: [../docs/CLIENT_SDK.md](../docs/CLIENT_SDK.md)
- **Setup Guide**: [../docs/SETUP_GUIDE.md](../docs/SETUP_GUIDE.md)

## Support

For issues or questions:
- Check the documentation first
- Open an issue on GitHub
- Review the examples in this directory

## License

MIT © Livshitz





