@avalw/search-worker 1.0.2 → 1.1.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 (4) hide show
  1. package/README.md +270 -94
  2. package/bin/cli.js +23 -16
  3. package/lib/worker.js +190 -29
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -7,39 +7,217 @@ Free privacy-focused search API in exchange for compute power.
7
7
 
8
8
  ## What is AVALW Worker?
9
9
 
10
- AVALW Worker is a lightweight Node.js application that runs on your server and contributes a small amount of CPU power to the AVALW distributed network. In return, you get **free, unlimited access** to the AVALW Search API - a privacy-focused search engine that doesn't track users.
10
+ AVALW Worker is a lightweight Node.js application that runs on your server and contributes CPU power to the AVALW distributed network. In return, you get **free access** to the AVALW Search API - a privacy-focused search engine that doesn't track users. Your API quota scales with your contribution.
11
11
 
12
12
  **No tracking. No ads. No data collection. Just search.**
13
13
 
14
14
  ## How It Works
15
15
 
16
16
  ```
17
- ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
18
- Your Server │ │ AVALW Network │ │ Your Users
19
- │ │ │ │ │ │
20
- ┌───────────┐ │ │ │ │
21
- │ Worker │──┼─────►│ Contributes │ │
22
- Process │ │ │ compute power │ │ │
23
- └───────────┘ │ │ │ │
24
- │ │ │ │ │ │
25
- ┌───────────┐ ┌───────────┐ │
26
- Your App │◄─┼──────┤ Search API │◄─────┼──│ Search
27
- (free access) │ │ Queries │ │
28
- └───────────┘ └───────────┘ │
29
- └─────────────────┘ └─────────────────┘ └─────────────────┘
17
+ ┌─────────────────────────────────────────────────────────────────────────────┐
18
+ AVALW WORKER SYSTEM
19
+ ├─────────────────────────────────────────────────────────────────────────────┤
20
+
21
+ YOUR SERVER AVALW NETWORK YOUR USERS
22
+ ─────────── ──────────── ──────────
23
+
24
+ ┌─────────────┐ ┌─────────────┐
25
+ Worker ───────────────►│ Compute
26
+ Process Contributes Pool │ │
27
+ Core-Hours
28
+ CPU: ████░ │ │ ┌─┐┌─┐┌─┐┌─┐│
29
+ │ │ 70% │ │ └─┘└─┘└─┘└─┘│ │
30
+ │ └─────────────┘ └──────┬──────┘ │
31
+ │ │ │ │
32
+ │ │ Reports: │ Calculates: │
33
+ │ │ • CPU cores │ • Core-hours │
34
+ │ │ • CPU speed (GHz) │ • Your tier │
35
+ │ │ • Usage % │ • API quota │
36
+ │ │ • Online time │ │
37
+ │ ▼ ▼ │
38
+ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
39
+ │ │ Your App │◄────────────────│ Search API │◄───────│ Search │ │
40
+ │ │ │ Free access │ (quota │ │ Query │ │
41
+ │ │ // search │ based on │ based) │ │ │ │
42
+ │ │ fetch(..); │ contribution │ │ │ "weather" │ │
43
+ │ └─────────────┘ └─────────────┘ └─────────────┘ │
44
+ │ │
45
+ └─────────────────────────────────────────────────────────────────────────────┘
30
46
  ```
31
47
 
32
- ## Tiers
48
+ ## Core-Hours System
33
49
 
34
- Choose the tier that fits your needs:
50
+ Unlike simple percentage-based systems, AVALW uses **Core-Hours** - a fair metric that accounts for your actual hardware contribution.
35
51
 
36
- | Tier | Requests/Day | CPU Contribution |
37
- |------------|--------------|------------------|
38
- | Starter | 1,000 | 2% |
39
- | Basic | 5,000 | 5% |
40
- | Pro | 20,000 | 10% |
41
- | Business | 50,000 | 20% |
42
- | Enterprise | 500,000 | 50% |
52
+ ### What is a Core-Hour?
53
+
54
+ ```
55
+ ┌─────────────────────────────────────────────────────────────────────────────┐
56
+ │ CORE-HOUR CALCULATION │
57
+ ├─────────────────────────────────────────────────────────────────────────────┤
58
+ │ │
59
+ │ Core-Hours = CPU Cores × (CPU Speed ÷ 3.0 GHz) × Usage% × Hours Online │
60
+ │ │
61
+ │ ═══════════════════════════════════════════════════════════════════════ │
62
+ │ │
63
+ │ EXAMPLE: Intel i7-10700 running for 24 hours at 50% │
64
+ │ │
65
+ │ • Cores: 8 │
66
+ │ • Speed: 2.9 GHz base (normalized to 3.0 GHz baseline) │
67
+ │ • Usage: 50% │
68
+ │ • Time: 24 hours │
69
+ │ │
70
+ │ Calculation: 8 × (2.9 ÷ 3.0) × 0.50 × 24 = 92.8 core-hours/day │
71
+ │ │
72
+ └─────────────────────────────────────────────────────────────────────────────┘
73
+ ```
74
+
75
+ ### Tiers Based on Core-Hours
76
+
77
+ | Tier | Requests/Day | Core-Hours/Day | Minimum Cores |
78
+ |------|--------------|----------------|---------------|
79
+ | **Starter** | 1,000 | 3 | 3 cores |
80
+ | **Basic** | 5,000 | 12 | 4 cores |
81
+ | **Pro** | 20,000 | 36 | 6 cores |
82
+ | **Business** | 50,000 | 72 | 8 cores |
83
+ | **Enterprise** | 500,000 | 240 | 16 cores |
84
+
85
+ ## Real CPU Examples
86
+
87
+ ### Desktop CPUs
88
+
89
+ ```
90
+ ┌─────────────────────────────────────────────────────────────────────────────┐
91
+ │ DESKTOP CPU EXAMPLES │
92
+ ├─────────────────────────────────────────────────────────────────────────────┤
93
+ │ │
94
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
95
+ │ │ Intel Core i5-10400 (6 cores @ 2.9 GHz) │ │
96
+ │ ├─────────────────────────────────────────────────────────────────────┤ │
97
+ │ │ At 50% for 24h: 6 × 0.97 × 0.50 × 24 = 69.8 core-hours │ │
98
+ │ │ ✓ Qualifies for: PRO tier (20,000 requests/day) │ │
99
+ │ │ │ │
100
+ │ │ At 30% for 24h: 6 × 0.97 × 0.30 × 24 = 41.9 core-hours │ │
101
+ │ │ ✓ Qualifies for: PRO tier (20,000 requests/day) │ │
102
+ │ └─────────────────────────────────────────────────────────────────────┘ │
103
+ │ │
104
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
105
+ │ │ Intel Core i7-10700 (8 cores @ 2.9 GHz) │ │
106
+ │ ├─────────────────────────────────────────────────────────────────────┤ │
107
+ │ │ At 50% for 24h: 8 × 0.97 × 0.50 × 24 = 93.1 core-hours │ │
108
+ │ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
109
+ │ │ │ │
110
+ │ │ At 25% for 24h: 8 × 0.97 × 0.25 × 24 = 46.6 core-hours │ │
111
+ │ │ ✓ Qualifies for: PRO tier (20,000 requests/day) │ │
112
+ │ └─────────────────────────────────────────────────────────────────────┘ │
113
+ │ │
114
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
115
+ │ │ Intel Core i9-10900 (10 cores @ 2.8 GHz) │ │
116
+ │ ├─────────────────────────────────────────────────────────────────────┤ │
117
+ │ │ At 50% for 24h: 10 × 0.93 × 0.50 × 24 = 111.6 core-hours │ │
118
+ │ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
119
+ │ │ │ │
120
+ │ │ At 80% for 24h: 10 × 0.93 × 0.80 × 24 = 178.6 core-hours │ │
121
+ │ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
122
+ │ └─────────────────────────────────────────────────────────────────────┘ │
123
+ │ │
124
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
125
+ │ │ AMD Ryzen 5 5600X (6 cores @ 3.7 GHz) │ │
126
+ │ ├─────────────────────────────────────────────────────────────────────┤ │
127
+ │ │ At 50% for 24h: 6 × 1.23 × 0.50 × 24 = 88.6 core-hours │ │
128
+ │ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
129
+ │ └─────────────────────────────────────────────────────────────────────┘ │
130
+ │ │
131
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
132
+ │ │ AMD Ryzen 7 5800X (8 cores @ 3.8 GHz) │ │
133
+ │ ├─────────────────────────────────────────────────────────────────────┤ │
134
+ │ │ At 50% for 24h: 8 × 1.27 × 0.50 × 24 = 121.9 core-hours │ │
135
+ │ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
136
+ │ └─────────────────────────────────────────────────────────────────────┘ │
137
+ │ │
138
+ └─────────────────────────────────────────────────────────────────────────────┘
139
+ ```
140
+
141
+ ### Server CPUs
142
+
143
+ ```
144
+ ┌─────────────────────────────────────────────────────────────────────────────┐
145
+ │ SERVER CPU EXAMPLES │
146
+ ├─────────────────────────────────────────────────────────────────────────────┤
147
+ │ │
148
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
149
+ │ │ Intel Xeon E-2288G (8 cores @ 3.7 GHz) │ │
150
+ │ ├─────────────────────────────────────────────────────────────────────┤ │
151
+ │ │ At 30% for 24h: 8 × 1.23 × 0.30 × 24 = 70.8 core-hours │ │
152
+ │ │ ✓ Qualifies for: PRO tier (20,000 requests/day) │ │
153
+ │ │ │ │
154
+ │ │ At 50% for 24h: 8 × 1.23 × 0.50 × 24 = 118.1 core-hours │ │
155
+ │ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
156
+ │ └─────────────────────────────────────────────────────────────────────┘ │
157
+ │ │
158
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
159
+ │ │ AMD EPYC 7302 (16 cores @ 3.0 GHz) │ │
160
+ │ ├─────────────────────────────────────────────────────────────────────┤ │
161
+ │ │ At 30% for 24h: 16 × 1.00 × 0.30 × 24 = 115.2 core-hours │ │
162
+ │ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
163
+ │ │ │ │
164
+ │ │ At 60% for 24h: 16 × 1.00 × 0.60 × 24 = 230.4 core-hours │ │
165
+ │ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
166
+ │ └─────────────────────────────────────────────────────────────────────┘ │
167
+ │ │
168
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
169
+ │ │ AMD EPYC 7742 (64 cores @ 2.25 GHz) │ │
170
+ │ ├─────────────────────────────────────────────────────────────────────┤ │
171
+ │ │ At 20% for 24h: 64 × 0.75 × 0.20 × 24 = 230.4 core-hours │ │
172
+ │ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
173
+ │ │ │ │
174
+ │ │ At 50% for 24h: 64 × 0.75 × 0.50 × 24 = 576.0 core-hours │ │
175
+ │ │ ✓ Qualifies for: ENTERPRISE tier (500,000 requests/day) │ │
176
+ │ └─────────────────────────────────────────────────────────────────────┘ │
177
+ │ │
178
+ └─────────────────────────────────────────────────────────────────────────────┘
179
+ ```
180
+
181
+ ### VPS / Cloud Examples
182
+
183
+ ```
184
+ ┌─────────────────────────────────────────────────────────────────────────────┐
185
+ │ VPS / CLOUD EXAMPLES │
186
+ ├─────────────────────────────────────────────────────────────────────────────┤
187
+ │ │
188
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
189
+ │ │ Basic VPS (2 vCPU @ 2.5 GHz) - ~$5/month │ │
190
+ │ ├─────────────────────────────────────────────────────────────────────┤ │
191
+ │ │ At 80% for 24h: 2 × 0.83 × 0.80 × 24 = 31.9 core-hours │ │
192
+ │ │ ✗ Not enough for Starter (needs 3 cores minimum) │ │
193
+ │ └─────────────────────────────────────────────────────────────────────┘ │
194
+ │ │
195
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
196
+ │ │ Standard VPS (4 vCPU @ 2.5 GHz) - ~$20/month │ │
197
+ │ ├─────────────────────────────────────────────────────────────────────┤ │
198
+ │ │ At 50% for 24h: 4 × 0.83 × 0.50 × 24 = 39.8 core-hours │ │
199
+ │ │ ✓ Qualifies for: PRO tier (20,000 requests/day) │ │
200
+ │ └─────────────────────────────────────────────────────────────────────┘ │
201
+ │ │
202
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
203
+ │ │ Premium VPS (8 vCPU @ 3.0 GHz) - ~$80/month │ │
204
+ │ ├─────────────────────────────────────────────────────────────────────┤ │
205
+ │ │ At 50% for 24h: 8 × 1.00 × 0.50 × 24 = 96.0 core-hours │ │
206
+ │ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
207
+ │ └─────────────────────────────────────────────────────────────────────┘ │
208
+ │ │
209
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │
210
+ │ │ AWS EC2 c5.4xlarge (16 vCPU @ 3.4 GHz) │ │
211
+ │ ├─────────────────────────────────────────────────────────────────────┤ │
212
+ │ │ At 40% for 24h: 16 × 1.13 × 0.40 × 24 = 173.6 core-hours │ │
213
+ │ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
214
+ │ │ │ │
215
+ │ │ At 70% for 24h: 16 × 1.13 × 0.70 × 24 = 303.7 core-hours │ │
216
+ │ │ ✓ Qualifies for: ENTERPRISE tier (500,000 requests/day) │ │
217
+ │ └─────────────────────────────────────────────────────────────────────┘ │
218
+ │ │
219
+ └─────────────────────────────────────────────────────────────────────────────┘
220
+ ```
43
221
 
44
222
  ## Quick Start
45
223
 
@@ -61,49 +239,41 @@ npm install -g @avalw/search-worker
61
239
  avalw-worker YOUR_WORKER_TOKEN
62
240
  ```
63
241
 
64
- You should see:
242
+ You'll see real-time stats:
65
243
  ```
66
- ╔═══════════════════════════════════════════════╗
67
- AVALW Search Worker v1.0.0
68
- ╠═══════════════════════════════════════════════╣
69
- ║ Free Search API in exchange for compute
70
- ╚═══════════════════════════════════════════════╝
71
-
72
- API URL: https://worker.avalw.org
73
- Token: abc123def456...
74
-
75
- [10:30:45] Heartbeat OK | Tier: Starter | CPU Limit: 2%
76
- Worker started. Press Ctrl+C to stop.
244
+ ╔═══════════════════════════════════════════════════════════════════╗
245
+ AVALW Search Worker v1.1.0
246
+ ╠═══════════════════════════════════════════════════════════════════╣
247
+ ║ Free Search API in exchange for compute
248
+ ╚═══════════════════════════════════════════════════════════════════╝
249
+
250
+ System Info:
251
+ ├─ CPU: Intel(R) Core(TM) i7-10700 @ 2.90GHz
252
+ ├─ Cores: 8
253
+ ├─ Speed Factor: 0.97x (normalized to 3.0 GHz)
254
+ └─ Memory: 32 GB
255
+
256
+ Worker Status:
257
+ ├─ Token: abc123def456...
258
+ ├─ API URL: https://worker.avalw.org
259
+ └─ Target Usage: 50%
260
+
261
+ [10:30:45] ✓ Heartbeat OK
262
+ ├─ Core-Hours Today: 46.5 / 72 needed for BUSINESS
263
+ ├─ Current Tier: PRO (20,000 req/day)
264
+ ├─ Usage Today: 1,234 / 20,000
265
+ └─ Online: 12h 35m
266
+
267
+ Press Ctrl+C to stop.
77
268
  ```
78
269
 
79
270
  ### 4. Use the Search API
80
271
 
81
- Once your worker is running, make API requests from your whitelisted domains:
82
-
83
272
  ```javascript
84
- // Node.js / JavaScript
85
273
  const response = await fetch(
86
274
  'https://worker.avalw.org/api/search?q=your+query&token=YOUR_TOKEN'
87
275
  );
88
276
  const results = await response.json();
89
- console.log(results);
90
- ```
91
-
92
- ```python
93
- # Python
94
- import requests
95
-
96
- response = requests.get(
97
- 'https://worker.avalw.org/api/search',
98
- params={'q': 'your query', 'token': 'YOUR_TOKEN'}
99
- )
100
- results = response.json()
101
- print(results)
102
- ```
103
-
104
- ```bash
105
- # cURL
106
- curl "https://worker.avalw.org/api/search?q=your+query&token=YOUR_TOKEN"
107
277
  ```
108
278
 
109
279
  ## Running as a Service
@@ -114,9 +284,12 @@ curl "https://worker.avalw.org/api/search?q=your+query&token=YOUR_TOKEN"
114
284
  # Install PM2
115
285
  npm install -g pm2
116
286
 
117
- # Start worker
287
+ # Start worker with 50% CPU target
118
288
  pm2 start avalw-worker -- YOUR_WORKER_TOKEN
119
289
 
290
+ # Or specify custom CPU percentage
291
+ pm2 start avalw-worker -- YOUR_WORKER_TOKEN --cpu 30
292
+
120
293
  # Save for auto-restart
121
294
  pm2 save
122
295
  pm2 startup
@@ -161,26 +334,6 @@ docker build -t avalw-worker .
161
334
  docker run -d --name avalw-worker avalw-worker
162
335
  ```
163
336
 
164
- ## Programmatic Usage
165
-
166
- You can also use the worker programmatically in your Node.js application:
167
-
168
- ```javascript
169
- const { AvalwWorker } = require('@avalw/search-worker');
170
-
171
- const worker = new AvalwWorker('YOUR_WORKER_TOKEN');
172
-
173
- // Start the worker
174
- await worker.start();
175
-
176
- // Get system info
177
- const info = worker.getSystemInfo();
178
- console.log(info);
179
-
180
- // Stop the worker
181
- await worker.stop();
182
- ```
183
-
184
337
  ## API Reference
185
338
 
186
339
  ### Search Endpoint
@@ -189,7 +342,6 @@ await worker.stop();
189
342
  GET https://worker.avalw.org/api/search
190
343
  ```
191
344
 
192
- **Parameters:**
193
345
  | Parameter | Type | Required | Description |
194
346
  |-----------|--------|----------|--------------------------------|
195
347
  | q | string | Yes | Search query |
@@ -209,29 +361,46 @@ GET https://worker.avalw.org/api/search
209
361
  }
210
362
  ],
211
363
  "total": 100,
212
- "page": 1
364
+ "page": 1,
365
+ "tier": "PRO",
366
+ "usage": {
367
+ "today": 1234,
368
+ "limit": 20000,
369
+ "core_hours": 46.5
370
+ }
213
371
  }
214
372
  ```
215
373
 
216
- ## Domain Whitelisting
374
+ ## FAQ
217
375
 
218
- For security, API requests only work from whitelisted domains. Manage your domains at [worker.avalw.org](https://worker.avalw.org) dashboard.
376
+ ### Why do I need minimum 3 cores?
219
377
 
220
- ## Troubleshooting
378
+ The AVALW network requires meaningful contributions to remain sustainable. A 3-core minimum ensures:
379
+ - Fair distribution of compute power
380
+ - Quality of service for all users
381
+ - Sustainable network operation
221
382
 
222
- ### Worker won't connect
223
- - Check your internet connection
224
- - Verify your token is correct
225
- - Ensure port 443 (HTTPS) is not blocked
383
+ ### Can I run on a 2-core VPS?
226
384
 
227
- ### API returns "Worker offline"
228
- - Make sure your worker is running
229
- - Check the worker console for errors
230
- - Worker must send heartbeat every 30 seconds
385
+ Unfortunately, 2 cores don't meet the minimum requirement. Consider:
386
+ - Upgrading to a 4-core VPS
387
+ - Running on a different server with more cores
388
+ - Combining with another server (coming soon: multi-worker support)
231
389
 
232
- ### Rate limit exceeded
233
- - Upgrade to a higher tier for more requests
234
- - Wait until the daily limit resets (midnight UTC)
390
+ ### How is my tier calculated?
391
+
392
+ Your tier is recalculated every hour based on your rolling 24-hour core-hours contribution. The formula:
393
+
394
+ ```
395
+ Core-Hours = Cores × (Speed ÷ 3.0) × Usage% × Hours
396
+ ```
397
+
398
+ ### What if my server goes offline?
399
+
400
+ Your core-hours accumulate only while online. If you go offline:
401
+ - Your accumulated core-hours for the day remain
402
+ - Your tier may drop if you don't maintain the required hours
403
+ - API calls will fail until your worker reconnects
235
404
 
236
405
  ## Security
237
406
 
@@ -271,4 +440,11 @@ SOFTWARE.
271
440
 
272
441
  ---
273
442
 
274
- Made with privacy in mind by [AVALW](https://avalw.org)
443
+ Made with privacy in mind by [AVALW](https://cronos.avalw.com/about)
444
+
445
+ ### Our Projects
446
+
447
+ - [AVALW Search](https://avalw.org) - Privacy-focused search engine
448
+ - [Cronos Browser](https://cronos.avalw.com) - Secure, private browser
449
+ - [AVALW Protocol](https://avalw.com) - Decentralized communication protocol
450
+ - [Worker API](https://worker.avalw.org) - This project
package/bin/cli.js CHANGED
@@ -1,45 +1,52 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { AvalwWorker } = require('../lib/worker');
3
+ const { AvalwWorker, TIERS } = require('../lib/worker');
4
4
 
5
5
  const token = process.argv[2];
6
6
  const apiUrl = process.argv[3] || 'https://worker.avalw.org';
7
7
 
8
- if (!token) {
8
+ if (!token || token === '--help' || token === '-h') {
9
9
  console.log('');
10
- console.log(' AVALW Search Worker');
11
- console.log(' ====================');
10
+ console.log(' ╔═══════════════════════════════════════════════════════════════════╗');
11
+ console.log(' ║ AVALW Search Worker v1.1.0 ║');
12
+ console.log(' ╚═══════════════════════════════════════════════════════════════════╝');
12
13
  console.log('');
13
14
  console.log(' Usage: avalw-worker <WORKER_TOKEN> [API_URL]');
14
15
  console.log('');
15
16
  console.log(' Get your worker token at: https://worker.avalw.org');
16
17
  console.log('');
18
+ console.log(' Tiers (based on Core-Hours):');
19
+ console.log(' ┌───────────┬─────────────┬──────────────┬─────────────┐');
20
+ console.log(' │ Tier │ Requests │ Core-Hours │ Min Cores │');
21
+ console.log(' ├───────────┼─────────────┼──────────────┼─────────────┤');
22
+ console.log(' │ Starter │ 1,000/day │ 3/day │ 3 cores │');
23
+ console.log(' │ Basic │ 5,000/day │ 12/day │ 4 cores │');
24
+ console.log(' │ Pro │ 20,000/day │ 36/day │ 6 cores │');
25
+ console.log(' │ Business │ 50,000/day │ 72/day │ 8 cores │');
26
+ console.log(' │ Enterprise│ 500,000/day │ 240/day │ 16 cores │');
27
+ console.log(' └───────────┴─────────────┴──────────────┴─────────────┘');
28
+ console.log('');
29
+ console.log(' Core-Hours Formula:');
30
+ console.log(' Cores × (Speed ÷ 3.0 GHz) × Usage% × Hours');
31
+ console.log('');
17
32
  console.log(' Example:');
18
33
  console.log(' avalw-worker abc123def456...');
19
34
  console.log('');
20
35
  process.exit(1);
21
36
  }
22
37
 
23
- console.log('');
24
- console.log(' ╔═══════════════════════════════════════════════╗');
25
- console.log(' ║ AVALW Search Worker v1.0.0 ║');
26
- console.log(' ╠═══════════════════════════════════════════════╣');
27
- console.log(' ║ Free Search API in exchange for compute ║');
28
- console.log(' ╚═══════════════════════════════════════════════╝');
29
- console.log('');
30
-
31
38
  const worker = new AvalwWorker(token, apiUrl);
32
39
 
33
40
  // Handle graceful shutdown
34
- process.on('SIGINT', () => {
41
+ process.on('SIGINT', async () => {
35
42
  console.log('\n Shutting down worker...');
36
- worker.stop();
43
+ await worker.stop();
37
44
  process.exit(0);
38
45
  });
39
46
 
40
- process.on('SIGTERM', () => {
47
+ process.on('SIGTERM', async () => {
41
48
  console.log('\n Shutting down worker...');
42
- worker.stop();
49
+ await worker.stop();
43
50
  process.exit(0);
44
51
  });
45
52
 
package/lib/worker.js CHANGED
@@ -1,23 +1,99 @@
1
1
  /**
2
- * AVALW Search Worker
2
+ * AVALW Search Worker v1.1.0
3
3
  * Connects to worker.avalw.org and contributes compute power
4
4
  * in exchange for free search API access.
5
+ *
6
+ * Uses Core-Hours calculation for fair tier distribution.
5
7
  */
6
8
 
7
9
  const https = require('https');
8
10
  const http = require('http');
9
11
  const os = require('os');
10
12
 
13
+ // Tier definitions based on core-hours
14
+ const TIERS = {
15
+ STARTER: { name: 'Starter', coreHours: 3, requests: 1000, minCores: 3 },
16
+ BASIC: { name: 'Basic', coreHours: 12, requests: 5000, minCores: 4 },
17
+ PRO: { name: 'Pro', coreHours: 36, requests: 20000, minCores: 6 },
18
+ BUSINESS: { name: 'Business', coreHours: 72, requests: 50000, minCores: 8 },
19
+ ENTERPRISE: { name: 'Enterprise', coreHours: 240, requests: 500000, minCores: 16 }
20
+ };
21
+
11
22
  class AvalwWorker {
12
23
  constructor(token, apiUrl = 'https://worker.avalw.org') {
13
24
  this.token = token;
14
25
  this.apiUrl = apiUrl;
15
26
  this.running = false;
16
27
  this.heartbeatInterval = null;
17
- this.cpuLimit = 10; // Default 10%, updated by server
18
- this.tier = 'Unknown';
19
- this.taskCount = 0;
20
- this.lastHeartbeat = null;
28
+ this.startTime = null;
29
+ this.coreHoursToday = 0;
30
+ this.currentTier = null;
31
+ this.cpuInfo = this.getCpuInfo();
32
+ }
33
+
34
+ /**
35
+ * Get detailed CPU information
36
+ */
37
+ getCpuInfo() {
38
+ const cpus = os.cpus();
39
+ const cores = cpus.length;
40
+ const model = cpus[0]?.model || 'Unknown';
41
+
42
+ // Extract speed from CPU model or use reported speed
43
+ let speedGHz = cpus[0]?.speed ? cpus[0].speed / 1000 : 2.5;
44
+
45
+ // Try to parse speed from model string (e.g., "@ 2.90GHz")
46
+ const speedMatch = model.match(/@\s*([\d.]+)\s*GHz/i);
47
+ if (speedMatch) {
48
+ speedGHz = parseFloat(speedMatch[1]);
49
+ }
50
+
51
+ // Speed factor normalized to 3.0 GHz baseline
52
+ const speedFactor = speedGHz / 3.0;
53
+
54
+ return {
55
+ cores,
56
+ model,
57
+ speedGHz,
58
+ speedFactor: Math.round(speedFactor * 100) / 100,
59
+ totalMemoryGB: Math.round(os.totalmem() / 1024 / 1024 / 1024 * 10) / 10
60
+ };
61
+ }
62
+
63
+ /**
64
+ * Calculate core-hours contribution
65
+ * @param {number} usagePercent - CPU usage percentage (0-100)
66
+ * @param {number} hours - Time in hours
67
+ */
68
+ calculateCoreHours(usagePercent, hours) {
69
+ const { cores, speedFactor } = this.cpuInfo;
70
+ return cores * speedFactor * (usagePercent / 100) * hours;
71
+ }
72
+
73
+ /**
74
+ * Determine tier based on core-hours and minimum cores
75
+ */
76
+ determineTier(coreHours) {
77
+ const { cores } = this.cpuInfo;
78
+
79
+ // Check from highest to lowest tier
80
+ if (cores >= TIERS.ENTERPRISE.minCores && coreHours >= TIERS.ENTERPRISE.coreHours) {
81
+ return TIERS.ENTERPRISE;
82
+ }
83
+ if (cores >= TIERS.BUSINESS.minCores && coreHours >= TIERS.BUSINESS.coreHours) {
84
+ return TIERS.BUSINESS;
85
+ }
86
+ if (cores >= TIERS.PRO.minCores && coreHours >= TIERS.PRO.coreHours) {
87
+ return TIERS.PRO;
88
+ }
89
+ if (cores >= TIERS.BASIC.minCores && coreHours >= TIERS.BASIC.coreHours) {
90
+ return TIERS.BASIC;
91
+ }
92
+ if (cores >= TIERS.STARTER.minCores && coreHours >= TIERS.STARTER.coreHours) {
93
+ return TIERS.STARTER;
94
+ }
95
+
96
+ return null; // Not enough cores or core-hours
21
97
  }
22
98
 
23
99
  /**
@@ -25,21 +101,51 @@ class AvalwWorker {
25
101
  */
26
102
  async start() {
27
103
  this.running = true;
28
- console.log(` API URL: ${this.apiUrl}`);
29
- console.log(` Token: ${this.token.substring(0, 12)}...`);
104
+ this.startTime = Date.now();
105
+
106
+ // Print banner
107
+ console.log('');
108
+ console.log(' ╔═══════════════════════════════════════════════════════════════════╗');
109
+ console.log(' ║ AVALW Search Worker v1.1.0 ║');
110
+ console.log(' ╠═══════════════════════════════════════════════════════════════════╣');
111
+ console.log(' ║ Free Search API in exchange for compute ║');
112
+ console.log(' ╚═══════════════════════════════════════════════════════════════════╝');
113
+ console.log('');
114
+
115
+ // Print system info
116
+ console.log(' System Info:');
117
+ console.log(` ├─ CPU: ${this.cpuInfo.model}`);
118
+ console.log(` ├─ Cores: ${this.cpuInfo.cores}`);
119
+ console.log(` ├─ Speed: ${this.cpuInfo.speedGHz} GHz (factor: ${this.cpuInfo.speedFactor}x)`);
120
+ console.log(` └─ Memory: ${this.cpuInfo.totalMemoryGB} GB`);
121
+ console.log('');
122
+
123
+ // Check minimum cores requirement
124
+ if (this.cpuInfo.cores < TIERS.STARTER.minCores) {
125
+ console.log(` ⚠ WARNING: Your system has ${this.cpuInfo.cores} cores.`);
126
+ console.log(` ⚠ Minimum ${TIERS.STARTER.minCores} cores required for Starter tier.`);
127
+ console.log(` ⚠ Worker will run but you won't qualify for any tier.`);
128
+ console.log('');
129
+ }
130
+
131
+ // Print worker status
132
+ console.log(' Worker Status:');
133
+ console.log(` ├─ Token: ${this.token.substring(0, 12)}...`);
134
+ console.log(` ├─ API URL: ${this.apiUrl}`);
135
+ console.log(` └─ Target Usage: 50%`);
30
136
  console.log('');
31
137
 
32
138
  // Initial heartbeat
33
139
  await this.sendHeartbeat();
34
140
 
35
- // Start heartbeat loop
141
+ // Start heartbeat loop (every 30 seconds)
36
142
  this.heartbeatInterval = setInterval(() => {
37
143
  if (this.running) {
38
144
  this.sendHeartbeat();
39
145
  }
40
- }, 30000); // Every 30 seconds
146
+ }, 30000);
41
147
 
42
- console.log(' Worker started. Press Ctrl+C to stop.');
148
+ console.log(' Press Ctrl+C to stop.');
43
149
  console.log('');
44
150
  }
45
151
 
@@ -59,29 +165,59 @@ class AvalwWorker {
59
165
  await this.apiRequest('/api/worker/offline', 'POST', {
60
166
  worker_token: this.token
61
167
  });
62
- console.log(' Worker marked offline.');
168
+ console.log('');
169
+ console.log(' Worker stopped and marked offline.');
63
170
  } catch (error) {
64
171
  // Ignore errors during shutdown
65
172
  }
66
173
  }
67
174
 
68
175
  /**
69
- * Send heartbeat to server
176
+ * Send heartbeat to server with core-hours data
70
177
  */
71
178
  async sendHeartbeat() {
72
179
  try {
180
+ // Calculate hours online since start
181
+ const hoursOnline = (Date.now() - this.startTime) / 1000 / 60 / 60;
182
+
183
+ // Estimate core-hours (assuming 50% usage for now)
184
+ // In a real implementation, you'd measure actual CPU usage
185
+ const estimatedUsage = 50;
186
+ const sessionCoreHours = this.calculateCoreHours(estimatedUsage, hoursOnline);
187
+
73
188
  const response = await this.apiRequest('/api/worker/heartbeat', 'POST', {
74
189
  worker_token: this.token,
75
- system_info: this.getSystemInfo()
190
+ system_info: {
191
+ platform: os.platform(),
192
+ arch: os.arch(),
193
+ cores: this.cpuInfo.cores,
194
+ cpu_model: this.cpuInfo.model,
195
+ cpu_speed_ghz: this.cpuInfo.speedGHz,
196
+ speed_factor: this.cpuInfo.speedFactor,
197
+ total_memory_gb: this.cpuInfo.totalMemoryGB,
198
+ free_memory_gb: Math.round(os.freemem() / 1024 / 1024 / 1024 * 10) / 10,
199
+ uptime: os.uptime(),
200
+ worker_uptime_hours: Math.round(hoursOnline * 100) / 100,
201
+ session_core_hours: Math.round(sessionCoreHours * 100) / 100,
202
+ estimated_usage_percent: estimatedUsage
203
+ }
76
204
  });
77
205
 
78
206
  if (response.success) {
79
- this.cpuLimit = response.cpu_limit || this.cpuLimit;
80
- this.tier = response.tier || this.tier;
81
- this.lastHeartbeat = new Date();
207
+ this.coreHoursToday = response.core_hours_today || sessionCoreHours;
208
+ this.currentTier = response.tier || this.determineTier(this.coreHoursToday);
82
209
 
83
- const time = this.lastHeartbeat.toLocaleTimeString();
84
- console.log(` [${time}] Heartbeat OK | Tier: ${this.tier} | CPU Limit: ${this.cpuLimit}%`);
210
+ const time = new Date().toLocaleTimeString();
211
+ const tierName = this.currentTier?.name || 'None';
212
+ const tierRequests = this.currentTier?.requests?.toLocaleString() || '0';
213
+ const nextTier = this.getNextTier();
214
+
215
+ console.log(` [${time}] ✓ Heartbeat OK`);
216
+ console.log(` ├─ Core-Hours Today: ${this.coreHoursToday.toFixed(1)}${nextTier ? ` / ${nextTier.coreHours} needed for ${nextTier.name}` : ''}`);
217
+ console.log(` ├─ Current Tier: ${tierName} (${tierRequests} req/day)`);
218
+ console.log(` ├─ Usage Today: ${(response.usage_today || 0).toLocaleString()} / ${tierRequests}`);
219
+ console.log(` └─ Online: ${this.formatUptime(hoursOnline)}`);
220
+ console.log('');
85
221
  } else {
86
222
  console.error(` [ERROR] Heartbeat failed: ${response.error}`);
87
223
  }
@@ -91,20 +227,45 @@ class AvalwWorker {
91
227
  }
92
228
 
93
229
  /**
94
- * Get system information
230
+ * Get the next tier to aim for
95
231
  */
96
- getSystemInfo() {
97
- const cpus = os.cpus();
98
- const totalMem = os.totalmem();
99
- const freeMem = os.freemem();
232
+ getNextTier() {
233
+ const tierOrder = [TIERS.STARTER, TIERS.BASIC, TIERS.PRO, TIERS.BUSINESS, TIERS.ENTERPRISE];
100
234
 
235
+ for (const tier of tierOrder) {
236
+ if (this.cpuInfo.cores >= tier.minCores && this.coreHoursToday < tier.coreHours) {
237
+ return tier;
238
+ }
239
+ }
240
+
241
+ return null; // Already at max tier or can't qualify
242
+ }
243
+
244
+ /**
245
+ * Format uptime as human readable
246
+ */
247
+ formatUptime(hours) {
248
+ if (hours < 1) {
249
+ return `${Math.round(hours * 60)}m`;
250
+ }
251
+ const h = Math.floor(hours);
252
+ const m = Math.round((hours - h) * 60);
253
+ return `${h}h ${m}m`;
254
+ }
255
+
256
+ /**
257
+ * Get system information (legacy method for compatibility)
258
+ */
259
+ getSystemInfo() {
101
260
  return {
102
261
  platform: os.platform(),
103
262
  arch: os.arch(),
104
- cpus: cpus.length,
105
- cpu_model: cpus[0]?.model || 'Unknown',
106
- total_memory: Math.round(totalMem / 1024 / 1024 / 1024 * 10) / 10, // GB
107
- free_memory: Math.round(freeMem / 1024 / 1024 / 1024 * 10) / 10, // GB
263
+ cpus: this.cpuInfo.cores,
264
+ cpu_model: this.cpuInfo.model,
265
+ cpu_speed_ghz: this.cpuInfo.speedGHz,
266
+ speed_factor: this.cpuInfo.speedFactor,
267
+ total_memory: this.cpuInfo.totalMemoryGB,
268
+ free_memory: Math.round(os.freemem() / 1024 / 1024 / 1024 * 10) / 10,
108
269
  uptime: os.uptime()
109
270
  };
110
271
  }
@@ -125,7 +286,7 @@ class AvalwWorker {
125
286
  method: method,
126
287
  headers: {
127
288
  'Content-Type': 'application/json',
128
- 'User-Agent': 'AvalwWorker/1.0.0'
289
+ 'User-Agent': 'AvalwWorker/1.1.0'
129
290
  }
130
291
  };
131
292
 
@@ -155,4 +316,4 @@ class AvalwWorker {
155
316
  }
156
317
  }
157
318
 
158
- module.exports = { AvalwWorker };
319
+ module.exports = { AvalwWorker, TIERS };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avalw/search-worker",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "AVALW Search Worker - Contribute compute power, get free privacy-focused search API access",
5
5
  "main": "lib/worker.js",
6
6
  "bin": {