@rwendell/dossier 0.0.0-stage → 0.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.
- package/LICENSE +21 -0
- package/README.md +322 -2
- package/agents/dossier-answerer.md +168 -0
- package/agents/dossier-proposer.md +215 -0
- package/agents/dossier-tailor.md +232 -0
- package/dist/answer/prompt.d.ts +17 -0
- package/dist/answer/prompt.js +44 -0
- package/dist/answer/prompt.js.map +1 -0
- package/dist/answer/run.d.ts +21 -0
- package/dist/answer/run.js +272 -0
- package/dist/answer/run.js.map +1 -0
- package/dist/career/import-resume.d.ts +17 -0
- package/dist/career/import-resume.js +194 -0
- package/dist/career/import-resume.js.map +1 -0
- package/dist/career/load.d.ts +10 -0
- package/dist/career/load.js +96 -0
- package/dist/career/load.js.map +1 -0
- package/dist/career/schema.d.ts +147 -0
- package/dist/career/schema.js +95 -0
- package/dist/career/schema.js.map +1 -0
- package/dist/clean/run.d.ts +1 -0
- package/dist/clean/run.js +8 -0
- package/dist/clean/run.js.map +1 -0
- package/dist/cli/commands/answer.d.ts +23 -0
- package/dist/cli/commands/answer.js +110 -0
- package/dist/cli/commands/answer.js.map +1 -0
- package/dist/cli/commands/clean.d.ts +2 -0
- package/dist/cli/commands/clean.js +11 -0
- package/dist/cli/commands/clean.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.js +83 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.d.ts +7 -0
- package/dist/cli/commands/init.js +80 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/paths.d.ts +7 -0
- package/dist/cli/commands/paths.js +42 -0
- package/dist/cli/commands/paths.js.map +1 -0
- package/dist/cli/commands/proposal.d.ts +30 -0
- package/dist/cli/commands/proposal.js +148 -0
- package/dist/cli/commands/proposal.js.map +1 -0
- package/dist/cli/commands/pull-private.d.ts +8 -0
- package/dist/cli/commands/pull-private.js +30 -0
- package/dist/cli/commands/pull-private.js.map +1 -0
- package/dist/cli/commands/score.d.ts +11 -0
- package/dist/cli/commands/score.js +58 -0
- package/dist/cli/commands/score.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +13 -0
- package/dist/cli/commands/sync.js +65 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/commands/tailor.d.ts +24 -0
- package/dist/cli/commands/tailor.js +113 -0
- package/dist/cli/commands/tailor.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +6 -0
- package/dist/cli/commands/verify.js +15 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +85 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/config.d.ts +36 -0
- package/dist/config/config.js +71 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/paths.d.ts +34 -0
- package/dist/config/paths.js +126 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/evidence/numbers.d.ts +2 -0
- package/dist/evidence/numbers.js +26 -0
- package/dist/evidence/numbers.js.map +1 -0
- package/dist/evidence/verify.d.ts +109 -0
- package/dist/evidence/verify.js +445 -0
- package/dist/evidence/verify.js.map +1 -0
- package/dist/job/input.d.ts +9 -0
- package/dist/job/input.js +141 -0
- package/dist/job/input.js.map +1 -0
- package/dist/job/page.d.ts +14 -0
- package/dist/job/page.js +426 -0
- package/dist/job/page.js.map +1 -0
- package/dist/job/types.d.ts +30 -0
- package/dist/job/types.js +2 -0
- package/dist/job/types.js.map +1 -0
- package/dist/llm/agents.d.ts +7 -0
- package/dist/llm/agents.js +46 -0
- package/dist/llm/agents.js.map +1 -0
- package/dist/llm/opencode.d.ts +19 -0
- package/dist/llm/opencode.js +117 -0
- package/dist/llm/opencode.js.map +1 -0
- package/dist/llm/providers.d.ts +63 -0
- package/dist/llm/providers.js +207 -0
- package/dist/llm/providers.js.map +1 -0
- package/dist/private/pull.d.ts +7 -0
- package/dist/private/pull.js +168 -0
- package/dist/private/pull.js.map +1 -0
- package/dist/projects/rank.d.ts +17 -0
- package/dist/projects/rank.js +100 -0
- package/dist/projects/rank.js.map +1 -0
- package/dist/projects/store.d.ts +7 -0
- package/dist/projects/store.js +31 -0
- package/dist/projects/store.js.map +1 -0
- package/dist/projects/sync-github.d.ts +11 -0
- package/dist/projects/sync-github.js +269 -0
- package/dist/projects/sync-github.js.map +1 -0
- package/dist/projects/sync-local.d.ts +8 -0
- package/dist/projects/sync-local.js +318 -0
- package/dist/projects/sync-local.js.map +1 -0
- package/dist/projects/types.d.ts +71 -0
- package/dist/projects/types.js +2 -0
- package/dist/projects/types.js.map +1 -0
- package/dist/proposal/prompt.d.ts +20 -0
- package/dist/proposal/prompt.js +64 -0
- package/dist/proposal/prompt.js.map +1 -0
- package/dist/proposal/run.d.ts +28 -0
- package/dist/proposal/run.js +386 -0
- package/dist/proposal/run.js.map +1 -0
- package/dist/resume/basics.d.ts +4 -0
- package/dist/resume/basics.js +33 -0
- package/dist/resume/basics.js.map +1 -0
- package/dist/resume/find.d.ts +12 -0
- package/dist/resume/find.js +27 -0
- package/dist/resume/find.js.map +1 -0
- package/dist/resume/format.d.ts +3 -0
- package/dist/resume/format.js +53 -0
- package/dist/resume/format.js.map +1 -0
- package/dist/resume/one-page.d.ts +149 -0
- package/dist/resume/one-page.js +164 -0
- package/dist/resume/one-page.js.map +1 -0
- package/dist/resume/prompt.d.ts +10 -0
- package/dist/resume/prompt.js +23 -0
- package/dist/resume/prompt.js.map +1 -0
- package/dist/resume/render.d.ts +8 -0
- package/dist/resume/render.js +84 -0
- package/dist/resume/render.js.map +1 -0
- package/dist/resume/run.d.ts +21 -0
- package/dist/resume/run.js +350 -0
- package/dist/resume/run.js.map +1 -0
- package/dist/resume/skills.d.ts +6 -0
- package/dist/resume/skills.js +47 -0
- package/dist/resume/skills.js.map +1 -0
- package/dist/resume/trace.d.ts +13 -0
- package/dist/resume/trace.js +82 -0
- package/dist/resume/trace.js.map +1 -0
- package/dist/resume/types.d.ts +94 -0
- package/dist/resume/types.js +2 -0
- package/dist/resume/types.js.map +1 -0
- package/dist/resume/verify.d.ts +19 -0
- package/dist/resume/verify.js +193 -0
- package/dist/resume/verify.js.map +1 -0
- package/dist/upwork/profile.d.ts +50 -0
- package/dist/upwork/profile.js +302 -0
- package/dist/upwork/profile.js.map +1 -0
- package/dist/upwork/settings.d.ts +96 -0
- package/dist/upwork/settings.js +166 -0
- package/dist/upwork/settings.js.map +1 -0
- package/dist/util/open-file.d.ts +1 -0
- package/dist/util/open-file.js +24 -0
- package/dist/util/open-file.js.map +1 -0
- package/dist/util/slug.d.ts +2 -0
- package/dist/util/slug.js +13 -0
- package/dist/util/slug.js.map +1 -0
- package/dist/verify/run.d.ts +4 -0
- package/dist/verify/run.js +91 -0
- package/dist/verify/run.js.map +1 -0
- package/package.json +67 -4
- package/templates/career.example.yml +63 -0
- package/templates/career.private.example.yml +10 -0
- package/templates/config.example.yml +16 -0
- package/templates/freelance.example.yml +48 -0
package/dist/job/page.js
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import * as cheerio from 'cheerio';
|
|
2
|
+
import { htmlToText } from 'html-to-text';
|
|
3
|
+
const JOB_BOARD_HOSTS = [
|
|
4
|
+
'greenhouse.io',
|
|
5
|
+
'lever.co',
|
|
6
|
+
'workday.com',
|
|
7
|
+
'myworkdayjobs.com',
|
|
8
|
+
'linkedin.com',
|
|
9
|
+
'indeed.com',
|
|
10
|
+
'glassdoor.com',
|
|
11
|
+
'ashbyhq.com',
|
|
12
|
+
'smartrecruiters.com',
|
|
13
|
+
'jobvite.com',
|
|
14
|
+
'icims.com',
|
|
15
|
+
'taleo.net',
|
|
16
|
+
'brassring.com',
|
|
17
|
+
'recruitee.com',
|
|
18
|
+
'workable.com',
|
|
19
|
+
'upwork.com',
|
|
20
|
+
];
|
|
21
|
+
const FETCH_HEADERS = {
|
|
22
|
+
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36',
|
|
23
|
+
accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,text/plain;q=0.8,*/*;q=0.7',
|
|
24
|
+
'accept-language': 'en-US,en;q=0.9',
|
|
25
|
+
};
|
|
26
|
+
export class JobPageError extends Error {
|
|
27
|
+
}
|
|
28
|
+
export function isUrl(value) {
|
|
29
|
+
return /^https?:\/\//i.test(String(value ?? '').trim());
|
|
30
|
+
}
|
|
31
|
+
export function isUpworkUrl(value) {
|
|
32
|
+
try {
|
|
33
|
+
const host = new URL(String(value)).hostname.replace(/^www\./, '');
|
|
34
|
+
return host === 'upwork.com' || host.endsWith('.upwork.com');
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function isUpworkSavedJobUrl(value) {
|
|
41
|
+
return /^https?:\/\/(?:www\.)?upwork\.com\/nx\/search\/jobs\/saved\/details\//i.test(String(value ?? ''));
|
|
42
|
+
}
|
|
43
|
+
export function isUpworkSearchUrl(value) {
|
|
44
|
+
return /^https?:\/\/(?:www\.)?upwork\.com\/(?:nx\/search\/jobs|jobs\/search)(?:\/|\?|$)/i.test(String(value ?? ''));
|
|
45
|
+
}
|
|
46
|
+
export async function fetchJobPage(url, { timeout = 20000, browserFallback = true } = {}) {
|
|
47
|
+
if (isUpworkSavedJobUrl(url)) {
|
|
48
|
+
throw new JobPageError('This is an Upwork saved-jobs modal URL that only works inside your logged-in Upwork session. Open the job and copy its public /jobs/... URL, or save the job description to a file and pass the file path instead.');
|
|
49
|
+
}
|
|
50
|
+
if (isUpworkSearchUrl(url)) {
|
|
51
|
+
throw new JobPageError('This is an Upwork search URL, not a job posting. Open the job and copy its public /jobs/... URL, or save the job description to a file and pass the file path instead.');
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
return await fetchJobPageWithHttp(url, timeout);
|
|
55
|
+
}
|
|
56
|
+
catch (httpError) {
|
|
57
|
+
if (!browserFallback)
|
|
58
|
+
throw httpError;
|
|
59
|
+
console.warn(`job-page: direct fetch failed (${httpError.message}); retrying with headless Chrome`);
|
|
60
|
+
try {
|
|
61
|
+
return await fetchJobPageWithBrowser(url, timeout);
|
|
62
|
+
}
|
|
63
|
+
catch (browserError) {
|
|
64
|
+
throw new JobPageError(`${httpError.message}\nHeadless browser fallback also failed: ${browserError.message}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function fetchJobPageWithHttp(url, timeout) {
|
|
69
|
+
let response;
|
|
70
|
+
try {
|
|
71
|
+
response = await fetch(url, {
|
|
72
|
+
redirect: 'follow',
|
|
73
|
+
headers: FETCH_HEADERS,
|
|
74
|
+
signal: AbortSignal.timeout(timeout),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
if (error.name === 'TimeoutError') {
|
|
79
|
+
throw new JobPageError(`Timed out after ${timeout}ms fetching ${url}`);
|
|
80
|
+
}
|
|
81
|
+
throw new JobPageError(`Could not fetch ${url}: ${error.message}`);
|
|
82
|
+
}
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
throw new JobPageError(`Could not fetch ${url}: HTTP ${response.status} ${response.statusText}`);
|
|
85
|
+
}
|
|
86
|
+
const contentType = response.headers.get('content-type') || '';
|
|
87
|
+
if (!/text\/html|application\/xhtml|text\/plain/i.test(contentType)) {
|
|
88
|
+
throw new JobPageError(`${url} returned ${contentType || 'an unknown content type'}, not an HTML job page.`);
|
|
89
|
+
}
|
|
90
|
+
return extractJobFromHtml(await response.text(), url);
|
|
91
|
+
}
|
|
92
|
+
async function fetchJobPageWithBrowser(url, timeout) {
|
|
93
|
+
const html = await fetchRenderedHtml(url, { timeout });
|
|
94
|
+
return extractJobFromHtml(html, url);
|
|
95
|
+
}
|
|
96
|
+
export async function fetchRenderedHtml(url, { timeout = 20000 } = {}) {
|
|
97
|
+
let browser = null;
|
|
98
|
+
try {
|
|
99
|
+
const puppeteer = (await import('puppeteer')).default;
|
|
100
|
+
browser = await puppeteer.launch({
|
|
101
|
+
headless: true,
|
|
102
|
+
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
103
|
+
});
|
|
104
|
+
const page = await browser.newPage();
|
|
105
|
+
await page.setUserAgent(FETCH_HEADERS['user-agent']);
|
|
106
|
+
try {
|
|
107
|
+
await page.goto(url, { waitUntil: 'networkidle2', timeout });
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (error.name !== 'TimeoutError')
|
|
111
|
+
throw error;
|
|
112
|
+
// A slow page may still have rendered the content.
|
|
113
|
+
}
|
|
114
|
+
return await page.content();
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
if (browser)
|
|
118
|
+
await browser.close();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
export function extractJobFromHtml(html, url = '') {
|
|
122
|
+
const $ = cheerio.load(html);
|
|
123
|
+
const pageTitle = textOf($('title').first().text());
|
|
124
|
+
const visibleText = $('body')
|
|
125
|
+
.clone()
|
|
126
|
+
.find('script, style, noscript')
|
|
127
|
+
.remove()
|
|
128
|
+
.end()
|
|
129
|
+
.text();
|
|
130
|
+
if (looksLikeBlockedPage(visibleText, pageTitle)) {
|
|
131
|
+
throw new JobPageError(`Could not load ${url || 'the job page'}: the site returned a login or bot-check page. Save the job description to a file and pass the file path instead, or pass --title and --company with --description.`);
|
|
132
|
+
}
|
|
133
|
+
if (isUpworkUrl(url)) {
|
|
134
|
+
return extractUpworkJob($, url);
|
|
135
|
+
}
|
|
136
|
+
const posting = findJobPosting($);
|
|
137
|
+
let title = posting ? textOf(stringValue(posting.title)) : '';
|
|
138
|
+
let company = posting ? companyName(posting.hiringOrganization) : '';
|
|
139
|
+
let descriptionHtml = posting ? textOf(stringValue(posting.description)) : '';
|
|
140
|
+
if (!descriptionHtml) {
|
|
141
|
+
$('script, style, noscript, iframe, svg, nav, header, footer, form, aside').remove();
|
|
142
|
+
const main = $('main').length
|
|
143
|
+
? $('main')
|
|
144
|
+
: $('article').length
|
|
145
|
+
? $('article')
|
|
146
|
+
: $('body');
|
|
147
|
+
descriptionHtml = main.html() ?? '';
|
|
148
|
+
}
|
|
149
|
+
if (!title) {
|
|
150
|
+
title =
|
|
151
|
+
attr($, 'meta[property="og:title"]', 'content') ||
|
|
152
|
+
textOf($('title').first().text());
|
|
153
|
+
}
|
|
154
|
+
if (!company) {
|
|
155
|
+
company = attr($, 'meta[property="og:site_name"]', 'content');
|
|
156
|
+
}
|
|
157
|
+
if (!company) {
|
|
158
|
+
company = splitTitleCompany(cleanTitle(title), '').company;
|
|
159
|
+
}
|
|
160
|
+
if (!company) {
|
|
161
|
+
const host = safeHost(url);
|
|
162
|
+
if (host && !isJobBoardHost(host))
|
|
163
|
+
company = host;
|
|
164
|
+
}
|
|
165
|
+
const normalizedTitle = splitTitleCompany(cleanTitle(title), company);
|
|
166
|
+
title = normalizedTitle.title;
|
|
167
|
+
company = normalizedTitle.company;
|
|
168
|
+
const body = toText(descriptionHtml);
|
|
169
|
+
if (body.length < 150 || looksLikeBlockedPage(body)) {
|
|
170
|
+
throw new JobPageError(`Could not extract a job description from ${url}. The page may require JavaScript or login. Save the job text to a file and pass the file instead.`);
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
title,
|
|
174
|
+
company,
|
|
175
|
+
body,
|
|
176
|
+
url,
|
|
177
|
+
source: 'url',
|
|
178
|
+
details: {},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function extractUpworkJob($, url) {
|
|
182
|
+
const rawTitle = textOf($('h1').first().text()) || textOf($('title').first().text());
|
|
183
|
+
const title = cleanUpworkTitle(rawTitle);
|
|
184
|
+
if (/^search freelance jobs/i.test(title)) {
|
|
185
|
+
throw new JobPageError('This Upwork URL points at a search page, not a job posting. Open the job and copy its public /jobs/... URL, or save the job description to a file and pass the file path instead.');
|
|
186
|
+
}
|
|
187
|
+
const posting = findJobPosting($);
|
|
188
|
+
let body = posting ? toText(stringValue(posting.description)) : '';
|
|
189
|
+
if (!body) {
|
|
190
|
+
const description = $('[data-test="Description"]').first();
|
|
191
|
+
body = description.length
|
|
192
|
+
? toText(String(description.html() ?? '').replace(/\n/g, '<br>'))
|
|
193
|
+
: '';
|
|
194
|
+
}
|
|
195
|
+
if (body.length < 80) {
|
|
196
|
+
throw new JobPageError(`Could not extract the Upwork job description from ${url}. Upwork may be showing a bot check or a page that needs a logged-in session. Save the job text to a file and pass the file instead.`);
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
title,
|
|
200
|
+
company: '',
|
|
201
|
+
body,
|
|
202
|
+
url,
|
|
203
|
+
source: 'url',
|
|
204
|
+
details: extractUpworkDetails($),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function extractUpworkDetails($) {
|
|
208
|
+
const details = {};
|
|
209
|
+
$('ul.features > li').each((_, element) => {
|
|
210
|
+
const item = $(element);
|
|
211
|
+
const fullText = normalizeText(item.text()).replace(/\s+/g, ' ').trim();
|
|
212
|
+
const label = normalizeText(item.clone().find('strong').remove().end().text())
|
|
213
|
+
.replace(/\s+/g, ' ')
|
|
214
|
+
.replace(/^[-–—:\s]+/, '')
|
|
215
|
+
.trim();
|
|
216
|
+
let value = textOf(item.find('strong').first().text());
|
|
217
|
+
if (label && fullText.toLowerCase().endsWith(label.toLowerCase())) {
|
|
218
|
+
value = fullText
|
|
219
|
+
.slice(0, -label.length)
|
|
220
|
+
.replace(/[-–—:\s]+$/, '')
|
|
221
|
+
.trim();
|
|
222
|
+
}
|
|
223
|
+
if (!value)
|
|
224
|
+
return;
|
|
225
|
+
const key = label.toLowerCase();
|
|
226
|
+
if (key === 'duration') {
|
|
227
|
+
details.duration = value;
|
|
228
|
+
}
|
|
229
|
+
else if (key === 'experience level') {
|
|
230
|
+
details.experienceLevel = value;
|
|
231
|
+
}
|
|
232
|
+
else if (key === 'project type') {
|
|
233
|
+
details.projectType = value;
|
|
234
|
+
}
|
|
235
|
+
else if (key === 'hourly' || key === 'fixed-price') {
|
|
236
|
+
details.budgetType = key === 'fixed-price' ? 'fixed' : 'hourly';
|
|
237
|
+
if (/^\$/.test(value))
|
|
238
|
+
details.budget = value;
|
|
239
|
+
else
|
|
240
|
+
details.workload = value;
|
|
241
|
+
}
|
|
242
|
+
else if (!key) {
|
|
243
|
+
if (/hrs?\s*\/\s*week|hours?\s*\/\s*week/i.test(value)) {
|
|
244
|
+
details.workload = value;
|
|
245
|
+
}
|
|
246
|
+
else if (/remote|onsite|hybrid/i.test(value)) {
|
|
247
|
+
details.jobLocation = value;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
details[label] = value;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
details[label] = value;
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
const jobHeader = $('h1').first().closest('header');
|
|
258
|
+
const posted = jobHeader.find('.posted-on-line').first().text();
|
|
259
|
+
if (posted.trim())
|
|
260
|
+
details.posted = normalizeText(posted);
|
|
261
|
+
const jobLocation = toText(jobHeader.find('p').first().html() ?? '').replace(/([.!?])(?=[A-Z])/g, '$1 ');
|
|
262
|
+
if (jobLocation)
|
|
263
|
+
details.jobLocation = jobLocation;
|
|
264
|
+
const skillsHeading = $('h3, h4, h5')
|
|
265
|
+
.filter((_, element) => /skills and expertise/i.test($(element).text()))
|
|
266
|
+
.first();
|
|
267
|
+
if (skillsHeading.length) {
|
|
268
|
+
const skills = [];
|
|
269
|
+
skillsHeading
|
|
270
|
+
.closest('section')
|
|
271
|
+
.find('.air3-badge')
|
|
272
|
+
.each((_, element) => {
|
|
273
|
+
const text = textOf($(element).text()).replace(/\s+/g, ' ').trim();
|
|
274
|
+
if (text &&
|
|
275
|
+
!/^\+\s*\d+\s+more$/i.test(text) &&
|
|
276
|
+
!skills.includes(text)) {
|
|
277
|
+
skills.push(text);
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
if (skills.length > 0)
|
|
281
|
+
details.skills = skills;
|
|
282
|
+
}
|
|
283
|
+
const clientSection = $('.cfe-about-client-v2').first();
|
|
284
|
+
if (clientSection.length) {
|
|
285
|
+
const client = toText(clientSection.html() ?? '')
|
|
286
|
+
.replace(/^About the client\s*/i, '')
|
|
287
|
+
.replace(/\n\s*\*\s*/g, '\n')
|
|
288
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
289
|
+
.replace(/([A-Za-z])(\d{1,2}:\d{2})/g, '$1 $2')
|
|
290
|
+
.trim();
|
|
291
|
+
if (client)
|
|
292
|
+
details.client = client;
|
|
293
|
+
const location = toText(clientSection.find('[data-qa="client-location"]').html() ?? '').replace(/([A-Za-z])(\d{1,2}:\d{2})/g, '$1 $2');
|
|
294
|
+
if (location)
|
|
295
|
+
details.clientLocation = location;
|
|
296
|
+
const memberSince = toText(clientSection.find('[data-qa="client-contract-date"]').html() ?? '');
|
|
297
|
+
if (memberSince)
|
|
298
|
+
details.clientMemberSince = memberSince;
|
|
299
|
+
}
|
|
300
|
+
return details;
|
|
301
|
+
}
|
|
302
|
+
function cleanUpworkTitle(value) {
|
|
303
|
+
return String(value ?? '')
|
|
304
|
+
.replace(/\s+/g, ' ')
|
|
305
|
+
.replace(/\s*[|]\s*Upwork\s*$/i, '')
|
|
306
|
+
.replace(/\s*-\s*Upwork\s*$/i, '')
|
|
307
|
+
.trim();
|
|
308
|
+
}
|
|
309
|
+
function findJobPosting($) {
|
|
310
|
+
const objects = [];
|
|
311
|
+
$('script[type="application/ld+json"]').each((_, element) => {
|
|
312
|
+
const raw = $(element).contents().text().trim();
|
|
313
|
+
if (!raw)
|
|
314
|
+
return;
|
|
315
|
+
try {
|
|
316
|
+
collectJsonLd(JSON.parse(raw), objects);
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
// Ignore malformed JSON-LD.
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
return (objects.find((object) => types(object).some((type) => String(type).toLowerCase() === 'jobposting')) ?? null);
|
|
323
|
+
}
|
|
324
|
+
function collectJsonLd(value, out) {
|
|
325
|
+
if (Array.isArray(value)) {
|
|
326
|
+
for (const item of value)
|
|
327
|
+
collectJsonLd(item, out);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (!value || typeof value !== 'object')
|
|
331
|
+
return;
|
|
332
|
+
const record = value;
|
|
333
|
+
out.push(record);
|
|
334
|
+
if (record['@graph'])
|
|
335
|
+
collectJsonLd(record['@graph'], out);
|
|
336
|
+
}
|
|
337
|
+
function types(value) {
|
|
338
|
+
const type = value?.['@type'];
|
|
339
|
+
if (Array.isArray(type))
|
|
340
|
+
return type;
|
|
341
|
+
return type ? [type] : [];
|
|
342
|
+
}
|
|
343
|
+
function companyName(value) {
|
|
344
|
+
if (!value)
|
|
345
|
+
return '';
|
|
346
|
+
if (typeof value === 'string')
|
|
347
|
+
return value.trim();
|
|
348
|
+
if (typeof value !== 'object')
|
|
349
|
+
return '';
|
|
350
|
+
const record = value;
|
|
351
|
+
return String(record.name ?? record.legalName ?? '').trim();
|
|
352
|
+
}
|
|
353
|
+
function stringValue(value) {
|
|
354
|
+
return typeof value === 'string' ? value : '';
|
|
355
|
+
}
|
|
356
|
+
function splitTitleCompany(title, company) {
|
|
357
|
+
const match = title.match(/^(.+?)\s+(?:at|@)\s+(.+)$/i);
|
|
358
|
+
if (match) {
|
|
359
|
+
return {
|
|
360
|
+
title: match[1].trim(),
|
|
361
|
+
company: company || match[2].trim(),
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
return { title, company };
|
|
365
|
+
}
|
|
366
|
+
function cleanTitle(value) {
|
|
367
|
+
return String(value ?? '')
|
|
368
|
+
.replace(/\s+/g, ' ')
|
|
369
|
+
.replace(/^Job Application for\s+/i, '')
|
|
370
|
+
.replace(/\s*[|•-]\s*(LinkedIn|Indeed|Glassdoor|Greenhouse|Lever|Workday|Ashby|SmartRecruiters|Upwork)\b.*$/i, '')
|
|
371
|
+
.trim();
|
|
372
|
+
}
|
|
373
|
+
function toText(html) {
|
|
374
|
+
if (!html)
|
|
375
|
+
return '';
|
|
376
|
+
if (!/<[a-z][\s\S]*>/i.test(html))
|
|
377
|
+
return normalizeText(html);
|
|
378
|
+
const text = htmlToText(html, {
|
|
379
|
+
wordwrap: false,
|
|
380
|
+
selectors: [
|
|
381
|
+
{ selector: 'a', options: { ignoreHref: true } },
|
|
382
|
+
{ selector: 'img', format: 'skip' },
|
|
383
|
+
{ selector: 'h1', options: { uppercase: false } },
|
|
384
|
+
{ selector: 'h2', options: { uppercase: false } },
|
|
385
|
+
{ selector: 'h3', options: { uppercase: false } },
|
|
386
|
+
{ selector: 'h4', options: { uppercase: false } },
|
|
387
|
+
],
|
|
388
|
+
});
|
|
389
|
+
return normalizeText(text);
|
|
390
|
+
}
|
|
391
|
+
function normalizeText(text) {
|
|
392
|
+
return String(text)
|
|
393
|
+
.replace(/\r\n/g, '\n')
|
|
394
|
+
.replace(/[ \t]+\n/g, '\n')
|
|
395
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
396
|
+
.trim();
|
|
397
|
+
}
|
|
398
|
+
function textOf(value) {
|
|
399
|
+
return String(value ?? '').trim();
|
|
400
|
+
}
|
|
401
|
+
function attr($, selector, name) {
|
|
402
|
+
return String($(selector).first().attr(name) ?? '').trim();
|
|
403
|
+
}
|
|
404
|
+
function safeHost(url) {
|
|
405
|
+
try {
|
|
406
|
+
return new URL(url).hostname.replace(/^www\./, '');
|
|
407
|
+
}
|
|
408
|
+
catch {
|
|
409
|
+
return '';
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function isJobBoardHost(host) {
|
|
413
|
+
return JOB_BOARD_HOSTS.some((domain) => host === domain || host.endsWith(`.${domain}`));
|
|
414
|
+
}
|
|
415
|
+
function looksLikeBlockedPage(text, title = '') {
|
|
416
|
+
if (/attention required!?\s*\|?\s*cloudflare|just a moment\.\.\.|cf-error-details|challenge-platform/i.test(title)) {
|
|
417
|
+
return true;
|
|
418
|
+
}
|
|
419
|
+
if (/^\s*(?:please enable cookies\.?\s*)?sorry, you have been blocked|^\s*enable javascript and cookies to continue|^\s*verify you are human|^\s*access denied\b/i.test(text)) {
|
|
420
|
+
return true;
|
|
421
|
+
}
|
|
422
|
+
if (text.length >= 500)
|
|
423
|
+
return false;
|
|
424
|
+
return /\b(sign in|log in|create an account|enable javascript|access denied|are you a robot)\b/i.test(text);
|
|
425
|
+
}
|
|
426
|
+
//# sourceMappingURL=page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/job/page.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface JobDetails {
|
|
2
|
+
budget?: string;
|
|
3
|
+
budgetType?: 'hourly' | 'fixed';
|
|
4
|
+
workload?: string;
|
|
5
|
+
duration?: string;
|
|
6
|
+
experienceLevel?: string;
|
|
7
|
+
projectType?: string;
|
|
8
|
+
jobLocation?: string;
|
|
9
|
+
posted?: string;
|
|
10
|
+
skills?: string[];
|
|
11
|
+
client?: string;
|
|
12
|
+
clientLocation?: string;
|
|
13
|
+
clientMemberSince?: string;
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface Job {
|
|
17
|
+
title: string;
|
|
18
|
+
company: string;
|
|
19
|
+
url: string;
|
|
20
|
+
body: string;
|
|
21
|
+
source: string;
|
|
22
|
+
details: JobDetails;
|
|
23
|
+
}
|
|
24
|
+
export interface JobInputOptions {
|
|
25
|
+
input?: string;
|
|
26
|
+
title?: string;
|
|
27
|
+
company?: string;
|
|
28
|
+
url?: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/job/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function ensureAgents(): string;
|
|
2
|
+
/**
|
|
3
|
+
* New agent files are not always visible to a running OpenCode service until
|
|
4
|
+
* its configuration is reloaded. `opencode reload` is the supported V2 command
|
|
5
|
+
* and does not restart the service.
|
|
6
|
+
*/
|
|
7
|
+
export declare function reloadOpencode(): void;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, } from 'node:fs';
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { ensureRuntimeDir, getAgentsDir, opencodeAgentsDir, } from '../config/paths.js';
|
|
5
|
+
export function ensureAgents() {
|
|
6
|
+
ensureRuntimeDir();
|
|
7
|
+
const agentsDir = getAgentsDir();
|
|
8
|
+
mkdirSync(opencodeAgentsDir, { recursive: true });
|
|
9
|
+
const source = fileURLToPath(new URL('../../agents/', import.meta.url));
|
|
10
|
+
try {
|
|
11
|
+
for (const file of readdirSync(source)) {
|
|
12
|
+
if (!file.endsWith('.md'))
|
|
13
|
+
continue;
|
|
14
|
+
const contents = `${source}/${file}`;
|
|
15
|
+
copyIfChanged(contents, `${agentsDir}/${file}`);
|
|
16
|
+
copyIfChanged(contents, `${opencodeAgentsDir}/${file}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
throw new Error(`Could not install OpenCode agents from ${source}: ${error.message}`);
|
|
21
|
+
}
|
|
22
|
+
mkdirSync(agentsDir, { recursive: true });
|
|
23
|
+
return agentsDir;
|
|
24
|
+
}
|
|
25
|
+
function copyIfChanged(source, target) {
|
|
26
|
+
if (existsSync(target) && readFileSync(target, 'utf8') === readFileSync(source, 'utf8')) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
cpSync(source, target, { force: true });
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* New agent files are not always visible to a running OpenCode service until
|
|
33
|
+
* its configuration is reloaded. `opencode reload` is the supported V2 command
|
|
34
|
+
* and does not restart the service.
|
|
35
|
+
*/
|
|
36
|
+
export function reloadOpencode() {
|
|
37
|
+
const result = spawnSync('opencode', ['reload'], {
|
|
38
|
+
encoding: 'utf8',
|
|
39
|
+
timeout: 15_000,
|
|
40
|
+
});
|
|
41
|
+
if (result.error || result.status !== 0) {
|
|
42
|
+
const detail = result.error?.message || result.stderr || 'unknown error';
|
|
43
|
+
console.warn(`dossier: could not reload OpenCode configuration: ${detail}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/llm/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,UAAU,EACV,SAAS,EACT,YAAY,EACZ,WAAW,GACZ,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,UAAU,YAAY;IAC1B,gBAAgB,EAAE,CAAC;IACnB,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IACjC,SAAS,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,eAAe,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACxE,IAAI,CAAC;QACH,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YACpC,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC;YACrC,aAAa,CAAC,QAAQ,EAAE,GAAG,SAAS,IAAI,IAAI,EAAE,CAAC,CAAC;YAChD,aAAa,CAAC,QAAQ,EAAE,GAAG,iBAAiB,IAAI,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,0CAA0C,MAAM,KAAM,KAAe,CAAC,OAAO,EAAE,CAChF,CAAC;IACJ,CAAC;IACD,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,aAAa,CAAC,MAAc,EAAE,MAAc;IACnD,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;QACxF,OAAO;IACT,CAAC;IACD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE;QAC/C,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,MAAM;KAChB,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,MAAM,IAAI,eAAe,CAAC;QACzE,OAAO,CAAC,IAAI,CAAC,qDAAqD,MAAM,EAAE,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
export interface RunOpencodeOptions {
|
|
3
|
+
prompt: string;
|
|
4
|
+
agent: string;
|
|
5
|
+
model?: string | null;
|
|
6
|
+
title?: string;
|
|
7
|
+
timeout: number;
|
|
8
|
+
cwd: string;
|
|
9
|
+
}
|
|
10
|
+
export interface OpencodeStats {
|
|
11
|
+
cost: number;
|
|
12
|
+
input: number;
|
|
13
|
+
output: number;
|
|
14
|
+
reasoning: number;
|
|
15
|
+
}
|
|
16
|
+
export declare function runOpencode({ prompt, agent, model, title, timeout, cwd, }: RunOpencodeOptions): ReturnType<typeof spawnSync>;
|
|
17
|
+
export declare function parseOpencodeStats(stdout: string): OpencodeStats | null;
|
|
18
|
+
export declare function parseOpencodeOutput(stdout: string): Record<string, unknown> | null;
|
|
19
|
+
export declare function extractJson(text: string): Record<string, unknown> | null;
|