mirror of
https://github.com/jina-ai/node-DeepResearch.git
synced 2026-03-22 07:29:35 +08:00
Merge branch 'main' of https://github.com/jina-ai/node-DeepResearch
This commit is contained in:
40
src/__tests__/cli.test.ts
Normal file
40
src/__tests__/cli.test.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { exec } from 'child_process';
|
||||
import { promisify } from 'util';
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
// Mock environment variables
|
||||
process.env.GEMINI_API_KEY = 'test-key';
|
||||
process.env.JINA_API_KEY = 'test-key';
|
||||
|
||||
jest.mock('../agent', () => ({
|
||||
getResponse: jest.fn().mockResolvedValue({
|
||||
result: {
|
||||
action: 'answer',
|
||||
answer: 'Test answer',
|
||||
references: []
|
||||
}
|
||||
})
|
||||
}));
|
||||
|
||||
describe('CLI', () => {
|
||||
test('shows version', async () => {
|
||||
const { stdout } = await execAsync('ts-node src/cli.ts --version');
|
||||
expect(stdout.trim()).toMatch(/\d+\.\d+\.\d+/);
|
||||
});
|
||||
|
||||
test('shows help', async () => {
|
||||
const { stdout } = await execAsync('ts-node src/cli.ts --help');
|
||||
expect(stdout).toContain('deepresearch');
|
||||
expect(stdout).toContain('AI-powered research assistant');
|
||||
});
|
||||
|
||||
test('handles invalid token budget', async () => {
|
||||
try {
|
||||
await execAsync('ts-node src/cli.ts -t invalid "test query"');
|
||||
fail('Should have thrown');
|
||||
} catch (error) {
|
||||
expect((error as { stderr: string }).stderr).toContain('Invalid token budget: must be a number');
|
||||
}
|
||||
});
|
||||
});
|
||||
48
src/cli.ts
Normal file
48
src/cli.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env node
|
||||
import { Command } from 'commander';
|
||||
import { getResponse } from './agent';
|
||||
import { version } from '../package.json';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name('deepresearch')
|
||||
.description('AI-powered research assistant that keeps searching until it finds the answer')
|
||||
.version(version)
|
||||
.argument('<query>', 'The research query to investigate')
|
||||
.option('-t, --token-budget <number>', 'Maximum token budget', (val) => {
|
||||
const num = parseInt(val);
|
||||
if (isNaN(num)) throw new Error('Invalid token budget: must be a number');
|
||||
return num;
|
||||
}, 1000000)
|
||||
.option('-m, --max-attempts <number>', 'Maximum bad attempts before giving up', (val) => {
|
||||
const num = parseInt(val);
|
||||
if (isNaN(num)) throw new Error('Invalid max attempts: must be a number');
|
||||
return num;
|
||||
}, 3)
|
||||
.option('-v, --verbose', 'Show detailed progress')
|
||||
.action(async (query: string, options: any) => {
|
||||
try {
|
||||
const { result } = await getResponse(
|
||||
query,
|
||||
parseInt(options.tokenBudget),
|
||||
parseInt(options.maxAttempts)
|
||||
);
|
||||
|
||||
if (result.action === 'answer') {
|
||||
console.log('\nAnswer:', result.answer);
|
||||
if (result.references?.length) {
|
||||
console.log('\nReferences:');
|
||||
result.references.forEach(ref => {
|
||||
console.log(`- ${ref.url}`);
|
||||
console.log(` "${ref.exactQuote}"`);
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error instanceof Error ? error.message : String(error));
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program.parse();
|
||||
Reference in New Issue
Block a user