@vinitngr/serper-v 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/SKILL.md +20 -0
  2. package/dist/index.js +105 -0
  3. package/package.json +38 -0
package/SKILL.md ADDED
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: serperV
3
+ description: Real-time web search (news, places, organic) via Serper API.
4
+ ---
5
+
6
+ # Serper Search
7
+
8
+ ## Usage
9
+ ```bash
10
+ serperV search --query "Term" --type search --limit 5
11
+ ```
12
+ - **Auth**: `serperV auth <key>` (saves to `~/.vinit/credentials.json`) or `export SERPER_API_KEY=key`.
13
+ - **Types**: `search`, `news`, `places`, `images`, `scholar`, `videos`.
14
+ - **Flags**: `-q` (query), `-l` (limit), `-t` (type), `-g` (country), `-h` (language).
15
+
16
+ ## Installation
17
+ `npm install -g @vinitngr/serper-v`
18
+
19
+ ## Errors
20
+ If 401/403: Run `serperV auth <new_key>`.
package/dist/index.js ADDED
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import axios from 'axios';
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ import os from 'os';
7
+ const CONFIG_DIR = path.join(os.homedir(), '.vinit');
8
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'credentials.json');
9
+ function getStoredApiKey() {
10
+ try {
11
+ if (fs.existsSync(CONFIG_FILE)) {
12
+ const config = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8'));
13
+ return config.serperV || null;
14
+ }
15
+ }
16
+ catch (error) {
17
+ }
18
+ return null;
19
+ }
20
+ const program = new Command();
21
+ program
22
+ .name('serperV')
23
+ .description('Optimal Serper search for AI agents (TypeScript)')
24
+ .version('2.1.0');
25
+ program
26
+ .command('auth')
27
+ .description('Store Serper API key persistently')
28
+ .argument('<key>', 'Your Serper API key')
29
+ .action((key) => {
30
+ try {
31
+ if (!fs.existsSync(CONFIG_DIR)) {
32
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
33
+ }
34
+ const config = fs.existsSync(CONFIG_FILE)
35
+ ? JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8'))
36
+ : {};
37
+ config.serperV = key;
38
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
39
+ console.log('\nāœ… API Key stored successfully in ~/.vinit/credentials.json\n');
40
+ }
41
+ catch (error) {
42
+ console.error('\nāŒ Failed to store API key:', error.message, '\n');
43
+ process.exit(1);
44
+ }
45
+ });
46
+ program
47
+ .command('search')
48
+ .description('Search the web using Serper API')
49
+ .requiredOption('-q, --query <string>', 'Search query')
50
+ .option('-l, --limit <number>', 'Number of results', (val) => parseInt(val), 10)
51
+ .option('-t, --type <string>', 'Search type (search, news, places, images, scholar, videos, shopping)', 'search')
52
+ .option('-g, --gl <string>', 'Country code (e.g., us, in)', 'us')
53
+ .option('-h, --hl <string>', 'Language code (e.g., en, hi)', 'en')
54
+ .option('-p, --page <number>', 'Page number', (val) => parseInt(val), 1)
55
+ .option('-a, --autocorrect <boolean>', 'Enable/disable autocorrect', (val) => val === 'true', true)
56
+ .action(async (options) => {
57
+ const apiKey = process.env.SERPER_API_KEY || getStoredApiKey();
58
+ if (!apiKey) {
59
+ console.error('\nāŒ Error: Serper API key not found.');
60
+ console.error('šŸ’” Please set it using: serperV auth <your_key>');
61
+ console.error('šŸ› ļø Or via environment: export SERPER_API_KEY="your_key_here"\n');
62
+ process.exit(1);
63
+ }
64
+ const config = {
65
+ method: 'post',
66
+ url: `https://google.serper.dev/${options.type}`,
67
+ headers: {
68
+ 'X-API-KEY': apiKey,
69
+ 'Content-Type': 'application/json'
70
+ },
71
+ data: {
72
+ q: options.query,
73
+ num: options.limit,
74
+ gl: options.gl,
75
+ hl: options.hl,
76
+ page: options.page,
77
+ autocorrect: options.autocorrect
78
+ }
79
+ };
80
+ try {
81
+ const response = await axios(config);
82
+ console.log(JSON.stringify(response.data, null, 2));
83
+ }
84
+ catch (error) {
85
+ if (axios.isAxiosError(error)) {
86
+ const axiosError = error;
87
+ if (axiosError.response?.status === 401 || axiosError.response?.status === 403) {
88
+ console.error('\nāŒ Error: Unauthorized. Your Serper API key is invalid or expired.');
89
+ console.error('šŸ’” Update it using: serperV auth <new_key>\n');
90
+ }
91
+ else {
92
+ console.error('\nāŒ Search failed:', axiosError.response?.data?.message || axiosError.message);
93
+ if (axiosError.response?.data) {
94
+ console.error('Details:', JSON.stringify(axiosError.response.data, null, 2));
95
+ }
96
+ console.error('');
97
+ }
98
+ }
99
+ else {
100
+ console.error('\nāŒ An unexpected error occurred:', error.message, '\n');
101
+ }
102
+ process.exit(1);
103
+ }
104
+ });
105
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@vinitngr/serper-v",
3
+ "version": "1.0.0",
4
+ "description": "Optimal Serper Search CLI for AI Agents",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "serperV": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "SKILL.md"
12
+ ],
13
+ "type": "module",
14
+ "scripts": {
15
+ "build": "tsc && chmod +x dist/index.js",
16
+ "test": "echo \"Error: no test specified\" && exit 1",
17
+ "test:search": "node test-serper.js"
18
+ },
19
+ "keywords": [
20
+ "serper",
21
+ "search",
22
+ "cli",
23
+ "ai",
24
+ "agent"
25
+ ],
26
+ "author": "vinitngr",
27
+ "license": "ISC",
28
+ "dependencies": {
29
+ "commander": "^11.0.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/commander": "^2.12.0",
33
+ "@types/node": "^25.2.1",
34
+ "axios": "^1.13.4",
35
+ "ts-node": "^10.9.2",
36
+ "typescript": "^5.9.3"
37
+ }
38
+ }