careerclaw-js 1.9.0 → 1.10.1
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.
- package/CHANGELOG.md +14 -0
- package/README.md +74 -36
- package/SKILL.md +1 -1
- package/dist/adapters/index.d.ts +1 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +1 -0
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/serpapi-google-jobs.d.ts +83 -0
- package/dist/adapters/serpapi-google-jobs.d.ts.map +1 -0
- package/dist/adapters/serpapi-google-jobs.js +433 -0
- package/dist/adapters/serpapi-google-jobs.js.map +1 -0
- package/dist/briefing.d.ts +3 -3
- package/dist/briefing.d.ts.map +1 -1
- package/dist/briefing.js +1 -1
- package/dist/briefing.js.map +1 -1
- package/dist/config.d.ts +33 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +34 -1
- package/dist/config.js.map +1 -1
- package/dist/core/skill-taxonomy.d.ts.map +1 -1
- package/dist/core/skill-taxonomy.js +57 -0
- package/dist/core/skill-taxonomy.js.map +1 -1
- package/dist/core/text-processing.js +1 -1
- package/dist/core/text-processing.js.map +1 -1
- package/dist/matching/semantic-scoring.d.ts.map +1 -1
- package/dist/matching/semantic-scoring.js +14 -1
- package/dist/matching/semantic-scoring.js.map +1 -1
- package/dist/models.d.ts +14 -1
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +1 -0
- package/dist/models.js.map +1 -1
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/sources.d.ts +7 -19
- package/dist/sources.d.ts.map +1 -1
- package/dist/sources.js +31 -35
- package/dist/sources.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,20 @@ Versioning follows [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## [1.10.1](https://github.com/orestes-garcia-martinez/careerclaw-js/compare/careerclaw-js-v1.10.0...careerclaw-js-v1.10.1) (2026-04-07)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* **matching:** add design/ux taxonomy domain and fix phantom concept expansion ([#74](https://github.com/orestes-garcia-martinez/careerclaw-js/issues/74)) ([64c41ce](https://github.com/orestes-garcia-martinez/careerclaw-js/commit/64c41ce62910b5fbdac515ef7af4e9fc7bb9c7e1))
|
|
15
|
+
|
|
16
|
+
## [1.10.0](https://github.com/orestes-garcia-martinez/careerclaw-js/compare/careerclaw-js-v1.9.0...careerclaw-js-v1.10.0) (2026-04-07)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* **adapters:** add SerpApi Google Jobs aggregator source ([#71](https://github.com/orestes-garcia-martinez/careerclaw-js/issues/71)) ([ea086db](https://github.com/orestes-garcia-martinez/careerclaw-js/commit/ea086db3b0bcd08e085473299b9ff0f9bf560ddd))
|
|
22
|
+
|
|
9
23
|
## [1.9.0](https://github.com/orestes-garcia-martinez/careerclaw-js/compare/careerclaw-js-v1.8.0...careerclaw-js-v1.9.0) (2026-04-04)
|
|
10
24
|
|
|
11
25
|
|
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ fetch listings → rank matches → draft outreach → track applications.
|
|
|
22
22
|
|
|
23
23
|
## How It Works
|
|
24
24
|
|
|
25
|
-
1. **Fetches** job listings from RemoteOK RSS
|
|
25
|
+
1. **Fetches** job listings from RemoteOK RSS, Hacker News Who's Hiring, and optionally SerpApi's Google Jobs aggregator for broader multi-board coverage
|
|
26
26
|
2. **Ranks** them against your profile using keyword overlap, experience alignment, salary fit, and work-mode preference
|
|
27
27
|
3. **Drafts** outreach for each top match (deterministic template on Free; LLM-enhanced on Pro)
|
|
28
28
|
4. **Tracks** your application pipeline locally in `.careerclaw/`
|
|
@@ -76,10 +76,13 @@ Create : `~/.careerclaw/profile.json`
|
|
|
76
76
|
"work_mode": "remote",
|
|
77
77
|
"resume_summary": "Senior engineer with 7 years building distributed systems and developer tools.",
|
|
78
78
|
"location": "Austin, TX",
|
|
79
|
+
"location_radius_km": null,
|
|
79
80
|
"salary_min": 150000
|
|
80
81
|
}
|
|
81
82
|
```
|
|
82
83
|
|
|
84
|
+
`location_radius_km` is optional. When set, it limits location-based job source searches (e.g. SerpApi) to within that radius. Only applied when `work_mode` is `"onsite"` or `"hybrid"`. Defaults to the operator cap (161 km / ~100 mi) when null. ClawOS users set this in miles through the UI — the platform converts to km automatically.
|
|
85
|
+
|
|
83
86
|
### 4. Run your first standalone briefing
|
|
84
87
|
|
|
85
88
|
```bash
|
|
@@ -99,8 +102,8 @@ careerclaw-js --resume-txt ~/.careerclaw/resume.txt --json
|
|
|
99
102
|
Sample Output
|
|
100
103
|
|
|
101
104
|
=== CareerClaw Daily Briefing ===
|
|
102
|
-
Fetched jobs:
|
|
103
|
-
Duration:
|
|
105
|
+
Fetched jobs: 303 | Sources: remoteok: 97 | hackernews: 196 | serpapi_google_jobs: 10
|
|
106
|
+
Duration: 1922ms fetch + 182ms rank
|
|
104
107
|
|
|
105
108
|
Top Matches:
|
|
106
109
|
|
|
@@ -116,15 +119,15 @@ Top Matches:
|
|
|
116
119
|
|
|
117
120
|
CareerClaw has two ways to unlock Pro features depending on how you run it:
|
|
118
121
|
|
|
119
|
-
| Feature
|
|
120
|
-
|
|
121
|
-
| Daily briefing
|
|
122
|
-
| Top 3 ranked matches
|
|
123
|
-
| Application tracking
|
|
124
|
-
| Outreach email draft (template)
|
|
125
|
-
| LLM-enhanced outreach email
|
|
126
|
-
| Resume gap analysis | — | ✅
|
|
127
|
-
| Cover letter (tailored, <300 words) | — | ✅
|
|
122
|
+
| Feature | Free | Pro |
|
|
123
|
+
|--------------------------------------------------|------|-------|
|
|
124
|
+
| Daily briefing | ✅ | ✅ |
|
|
125
|
+
| Top 3 ranked matches | ✅ | ✅ |
|
|
126
|
+
| Application tracking | ✅ | ✅ |
|
|
127
|
+
| Outreach email draft (template) | ✅ | ✅ |
|
|
128
|
+
| LLM-enhanced outreach email | — | ✅ |
|
|
129
|
+
| LLM-enhanced Resume gap analysis | — | ✅ |
|
|
130
|
+
| LLM-enhanced Cover letter (tailored, <300 words) | — | ✅ |
|
|
128
131
|
|
|
129
132
|
### Pro pricing
|
|
130
133
|
|
|
@@ -133,7 +136,7 @@ CareerClaw has two ways to unlock Pro features depending on how you run it:
|
|
|
133
136
|
| **ClawOS (recommended)** | **$9/month** | Managed billing, trusted platform activation, no key management. Visit [clawoshq.com](https://clawoshq.com/) |
|
|
134
137
|
| **Standalone** | **$39 one-time (lifetime license)** | Gumroad key validated against API, cached locally. Purchase at [ogm.gumroad.com/l/careerclaw-pro](https://ogm.gumroad.com/l/careerclaw-pro) |
|
|
135
138
|
|
|
136
|
-
Recommendation: If you're using ClawOS, purchase Pro through the platform — it handles entitlement, billing, and activation for you.
|
|
139
|
+
Recommendation: If you're using ClawOS, purchase Pro through the platform — it handles entitlement, billing, and activation for you.
|
|
137
140
|
The standalone Gumroad license is intended for users running the CLI directly or integrating CareerClaw as a skill on other agentic platforms.
|
|
138
141
|
|
|
139
142
|
### Pro: Activating
|
|
@@ -146,8 +149,8 @@ In ClawOS mode:
|
|
|
146
149
|
|
|
147
150
|
#### Standalone users
|
|
148
151
|
Purchase a license key on Gumroad. The key is emailed immediately after payment.
|
|
149
|
-
Add your standalone Pro key to .env or your process environment.
|
|
150
|
-
The key is validated against Gumroad on first use and cached locally as a SHA-256 hash.
|
|
152
|
+
Add your standalone Pro key to .env or your process environment.
|
|
153
|
+
The key is validated against Gumroad on first use and cached locally as a SHA-256 hash.
|
|
151
154
|
Re-validation happens every 7 days (requires internet).
|
|
152
155
|
|
|
153
156
|
### Docker / self-hosted
|
|
@@ -158,23 +161,51 @@ CAREERCLAW_OPENAI_KEY=sk-...
|
|
|
158
161
|
|
|
159
162
|
### Pro: LLM-Enhanced Drafts
|
|
160
163
|
|
|
161
|
-
With a valid Pro license and an LLM API key, CareerClaw
|
|
162
|
-
|
|
163
|
-
silently on any LLM failure.
|
|
164
|
+
With a valid Pro license and an LLM API key, CareerClaw:
|
|
165
|
+
|
|
166
|
+
- Writes personalized outreach emails using your actual resume signals mapped to each job's specific requirements. Falls back to the deterministic template silently on any LLM failure.
|
|
167
|
+
- Enhances the algorithmic gap analysis with personalized insights and recommendations.
|
|
168
|
+
- Generates a tailored cover letter (<300 words) for a specific job match.
|
|
169
|
+
|
|
164
170
|
Failover chain example (tries Anthropic first, falls back to OpenAI):
|
|
165
171
|
|
|
172
|
+
```bash
|
|
166
173
|
CAREERCLAW_ANTHROPIC_KEY=sk-ant-...
|
|
167
174
|
CAREERCLAW_OPENAI_KEY=sk-...
|
|
168
175
|
CAREERCLAW_LLM_CHAIN=anthropic/claude-haiku-4-5-20251001,openai/gpt-4o-mini
|
|
176
|
+
```
|
|
169
177
|
|
|
170
178
|
Estimated cost per run: ~$0.003 at claude-haiku-4-5-20251001 pricing (3 drafts).
|
|
171
179
|
|
|
180
|
+
### Optional: SerpApi Google Jobs aggregator
|
|
181
|
+
|
|
182
|
+
For broader job coverage, you can enable SerpApi's Google Jobs engine. This surfaces listings from LinkedIn, ZipRecruiter, Lever, Greenhouse, and company career pages through one structured API — without maintaining site-specific scrapers.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
CAREERCLAW_SERPAPI_API_KEY=...
|
|
186
|
+
CAREERCLAW_SERPAPI_GOOGLE_JOBS_ENABLED=true
|
|
187
|
+
CAREERCLAW_SERPAPI_GOOGLE_JOBS_MAX_PAGES=1 # pages per run (1–5)
|
|
188
|
+
CAREERCLAW_SERPAPI_GOOGLE_JOBS_RADIUS_KM=161 # operator hard cap (~100 mi); user radius is capped here
|
|
189
|
+
CAREERCLAW_SERPAPI_GOOGLE_JOBS_GL=us # Google country domain
|
|
190
|
+
CAREERCLAW_SERPAPI_GOOGLE_JOBS_HL=en # UI language
|
|
191
|
+
CAREERCLAW_SERPAPI_GOOGLE_JOBS_NO_CACHE=false # true = bypass SerpApi cache (uses search credits)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**How location and radius work:**
|
|
195
|
+
|
|
196
|
+
- `work_mode: "remote"` — uses SerpApi's native remote filter (`ltype=1`). No geographic `location` or radius is sent.
|
|
197
|
+
- `work_mode: "onsite"` / `"hybrid"` — passes `profile.location` as the geographic anchor and `profile.location_radius_km` as the search radius (`lrad`), capped at `CAREERCLAW_SERPAPI_GOOGLE_JOBS_RADIUS_KM`.
|
|
198
|
+
|
|
199
|
+
**ClawOS users** set `CAREERCLAW_SERPAPI_API_KEY` (and optionally the other vars) on the **worker** service. The radius is configured in miles through the ClawOS settings UI and converted to km automatically.
|
|
200
|
+
|
|
201
|
+
**Standalone users** place these in `.env`; `location_radius_km` in `profile.json` accepts kilometres directly.
|
|
202
|
+
|
|
172
203
|
### Programmatic Integration
|
|
173
204
|
|
|
174
205
|
CareerClaw exposes a direct-import runtime for both trusted platform adapters and standalone programmatic use.
|
|
175
206
|
|
|
176
207
|
#### ClawOS (trusted platform context)
|
|
177
|
-
Use createClawOsExecutionContext() to build a verified context after upstream entitlement checks.
|
|
208
|
+
Use createClawOsExecutionContext() to build a verified context after upstream entitlement checks.
|
|
178
209
|
CareerClaw trusts this context and skips standalone license validation entirely.
|
|
179
210
|
|
|
180
211
|
```ts
|
|
@@ -200,7 +231,7 @@ const result = await runCareerClawWithContext(
|
|
|
200
231
|
);
|
|
201
232
|
```
|
|
202
233
|
|
|
203
|
-
This API is intended for trusted platform code paths such as the ClawOS worker after assertion verification.
|
|
234
|
+
This API is intended for trusted platform code paths such as the ClawOS worker after assertion verification.
|
|
204
235
|
The public standalone CLI keeps its own standalone license flow.
|
|
205
236
|
|
|
206
237
|
### Standalone (programmatic)
|
|
@@ -251,22 +282,29 @@ Runtime files — all stored under .careerclaw/:
|
|
|
251
282
|
| `runs.jsonl` | Append-only run log (one line per run) |
|
|
252
283
|
| `.license_cache` | Pro license validation cache (SHA-256 hash only) |
|
|
253
284
|
|
|
254
|
-
File format compatibility: careerclaw-js uses the same JSON formats as the Python careerclaw package.
|
|
255
|
-
profile.json, tracking.json, and runs.jsonl are fully interchangeable between both implementations.
|
|
285
|
+
File format compatibility: careerclaw-js uses the same JSON formats as the Python careerclaw package.
|
|
286
|
+
profile.json, tracking.json, and runs.jsonl are fully interchangeable between both implementations.
|
|
256
287
|
|
|
257
288
|
### Environment Variables
|
|
258
289
|
|
|
259
|
-
| Variable
|
|
260
|
-
|
|
261
|
-
| `CAREERCLAW_PRO_KEY`
|
|
262
|
-
| `CAREERCLAW_ANTHROPIC_KEY` | Anthropic API key for LLM draft enhancement |
|
|
263
|
-
| `CAREERCLAW_OPENAI_KEY`
|
|
264
|
-
| `CAREERCLAW_LLM_KEY`
|
|
265
|
-
| `CAREERCLAW_LLM_CHAIN`
|
|
266
|
-
| `CAREERCLAW_LLM_MODEL`
|
|
267
|
-
| `CAREERCLAW_LLM_PROVIDER`
|
|
268
|
-
| `CAREERCLAW_DIR`
|
|
269
|
-
| `HN_WHO_IS_HIRING_ID`
|
|
290
|
+
| Variable | Default | Description |
|
|
291
|
+
|---------------------------------------------|----------|---------------------------------------------------------------------------------------|
|
|
292
|
+
| `CAREERCLAW_PRO_KEY` | — | Pro license key (Gumroad) |
|
|
293
|
+
| `CAREERCLAW_ANTHROPIC_KEY` | — | Anthropic API key for LLM draft enhancement |
|
|
294
|
+
| `CAREERCLAW_OPENAI_KEY` | — | OpenAI API key for LLM draft enhancement |
|
|
295
|
+
| `CAREERCLAW_LLM_KEY` | — | Legacy single-provider key fallback |
|
|
296
|
+
| `CAREERCLAW_LLM_CHAIN` | — | Ordered failover chain, e.g. `anthropic/claude-haiku-4-5-20251001,openai/gpt-4o-mini` |
|
|
297
|
+
| `CAREERCLAW_LLM_MODEL` | — | Override default LLM model |
|
|
298
|
+
| `CAREERCLAW_LLM_PROVIDER` | — | `anthropic` or `openai` (inferred from key when not set) |
|
|
299
|
+
| `CAREERCLAW_DIR` | — | Override runtime directory (default: `.careerclaw`) |
|
|
300
|
+
| `HN_WHO_IS_HIRING_ID` | — | Override HN thread ID (updated monthly) |
|
|
301
|
+
| `CAREERCLAW_SERPAPI_API_KEY` | — | SerpApi key — enables Google Jobs aggregator when set |
|
|
302
|
+
| `CAREERCLAW_SERPAPI_GOOGLE_JOBS_ENABLED` | `false` | Explicitly enable/disable the SerpApi source (`true` auto-set when key is present) |
|
|
303
|
+
| `CAREERCLAW_SERPAPI_GOOGLE_JOBS_MAX_PAGES` | `1` | Pages per run (1–5). Each page ~10 results. |
|
|
304
|
+
| `CAREERCLAW_SERPAPI_GOOGLE_JOBS_RADIUS_KM` | `161` | Operator hard cap on location radius (~100 mi). User's `location_radius_km` is capped here. |
|
|
305
|
+
| `CAREERCLAW_SERPAPI_GOOGLE_JOBS_GL` | `us` | Google country domain for job results |
|
|
306
|
+
| `CAREERCLAW_SERPAPI_GOOGLE_JOBS_HL` | `en` | UI language for job results |
|
|
307
|
+
| `CAREERCLAW_SERPAPI_GOOGLE_JOBS_NO_CACHE` | `false` | Bypass SerpApi's 1-hour cache (consumes search credits) |
|
|
270
308
|
|
|
271
309
|
Copy .env.example to .env and fill in your values.
|
|
272
310
|
|
|
@@ -301,7 +339,7 @@ npm run lint
|
|
|
301
339
|
#### ### Smoke tests (live network — run before release)
|
|
302
340
|
|
|
303
341
|
```bash
|
|
304
|
-
npm run smoke:sources # RemoteOK
|
|
342
|
+
npm run smoke:sources # RemoteOK, HN, and SerpApi connectivity (SerpApi skipped when not configured)
|
|
305
343
|
npm run smoke:briefing # Full pipeline end-to-end
|
|
306
344
|
npm run smoke:llm # LLM keys + Pro license validation
|
|
307
345
|
```
|
|
@@ -310,7 +348,7 @@ npm run smoke:llm # LLM keys + Pro license validation
|
|
|
310
348
|
```
|
|
311
349
|
careerclaw-js/
|
|
312
350
|
├── src/
|
|
313
|
-
│ ├── adapters/ # RemoteOK RSS
|
|
351
|
+
│ ├── adapters/ # RemoteOK RSS, HN Firebase, and SerpApi Google Jobs adapters
|
|
314
352
|
│ ├── core/ # Shared text processing
|
|
315
353
|
│ ├── matching/ # Scoring engine
|
|
316
354
|
│ ├── tests/ # Vitest test suite (270 tests, fully offline)
|
|
@@ -345,7 +383,7 @@ careerclaw-js is built on a local-first architecture.
|
|
|
345
383
|
- API keys never stored. Keys are read from the environment at runtime only.
|
|
346
384
|
- License cache is hash-only. Only SHA-256 of the license key is written to disk.
|
|
347
385
|
- LLM privacy. Only extracted keyword signals sent to the LLM — never raw resume text.
|
|
348
|
-
- External calls: remoteok.com, hacker-news.firebaseio.com, api.gumroad.com, and your configured LLM provider (using your own key).
|
|
386
|
+
- External calls: remoteok.com, hacker-news.firebaseio.com, api.gumroad.com, serpapi.com (only when SerpApi is enabled), and your configured LLM provider (using your own key).
|
|
349
387
|
|
|
350
388
|
See SECURITY.md for the vulnerability disclosure policy.
|
|
351
389
|
|
package/SKILL.md
CHANGED
package/dist/adapters/index.d.ts
CHANGED
|
@@ -7,4 +7,5 @@
|
|
|
7
7
|
export { fetchRemoteOkJobs, parseRss, stripHtml, stableId } from "./remoteok.js";
|
|
8
8
|
export { fetchHnJobs, parseComment } from "./hackernews.js";
|
|
9
9
|
export type { HnItem } from "./hackernews.js";
|
|
10
|
+
export { fetchSerpApiGoogleJobs, buildSerpApiGoogleJobsRequest, mapSerpApiJobToNormalizedJob, SerpApiConfigurationError, SerpApiInvalidApiKeyError, SerpApiRateLimitError, SerpApiRequestError, } from "./serpapi-google-jobs.js";
|
|
10
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC5D,YAAY,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACL,sBAAsB,EACtB,6BAA6B,EAC7B,4BAA4B,EAC5B,yBAAyB,EACzB,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC"}
|
package/dist/adapters/index.js
CHANGED
|
@@ -6,4 +6,5 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { fetchRemoteOkJobs, parseRss, stripHtml, stableId } from "./remoteok.js";
|
|
8
8
|
export { fetchHnJobs, parseComment } from "./hackernews.js";
|
|
9
|
+
export { fetchSerpApiGoogleJobs, buildSerpApiGoogleJobsRequest, mapSerpApiJobToNormalizedJob, SerpApiConfigurationError, SerpApiInvalidApiKeyError, SerpApiRateLimitError, SerpApiRequestError, } from "./serpapi-google-jobs.js";
|
|
9
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE5D,OAAO,EACL,sBAAsB,EACtB,6BAA6B,EAC7B,4BAA4B,EAC5B,yBAAyB,EACzB,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* adapters/serpapi-google-jobs.ts — SerpApi Google Jobs aggregator adapter.
|
|
3
|
+
*
|
|
4
|
+
* Purpose:
|
|
5
|
+
* - Expand CareerClaw coverage without maintaining dozens of custom scrapers.
|
|
6
|
+
* - Query Google Jobs via SerpApi and map results into CareerClaw's
|
|
7
|
+
* NormalizedJob shape.
|
|
8
|
+
*
|
|
9
|
+
* Design notes:
|
|
10
|
+
* - Opt-in via CAREERCLAW_SERPAPI_API_KEY (and optional enabled flag).
|
|
11
|
+
* - Profile-aware query generation so the source is relevant to the user.
|
|
12
|
+
* - Fail-soft by throwing typed, descriptive errors that the source
|
|
13
|
+
* orchestration layer can capture without breaking the full briefing.
|
|
14
|
+
*/
|
|
15
|
+
import type { NormalizedJob, UserProfile } from "../models.js";
|
|
16
|
+
export interface SerpApiGoogleJobsFetchOptions {
|
|
17
|
+
apiKey?: string;
|
|
18
|
+
maxPages?: number;
|
|
19
|
+
noCache?: boolean;
|
|
20
|
+
fetchFn?: typeof fetch;
|
|
21
|
+
}
|
|
22
|
+
export interface SerpApiGoogleJobsRequest {
|
|
23
|
+
q: string;
|
|
24
|
+
location?: string;
|
|
25
|
+
/** SerpApi remote-job filter. Pass "1" to activate Google's native remote filter. */
|
|
26
|
+
ltype?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Effective search radius in km, already capped at the operator limit.
|
|
29
|
+
* Only set when `location` is also present.
|
|
30
|
+
*/
|
|
31
|
+
radiusKm?: number;
|
|
32
|
+
nextPageToken?: string;
|
|
33
|
+
}
|
|
34
|
+
interface SerpApiDetectedExtensions {
|
|
35
|
+
posted_at?: string;
|
|
36
|
+
schedule_type?: string;
|
|
37
|
+
}
|
|
38
|
+
interface SerpApiJobHighlight {
|
|
39
|
+
title?: string;
|
|
40
|
+
items?: string[];
|
|
41
|
+
}
|
|
42
|
+
interface SerpApiApplyOption {
|
|
43
|
+
title?: string;
|
|
44
|
+
link?: string;
|
|
45
|
+
}
|
|
46
|
+
interface SerpApiJobResult {
|
|
47
|
+
title?: string;
|
|
48
|
+
company_name?: string;
|
|
49
|
+
location?: string;
|
|
50
|
+
via?: string;
|
|
51
|
+
share_link?: string;
|
|
52
|
+
description?: string;
|
|
53
|
+
extensions?: string[];
|
|
54
|
+
detected_extensions?: SerpApiDetectedExtensions;
|
|
55
|
+
job_highlights?: SerpApiJobHighlight[];
|
|
56
|
+
apply_options?: SerpApiApplyOption[];
|
|
57
|
+
job_id?: string;
|
|
58
|
+
}
|
|
59
|
+
declare class SerpApiGoogleJobsError extends Error {
|
|
60
|
+
readonly code: string;
|
|
61
|
+
readonly status: number | null;
|
|
62
|
+
constructor(message: string, code: string, status?: number | null);
|
|
63
|
+
}
|
|
64
|
+
export declare class SerpApiInvalidApiKeyError extends SerpApiGoogleJobsError {
|
|
65
|
+
constructor(message?: string);
|
|
66
|
+
}
|
|
67
|
+
export declare class SerpApiRateLimitError extends SerpApiGoogleJobsError {
|
|
68
|
+
constructor(message?: string);
|
|
69
|
+
}
|
|
70
|
+
export declare class SerpApiConfigurationError extends SerpApiGoogleJobsError {
|
|
71
|
+
constructor(message: string);
|
|
72
|
+
}
|
|
73
|
+
export declare class SerpApiRequestError extends SerpApiGoogleJobsError {
|
|
74
|
+
constructor(message: string, status?: number | null);
|
|
75
|
+
}
|
|
76
|
+
export declare function fetchSerpApiGoogleJobs(profile: UserProfile, options?: SerpApiGoogleJobsFetchOptions): Promise<NormalizedJob[]>;
|
|
77
|
+
export declare function buildSerpApiGoogleJobsRequest(profile: UserProfile): SerpApiGoogleJobsRequest;
|
|
78
|
+
export declare function mapSerpApiJobToNormalizedJob(job: SerpApiJobResult, context: {
|
|
79
|
+
query: string;
|
|
80
|
+
fetchedAt: string;
|
|
81
|
+
}): NormalizedJob;
|
|
82
|
+
export {};
|
|
83
|
+
//# sourceMappingURL=serpapi-google-jobs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serpapi-google-jobs.d.ts","sourceRoot":"","sources":["../../src/adapters/serpapi-google-jobs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAY,MAAM,cAAc,CAAC;AAmBzE,MAAM,WAAW,6BAA6B;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,CAAC,EAAE,MAAM,CAAC;IACV,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qFAAqF;IACrF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAUD,UAAU,yBAAyB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,mBAAmB;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,UAAU,kBAAkB;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,mBAAmB,CAAC,EAAE,yBAAyB,CAAC;IAChD,cAAc,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACvC,aAAa,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAaD,cAAM,sBAAuB,SAAQ,KAAK;aAGtB,IAAI,EAAE,MAAM;aACZ,MAAM,EAAE,MAAM,GAAG,IAAI;gBAFrC,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,MAAM,GAAG,IAAW;CAK/C;AAED,qBAAa,yBAA0B,SAAQ,sBAAsB;gBACvD,OAAO,SAA6C;CAIjE;AAED,qBAAa,qBAAsB,SAAQ,sBAAsB;gBACnD,OAAO,SAAiF;CAIrG;AAED,qBAAa,yBAA0B,SAAQ,sBAAsB;gBACvD,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,mBAAoB,SAAQ,sBAAsB;gBACjD,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,GAAG,IAAW;CAI1D;AAMD,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,6BAAkC,GAC1C,OAAO,CAAC,aAAa,EAAE,CAAC,CAiD1B;AAED,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,WAAW,GACnB,wBAAwB,CAgC1B;AAED,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,gBAAgB,EACrB,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC5C,aAAa,CA4Bf"}
|