jobseek-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/applications.d.ts +2 -0
- package/dist/commands/applications.js +198 -0
- package/dist/commands/applications.js.map +1 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.js +315 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/claims.d.ts +2 -0
- package/dist/commands/claims.js +355 -0
- package/dist/commands/claims.js.map +1 -0
- package/dist/commands/jobs.d.ts +2 -0
- package/dist/commands/jobs.js +240 -0
- package/dist/commands/jobs.js.map +1 -0
- package/dist/commands/profile.d.ts +2 -0
- package/dist/commands/profile.js +116 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/question.d.ts +2 -0
- package/dist/commands/question.js +54 -0
- package/dist/commands/question.js.map +1 -0
- package/dist/commands/resume.d.ts +2 -0
- package/dist/commands/resume.js +209 -0
- package/dist/commands/resume.js.map +1 -0
- package/dist/commands/search.d.ts +2 -0
- package/dist/commands/search.js +192 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/ssh-key.d.ts +2 -0
- package/dist/commands/ssh-key.js +151 -0
- package/dist/commands/ssh-key.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-client.d.ts +16 -0
- package/dist/lib/api-client.js +59 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/config.d.ts +19 -0
- package/dist/lib/config.js +56 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/errors.d.ts +11 -0
- package/dist/lib/errors.js +23 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/oauth.d.ts +41 -0
- package/dist/lib/oauth.js +210 -0
- package/dist/lib/oauth.js.map +1 -0
- package/dist/lib/output.d.ts +20 -0
- package/dist/lib/output.js +109 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/ssh.d.ts +25 -0
- package/dist/lib/ssh.js +103 -0
- package/dist/lib/ssh.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { requireApiKey, resolveApiUrl } from '../lib/config.js';
|
|
2
|
+
import { ApiClient } from '../lib/api-client.js';
|
|
3
|
+
import * as out from '../lib/output.js';
|
|
4
|
+
export function registerProfileCommands(program) {
|
|
5
|
+
const profile = program
|
|
6
|
+
.command('profile')
|
|
7
|
+
.description('View your JobSeek profile')
|
|
8
|
+
.action(async () => {
|
|
9
|
+
const parentOpts = program.opts();
|
|
10
|
+
const apiKey = requireApiKey(parentOpts.apiKey);
|
|
11
|
+
const apiUrl = resolveApiUrl(parentOpts.apiUrl);
|
|
12
|
+
const client = new ApiClient(apiUrl, apiKey);
|
|
13
|
+
const spin = out.spinner('Fetching profile...');
|
|
14
|
+
spin.start();
|
|
15
|
+
try {
|
|
16
|
+
const data = await client.get('/api/profile/mcp');
|
|
17
|
+
spin.stop();
|
|
18
|
+
const p = data.profile;
|
|
19
|
+
if (out.isJsonMode()) {
|
|
20
|
+
out.outputJson(p);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
out.heading('Profile');
|
|
24
|
+
out.keyValue('Name', p.name || 'N/A');
|
|
25
|
+
out.keyValue('Email', p.email || 'N/A');
|
|
26
|
+
out.keyValue('Phone', p.phone || 'N/A');
|
|
27
|
+
out.keyValue('Location', p.location || 'N/A');
|
|
28
|
+
out.keyValue('LinkedIn', p.linkedinUrl || 'N/A');
|
|
29
|
+
if (p.summary) {
|
|
30
|
+
console.log();
|
|
31
|
+
out.heading('Summary');
|
|
32
|
+
console.log(' ' + p.summary);
|
|
33
|
+
}
|
|
34
|
+
if (p.skills?.length) {
|
|
35
|
+
console.log();
|
|
36
|
+
out.heading('Skills');
|
|
37
|
+
console.log(' ' + p.skills.join(', '));
|
|
38
|
+
}
|
|
39
|
+
if (p.experience?.length) {
|
|
40
|
+
console.log();
|
|
41
|
+
out.heading('Experience');
|
|
42
|
+
for (const exp of p.experience) {
|
|
43
|
+
console.log(` ${exp.title} at ${exp.company}`);
|
|
44
|
+
if (exp.startDate || exp.endDate) {
|
|
45
|
+
console.log(` ${exp.startDate || '?'} – ${exp.endDate || 'Present'}`);
|
|
46
|
+
}
|
|
47
|
+
console.log();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (p.education?.length) {
|
|
51
|
+
out.heading('Education');
|
|
52
|
+
for (const edu of p.education) {
|
|
53
|
+
console.log(` ${edu.degree} – ${edu.school}`);
|
|
54
|
+
if (edu.graduationDate)
|
|
55
|
+
console.log(` ${edu.graduationDate}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
spin.stop();
|
|
61
|
+
out.error(err.message);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
profile
|
|
66
|
+
.command('form-data')
|
|
67
|
+
.description('Get structured profile data for form filling')
|
|
68
|
+
.option('--fields <fields>', 'Comma-separated list of fields to include')
|
|
69
|
+
.action(async (opts) => {
|
|
70
|
+
const parentOpts = program.opts();
|
|
71
|
+
const apiKey = requireApiKey(parentOpts.apiKey);
|
|
72
|
+
const apiUrl = resolveApiUrl(parentOpts.apiUrl);
|
|
73
|
+
const client = new ApiClient(apiUrl, apiKey);
|
|
74
|
+
const spin = out.spinner('Fetching form data...');
|
|
75
|
+
spin.start();
|
|
76
|
+
try {
|
|
77
|
+
const params = {};
|
|
78
|
+
if (opts.fields)
|
|
79
|
+
params.fields = opts.fields;
|
|
80
|
+
const data = await client.get('/api/profile/mcp', params);
|
|
81
|
+
spin.stop();
|
|
82
|
+
// The form-data endpoint returns the same profile but we format it for forms
|
|
83
|
+
const p = data.profile;
|
|
84
|
+
const formData = {
|
|
85
|
+
fullName: p.name,
|
|
86
|
+
email: p.email,
|
|
87
|
+
phone: p.phone,
|
|
88
|
+
location: p.location,
|
|
89
|
+
linkedinUrl: p.linkedinUrl,
|
|
90
|
+
summary: p.summary,
|
|
91
|
+
skills: p.skills,
|
|
92
|
+
experience: p.experience,
|
|
93
|
+
education: p.education,
|
|
94
|
+
};
|
|
95
|
+
if (out.isJsonMode()) {
|
|
96
|
+
out.outputJson(formData);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
out.heading('Form Data');
|
|
100
|
+
for (const [key, value] of Object.entries(formData)) {
|
|
101
|
+
if (Array.isArray(value)) {
|
|
102
|
+
out.keyValue(key, typeof value[0] === 'string' ? value.join(', ') : `[${value.length} items]`);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
out.keyValue(key, String(value || 'N/A'));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
spin.stop();
|
|
111
|
+
out.error(err.message);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/commands/profile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,GAAG,MAAM,kBAAkB,CAAC;AAExC,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACpD,MAAM,OAAO,GAAG,OAAO;SAClB,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,2BAA2B,CAAC;SACxC,MAAM,CAAC,KAAK,IAAI,EAAE;QACf,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAE7C,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAmB,kBAAkB,CAAC,CAAC;YACpE,IAAI,CAAC,IAAI,EAAE,CAAC;YAEZ,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;YAEvB,IAAI,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC;gBACnB,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;gBAClB,OAAO;YACX,CAAC;YAED,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACvB,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC;YACtC,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC;YACxC,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC;YACxC,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,CAAC;YAC9C,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,WAAW,IAAI,KAAK,CAAC,CAAC;YAEjD,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,GAAG,EAAE,CAAC;gBACd,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBACvB,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;YAClC,CAAC;YAED,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;gBACnB,OAAO,CAAC,GAAG,EAAE,CAAC;gBACd,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACtB,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5C,CAAC;YAED,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;gBACvB,OAAO,CAAC,GAAG,EAAE,CAAC;gBACd,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;gBAC1B,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;oBAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,KAAK,OAAO,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;oBAChD,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;wBAC/B,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,SAAS,IAAI,GAAG,MAAM,GAAG,CAAC,OAAO,IAAI,SAAS,EAAE,CAAC,CAAC;oBAC7E,CAAC;oBACD,OAAO,CAAC,GAAG,EAAE,CAAC;gBAClB,CAAC;YACL,CAAC;YAED,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;gBACtB,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;gBACzB,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;oBAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;oBAC/C,IAAI,GAAG,CAAC,cAAc;wBAAE,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;gBACrE,CAAC;YACL,CAAC;QACL,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACL,CAAC,CAAC,CAAC;IAEP,OAAO;SACF,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,8CAA8C,CAAC;SAC3D,MAAM,CAAC,mBAAmB,EAAE,2CAA2C,CAAC;SACxE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACnB,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAE7C,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;QAClD,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,IAAI,CAAC;YACD,MAAM,MAAM,GAAuC,EAAE,CAAC;YACtD,IAAI,IAAI,CAAC,MAAM;gBAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAE7C,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAM,kBAAkB,EAAE,MAAM,CAAC,CAAC;YAC/D,IAAI,CAAC,IAAI,EAAE,CAAC;YAEZ,6EAA6E;YAC7E,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;YACvB,MAAM,QAAQ,GAAwB;gBAClC,QAAQ,EAAE,CAAC,CAAC,IAAI;gBAChB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,UAAU,EAAE,CAAC,CAAC,UAAU;gBACxB,SAAS,EAAE,CAAC,CAAC,SAAS;aACzB,CAAC;YAEF,IAAI,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC;gBACnB,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;gBACzB,OAAO;YACX,CAAC;YAED,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;YACzB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACvB,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,SAAS,CAAC,CAAC;gBACnG,CAAC;qBAAM,CAAC;oBACJ,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC;gBAC9C,CAAC;YACL,CAAC;QACL,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACL,CAAC,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { input } from '@inquirer/prompts';
|
|
2
|
+
import { requireApiKey, resolveApiUrl } from '../lib/config.js';
|
|
3
|
+
import { ApiClient } from '../lib/api-client.js';
|
|
4
|
+
import * as out from '../lib/output.js';
|
|
5
|
+
export function registerQuestionCommands(program) {
|
|
6
|
+
program
|
|
7
|
+
.command('question [text...]')
|
|
8
|
+
.description('Get AI-powered interview answer suggestions (STAR format)')
|
|
9
|
+
.action(async (textParts) => {
|
|
10
|
+
const parentOpts = program.opts();
|
|
11
|
+
const apiKey = requireApiKey(parentOpts.apiKey);
|
|
12
|
+
const apiUrl = resolveApiUrl(parentOpts.apiUrl);
|
|
13
|
+
const client = new ApiClient(apiUrl, apiKey);
|
|
14
|
+
let question = textParts?.length ? textParts.join(' ') : '';
|
|
15
|
+
if (!question) {
|
|
16
|
+
question = await input({ message: 'Enter interview question:' });
|
|
17
|
+
}
|
|
18
|
+
if (!question.trim()) {
|
|
19
|
+
out.error('No question provided.');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const spin = out.spinner('Generating answer suggestions...');
|
|
23
|
+
spin.start();
|
|
24
|
+
try {
|
|
25
|
+
const data = await client.post('/api/question-helper', { question });
|
|
26
|
+
spin.stop();
|
|
27
|
+
if (out.isJsonMode()) {
|
|
28
|
+
out.outputJson(data);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
out.heading('Interview Question');
|
|
32
|
+
console.log(' ' + data.question);
|
|
33
|
+
if (data.answers?.length) {
|
|
34
|
+
for (let i = 0; i < data.answers.length; i++) {
|
|
35
|
+
const ans = data.answers[i];
|
|
36
|
+
console.log();
|
|
37
|
+
out.heading(`Answer ${i + 1}: ${ans.approach}`);
|
|
38
|
+
console.log(ans.answer);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (data.tips?.length) {
|
|
42
|
+
console.log();
|
|
43
|
+
out.heading('Tips');
|
|
44
|
+
out.bulletList(data.tips);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
spin.stop();
|
|
49
|
+
out.error(err.message);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=question.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"question.js","sourceRoot":"","sources":["../../src/commands/question.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { basename, resolve } from 'node:path';
|
|
3
|
+
import { requireApiKey, resolveApiUrl } from '../lib/config.js';
|
|
4
|
+
import { ApiClient } from '../lib/api-client.js';
|
|
5
|
+
import * as out from '../lib/output.js';
|
|
6
|
+
export function registerResumeCommands(program) {
|
|
7
|
+
const resume = program
|
|
8
|
+
.command('resume')
|
|
9
|
+
.description('View your current resume')
|
|
10
|
+
.action(async () => {
|
|
11
|
+
const parentOpts = program.opts();
|
|
12
|
+
const apiKey = requireApiKey(parentOpts.apiKey);
|
|
13
|
+
const apiUrl = resolveApiUrl(parentOpts.apiUrl);
|
|
14
|
+
const client = new ApiClient(apiUrl, apiKey);
|
|
15
|
+
const spin = out.spinner('Fetching resume...');
|
|
16
|
+
spin.start();
|
|
17
|
+
try {
|
|
18
|
+
const data = await client.get('/api/profile/mcp');
|
|
19
|
+
spin.stop();
|
|
20
|
+
const p = data.profile;
|
|
21
|
+
if (out.isJsonMode()) {
|
|
22
|
+
out.outputJson(p);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
out.heading('Resume');
|
|
26
|
+
out.keyValue('Name', p.name || 'N/A');
|
|
27
|
+
out.keyValue('Email', p.email || 'N/A');
|
|
28
|
+
if (p.summary) {
|
|
29
|
+
console.log();
|
|
30
|
+
console.log(' ' + p.summary);
|
|
31
|
+
}
|
|
32
|
+
if (p.skills?.length) {
|
|
33
|
+
console.log();
|
|
34
|
+
out.heading('Skills');
|
|
35
|
+
console.log(' ' + p.skills.join(', '));
|
|
36
|
+
}
|
|
37
|
+
if (p.experience?.length) {
|
|
38
|
+
console.log();
|
|
39
|
+
out.heading(`Experience (${p.experience.length})`);
|
|
40
|
+
for (const exp of p.experience) {
|
|
41
|
+
console.log(` ${exp.title} at ${exp.company}`);
|
|
42
|
+
if (exp.startDate || exp.endDate) {
|
|
43
|
+
console.log(` ${exp.startDate || '?'} – ${exp.endDate || 'Present'}`);
|
|
44
|
+
}
|
|
45
|
+
if (exp.description) {
|
|
46
|
+
console.log(` ${out.truncate(exp.description, 120)}`);
|
|
47
|
+
}
|
|
48
|
+
console.log();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (p.education?.length) {
|
|
52
|
+
out.heading(`Education (${p.education.length})`);
|
|
53
|
+
for (const edu of p.education) {
|
|
54
|
+
console.log(` ${edu.degree} – ${edu.school}`);
|
|
55
|
+
if (edu.graduationDate)
|
|
56
|
+
console.log(` ${edu.graduationDate}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
spin.stop();
|
|
62
|
+
out.error(err.message);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
resume
|
|
67
|
+
.command('upload <file>')
|
|
68
|
+
.description('Upload a resume PDF')
|
|
69
|
+
.action(async (file) => {
|
|
70
|
+
const parentOpts = program.opts();
|
|
71
|
+
const apiKey = requireApiKey(parentOpts.apiKey);
|
|
72
|
+
const apiUrl = resolveApiUrl(parentOpts.apiUrl);
|
|
73
|
+
const client = new ApiClient(apiUrl, apiKey);
|
|
74
|
+
const filePath = resolve(file.replace(/^~/, process.env.HOME || ''));
|
|
75
|
+
const fileName = basename(filePath);
|
|
76
|
+
if (!fileName.toLowerCase().endsWith('.pdf')) {
|
|
77
|
+
out.error('Only PDF files are supported.');
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
let pdfBase64;
|
|
81
|
+
try {
|
|
82
|
+
const buffer = readFileSync(filePath);
|
|
83
|
+
pdfBase64 = buffer.toString('base64');
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
out.error(`Cannot read file: ${err.message}`);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
const spin = out.spinner('Uploading resume...');
|
|
90
|
+
spin.start();
|
|
91
|
+
try {
|
|
92
|
+
const data = await client.post('/api/resumes/upload', { pdfBase64, fileName });
|
|
93
|
+
spin.stop();
|
|
94
|
+
if (out.isJsonMode()) {
|
|
95
|
+
out.outputJson(data);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
out.success(`Resume uploaded: ${data.fileName}`);
|
|
99
|
+
out.keyValue('Skills found', String(data.skillsCount));
|
|
100
|
+
out.keyValue('Experience entries', String(data.experienceCount));
|
|
101
|
+
if (data.summary) {
|
|
102
|
+
console.log();
|
|
103
|
+
console.log(' ' + out.truncate(data.summary, 200));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
spin.stop();
|
|
108
|
+
out.error(err.message);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
resume
|
|
113
|
+
.command('optimize')
|
|
114
|
+
.description('Optimize resume for ATS systems')
|
|
115
|
+
.option('--feedback <text>', 'Specific feedback for optimization')
|
|
116
|
+
.action(async (opts) => {
|
|
117
|
+
const parentOpts = program.opts();
|
|
118
|
+
const apiKey = requireApiKey(parentOpts.apiKey);
|
|
119
|
+
const apiUrl = resolveApiUrl(parentOpts.apiUrl);
|
|
120
|
+
const client = new ApiClient(apiUrl, apiKey);
|
|
121
|
+
const spin = out.spinner('Optimizing resume for ATS...');
|
|
122
|
+
spin.start();
|
|
123
|
+
try {
|
|
124
|
+
const body = {};
|
|
125
|
+
if (opts.feedback)
|
|
126
|
+
body.feedback = opts.feedback;
|
|
127
|
+
const data = await client.post('/api/resumes/optimize', body);
|
|
128
|
+
spin.stop();
|
|
129
|
+
if (out.isJsonMode()) {
|
|
130
|
+
out.outputJson(data);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const { content, rationale } = data;
|
|
134
|
+
out.heading('Optimized Resume');
|
|
135
|
+
if (content.summary) {
|
|
136
|
+
out.heading('Summary');
|
|
137
|
+
console.log(' ' + content.summary);
|
|
138
|
+
}
|
|
139
|
+
if (content.skills?.length) {
|
|
140
|
+
console.log();
|
|
141
|
+
out.heading('Skills');
|
|
142
|
+
console.log(' ' + content.skills.join(', '));
|
|
143
|
+
}
|
|
144
|
+
if (content.experience?.length) {
|
|
145
|
+
console.log();
|
|
146
|
+
out.heading('Experience');
|
|
147
|
+
for (const exp of content.experience) {
|
|
148
|
+
console.log(` ${exp.title} at ${exp.company}`);
|
|
149
|
+
if (exp.duration)
|
|
150
|
+
console.log(` ${exp.duration}`);
|
|
151
|
+
if (exp.description)
|
|
152
|
+
console.log(` ${exp.description}`);
|
|
153
|
+
console.log();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (rationale) {
|
|
157
|
+
console.log();
|
|
158
|
+
out.heading('Changes Made');
|
|
159
|
+
if (rationale.summaryChanges)
|
|
160
|
+
out.keyValue('Summary', rationale.summaryChanges);
|
|
161
|
+
if (rationale.skillPrioritization)
|
|
162
|
+
out.keyValue('Skills', rationale.skillPrioritization);
|
|
163
|
+
if (rationale.experienceHighlights)
|
|
164
|
+
out.keyValue('Experience', rationale.experienceHighlights);
|
|
165
|
+
if (rationale.formattingChanges)
|
|
166
|
+
out.keyValue('Formatting', rationale.formattingChanges);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
spin.stop();
|
|
171
|
+
out.error(err.message);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
resume
|
|
176
|
+
.command('link')
|
|
177
|
+
.description('Generate temporary download link for your resume')
|
|
178
|
+
.option('--open', 'Open link in browser')
|
|
179
|
+
.action(async (opts) => {
|
|
180
|
+
const parentOpts = program.opts();
|
|
181
|
+
const apiKey = requireApiKey(parentOpts.apiKey);
|
|
182
|
+
const apiUrl = resolveApiUrl(parentOpts.apiUrl);
|
|
183
|
+
const client = new ApiClient(apiUrl, apiKey);
|
|
184
|
+
const spin = out.spinner('Generating download link...');
|
|
185
|
+
spin.start();
|
|
186
|
+
try {
|
|
187
|
+
const data = await client.post('/api/resumes/pdf');
|
|
188
|
+
spin.stop();
|
|
189
|
+
if (out.isJsonMode()) {
|
|
190
|
+
out.outputJson(data);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
out.success('Resume download link generated');
|
|
194
|
+
out.keyValue('URL', data.downloadUrl);
|
|
195
|
+
out.keyValue('Expires', data.expiresIn);
|
|
196
|
+
if (opts.open) {
|
|
197
|
+
const openModule = await import('open');
|
|
198
|
+
await openModule.default(data.downloadUrl);
|
|
199
|
+
out.info('Opened in browser');
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
spin.stop();
|
|
204
|
+
out.error(err.message);
|
|
205
|
+
process.exit(1);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=resume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../../src/commands/resume.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { input, select, checkbox } from '@inquirer/prompts';
|
|
2
|
+
import { requireApiKey, resolveApiUrl } from '../lib/config.js';
|
|
3
|
+
import { ApiClient } from '../lib/api-client.js';
|
|
4
|
+
import * as out from '../lib/output.js';
|
|
5
|
+
export function registerSearchCommands(program) {
|
|
6
|
+
const search = program
|
|
7
|
+
.command('search')
|
|
8
|
+
.description('Job search tools');
|
|
9
|
+
search
|
|
10
|
+
.command('launch')
|
|
11
|
+
.description('Open job search across major job boards')
|
|
12
|
+
.option('--query <text>', 'Custom search query')
|
|
13
|
+
.option('--no-open', 'Only show URLs, do not open browser')
|
|
14
|
+
.action(async (opts) => {
|
|
15
|
+
const parentOpts = program.opts();
|
|
16
|
+
const apiKey = requireApiKey(parentOpts.apiKey);
|
|
17
|
+
const apiUrl = resolveApiUrl(parentOpts.apiUrl);
|
|
18
|
+
const client = new ApiClient(apiUrl, apiKey);
|
|
19
|
+
const spin = out.spinner('Getting job board links...');
|
|
20
|
+
spin.start();
|
|
21
|
+
try {
|
|
22
|
+
const params = {};
|
|
23
|
+
if (opts.query)
|
|
24
|
+
params.query = opts.query;
|
|
25
|
+
const data = await client.get('/api/launchpad', params);
|
|
26
|
+
spin.stop();
|
|
27
|
+
if (out.isJsonMode()) {
|
|
28
|
+
out.outputJson(data);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
out.heading('Job Search Launch Pad');
|
|
32
|
+
out.keyValue('Search Query', data.searchQuery);
|
|
33
|
+
console.log();
|
|
34
|
+
for (const link of data.links) {
|
|
35
|
+
console.log(` ${link.icon} ${link.name}: ${link.url}`);
|
|
36
|
+
}
|
|
37
|
+
if (opts.open !== false) {
|
|
38
|
+
console.log();
|
|
39
|
+
const openModule = await import('open');
|
|
40
|
+
for (const link of data.links) {
|
|
41
|
+
try {
|
|
42
|
+
await openModule.default(link.url);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// Silently skip if browser can't open
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
out.success(`Opened ${data.links.length} job boards in your browser`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
spin.stop();
|
|
53
|
+
out.error(err.message);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
search
|
|
58
|
+
.command('auto')
|
|
59
|
+
.description('Run automated Dice job search with AI analysis')
|
|
60
|
+
.option('--keyword <text>', 'Search keyword')
|
|
61
|
+
.option('--location <text>', 'Location (omit for remote searches)')
|
|
62
|
+
.option('--remote', 'Remote jobs only')
|
|
63
|
+
.option('--hybrid', 'Hybrid jobs')
|
|
64
|
+
.option('--onsite', 'On-site jobs')
|
|
65
|
+
.option('--contract', 'Contract positions')
|
|
66
|
+
.option('--posted <days>', 'Posted within: ONE, THREE, SEVEN')
|
|
67
|
+
.option('--max-matches <n>', 'Maximum full matches to analyze', '10')
|
|
68
|
+
.option('--min-score <n>', 'Minimum match score threshold', '60')
|
|
69
|
+
.action(async (opts) => {
|
|
70
|
+
const parentOpts = program.opts();
|
|
71
|
+
const apiKey = requireApiKey(parentOpts.apiKey);
|
|
72
|
+
const apiUrl = resolveApiUrl(parentOpts.apiUrl);
|
|
73
|
+
const client = new ApiClient(apiUrl, apiKey);
|
|
74
|
+
let keyword = opts.keyword;
|
|
75
|
+
// Interactive wizard when no keyword provided
|
|
76
|
+
if (!keyword) {
|
|
77
|
+
keyword = await input({ message: 'Search keyword:' });
|
|
78
|
+
if (!opts.remote && !opts.hybrid && !opts.onsite) {
|
|
79
|
+
const workplaces = await checkbox({
|
|
80
|
+
message: 'Workplace type(s):',
|
|
81
|
+
choices: [
|
|
82
|
+
{ name: 'Remote', value: 'Remote' },
|
|
83
|
+
{ name: 'Hybrid', value: 'Hybrid' },
|
|
84
|
+
{ name: 'On-Site', value: 'On-Site' },
|
|
85
|
+
],
|
|
86
|
+
});
|
|
87
|
+
if (workplaces.includes('Remote'))
|
|
88
|
+
opts.remote = true;
|
|
89
|
+
if (workplaces.includes('Hybrid'))
|
|
90
|
+
opts.hybrid = true;
|
|
91
|
+
if (workplaces.includes('On-Site'))
|
|
92
|
+
opts.onsite = true;
|
|
93
|
+
}
|
|
94
|
+
if (!opts.location && !opts.remote) {
|
|
95
|
+
const loc = await input({ message: 'Location (leave empty for any):', default: '' });
|
|
96
|
+
if (loc)
|
|
97
|
+
opts.location = loc;
|
|
98
|
+
}
|
|
99
|
+
if (!opts.posted) {
|
|
100
|
+
const posted = await select({
|
|
101
|
+
message: 'Posted within:',
|
|
102
|
+
choices: [
|
|
103
|
+
{ name: 'Any time', value: '' },
|
|
104
|
+
{ name: 'Last 24 hours', value: 'ONE' },
|
|
105
|
+
{ name: 'Last 3 days', value: 'THREE' },
|
|
106
|
+
{ name: 'Last 7 days', value: 'SEVEN' },
|
|
107
|
+
],
|
|
108
|
+
});
|
|
109
|
+
if (posted)
|
|
110
|
+
opts.posted = posted;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Build workplace_types
|
|
114
|
+
const workplaceTypes = [];
|
|
115
|
+
if (opts.remote)
|
|
116
|
+
workplaceTypes.push('Remote');
|
|
117
|
+
if (opts.hybrid)
|
|
118
|
+
workplaceTypes.push('Hybrid');
|
|
119
|
+
if (opts.onsite)
|
|
120
|
+
workplaceTypes.push('On-Site');
|
|
121
|
+
// Build employment_types
|
|
122
|
+
const employmentTypes = [];
|
|
123
|
+
if (opts.contract)
|
|
124
|
+
employmentTypes.push('CONTRACTS');
|
|
125
|
+
const body = {
|
|
126
|
+
keyword,
|
|
127
|
+
maxFullMatches: Number(opts.maxMatches),
|
|
128
|
+
minMatchScore: Number(opts.minScore),
|
|
129
|
+
};
|
|
130
|
+
if (opts.location)
|
|
131
|
+
body.location = opts.location;
|
|
132
|
+
if (workplaceTypes.length)
|
|
133
|
+
body.workplaceTypes = workplaceTypes;
|
|
134
|
+
if (employmentTypes.length)
|
|
135
|
+
body.employmentTypes = employmentTypes;
|
|
136
|
+
if (opts.posted)
|
|
137
|
+
body.postedDate = opts.posted;
|
|
138
|
+
const spin = out.spinner('Starting automated search...');
|
|
139
|
+
spin.start();
|
|
140
|
+
try {
|
|
141
|
+
const createResult = await client.post('/api/automated-search/create', body);
|
|
142
|
+
const searchId = createResult.searchId;
|
|
143
|
+
spin.text = 'Searching Dice and analyzing matches...';
|
|
144
|
+
// Poll for status
|
|
145
|
+
let done = false;
|
|
146
|
+
let lastStatus = '';
|
|
147
|
+
while (!done) {
|
|
148
|
+
await new Promise(r => setTimeout(r, 3000));
|
|
149
|
+
const status = await client.get(`/api/automated-search/${searchId}/status`);
|
|
150
|
+
if (status.status !== lastStatus) {
|
|
151
|
+
lastStatus = status.status;
|
|
152
|
+
if (status.status === 'searching') {
|
|
153
|
+
spin.text = 'Searching Dice for jobs...';
|
|
154
|
+
}
|
|
155
|
+
else if (status.status === 'analyzing') {
|
|
156
|
+
spin.text = `Analyzing matches... (${status.totalPreScreened} pre-screened, ${status.totalMatched} matched so far)`;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else if (status.status === 'analyzing') {
|
|
160
|
+
spin.text = `Analyzing matches... (${status.totalPreScreened} pre-screened, ${status.totalMatched} matched)`;
|
|
161
|
+
}
|
|
162
|
+
if (status.status === 'completed' || status.status === 'failed') {
|
|
163
|
+
done = true;
|
|
164
|
+
spin.stop();
|
|
165
|
+
if (status.status === 'failed') {
|
|
166
|
+
out.error(`Search failed: ${status.error || 'Unknown error'}`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
if (out.isJsonMode()) {
|
|
170
|
+
out.outputJson(status);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
out.success('Automated search complete!');
|
|
174
|
+
console.log();
|
|
175
|
+
out.keyValue('Jobs fetched', String(status.totalFetched));
|
|
176
|
+
out.keyValue('Pre-screened', String(status.totalPreScreened));
|
|
177
|
+
out.keyValue('Full matches', String(status.totalMatched));
|
|
178
|
+
out.keyValue('Top matches', String(status.topMatchCount));
|
|
179
|
+
out.keyValue('Tokens used', status.tokensUsed.toLocaleString());
|
|
180
|
+
console.log();
|
|
181
|
+
out.info('View your matches with `jobseek jobs --sort matchScore`');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
spin.stop();
|
|
187
|
+
out.error(err.message);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"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"}
|