careerclaw-js 0.11.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 (81) hide show
  1. package/CHANGELOG.md +362 -0
  2. package/README.md +348 -0
  3. package/SECURITY.md +156 -0
  4. package/SKILL.md +463 -0
  5. package/dist/adapters/hackernews.d.ts +36 -0
  6. package/dist/adapters/hackernews.d.ts.map +1 -0
  7. package/dist/adapters/hackernews.js +164 -0
  8. package/dist/adapters/hackernews.js.map +1 -0
  9. package/dist/adapters/index.d.ts +10 -0
  10. package/dist/adapters/index.d.ts.map +1 -0
  11. package/dist/adapters/index.js +9 -0
  12. package/dist/adapters/index.js.map +1 -0
  13. package/dist/adapters/remoteok.d.ts +35 -0
  14. package/dist/adapters/remoteok.d.ts.map +1 -0
  15. package/dist/adapters/remoteok.js +212 -0
  16. package/dist/adapters/remoteok.js.map +1 -0
  17. package/dist/briefing.d.ts +81 -0
  18. package/dist/briefing.d.ts.map +1 -0
  19. package/dist/briefing.js +152 -0
  20. package/dist/briefing.js.map +1 -0
  21. package/dist/cli.d.ts +22 -0
  22. package/dist/cli.d.ts.map +1 -0
  23. package/dist/cli.js +235 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/config.d.ts +91 -0
  26. package/dist/config.d.ts.map +1 -0
  27. package/dist/config.js +126 -0
  28. package/dist/config.js.map +1 -0
  29. package/dist/core/text-processing.d.ts +62 -0
  30. package/dist/core/text-processing.d.ts.map +1 -0
  31. package/dist/core/text-processing.js +187 -0
  32. package/dist/core/text-processing.js.map +1 -0
  33. package/dist/drafting.d.ts +28 -0
  34. package/dist/drafting.d.ts.map +1 -0
  35. package/dist/drafting.js +116 -0
  36. package/dist/drafting.js.map +1 -0
  37. package/dist/gap.d.ts +27 -0
  38. package/dist/gap.d.ts.map +1 -0
  39. package/dist/gap.js +90 -0
  40. package/dist/gap.js.map +1 -0
  41. package/dist/license.d.ts +40 -0
  42. package/dist/license.d.ts.map +1 -0
  43. package/dist/license.js +122 -0
  44. package/dist/license.js.map +1 -0
  45. package/dist/llm-enhance.d.ts +69 -0
  46. package/dist/llm-enhance.d.ts.map +1 -0
  47. package/dist/llm-enhance.js +376 -0
  48. package/dist/llm-enhance.js.map +1 -0
  49. package/dist/matching/engine.d.ts +31 -0
  50. package/dist/matching/engine.d.ts.map +1 -0
  51. package/dist/matching/engine.js +51 -0
  52. package/dist/matching/engine.js.map +1 -0
  53. package/dist/matching/index.d.ts +8 -0
  54. package/dist/matching/index.d.ts.map +1 -0
  55. package/dist/matching/index.js +8 -0
  56. package/dist/matching/index.js.map +1 -0
  57. package/dist/matching/scoring.d.ts +84 -0
  58. package/dist/matching/scoring.d.ts.map +1 -0
  59. package/dist/matching/scoring.js +184 -0
  60. package/dist/matching/scoring.js.map +1 -0
  61. package/dist/models.d.ts +221 -0
  62. package/dist/models.d.ts.map +1 -0
  63. package/dist/models.js +28 -0
  64. package/dist/models.js.map +1 -0
  65. package/dist/requirements.d.ts +22 -0
  66. package/dist/requirements.d.ts.map +1 -0
  67. package/dist/requirements.js +30 -0
  68. package/dist/requirements.js.map +1 -0
  69. package/dist/resume-intel.d.ts +40 -0
  70. package/dist/resume-intel.d.ts.map +1 -0
  71. package/dist/resume-intel.js +111 -0
  72. package/dist/resume-intel.js.map +1 -0
  73. package/dist/sources.d.ts +32 -0
  74. package/dist/sources.d.ts.map +1 -0
  75. package/dist/sources.js +72 -0
  76. package/dist/sources.js.map +1 -0
  77. package/dist/tracking.d.ts +68 -0
  78. package/dist/tracking.d.ts.map +1 -0
  79. package/dist/tracking.js +140 -0
  80. package/dist/tracking.js.map +1 -0
  81. package/package.json +58 -0
@@ -0,0 +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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * adapters/index.ts — Public adapter API.
3
+ *
4
+ * Import adapters from here rather than individual files.
5
+ * sources.ts (Phase 3) will use fetchAll() to merge results.
6
+ */
7
+ export { fetchRemoteOkJobs, parseRss, stripHtml, stableId } from "./remoteok.js";
8
+ export { fetchHnJobs, parseComment } from "./hackernews.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * adapters/remoteok.ts — RemoteOK RSS adapter.
3
+ *
4
+ * Fetches the RemoteOK RSS feed and normalises each <item> into a
5
+ * NormalizedJob. Parsing is split from fetching so contract tests can
6
+ * call parseRss() directly with fixture XML — no network mocking needed.
7
+ *
8
+ * RemoteOK RSS structure (abridged):
9
+ * <item>
10
+ * <title><![CDATA[Senior Engineer at Acme]]></title>
11
+ * <link>https://remoteok.com/remote-jobs/123</link>
12
+ * <pubDate>Mon, 03 Mar 2026 10:00:00 +0000</pubDate>
13
+ * <description><![CDATA[<p>HTML description...</p>]]></description>
14
+ * <location>Worldwide</location> <!-- optional -->
15
+ * <salary>$120,000 - $180,000</salary> <!-- optional -->
16
+ * <company><![CDATA[Acme Corp]]></company> <!-- optional -->
17
+ * <tag>typescript</tag> <!-- 0-n tags -->
18
+ * </item>
19
+ */
20
+ import type { NormalizedJob } from "../models.js";
21
+ /** Fetch the RemoteOK RSS feed and return normalised jobs. */
22
+ export declare function fetchRemoteOkJobs(): Promise<NormalizedJob[]>;
23
+ /**
24
+ * Parse a RemoteOK RSS XML string into NormalizedJob[].
25
+ * Exported for offline contract testing.
26
+ */
27
+ export declare function parseRss(xml: string): NormalizedJob[];
28
+ /**
29
+ * Strip HTML tags and decode common entities.
30
+ * Intentionally minimal — avoids a DOM/cheerio dependency.
31
+ */
32
+ export declare function stripHtml(html: string): string;
33
+ /** SHA-256(text) → first 16 hex chars (matches Python job_id convention). */
34
+ export declare function stableId(text: string): string;
35
+ //# sourceMappingURL=remoteok.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteok.d.ts","sourceRoot":"","sources":["../../src/adapters/remoteok.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAY,MAAM,cAAc,CAAC;AA+B5D,8DAA8D;AAC9D,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAiBlE;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,EAAE,CAqBrD;AAkHD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoB9C;AAED,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C"}
@@ -0,0 +1,212 @@
1
+ /**
2
+ * adapters/remoteok.ts — RemoteOK RSS adapter.
3
+ *
4
+ * Fetches the RemoteOK RSS feed and normalises each <item> into a
5
+ * NormalizedJob. Parsing is split from fetching so contract tests can
6
+ * call parseRss() directly with fixture XML — no network mocking needed.
7
+ *
8
+ * RemoteOK RSS structure (abridged):
9
+ * <item>
10
+ * <title><![CDATA[Senior Engineer at Acme]]></title>
11
+ * <link>https://remoteok.com/remote-jobs/123</link>
12
+ * <pubDate>Mon, 03 Mar 2026 10:00:00 +0000</pubDate>
13
+ * <description><![CDATA[<p>HTML description...</p>]]></description>
14
+ * <location>Worldwide</location> <!-- optional -->
15
+ * <salary>$120,000 - $180,000</salary> <!-- optional -->
16
+ * <company><![CDATA[Acme Corp]]></company> <!-- optional -->
17
+ * <tag>typescript</tag> <!-- 0-n tags -->
18
+ * </item>
19
+ */
20
+ import { createHash } from "node:crypto";
21
+ import { XMLParser } from "fast-xml-parser";
22
+ import { utcNow } from "../models.js";
23
+ import { HTTP_TIMEOUT_MS, REMOTEOK_RSS_URL, USER_AGENT, } from "../config.js";
24
+ // ---------------------------------------------------------------------------
25
+ // Public API
26
+ // ---------------------------------------------------------------------------
27
+ /** Fetch the RemoteOK RSS feed and return normalised jobs. */
28
+ export async function fetchRemoteOkJobs() {
29
+ const controller = new AbortController();
30
+ const timer = setTimeout(() => controller.abort(), HTTP_TIMEOUT_MS);
31
+ try {
32
+ const res = await fetch(REMOTEOK_RSS_URL, {
33
+ signal: controller.signal,
34
+ headers: { "User-Agent": USER_AGENT },
35
+ });
36
+ if (!res.ok) {
37
+ throw new Error(`RemoteOK RSS returned HTTP ${res.status}`);
38
+ }
39
+ const xml = await res.text();
40
+ return parseRss(xml);
41
+ }
42
+ finally {
43
+ clearTimeout(timer);
44
+ }
45
+ }
46
+ /**
47
+ * Parse a RemoteOK RSS XML string into NormalizedJob[].
48
+ * Exported for offline contract testing.
49
+ */
50
+ export function parseRss(xml) {
51
+ const parser = new XMLParser({
52
+ ignoreAttributes: false,
53
+ cdataPropName: "__cdata",
54
+ isArray: (_name, jpath) => jpath === "rss.channel.item",
55
+ });
56
+ const feed = parser.parse(xml);
57
+ const rawItems = feed?.rss?.channel?.item;
58
+ if (!rawItems)
59
+ return [];
60
+ const items = Array.isArray(rawItems) ? rawItems : [rawItems];
61
+ const fetched_at = utcNow();
62
+ return items.flatMap((item) => {
63
+ try {
64
+ return [normaliseItem(item, fetched_at)];
65
+ }
66
+ catch {
67
+ // Skip malformed items rather than aborting the whole feed
68
+ return [];
69
+ }
70
+ });
71
+ }
72
+ // ---------------------------------------------------------------------------
73
+ // Internal helpers
74
+ // ---------------------------------------------------------------------------
75
+ function normaliseItem(item, fetched_at) {
76
+ const rawTitle = coerceString(item.title);
77
+ const url = coerceString(item.link);
78
+ const rawDescription = stripHtml(coerceString(item.description));
79
+ const rawLocation = coerceString(item.location);
80
+ const rawSalary = coerceString(item.salary);
81
+ const rawCompany = coerceString(item.company);
82
+ const { title, company } = parseTitle(rawTitle, rawCompany);
83
+ const { salary_min, salary_max } = parseSalary(rawSalary, rawDescription);
84
+ const work_mode = inferWorkMode(rawLocation, rawDescription);
85
+ const experience_years = inferExperienceYears(rawDescription);
86
+ // Combine location tag with description inference
87
+ const location = rawLocation || inferLocationLabel(rawDescription);
88
+ return {
89
+ job_id: stableId(url || `${company}:${title}`),
90
+ title,
91
+ company,
92
+ location,
93
+ description: rawDescription,
94
+ url,
95
+ source: "remoteok",
96
+ salary_min,
97
+ salary_max,
98
+ work_mode,
99
+ experience_years,
100
+ posted_at: parsePubDate(coerceString(item.pubDate)),
101
+ fetched_at,
102
+ };
103
+ }
104
+ /**
105
+ * Split "Senior Engineer at Acme Corp" → { title, company }.
106
+ * Falls back to raw company field if present, then empty string.
107
+ */
108
+ function parseTitle(raw, companyField) {
109
+ const atIdx = raw.lastIndexOf(" at ");
110
+ if (atIdx > 0) {
111
+ return {
112
+ title: raw.slice(0, atIdx).trim(),
113
+ company: raw.slice(atIdx + 4).trim(),
114
+ };
115
+ }
116
+ return { title: raw.trim(), company: companyField.trim() };
117
+ }
118
+ /** Parse "$120,000 - $180,000" or "$120k - $180k" into annualised USD. */
119
+ function parseSalary(salaryField, description) {
120
+ const src = salaryField || description;
121
+ // Match patterns: $120,000-$180,000 | $120k-$180k | 120000-180000
122
+ const m = src.match(/\$?([\d,]+)\s*k?\s*[-–to]+\s*\$?([\d,]+)\s*k?/i);
123
+ if (!m)
124
+ return { salary_min: null, salary_max: null };
125
+ const parse = (raw, isK) => {
126
+ const n = parseInt(raw.replace(/,/g, ""), 10);
127
+ return isK || n < 1_000 ? n * 1_000 : n;
128
+ };
129
+ const rawMin = m[1] ?? "";
130
+ const rawMax = m[2] ?? "";
131
+ const isK = /k/i.test(salaryField || "");
132
+ return {
133
+ salary_min: parse(rawMin, isK),
134
+ salary_max: parse(rawMax, isK),
135
+ };
136
+ }
137
+ function inferWorkMode(location, description) {
138
+ const text = `${location} ${description}`.toLowerCase();
139
+ if (/\bhybrid\b/.test(text))
140
+ return "hybrid";
141
+ if (/\bremote\b/.test(text))
142
+ return "remote";
143
+ if (/\bon-?site\b|\bin-?office\b/.test(text))
144
+ return "onsite";
145
+ return null;
146
+ }
147
+ function inferLocationLabel(description) {
148
+ if (/\bworldwide\b|\banywhere\b/i.test(description))
149
+ return "Worldwide";
150
+ if (/\bremote\b/i.test(description))
151
+ return "Remote";
152
+ return "";
153
+ }
154
+ function inferExperienceYears(text) {
155
+ const m = text.match(/(\d+)\+?\s*(?:or more\s+)?years?\s+(?:of\s+)?experience/i);
156
+ return m && m[1] ? parseInt(m[1], 10) : null;
157
+ }
158
+ function parsePubDate(raw) {
159
+ if (!raw)
160
+ return null;
161
+ try {
162
+ return new Date(raw).toISOString();
163
+ }
164
+ catch {
165
+ return null;
166
+ }
167
+ }
168
+ // ---------------------------------------------------------------------------
169
+ // Shared utilities
170
+ // ---------------------------------------------------------------------------
171
+ /**
172
+ * Strip HTML tags and decode common entities.
173
+ * Intentionally minimal — avoids a DOM/cheerio dependency.
174
+ */
175
+ export function stripHtml(html) {
176
+ return html
177
+ .replace(/<br\s*\/?>/gi, "\n")
178
+ .replace(/<p[^>]*>/gi, "\n") // opening <p> → newline (creates split point)
179
+ .replace(/<\/p>/gi, "")
180
+ .replace(/<[^>]+>/g, "")
181
+ .replace(/&amp;/g, "&")
182
+ .replace(/&lt;/g, "<")
183
+ .replace(/&gt;/g, ">")
184
+ .replace(/&quot;/g, '"')
185
+ .replace(/&#x27;/g, "'")
186
+ .replace(/&#39;/g, "'")
187
+ .replace(/&apos;/g, "'")
188
+ .replace(/&#x2F;/gi, "/")
189
+ .replace(/&#x([0-9a-f]{1,6});/gi, (_, hex) => String.fromCodePoint(parseInt(hex, 16)))
190
+ .replace(/&nbsp;/g, " ")
191
+ .replace(/\n{3,}/g, "\n\n")
192
+ .trim();
193
+ }
194
+ /** SHA-256(text) → first 16 hex chars (matches Python job_id convention). */
195
+ export function stableId(text) {
196
+ return createHash("sha256").update(text).digest("hex").slice(0, 16);
197
+ }
198
+ /** Safely coerce a parsed value to string (fast-xml-parser can return numbers). */
199
+ function coerceString(val) {
200
+ if (val === null || val === undefined)
201
+ return "";
202
+ if (typeof val === "string")
203
+ return val;
204
+ if (typeof val === "number")
205
+ return String(val);
206
+ // CDATA objects from fast-xml-parser
207
+ if (typeof val === "object" && val !== null && "__cdata" in val) {
208
+ return String(val["__cdata"] ?? "");
209
+ }
210
+ return "";
211
+ }
212
+ //# sourceMappingURL=remoteok.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteok.js","sourceRoot":"","sources":["../../src/adapters/remoteok.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * briefing.ts — Daily briefing pipeline orchestrator.
3
+ *
4
+ * `runBriefing()` is the single entry point that wires every module
5
+ * into the complete end-to-end workflow:
6
+ *
7
+ * fetch → deduplicate → rank → draft → persist → return bundle
8
+ *
9
+ * Design principles (from Phase 4 architecture doc):
10
+ * - Skill-first: accepts UserProfile as a parameter, not a file path.
11
+ * The caller (CLI or OpenClaw agent) is responsible for loading the
12
+ * profile; the orchestrator never touches the filesystem for input.
13
+ * - Dual-mode output: structured BriefingResult JSON for agents +
14
+ * per-stage timings for observability.
15
+ * - Dry-run: suppresses all writes; counts are still accurate.
16
+ * - Testable: fetchFn and repo are injectable; no live network calls
17
+ * required in tests.
18
+ * - Graceful degradation: if the fetch stage returns zero jobs (e.g.
19
+ * both adapters failed), the pipeline short-circuits cleanly with
20
+ * an empty result rather than crashing.
21
+ */
22
+ import type { UserProfile, BriefingResult, ResumeIntelligence } from "./models.js";
23
+ import { type FetchResult } from "./sources.js";
24
+ import { type EnhanceOptions } from "./llm-enhance.js";
25
+ import { type CheckLicenseOptions } from "./license.js";
26
+ import { TrackingRepository } from "./tracking.js";
27
+ export interface BriefingOptions {
28
+ /** Number of top matches to return (default: DEFAULT_TOP_K = 3). */
29
+ topK?: number;
30
+ /** Suppress all file writes when true. Counts remain accurate. */
31
+ dryRun?: boolean;
32
+ /**
33
+ * Injectable fetch function — defaults to the real fetchAllJobs().
34
+ * Pass a stub in tests to avoid live network calls.
35
+ */
36
+ fetchFn?: () => Promise<FetchResult>;
37
+ /**
38
+ * Injectable TrackingRepository — defaults to a new instance with
39
+ * standard paths. Pass a tmpdir-backed instance in tests.
40
+ */
41
+ repo?: TrackingRepository;
42
+ /**
43
+ * Resume intelligence from buildResumeIntelligence().
44
+ * Required for LLM draft enhancement — ignored when proKey is absent.
45
+ */
46
+ resumeIntel?: ResumeIntelligence;
47
+ /**
48
+ * CareerClaw Pro license key (CAREERCLAW_PRO_KEY).
49
+ * Validated against Gumroad before enabling LLM-enhanced drafts.
50
+ * Falls back to deterministic draft if validation fails.
51
+ */
52
+ proKey?: string;
53
+ /**
54
+ * Injectable fetch for the LLM API calls — passed through to enhanceDraft().
55
+ * Defaults to global fetch. Pass a stub in tests.
56
+ */
57
+ enhanceFetchFn?: EnhanceOptions["fetchFn"];
58
+ /**
59
+ * Injectable fetch for the Gumroad license API call.
60
+ * Defaults to global fetch. Pass a stub in tests.
61
+ */
62
+ licenseFetchFn?: CheckLicenseOptions["fetchFn"];
63
+ /**
64
+ * Override the license cache file path — for tests using a tmpdir.
65
+ */
66
+ licenseCachePath?: string;
67
+ }
68
+ /**
69
+ * Run a full briefing pipeline for the given user profile.
70
+ *
71
+ * Stages and timings:
72
+ * 1. fetch_ms — fetch + deduplicate jobs from all sources
73
+ * 2. rank_ms — score and rank jobs against profile
74
+ * 3. draft_ms — generate one OutreachDraft per top match
75
+ * 4. persist_ms — upsert tracking entries + append run record
76
+ *
77
+ * @param profile - User profile (passed in by caller, not loaded here)
78
+ * @param options - Injection points and run flags
79
+ */
80
+ export declare function runBriefing(profile: UserProfile, options?: BriefingOptions): Promise<BriefingResult>;
81
+ //# sourceMappingURL=briefing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"briefing.d.ts","sourceRoot":"","sources":["../src/briefing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EACV,WAAW,EAIX,cAAc,EACd,kBAAkB,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAG9D,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAOnD,MAAM,WAAW,eAAe;IAC9B,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;IACrC;;;OAGG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IAC3C;;;OAGG;IACH,cAAc,CAAC,EAAE,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAChD;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAMD;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,cAAc,CAAC,CAwHzB"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * briefing.ts — Daily briefing pipeline orchestrator.
3
+ *
4
+ * `runBriefing()` is the single entry point that wires every module
5
+ * into the complete end-to-end workflow:
6
+ *
7
+ * fetch → deduplicate → rank → draft → persist → return bundle
8
+ *
9
+ * Design principles (from Phase 4 architecture doc):
10
+ * - Skill-first: accepts UserProfile as a parameter, not a file path.
11
+ * The caller (CLI or OpenClaw agent) is responsible for loading the
12
+ * profile; the orchestrator never touches the filesystem for input.
13
+ * - Dual-mode output: structured BriefingResult JSON for agents +
14
+ * per-stage timings for observability.
15
+ * - Dry-run: suppresses all writes; counts are still accurate.
16
+ * - Testable: fetchFn and repo are injectable; no live network calls
17
+ * required in tests.
18
+ * - Graceful degradation: if the fetch stage returns zero jobs (e.g.
19
+ * both adapters failed), the pipeline short-circuits cleanly with
20
+ * an empty result rather than crashing.
21
+ */
22
+ import { randomUUID } from "crypto";
23
+ import { createRequire } from "module";
24
+ import { fetchAllJobs } from "./sources.js";
25
+ import { rankJobs } from "./matching/index.js";
26
+ import { draftOutreach } from "./drafting.js";
27
+ import { enhanceDraft } from "./llm-enhance.js";
28
+ import { checkLicense } from "./license.js";
29
+ import { TrackingRepository } from "./tracking.js";
30
+ import { DEFAULT_TOP_K } from "./config.js";
31
+ // ---------------------------------------------------------------------------
32
+ // Public API
33
+ // ---------------------------------------------------------------------------
34
+ /**
35
+ * Run a full briefing pipeline for the given user profile.
36
+ *
37
+ * Stages and timings:
38
+ * 1. fetch_ms — fetch + deduplicate jobs from all sources
39
+ * 2. rank_ms — score and rank jobs against profile
40
+ * 3. draft_ms — generate one OutreachDraft per top match
41
+ * 4. persist_ms — upsert tracking entries + append run record
42
+ *
43
+ * @param profile - User profile (passed in by caller, not loaded here)
44
+ * @param options - Injection points and run flags
45
+ */
46
+ export async function runBriefing(profile, options = {}) {
47
+ const { topK = DEFAULT_TOP_K, dryRun = false, fetchFn = fetchAllJobs, repo = new TrackingRepository({ dryRun }), resumeIntel, proKey, enhanceFetchFn, licenseFetchFn, licenseCachePath, } = options;
48
+ // Validate Pro license before enabling LLM enhancement.
49
+ // Runs only when proKey is present; result degrades gracefully on network
50
+ // failure (cached result used for up to LICENSE_CACHE_TTL_MS = 7 days).
51
+ let isProActive = false;
52
+ if (proKey && proKey.trim().length > 0 && resumeIntel) {
53
+ const licenseOptions = {};
54
+ if (licenseFetchFn !== undefined)
55
+ licenseOptions.fetchFn = licenseFetchFn;
56
+ if (licenseCachePath !== undefined)
57
+ licenseOptions.cachePath = licenseCachePath;
58
+ const licenseResult = await checkLicense(proKey, licenseOptions);
59
+ isProActive = licenseResult.valid;
60
+ }
61
+ const runAt = new Date().toISOString();
62
+ const runId = randomUUID();
63
+ const version = readPackageVersion();
64
+ // -------------------------------------------------------------------------
65
+ // Stage 1: Fetch + deduplicate
66
+ // -------------------------------------------------------------------------
67
+ const fetchStart = Date.now();
68
+ let fetchResult;
69
+ try {
70
+ fetchResult = await fetchFn();
71
+ }
72
+ catch {
73
+ // Catastrophic fetch failure — return an empty result rather than throwing
74
+ fetchResult = { jobs: [], counts: {}, errors: {} };
75
+ }
76
+ const fetchMs = Date.now() - fetchStart;
77
+ const { jobs, counts: sourceCounts } = fetchResult;
78
+ // -------------------------------------------------------------------------
79
+ // Stage 2: Rank
80
+ // -------------------------------------------------------------------------
81
+ const rankStart = Date.now();
82
+ const matches = jobs.length > 0 ? rankJobs(jobs, profile, topK) : [];
83
+ const rankMs = Date.now() - rankStart;
84
+ // -------------------------------------------------------------------------
85
+ // Stage 3: Draft
86
+ // -------------------------------------------------------------------------
87
+ const draftStart = Date.now();
88
+ const drafts = await Promise.all(matches.map(async (scored) => {
89
+ const baseline = draftOutreach(scored.job, profile, scored.matched_keywords);
90
+ if (isProActive) {
91
+ return enhanceDraft(scored.job, profile, resumeIntel, baseline, scored.gap_keywords, enhanceFetchFn !== undefined ? { fetchFn: enhanceFetchFn } : {});
92
+ }
93
+ return baseline;
94
+ }));
95
+ const draftMs = Date.now() - draftStart;
96
+ // -------------------------------------------------------------------------
97
+ // Stage 4: Persist
98
+ // -------------------------------------------------------------------------
99
+ const persistStart = Date.now();
100
+ const trackingResult = repo.upsertEntries(matches.map((s) => s.job), matches);
101
+ const run = {
102
+ run_id: runId,
103
+ run_at: runAt,
104
+ dry_run: dryRun,
105
+ jobs_fetched: jobs.length,
106
+ jobs_ranked: jobs.length,
107
+ jobs_matched: matches.length,
108
+ sources: sourceCounts,
109
+ timings: {
110
+ fetch_ms: fetchMs,
111
+ rank_ms: rankMs,
112
+ draft_ms: draftMs,
113
+ persist_ms: null, // filled below after appendRun
114
+ },
115
+ version,
116
+ };
117
+ repo.appendRun(run);
118
+ const persistMs = Date.now() - persistStart;
119
+ // Back-fill persist_ms (the field exists for observability; the run
120
+ // record on disk will have null for persist_ms — that is acceptable
121
+ // and consistent with the Python implementation)
122
+ run.timings.persist_ms = persistMs;
123
+ // -------------------------------------------------------------------------
124
+ // Result bundle
125
+ // -------------------------------------------------------------------------
126
+ return {
127
+ run,
128
+ matches,
129
+ drafts,
130
+ tracking: {
131
+ created: trackingResult.created,
132
+ already_present: trackingResult.already_present,
133
+ },
134
+ dry_run: dryRun,
135
+ };
136
+ }
137
+ // ---------------------------------------------------------------------------
138
+ // Helpers
139
+ // ---------------------------------------------------------------------------
140
+ /** Read the package version from package.json at runtime. */
141
+ function readPackageVersion() {
142
+ try {
143
+ const require = createRequire(import.meta.url);
144
+ // Walk up from src/ to find package.json
145
+ const pkg = require("../package.json");
146
+ return pkg.version;
147
+ }
148
+ catch {
149
+ return "unknown";
150
+ }
151
+ }
152
+ //# sourceMappingURL=briefing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"briefing.js","sourceRoot":"","sources":["../src/briefing.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * cli.ts — CareerClaw command-line entry point.
4
+ *
5
+ * Usage:
6
+ * npx careerclaw-js [options]
7
+ * node --env-file=.env dist/cli.js [options]
8
+ *
9
+ * Options:
10
+ * --profile PATH Path to profile.json (default: ~/.careerclaw/profile.json)
11
+ * --resume-txt PATH Plain-text resume file to enhance matching
12
+ * --top-k INT Number of top matches to return (default: 3)
13
+ * --dry-run Run without writing tracking or run log
14
+ * --json Print JSON output only (machine-readable; no colour)
15
+ * --help Print this help message and exit
16
+ *
17
+ * Exit codes:
18
+ * 0 — briefing completed (even if 0 matches — not an error)
19
+ * 1 — fatal error (profile not found, unreadable, or invalid JSON)
20
+ */
21
+ export {};
22
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;GAkBG"}