trackly-cli 0.2.1 → 0.2.2
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/bin/trackly +19 -2
- package/docs/trackly-tools.md +1 -1
- package/mcp/server.js +21 -2
- package/package.json +1 -1
- package/server.json +2 -2
package/bin/trackly
CHANGED
|
@@ -466,13 +466,30 @@ async function cmdStats() {
|
|
|
466
466
|
}
|
|
467
467
|
|
|
468
468
|
const ACTION_TO_COMMAND = { applied: 'apply', saved: 'save', dismissed: 'dismiss' };
|
|
469
|
+
|
|
470
|
+
// CLI surface accepts applied|saved|dismissed (legacy human-friendly terms).
|
|
471
|
+
// Backend `/api/jobscout/tracker/jobs/:id/stage` expects stage values:
|
|
472
|
+
// applied → applied, saved → backlog, dismissed → discarded
|
|
473
|
+
// The old `/api/jobscout-tracker/status` endpoint was removed; the new stage
|
|
474
|
+
// endpoint is what production actually serves (and what hosted MCP uses).
|
|
475
|
+
const ACTION_TO_STAGE = { applied: 'applied', saved: 'backlog', dismissed: 'discarded' };
|
|
476
|
+
|
|
469
477
|
async function cmdUpdateStatus(id, action) {
|
|
470
478
|
const jobId = parseJobId(id);
|
|
471
479
|
if (jobId === null) failNow(`Job ID must be a positive integer. Usage: trackly ${ACTION_TO_COMMAND[action] || action} <id>`);
|
|
472
480
|
if (!hasAuth()) failNow(AUTH_HELP_TEXT);
|
|
473
481
|
|
|
482
|
+
// action is already validated by the command dispatcher (apply/save/dismiss subcommands
|
|
483
|
+
// pass literal strings). No `|| action` fallback — if ACTION_TO_STAGE is ever widened
|
|
484
|
+
// without updating the dispatcher (or vice versa), fail loud rather than silently POST
|
|
485
|
+
// an unintended stage value (e.g., posting stage='snoozed' when backend only knows the
|
|
486
|
+
// stage column's allowlist). Mirrors the defensive throw in mcp/server.js.
|
|
487
|
+
const stage = ACTION_TO_STAGE[action];
|
|
488
|
+
if (!stage) {
|
|
489
|
+
failNow(`Internal error: unknown action "${action}" — expected applied|saved|dismissed.`);
|
|
490
|
+
}
|
|
474
491
|
try {
|
|
475
|
-
const result = await apiRequest('POST',
|
|
492
|
+
const result = await apiRequest('POST', `/api/jobscout/tracker/jobs/${jobId}/stage`, { stage });
|
|
476
493
|
if (isJSON()) return printJson(result);
|
|
477
494
|
console.log(color('green', `Job ${jobId} marked as ${STATUS_LABELS[action]}.`));
|
|
478
495
|
} catch (e) {
|
|
@@ -767,7 +784,7 @@ ${color('bold', 'Filter values:')}
|
|
|
767
784
|
--remote Flag (no value). Filters for remote jobs (equivalent to usStates=REMOTE).
|
|
768
785
|
--status new, applying, applied_confirmed, check_later, not_interested, all
|
|
769
786
|
(filters by YOUR application pipeline state)
|
|
770
|
-
--sort newest,
|
|
787
|
+
--sort newest (default), match (highest match score first, requires resume)
|
|
771
788
|
|
|
772
789
|
${color('bold', 'MCP Setup:')}
|
|
773
790
|
Claude Code: claude mcp add --scope user trackly -- trackly mcp
|
package/docs/trackly-tools.md
CHANGED
|
@@ -75,7 +75,7 @@ You can also pass `TRACKLY_API_KEY` as an environment variable for one-off runs.
|
|
|
75
75
|
- `jobModality`: `full_time`, `internship`, `all` — employment type, NOT work-location style. For remote/hybrid/onsite filtering, use the `remote` boolean or `locationFilter: "remote"`; hybrid and onsite are not exposed as filters.
|
|
76
76
|
- `remote` (boolean): filter to remote jobs only. Maps to `usStates=REMOTE`.
|
|
77
77
|
- `status`: your application pipeline state. Values: `new`, `applying`, `applied_confirmed`, `check_later`, `not_interested`, `all`.
|
|
78
|
-
- `sort`: `newest
|
|
78
|
+
- `sort`: `newest` (default) or `match` (highest match score first; requires a resume on file). Backend rejects the deprecated values `oldest` and `company` with HTTP 400.
|
|
79
79
|
- `keywords`, `companyId`, `limit`, `offset`.
|
|
80
80
|
- **trackly_get_job** — Get full job details by ID
|
|
81
81
|
- **trackly_search_companies** — Semantic company search
|
package/mcp/server.js
CHANGED
|
@@ -36,6 +36,16 @@ const STATUS_VALUES = ['new', 'applying', 'applied_confirmed', 'check_later', 'n
|
|
|
36
36
|
// `jobModality` enum matches `jobscout.ts:2870-2875`. Employment type, NOT work-location.
|
|
37
37
|
const JOB_MODALITIES = ['full_time', 'internship', 'all'];
|
|
38
38
|
|
|
39
|
+
// `sort` enum matches backend handler at `jobscout.ts:3053` — NOT the pre-fix
|
|
40
|
+
// `newest|oldest|company` (backend rejects oldest/company with HTTP 400).
|
|
41
|
+
const SORT_VALUES = ['newest', 'match'];
|
|
42
|
+
|
|
43
|
+
// Maps the user-facing trackly_update_status action to the backend's tracker
|
|
44
|
+
// stage column. Backend `/api/jobscout/tracker/jobs/:id/stage` expects the
|
|
45
|
+
// stage value, NOT the legacy action name. Hoisted to module scope so it's not
|
|
46
|
+
// rebuilt on every tool invocation.
|
|
47
|
+
const ACTION_TO_STAGE = { applied: 'applied', saved: 'backlog', dismissed: 'discarded' };
|
|
48
|
+
|
|
39
49
|
function createErrorResult(error, fallbackMessage, extra = {}) {
|
|
40
50
|
const payload = {
|
|
41
51
|
error: error?.error || error?.message || fallbackMessage,
|
|
@@ -111,7 +121,7 @@ function createServer() {
|
|
|
111
121
|
status: z.enum(STATUS_VALUES).optional().describe(
|
|
112
122
|
'Filter by YOUR application pipeline state. Not a generic job-posting status. Values: ' + STATUS_VALUES.join(', ')
|
|
113
123
|
),
|
|
114
|
-
sort: z.enum(
|
|
124
|
+
sort: z.enum(SORT_VALUES).optional().describe('Sort order: newest (default) or match (highest match score first; requires resume). Backend rejects legacy oldest/company with HTTP 400.'),
|
|
115
125
|
limit: z.number().max(50).optional().describe('Max results (default 20, max 50)'),
|
|
116
126
|
offset: z.number().min(0).optional().describe('Pagination offset'),
|
|
117
127
|
keywords: z.string().max(500).optional().describe('Keyword search in title, company, or description'),
|
|
@@ -194,7 +204,16 @@ function createServer() {
|
|
|
194
204
|
action: z.enum(['applied', 'saved', 'dismissed']).describe('Status action'),
|
|
195
205
|
},
|
|
196
206
|
wrapTool(async ({ id, action }) => {
|
|
197
|
-
|
|
207
|
+
// Backend expects the stage name, not the human-friendly action name.
|
|
208
|
+
// ACTION_TO_STAGE is defined at module scope (mirrors the same map in bin/trackly).
|
|
209
|
+
const stage = ACTION_TO_STAGE[action];
|
|
210
|
+
if (!stage) {
|
|
211
|
+
// Defensive: the z.enum above already rejects values outside applied|saved|dismissed,
|
|
212
|
+
// but if the enum is ever widened the mapping must be updated in lockstep — fail loud
|
|
213
|
+
// rather than silently sending an unintended stage.
|
|
214
|
+
throw new Error(`trackly_update_status: unknown action "${action}" — expected applied|saved|dismissed`);
|
|
215
|
+
}
|
|
216
|
+
return apiRequest('POST', `/api/jobscout/tracker/jobs/${id}/stage`, { stage }, false, false, MCP_USER_AGENT);
|
|
198
217
|
}, 'Failed to update job status')
|
|
199
218
|
);
|
|
200
219
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trackly-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"mcpName": "io.github.kevinastuhuaman/trackly",
|
|
5
5
|
"description": "AI job search CLI + hosted MCP server with OAuth. 128K+ jobs, 1,900+ companies, 40+ ATS. Works with Claude, ChatGPT, Cursor, Windsurf, Codex via hosted streamable-http or local stdio.",
|
|
6
6
|
"bin": {
|
package/server.json
CHANGED
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
]
|
|
18
18
|
}
|
|
19
19
|
],
|
|
20
|
-
"version": "0.2.
|
|
20
|
+
"version": "0.2.2",
|
|
21
21
|
"packages": [
|
|
22
22
|
{
|
|
23
23
|
"registryType": "npm",
|
|
24
24
|
"identifier": "trackly-cli",
|
|
25
|
-
"version": "0.2.
|
|
25
|
+
"version": "0.2.2",
|
|
26
26
|
"runtimeHint": "npx",
|
|
27
27
|
"runtimeArguments": [
|
|
28
28
|
{
|