mirror of
https://github.com/jina-ai/node-DeepResearch.git
synced 2025-12-25 22:16:49 +08:00
* feat: merge types and add tests - Merged types.ts and tracker.ts - Added Jest configuration and setup - Added comprehensive tests for tools and agent - Updated package.json with test scripts Co-Authored-By: Han Xiao <han.xiao@jina.ai> * chore: remove tracker.ts after merging into types.ts Co-Authored-By: Han Xiao <han.xiao@jina.ai> * fix: remove sensitive API keys from jest.setup.js Co-Authored-By: Han Xiao <han.xiao@jina.ai> * fix: improve error handling and test timeouts Co-Authored-By: Han Xiao <han.xiao@jina.ai> * feat: add token budget enforcement to TokenTracker Co-Authored-By: Han Xiao <han.xiao@jina.ai> * feat: add github actions workflow for CI and fix remaining issues Co-Authored-By: Han Xiao <han.xiao@jina.ai> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Han Xiao <han.xiao@jina.ai>
62 lines
1.8 KiB
TypeScript
62 lines
1.8 KiB
TypeScript
import https from 'https';
|
|
import { TokenTracker } from "../utils/token-tracker";
|
|
|
|
import { SearchResponse } from '../types';
|
|
|
|
export function search(query: string, token: string, tracker?: TokenTracker): Promise<{ response: SearchResponse, tokens: number }> {
|
|
return new Promise((resolve, reject) => {
|
|
if (!query.trim()) {
|
|
reject(new Error('Query cannot be empty'));
|
|
return;
|
|
}
|
|
|
|
const options = {
|
|
hostname: 's.jina.ai',
|
|
port: 443,
|
|
path: `/${encodeURIComponent(query)}`,
|
|
method: 'GET',
|
|
headers: {
|
|
'Accept': 'application/json',
|
|
'Authorization': `Bearer ${token}`,
|
|
'X-Retain-Images': 'none'
|
|
}
|
|
};
|
|
|
|
const req = https.request(options, (res) => {
|
|
let responseData = '';
|
|
res.on('data', (chunk) => responseData += chunk);
|
|
res.on('end', () => {
|
|
const response = JSON.parse(responseData) as SearchResponse;
|
|
console.log('Raw response:', response);
|
|
|
|
if (!query.trim()) {
|
|
reject(new Error('Query cannot be empty'));
|
|
return;
|
|
}
|
|
|
|
if (response.code === 402) {
|
|
reject(new Error(response.readableMessage || 'Insufficient balance'));
|
|
return;
|
|
}
|
|
|
|
if (!response.data || !Array.isArray(response.data)) {
|
|
reject(new Error('Invalid response format'));
|
|
return;
|
|
}
|
|
|
|
const totalTokens = response.data.reduce((sum, item) => sum + (item.usage?.tokens || 0), 0);
|
|
console.log('Search:', response.data.map(item => ({
|
|
title: item.title,
|
|
url: item.url,
|
|
tokens: item.usage?.tokens || 0
|
|
})));
|
|
(tracker || new TokenTracker()).trackUsage('search', totalTokens);
|
|
resolve({ response, tokens: totalTokens });
|
|
});
|
|
});
|
|
|
|
req.on('error', reject);
|
|
req.end();
|
|
});
|
|
}
|