kagi-client.ts•3.66 kB
import axios, { AxiosInstance } from 'axios';
export interface SearchResult {
t: number;
title: string;
url: string;
snippet: string;
published?: string;
}
export interface SearchResponse {
data: SearchResult[];
}
export interface SummarizerOptions {
url: string;
engine?: 'cecil' | 'agnes' | 'daphne' | 'muriel';
summary_type?: 'summary' | 'takeaway';
target_language?: string;
}
export interface SummarizerResponse {
data: {
output: string;
};
}
export class KagiClient {
private axios: AxiosInstance;
private apiKey: string;
constructor() {
const apiKey = process.env.KAGI_API_KEY;
if (!apiKey) {
throw new Error('KAGI_API_KEY environment variable is required');
}
this.apiKey = apiKey;
this.axios = axios.create({
baseURL: 'https://kagi.com/api/v0',
headers: {
'Authorization': `Bot ${this.apiKey}`,
'Content-Type': 'application/json',
},
timeout: 30000,
});
}
async search(query: string): Promise<SearchResponse> {
try {
const response = await this.axios.get('/search', {
params: { q: query },
});
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
let errorMessage = 'Unknown error';
if (error.response?.data) {
if (typeof error.response.data === 'string') {
errorMessage = error.response.data;
} else if (error.response.data.error) {
// Kagi API returns error as an array
if (Array.isArray(error.response.data.error)) {
errorMessage = error.response.data.error.map((e: any) => e.msg).join('; ');
} else {
errorMessage = error.response.data.error;
}
} else if (error.response.data.message) {
errorMessage = error.response.data.message;
} else {
errorMessage = JSON.stringify(error.response.data);
}
} else {
errorMessage = error.response?.statusText || error.message;
}
const statusCode = error.response?.status;
throw new Error(`Kagi search error (${statusCode}): ${errorMessage}`);
}
throw error;
}
}
async summarize(options: SummarizerOptions): Promise<SummarizerResponse> {
try {
const response = await this.axios.post('/summarize', {
url: options.url,
engine: options.engine || 'cecil',
summary_type: options.summary_type,
target_language: options.target_language,
});
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
let errorMessage = 'Unknown error';
if (error.response?.data) {
if (typeof error.response.data === 'string') {
errorMessage = error.response.data;
} else if (error.response.data.error) {
// Kagi API returns error as an array
if (Array.isArray(error.response.data.error)) {
errorMessage = error.response.data.error.map((e: any) => e.msg).join('; ');
} else {
errorMessage = error.response.data.error;
}
} else if (error.response.data.message) {
errorMessage = error.response.data.message;
} else {
errorMessage = JSON.stringify(error.response.data);
}
} else {
errorMessage = error.response?.statusText || error.message;
}
const statusCode = error.response?.status;
throw new Error(`Kagi summarizer error (${statusCode}): ${errorMessage}`);
}
throw error;
}
}
}