@curviate/cli 0.13.0 → 0.15.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.
@@ -1,8 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- BinaryOutputError,
4
- writeBinaryOutput
5
- } from "./chunk-UWO2D4HW.js";
6
2
  import {
7
3
  DEFAULT_FILTER_READERS,
8
4
  assembleFilters,
@@ -10,21 +6,26 @@ import {
10
6
  } from "./chunk-42VUUKQ3.js";
11
7
  import {
12
8
  AttachError,
13
- readAttachment
14
- } from "./chunk-Q43HZUN3.js";
9
+ readAttachment,
10
+ toAttachmentPayload
11
+ } from "./chunk-BGZW6B7G.js";
12
+ import {
13
+ BinaryOutputError,
14
+ writeBinaryOutput
15
+ } from "./chunk-UWO2D4HW.js";
15
16
  import {
16
17
  buildPreviewOutput
17
18
  } from "./chunk-R3VLWLVV.js";
18
- import {
19
- streamAll
20
- } from "./chunk-GXTZION6.js";
21
19
  import {
22
20
  slimJob
23
- } from "./chunk-SSPILTKF.js";
21
+ } from "./chunk-45KHSWCV.js";
24
22
  import {
25
23
  resolveIdentifier,
26
24
  resolveJobIdentifier
27
25
  } from "./chunk-DMQZEPQE.js";
26
+ import {
27
+ streamAll
28
+ } from "./chunk-DNTRQZBT.js";
28
29
  import {
29
30
  createClient,
30
31
  renderError,
@@ -35,7 +36,8 @@ import {
35
36
  import {
36
37
  GLOBAL_FLAGS,
37
38
  READ_SINGLE_FLAGS,
38
- WRITE_FLAGS
39
+ WRITE_FLAGS,
40
+ WRITE_SINGLE_FLAGS
39
41
  } from "./chunk-4JHGVY7R.js";
40
42
 
41
43
  // src/commands/recruiter.ts
@@ -75,13 +77,18 @@ function normalizeAttachPaths(attach) {
75
77
  async function handleSdkError(err, outOpts, out) {
76
78
  const { CurviateError } = await import("@curviate/sdk");
77
79
  if (err instanceof CurviateError) {
78
- const { getExitCode } = await import("./exit-codes-ZTY2NY3X.js");
80
+ const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
79
81
  renderError(err, outOpts, out);
80
82
  process.exit(getExitCode(err.code));
81
83
  }
82
84
  renderUnexpectedError(err, out);
83
85
  process.exit(1);
84
86
  }
87
+ function buildRecruiterRef(idValue, nameValue) {
88
+ if (idValue) return { id: idValue };
89
+ if (nameValue) return { name: nameValue };
90
+ return void 0;
91
+ }
85
92
  async function readStdin() {
86
93
  const chunks = [];
87
94
  for await (const chunk of process.stdin) {
@@ -93,7 +100,7 @@ var DEFAULT_JOB_CREATE_READERS = {
93
100
  readFile: (path) => readFile(path, "utf8"),
94
101
  readStdin
95
102
  };
96
- async function assembleJobCreateBody(flags, readers) {
103
+ async function assembleRecruiterJobBody(flags, readers) {
97
104
  let base = {};
98
105
  let raw;
99
106
  let source;
@@ -122,33 +129,72 @@ async function assembleJobCreateBody(flags, readers) {
122
129
  }
123
130
  base = parsed;
124
131
  }
125
- if (flags["job-title"] !== void 0) base["job_title"] = { text: flags["job-title"] };
132
+ if (flags["job-title-id"] !== void 0 || flags["job-title"] !== void 0) {
133
+ base["job_title"] = {
134
+ ...flags["job-title-id"] !== void 0 ? { id: flags["job-title-id"] } : {},
135
+ ...flags["job-title"] !== void 0 ? { name: flags["job-title"] } : {}
136
+ };
137
+ }
138
+ const company = buildRecruiterRef(flags["company-id"], flags["company-name"]);
139
+ if (company) base["company"] = company;
140
+ if (flags["workplace-type"] !== void 0) base["workplace_type"] = flags["workplace-type"];
141
+ if (flags.location !== void 0) base["location"] = flags.location;
142
+ if (flags["employment-status"] !== void 0) base["employment_status"] = flags["employment-status"];
143
+ if (flags["seniority-level"] !== void 0) base["seniority_level"] = flags["seniority-level"];
126
144
  if (flags.description !== void 0) base["description"] = flags.description;
127
- if (flags["employment-type"] !== void 0) base["employment_type"] = flags["employment-type"];
145
+ if (flags.industry !== void 0) base["industry"] = splitCsv(flags.industry);
146
+ if (flags["job-function"] !== void 0) base["job_function"] = splitCsv(flags["job-function"]);
147
+ if (flags["apply-method"] !== void 0) {
148
+ const method = flags["apply-method"];
149
+ base["apply_method"] = {
150
+ method,
151
+ ...method === "linkedin" && flags["notification-email"] !== void 0 ? { notification_email: flags["notification-email"] } : {},
152
+ ...method === "external" && flags["website-url"] !== void 0 ? { website_url: flags["website-url"] } : {}
153
+ };
154
+ }
155
+ if (flags["project-name"] !== void 0) base["project_name"] = flags["project-name"];
128
156
  return { body: base };
129
157
  }
130
- async function runRecruiterSync(client, flags, out) {
131
- rejectPreviewOnRead(flags.preview, out);
132
- const accountId = requireAccount(flags.account, out);
133
- const ns = client.account(accountId);
134
- const outOpts = resolveOutputOpts(flags);
135
- const params = {};
136
- if (flags.cursor) params["cursor"] = flags.cursor;
137
- if (flags.limit) params["limit"] = parseInt(flags.limit, 10);
138
- try {
139
- const result = await ns.recruiter.syncMessages(params);
140
- renderSuccess(result, outOpts, out);
141
- } catch (err) {
142
- await handleSdkError(err, outOpts, out);
158
+ var RECRUITER_JOB_REQUIRED_FIELDS = [
159
+ ["job_title", "--job-title-id (paired with --job-title)"],
160
+ ["company", "--company-id or --company-name"],
161
+ ["workplace_type", "--workplace-type"],
162
+ ["location", "--location"],
163
+ ["employment_status", "--employment-status"],
164
+ ["seniority_level", "--seniority-level"],
165
+ ["description", "--description"],
166
+ ["industry", "--industry"],
167
+ ["job_function", "--job-function"],
168
+ ["apply_method", "--apply-method"]
169
+ ];
170
+ function requireRecruiterJobFields(body, extra, out) {
171
+ for (const [key, flagDesc] of [...RECRUITER_JOB_REQUIRED_FIELDS, ...extra]) {
172
+ const value = body[key];
173
+ const missing = value === void 0 || value === null || Array.isArray(value) && value.length === 0;
174
+ if (missing) {
175
+ out.stderr.write(`error: ${flagDesc} is required (or ${key} in --body-file/--body -).
176
+ `);
177
+ process.exit(2);
178
+ }
143
179
  }
144
180
  }
145
181
  async function runRecruiterMessageNew(client, flags, out) {
146
182
  const accountId = requireAccount(flags.account, out);
147
183
  const to = flags.to ?? "";
148
184
  const text = flags.text ?? "";
185
+ const subject = flags.subject ?? "";
186
+ const signature = flags.signature ?? "";
149
187
  const attachPaths = normalizeAttachPaths(flags.attach);
150
188
  const voicePath = flags.voice;
151
189
  const videoPath = flags.video;
190
+ if (!subject) {
191
+ out.stderr.write("error: --subject is required (v2: REQUIRED for Recruiter messaging).\n");
192
+ process.exit(2);
193
+ }
194
+ if (!signature) {
195
+ out.stderr.write("error: --signature is required (v2: REQUIRED for Recruiter messaging).\n");
196
+ process.exit(2);
197
+ }
152
198
  let attachBuffers = [];
153
199
  let voiceBuffer;
154
200
  let videoBuffer;
@@ -164,15 +210,11 @@ async function runRecruiterMessageNew(client, flags, out) {
164
210
  }
165
211
  throw err;
166
212
  }
167
- const body = {
168
- attendees_ids: [to],
169
- text
170
- };
171
213
  if (flags.preview) {
172
214
  const preview = buildPreviewOutput({
173
215
  method: "recruiter.startChat",
174
216
  args: { attendees_ids: [to] },
175
- body: { ...body },
217
+ body: { attendees_ids: [to], text, subject, signature },
176
218
  account: accountId,
177
219
  attachments: [
178
220
  ...attachBuffers.map((buf, i) => ({
@@ -186,9 +228,18 @@ async function runRecruiterMessageNew(client, flags, out) {
186
228
  out.stdout.write(JSON.stringify(preview) + "\n");
187
229
  return;
188
230
  }
189
- if (attachBuffers.length > 0) body["attachments"] = attachBuffers;
190
- if (voiceBuffer) body["voice_message"] = voiceBuffer;
191
- if (videoBuffer) body["video_message"] = videoBuffer;
231
+ const attachments = [
232
+ ...attachPaths.map((p, i) => toAttachmentPayload(p, attachBuffers[i])),
233
+ ...voiceBuffer && voicePath ? [{ ...toAttachmentPayload(voicePath, voiceBuffer), send_mode: "native" }] : [],
234
+ ...videoBuffer && videoPath ? [{ ...toAttachmentPayload(videoPath, videoBuffer), send_mode: "native" }] : []
235
+ ];
236
+ const body = {
237
+ attendees_ids: [to],
238
+ text,
239
+ subject,
240
+ signature,
241
+ ...attachments.length > 0 ? { attachments } : {}
242
+ };
192
243
  const ns = client.account(accountId);
193
244
  const outOpts = resolveOutputOpts(flags);
194
245
  try {
@@ -249,8 +300,7 @@ async function runRecruiterSearchPeople(client, flags, out, readers = DEFAULT_FI
249
300
  };
250
301
  for await (const item of streamAll(fn, params, {
251
302
  maxPages,
252
- onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
253
- `)
303
+ out
254
304
  })) {
255
305
  out.stdout.write(JSON.stringify(item) + "\n");
256
306
  }
@@ -262,22 +312,73 @@ async function runRecruiterSearchPeople(client, flags, out, readers = DEFAULT_FI
262
312
  await handleSdkError(err, outOpts, out);
263
313
  }
264
314
  }
265
- async function runRecruiterGetParameters(client, flags, out) {
315
+ async function runRecruiterSearchParameters(client, flags, out) {
266
316
  rejectPreviewOnRead(flags.preview, out);
317
+ if (!flags.source) {
318
+ out.stderr.write("error: --source is required (APPLICANTS, PIPELINE, SEARCH, JOB_POSTING, or JOBS).\n");
319
+ process.exit(2);
320
+ }
321
+ if (!flags.type) {
322
+ out.stderr.write("error: --type is required.\n");
323
+ process.exit(2);
324
+ }
267
325
  const accountId = requireAccount(flags.account, out);
268
326
  const ns = client.account(accountId);
269
327
  const outOpts = resolveOutputOpts(flags);
328
+ const body = {
329
+ source: flags.source,
330
+ type: flags.type,
331
+ ...flags.keywords ? { keywords: flags.keywords } : {},
332
+ ...flags["project-id"] ? { project_id: flags["project-id"] } : {},
333
+ ...flags["stage-id"] ? { stage_id: flags["stage-id"] } : {}
334
+ };
270
335
  const params = {};
271
- if (flags.type) params["type"] = flags.type;
272
- if (flags.keywords) params["keywords"] = flags.keywords;
273
336
  if (flags.limit) params["limit"] = parseInt(flags.limit, 10);
274
337
  try {
275
- const result = await ns.recruiter.getParameters(params);
338
+ const result = await ns.recruiter.searchParameters(body, Object.keys(params).length > 0 ? params : void 0);
276
339
  renderSuccess(result, outOpts, out);
277
340
  } catch (err) {
278
341
  await handleSdkError(err, outOpts, out);
279
342
  }
280
343
  }
344
+ async function runRecruiterSearchFromUrl(client, flags, out) {
345
+ rejectPreviewOnRead(flags.preview, out);
346
+ const accountId = requireAccount(flags.account, out);
347
+ const url = flags.url ?? "";
348
+ const ns = client.account(accountId);
349
+ const outOpts = resolveOutputOpts(flags);
350
+ const all = flags.all ?? false;
351
+ const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
352
+ const limit = flags.limit ? parseInt(flags.limit, 10) : void 0;
353
+ const cursor = flags.cursor;
354
+ const body = { url };
355
+ const params = {};
356
+ if (limit !== void 0) params["limit"] = limit;
357
+ if (cursor) params["cursor"] = cursor;
358
+ try {
359
+ if (all) {
360
+ const fn = (p) => {
361
+ const { cursor: c, limit: l, ...restP } = p;
362
+ const callParams = {};
363
+ if (c) callParams["cursor"] = c;
364
+ if (l) callParams["limit"] = l;
365
+ void restP;
366
+ return ns.recruiter.searchFromUrl(body, callParams);
367
+ };
368
+ for await (const item of streamAll(fn, params, {
369
+ maxPages,
370
+ out
371
+ })) {
372
+ out.stdout.write(JSON.stringify(item) + "\n");
373
+ }
374
+ } else {
375
+ const result = await ns.recruiter.searchFromUrl(body, Object.keys(params).length > 0 ? params : void 0);
376
+ renderSuccess(result, outOpts, out);
377
+ }
378
+ } catch (err) {
379
+ await handleSdkError(err, outOpts, out);
380
+ }
381
+ }
281
382
  async function runRecruiterListProjects(client, flags, out) {
282
383
  rejectPreviewOnRead(flags.preview, out);
283
384
  const accountId = requireAccount(flags.account, out);
@@ -295,8 +396,7 @@ async function runRecruiterListProjects(client, flags, out) {
295
396
  const fn = (p) => ns.recruiter.listProjects(p);
296
397
  for await (const item of streamAll(fn, params, {
297
398
  maxPages,
298
- onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
299
- `)
399
+ out
300
400
  })) {
301
401
  out.stdout.write(JSON.stringify(item) + "\n");
302
402
  }
@@ -321,17 +421,28 @@ async function runRecruiterGetProject(client, flags, out) {
321
421
  await handleSdkError(err, outOpts, out);
322
422
  }
323
423
  }
324
- async function runRecruiterAddCandidate(client, flags, out) {
424
+ async function runRecruiterUpdateProject(client, flags, out) {
325
425
  const accountId = requireAccount(flags.account, out);
326
- const userId = flags.userId ?? "";
426
+ const projectId = flags.projectId ?? "";
327
427
  const outOpts = resolveOutputOpts(flags);
328
428
  const body = {};
329
- if (flags["hiring-project-id"]) body["hiring_project_id"] = flags["hiring-project-id"];
330
- if (flags.stage) body["stage"] = flags.stage;
429
+ if (flags.name !== void 0) body["name"] = flags.name;
430
+ if (flags.visibility !== void 0) body["visibility"] = flags.visibility;
431
+ if (flags.description !== void 0) body["description"] = flags.description;
432
+ const company = buildRecruiterRef(flags["company-id"], flags["company-name"]);
433
+ if (company) body["company"] = company;
434
+ if (flags["job-title-id"] !== void 0 || flags["job-title"] !== void 0) {
435
+ body["job_title"] = {
436
+ ...flags["job-title-id"] !== void 0 ? { id: flags["job-title-id"] } : {},
437
+ ...flags["job-title"] !== void 0 ? { name: flags["job-title"] } : {}
438
+ };
439
+ }
440
+ if (flags.location !== void 0) body["location"] = flags.location;
441
+ if (flags["seniority-level"] !== void 0) body["seniority_level"] = flags["seniority-level"];
331
442
  if (flags.preview) {
332
443
  const preview = buildPreviewOutput({
333
- method: "recruiter.addCandidate",
334
- args: { user_id: userId },
444
+ method: "recruiter.updateProject",
445
+ args: { project_id: projectId },
335
446
  body,
336
447
  account: accountId
337
448
  });
@@ -340,67 +451,97 @@ async function runRecruiterAddCandidate(client, flags, out) {
340
451
  }
341
452
  const ns = client.account(accountId);
342
453
  try {
343
- const result = await ns.recruiter.addCandidate(userId, body);
454
+ const result = await ns.recruiter.updateProject(projectId, body);
344
455
  renderSuccess(result, outOpts, out);
345
456
  } catch (err) {
346
457
  await handleSdkError(err, outOpts, out);
347
458
  }
348
459
  }
349
- async function runRecruiterAddApplicant(client, flags, out) {
460
+ async function runRecruiterListPipeline(client, flags, out) {
461
+ rejectPreviewOnRead(flags.preview, out);
350
462
  const accountId = requireAccount(flags.account, out);
351
- const userId = flags.userId ?? "";
463
+ const projectId = flags.projectId ?? "";
464
+ const ns = client.account(accountId);
352
465
  const outOpts = resolveOutputOpts(flags);
466
+ const all = flags.all ?? false;
467
+ const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
468
+ const limit = flags.limit ? parseInt(flags.limit, 10) : void 0;
469
+ const cursor = flags.cursor;
353
470
  const body = {};
354
- if (flags["hiring-project-id"]) body["hiring_project_id"] = flags["hiring-project-id"];
355
- if (flags.stage) body["stage"] = flags.stage;
356
- if (flags.preview) {
357
- const preview = buildPreviewOutput({
358
- method: "recruiter.addApplicant",
359
- args: { user_id: userId },
360
- body,
361
- account: accountId
362
- });
363
- out.stdout.write(JSON.stringify(preview) + "\n");
364
- return;
471
+ if (flags.keywords) body["keywords"] = flags.keywords;
472
+ if (flags["stage-id"]) body["stage_id"] = flags["stage-id"];
473
+ if (flags["sort-by"]) body["sort_by"] = flags["sort-by"];
474
+ if (flags.spotlights) body["spotlights"] = splitCsv(flags.spotlights);
475
+ const params = {};
476
+ if (limit !== void 0) params["limit"] = limit;
477
+ if (cursor) params["cursor"] = cursor;
478
+ try {
479
+ if (all) {
480
+ const fn = (p) => {
481
+ const { cursor: c, limit: l, ...restP } = p;
482
+ const callParams = {};
483
+ if (c) callParams["cursor"] = c;
484
+ if (l) callParams["limit"] = l;
485
+ void restP;
486
+ return ns.recruiter.listPipeline(projectId, body, callParams);
487
+ };
488
+ for await (const item of streamAll(fn, params, {
489
+ maxPages,
490
+ out
491
+ })) {
492
+ out.stdout.write(JSON.stringify(item) + "\n");
493
+ }
494
+ } else {
495
+ const result = await ns.recruiter.listPipeline(
496
+ projectId,
497
+ Object.keys(body).length > 0 ? body : void 0,
498
+ Object.keys(params).length > 0 ? params : void 0
499
+ );
500
+ renderSuccess(result, outOpts, out);
501
+ }
502
+ } catch (err) {
503
+ await handleSdkError(err, outOpts, out);
365
504
  }
505
+ }
506
+ async function runRecruiterGetProjectJob(client, flags, out) {
507
+ rejectPreviewOnRead(flags.preview, out);
508
+ const accountId = requireAccount(flags.account, out);
509
+ const projectId = flags.projectId ?? "";
366
510
  const ns = client.account(accountId);
511
+ const outOpts = resolveOutputOpts(flags);
367
512
  try {
368
- const result = await ns.recruiter.addApplicant(userId, body);
513
+ const result = await ns.recruiter.getProjectJob(projectId);
369
514
  renderSuccess(result, outOpts, out);
370
515
  } catch (err) {
371
516
  await handleSdkError(err, outOpts, out);
372
517
  }
373
518
  }
374
- async function runRecruiterRejectApplicant(client, flags, out) {
519
+ async function runRecruiterGetProjectJobBudget(client, flags, out) {
520
+ rejectPreviewOnRead(flags.preview, out);
375
521
  const accountId = requireAccount(flags.account, out);
376
- const userId = flags.userId ?? "";
522
+ const projectId = flags.projectId ?? "";
523
+ const jobId = flags.jobId ?? "";
524
+ const ns = client.account(accountId);
377
525
  const outOpts = resolveOutputOpts(flags);
378
- if (flags["notify-at"] && !flags.message) {
379
- out.stderr.write(
380
- "error: --notify-at requires --message (rejection_notification.message is required to send a notification).\n"
381
- );
382
- process.exit(2);
383
- }
384
- let notifyAt;
385
- if (flags["notify-at"]) {
386
- notifyAt = Number(flags["notify-at"]);
387
- if (!Number.isFinite(notifyAt)) {
388
- out.stderr.write("error: --notify-at must be a UNIX milliseconds timestamp (a number).\n");
389
- process.exit(2);
390
- }
391
- }
392
- const body = {};
393
- if (flags["hiring-project-id"]) body["hiring_project_id"] = flags["hiring-project-id"];
394
- if (flags.reason) body["reason"] = flags.reason;
395
- if (flags.message) {
396
- const rejectionNotification = { message: flags.message };
397
- if (notifyAt !== void 0) rejectionNotification["send_notification_at"] = notifyAt;
398
- body["rejection_notification"] = rejectionNotification;
526
+ try {
527
+ const result = await ns.recruiter.getProjectJobBudget(projectId, jobId);
528
+ renderSuccess(result, outOpts, out);
529
+ } catch (err) {
530
+ await handleSdkError(err, outOpts, out);
399
531
  }
532
+ }
533
+ async function runRecruiterSaveCandidate(client, flags, out) {
534
+ const accountId = requireAccount(flags.account, out);
535
+ const projectId = flags.projectId ?? "";
536
+ const outOpts = resolveOutputOpts(flags);
537
+ const body = {
538
+ stage_id: flags["stage-id"] ?? "",
539
+ candidate_id: flags["candidate-id"] ?? ""
540
+ };
400
541
  if (flags.preview) {
401
542
  const preview = buildPreviewOutput({
402
- method: "recruiter.rejectApplicant",
403
- args: { user_id: userId },
543
+ method: "recruiter.saveCandidate",
544
+ args: { project_id: projectId },
404
545
  body,
405
546
  account: accountId
406
547
  });
@@ -409,7 +550,7 @@ async function runRecruiterRejectApplicant(client, flags, out) {
409
550
  }
410
551
  const ns = client.account(accountId);
411
552
  try {
412
- const result = await ns.recruiter.rejectApplicant(userId, body);
553
+ const result = await ns.recruiter.saveCandidate(projectId, body);
413
554
  renderSuccess(result, outOpts, out);
414
555
  } catch (err) {
415
556
  await handleSdkError(err, outOpts, out);
@@ -432,8 +573,7 @@ async function runRecruiterListJobs(client, flags, out) {
432
573
  const fn = (p) => ns.recruiter.listJobs(p);
433
574
  for await (const item of streamAll(fn, params, {
434
575
  maxPages,
435
- onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
436
- `)
576
+ out
437
577
  })) {
438
578
  out.stdout.write(JSON.stringify(item) + "\n");
439
579
  }
@@ -448,13 +588,14 @@ async function runRecruiterListJobs(client, flags, out) {
448
588
  async function runRecruiterCreateJob(client, flags, out, readers = DEFAULT_JOB_CREATE_READERS) {
449
589
  const accountId = requireAccount(flags.account, out);
450
590
  const outOpts = resolveOutputOpts(flags);
451
- const assembled = await assembleJobCreateBody(flags, readers);
591
+ const assembled = await assembleRecruiterJobBody(flags, readers);
452
592
  if ("error" in assembled) {
453
593
  out.stderr.write(`error: ${assembled.error}
454
594
  `);
455
595
  process.exit(2);
456
596
  }
457
597
  const body = assembled.body;
598
+ requireRecruiterJobFields(body, [["project_name", "--project-name"]], out);
458
599
  if (flags.preview) {
459
600
  const preview = buildPreviewOutput({
460
601
  method: "recruiter.createJob",
@@ -473,16 +614,52 @@ async function runRecruiterCreateJob(client, flags, out, readers = DEFAULT_JOB_C
473
614
  await handleSdkError(err, outOpts, out);
474
615
  }
475
616
  }
476
- async function runRecruiterPublishJob(client, flags, out) {
617
+ async function runRecruiterCreateProjectJob(client, flags, out, readers = DEFAULT_JOB_CREATE_READERS) {
618
+ const accountId = requireAccount(flags.account, out);
619
+ const projectId = flags.projectId ?? "";
620
+ const outOpts = resolveOutputOpts(flags);
621
+ const assembled = await assembleRecruiterJobBody(flags, readers);
622
+ if ("error" in assembled) {
623
+ out.stderr.write(`error: ${assembled.error}
624
+ `);
625
+ process.exit(2);
626
+ }
627
+ const body = assembled.body;
628
+ requireRecruiterJobFields(body, [], out);
629
+ if (flags.preview) {
630
+ const preview = buildPreviewOutput({
631
+ method: "recruiter.createProjectJob",
632
+ args: { project_id: projectId },
633
+ body,
634
+ account: accountId
635
+ });
636
+ out.stdout.write(JSON.stringify(preview) + "\n");
637
+ return;
638
+ }
639
+ const ns = client.account(accountId);
640
+ try {
641
+ const result = await ns.recruiter.createProjectJob(projectId, body);
642
+ renderSuccess(result, outOpts, out);
643
+ } catch (err) {
644
+ await handleSdkError(err, outOpts, out);
645
+ }
646
+ }
647
+ async function runRecruiterUpdateProjectJob(client, flags, out, readers = DEFAULT_JOB_CREATE_READERS) {
477
648
  const accountId = requireAccount(flags.account, out);
649
+ const projectId = flags.projectId ?? "";
478
650
  const jobId = flags.jobId ?? "";
479
651
  const outOpts = resolveOutputOpts(flags);
480
- const body = {};
481
- if (flags.mode) body["mode"] = flags.mode;
652
+ const assembled = await assembleRecruiterJobBody(flags, readers);
653
+ if ("error" in assembled) {
654
+ out.stderr.write(`error: ${assembled.error}
655
+ `);
656
+ process.exit(2);
657
+ }
658
+ const body = assembled.body;
482
659
  if (flags.preview) {
483
660
  const preview = buildPreviewOutput({
484
- method: "recruiter.publishJob",
485
- args: { job_id: jobId },
661
+ method: "recruiter.updateProjectJob",
662
+ args: { project_id: projectId, job_id: jobId },
486
663
  body,
487
664
  account: accountId
488
665
  });
@@ -491,22 +668,59 @@ async function runRecruiterPublishJob(client, flags, out) {
491
668
  }
492
669
  const ns = client.account(accountId);
493
670
  try {
494
- const result = await ns.recruiter.publishJob(jobId, body);
671
+ const result = await ns.recruiter.updateProjectJob(projectId, jobId, body);
495
672
  renderSuccess(result, outOpts, out);
496
673
  } catch (err) {
497
674
  await handleSdkError(err, outOpts, out);
498
675
  }
499
676
  }
500
- async function runRecruiterJobCheckpoint(client, flags, out) {
677
+ var RECRUITER_PUBLISH_MODES = ["FREE", "PROMOTED", "PROMOTED_PLUS"];
678
+ var RECRUITER_BUDGET_SCOPES = ["DAILY", "TOTAL"];
679
+ async function runRecruiterPublishJob(client, flags, out) {
501
680
  const accountId = requireAccount(flags.account, out);
681
+ const projectId = flags.projectId ?? "";
502
682
  const jobId = flags.jobId ?? "";
503
683
  const outOpts = resolveOutputOpts(flags);
504
- const body = {};
505
- if (flags.input) body["input"] = flags.input;
684
+ if (!flags.mode) {
685
+ out.stderr.write("error: --mode is required (FREE, PROMOTED, or PROMOTED_PLUS).\n");
686
+ process.exit(2);
687
+ }
688
+ if (!RECRUITER_PUBLISH_MODES.includes(flags.mode)) {
689
+ out.stderr.write(`error: --mode must be one of: ${RECRUITER_PUBLISH_MODES.join(", ")}. Got "${flags.mode}".
690
+ `);
691
+ process.exit(2);
692
+ }
693
+ const mode = flags.mode;
694
+ let body = { mode };
695
+ if (mode === "PROMOTED" || mode === "PROMOTED_PLUS") {
696
+ if (!flags["budget-currency"]) {
697
+ out.stderr.write("error: --budget-currency is required for a paid publish (PROMOTED/PROMOTED_PLUS).\n");
698
+ process.exit(2);
699
+ }
700
+ if (!flags["budget-amount"]) {
701
+ out.stderr.write("error: --budget-amount is required for a paid publish (PROMOTED/PROMOTED_PLUS).\n");
702
+ process.exit(2);
703
+ }
704
+ if (!flags["budget-scope"]) {
705
+ out.stderr.write("error: --budget-scope is required for a paid publish (PROMOTED/PROMOTED_PLUS).\n");
706
+ process.exit(2);
707
+ }
708
+ if (!RECRUITER_BUDGET_SCOPES.includes(flags["budget-scope"])) {
709
+ out.stderr.write(`error: --budget-scope must be one of: ${RECRUITER_BUDGET_SCOPES.join(", ")}. Got "${flags["budget-scope"]}".
710
+ `);
711
+ process.exit(2);
712
+ }
713
+ const amount = Number(flags["budget-amount"]);
714
+ if (!Number.isFinite(amount) || amount < 0) {
715
+ out.stderr.write("error: --budget-amount must be a non-negative number.\n");
716
+ process.exit(2);
717
+ }
718
+ body = { mode, budget: { currency: flags["budget-currency"], amount, scope: flags["budget-scope"] } };
719
+ }
506
720
  if (flags.preview) {
507
721
  const preview = buildPreviewOutput({
508
- method: "recruiter.solveJobCheckpoint",
509
- args: { job_id: jobId },
722
+ method: "recruiter.publishJob",
723
+ args: { project_id: projectId, job_id: jobId },
510
724
  body,
511
725
  account: accountId
512
726
  });
@@ -515,23 +729,101 @@ async function runRecruiterJobCheckpoint(client, flags, out) {
515
729
  }
516
730
  const ns = client.account(accountId);
517
731
  try {
518
- const result = await ns.recruiter.solveJobCheckpoint(jobId, body);
732
+ const result = await ns.recruiter.publishJob(projectId, jobId, body);
519
733
  renderSuccess(result, outOpts, out);
520
734
  } catch (err) {
521
735
  await handleSdkError(err, outOpts, out);
522
736
  }
523
737
  }
738
+ async function runRecruiterCloseJob(client, flags, out) {
739
+ const accountId = requireAccount(flags.account, out);
740
+ const projectId = flags.projectId ?? "";
741
+ const jobId = flags.jobId ?? "";
742
+ if (flags.preview) {
743
+ const preview = buildPreviewOutput({
744
+ method: "recruiter.closeJob",
745
+ args: { project_id: projectId, job_id: jobId },
746
+ body: {},
747
+ account: accountId
748
+ });
749
+ out.stdout.write(JSON.stringify(preview) + "\n");
750
+ return;
751
+ }
752
+ const ns = client.account(accountId);
753
+ const outOpts = resolveOutputOpts(flags);
754
+ try {
755
+ const result = await ns.recruiter.closeJob(projectId, jobId);
756
+ renderSuccess(result, outOpts, out);
757
+ } catch (err) {
758
+ await handleSdkError(err, outOpts, out);
759
+ }
760
+ }
761
+ async function runRecruiterSearchTalentPool(client, flags, out, readers = DEFAULT_FILTER_READERS) {
762
+ rejectPreviewOnRead(flags.preview, out);
763
+ if (!flags["channel-id"]) {
764
+ out.stderr.write("error: --channel-id is required.\n");
765
+ process.exit(2);
766
+ }
767
+ const accountId = requireAccount(flags.account, out);
768
+ const projectId = flags.projectId ?? "";
769
+ const ns = client.account(accountId);
770
+ const outOpts = resolveOutputOpts(flags);
771
+ const all = flags.all ?? false;
772
+ const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
773
+ const limit = flags.limit ? parseInt(flags.limit, 10) : void 0;
774
+ const cursor = flags.cursor;
775
+ const assembled = await assembleFilters(flags, readers);
776
+ if ("error" in assembled) {
777
+ out.stderr.write(`error: ${assembled.error}
778
+ `);
779
+ process.exit(2);
780
+ }
781
+ const body = assembled.body;
782
+ body["channel_id"] = flags["channel-id"];
783
+ if (flags.keywords) body["keywords"] = flags.keywords;
784
+ const params = {};
785
+ if (limit !== void 0) params["limit"] = limit;
786
+ if (cursor) params["cursor"] = cursor;
787
+ try {
788
+ if (all) {
789
+ const fn = (p) => {
790
+ const { cursor: c, limit: l, ...restP } = p;
791
+ const callParams = {};
792
+ if (c) callParams["cursor"] = c;
793
+ if (l) callParams["limit"] = l;
794
+ void restP;
795
+ return ns.recruiter.searchTalentPool(projectId, body, callParams);
796
+ };
797
+ for await (const item of streamAll(fn, params, {
798
+ maxPages,
799
+ out
800
+ })) {
801
+ out.stdout.write(JSON.stringify(item) + "\n");
802
+ }
803
+ } else {
804
+ const result = await ns.recruiter.searchTalentPool(projectId, body, Object.keys(params).length > 0 ? params : void 0);
805
+ renderSuccess(result, outOpts, out);
806
+ }
807
+ } catch (err) {
808
+ await handleSdkError(err, outOpts, out);
809
+ }
810
+ }
524
811
  async function runRecruiterListApplicants(client, flags, out) {
525
812
  rejectPreviewOnRead(flags.preview, out);
813
+ if (!flags["channel-id"]) {
814
+ out.stderr.write("error: --channel-id is required.\n");
815
+ process.exit(2);
816
+ }
526
817
  const accountId = requireAccount(flags.account, out);
527
- const jobId = flags.jobId ?? "";
818
+ const projectId = flags.projectId ?? "";
528
819
  const ns = client.account(accountId);
529
820
  const outOpts = resolveOutputOpts(flags);
821
+ const body = { channel_id: flags["channel-id"] };
530
822
  const params = {};
531
823
  if (flags.limit) params["limit"] = parseInt(flags.limit, 10);
532
824
  if (flags.cursor) params["cursor"] = flags.cursor;
533
825
  try {
534
- const result = await ns.recruiter.listApplicants(jobId, Object.keys(params).length > 0 ? params : void 0);
826
+ const result = await ns.recruiter.listApplicants(projectId, body, Object.keys(params).length > 0 ? params : void 0);
535
827
  renderSuccess(result, outOpts, out);
536
828
  } catch (err) {
537
829
  await handleSdkError(err, outOpts, out);
@@ -554,11 +846,12 @@ async function runRecruiterGetJob(client, flags, out) {
554
846
  async function runRecruiterGetApplicant(client, flags, out) {
555
847
  rejectPreviewOnRead(flags.preview, out);
556
848
  const accountId = requireAccount(flags.account, out);
849
+ const projectId = flags.projectId ?? "";
557
850
  const applicantId = flags.applicantId ?? "";
558
851
  const ns = client.account(accountId);
559
852
  const outOpts = resolveOutputOpts(flags);
560
853
  try {
561
- const result = await ns.recruiter.getApplicant(applicantId);
854
+ const result = await ns.recruiter.getApplicant(projectId, applicantId);
562
855
  renderSuccess(result, outOpts, out);
563
856
  } catch (err) {
564
857
  await handleSdkError(err, outOpts, out);
@@ -567,10 +860,11 @@ async function runRecruiterGetApplicant(client, flags, out) {
567
860
  async function runRecruiterDownloadResume(client, flags, out, isTTY) {
568
861
  rejectPreviewOnRead(flags.preview, out);
569
862
  const accountId = requireAccount(flags.account, out);
863
+ const projectId = flags.projectId ?? "";
570
864
  const applicantId = flags.applicantId ?? "";
571
865
  const ns = client.account(accountId);
572
866
  try {
573
- const data = await ns.recruiter.downloadResume(applicantId);
867
+ const data = await ns.recruiter.downloadResume(projectId, applicantId);
574
868
  await writeBinaryOutput(data, {
575
869
  outputPath: flags.output,
576
870
  isTTY,
@@ -586,27 +880,6 @@ async function runRecruiterDownloadResume(client, flags, out, isTTY) {
586
880
  await handleSdkError(err, outOpts, out);
587
881
  }
588
882
  }
589
- var recruiterSyncCommand = defineCommand({
590
- meta: { name: "sync", description: "Sync Recruiter message history for an account." },
591
- args: { ...GLOBAL_FLAGS },
592
- async run({ args }) {
593
- const flags = args;
594
- const cfg = await resolveEffectiveConfig({
595
- apiKey: flags["api-key"],
596
- baseUrl: flags["base-url"],
597
- timeout: flags.timeout,
598
- account: flags.account,
599
- profile: flags.profile
600
- });
601
- if (!cfg.apiKey) {
602
- process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
603
- process.exit(3);
604
- }
605
- const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
606
- const out = buildOutputStreams();
607
- await runRecruiterSync(client, { ...flags, account: flags.account ?? cfg.account }, out);
608
- }
609
- });
610
883
  var recruiterMessageNewCommand = defineCommand({
611
884
  meta: { name: "new", description: "Start a new Recruiter chat with a member." },
612
885
  args: {
@@ -617,6 +890,8 @@ var recruiterMessageNewCommand = defineCommand({
617
890
  description: "Recipient's LinkedIn provider ID (AE\u2026 format, e.g. from a Recruiter search result or profile). Not resolved from a URL/slug \u2014 pass the provider ID directly.",
618
891
  required: true
619
892
  },
893
+ subject: { type: "string", description: "Message subject line (required for Recruiter InMail).", required: true },
894
+ signature: { type: "string", description: "Sender signature (required for Recruiter InMail).", required: true },
620
895
  text: { type: "positional", description: "Opening message text." },
621
896
  attach: { type: "string", description: "File to attach (repeatable, max 7 MiB each)." },
622
897
  voice: { type: "string", description: "Voice message file (max 7 MiB)." },
@@ -706,15 +981,22 @@ var recruiterSearchPeopleCommand = defineCommand({
706
981
  }
707
982
  });
708
983
  var recruiterSearchParametersCommand = defineCommand({
709
- meta: { name: "parameters", description: "Resolve Recruiter filter parameter IDs." },
984
+ meta: { name: "parameters", description: "Resolve Recruiter filter parameter IDs (POST \u2014 source-scoped)." },
710
985
  args: {
711
986
  ...GLOBAL_FLAGS,
987
+ source: {
988
+ type: "string",
989
+ description: "Filter family to resolve within: APPLICANTS or PIPELINE (both require --project-id), SEARCH, JOB_POSTING, or JOBS.",
990
+ required: true
991
+ },
712
992
  type: {
713
993
  type: "string",
714
- description: "Parameter type to resolve. One of: GROUPS, DEPARTMENT, HIRING_PROJECTS, SAVED_SEARCHES, SAVED_FILTERS, DEGREE.",
994
+ description: "Parameter type to resolve; the valid set depends on --source (e.g. SKILL/LOCATION/JOB_TITLE for APPLICANTS, CONTRACT/SEAT/LOCATION for JOBS).",
715
995
  required: true
716
996
  },
717
- keywords: { type: "string", description: "Human term to resolve (e.g. Berlin)." }
997
+ keywords: { type: "string", description: "Human term to resolve (e.g. Berlin)." },
998
+ "project-id": { type: "string", description: "Recruiter project ID (required for --source APPLICANTS or PIPELINE)." },
999
+ "stage-id": { type: "string", description: "Pipeline stage ID to filter to (only meaningful for --source PIPELINE)." }
718
1000
  },
719
1001
  async run({ args }) {
720
1002
  const flags = args;
@@ -731,20 +1013,45 @@ var recruiterSearchParametersCommand = defineCommand({
731
1013
  }
732
1014
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
733
1015
  const out = buildOutputStreams();
734
- await runRecruiterGetParameters(client, { ...flags, account: flags.account ?? cfg.account }, out);
1016
+ await runRecruiterSearchParameters(client, { ...flags, account: flags.account ?? cfg.account }, out);
735
1017
  }
736
1018
  });
737
1019
  var recruiterSearchCommand = defineCommand({
738
- meta: { name: "search", description: "Recruiter search operations." },
739
- args: { ...GLOBAL_FLAGS },
1020
+ meta: { name: "search", description: "Recruiter search operations. Also runs a pasted Recruiter search/talent-pool/applicant URL directly." },
1021
+ args: {
1022
+ ...GLOBAL_FLAGS,
1023
+ url: {
1024
+ type: "positional",
1025
+ required: false,
1026
+ description: "A pasted Recruiter search, talent-pool, or applicant URL. Runs it directly (recruiter.searchFromUrl)."
1027
+ }
1028
+ },
740
1029
  subCommands: {
741
1030
  people: recruiterSearchPeopleCommand,
742
1031
  parameters: recruiterSearchParametersCommand
743
1032
  },
744
- async run() {
745
- process.stderr.write(
746
- "Usage: curviate recruiter search people [--keywords <k>]\n curviate recruiter search parameters --type <t>\n"
747
- );
1033
+ async run({ args }) {
1034
+ const flags = args;
1035
+ if (!flags.url) {
1036
+ process.stderr.write(
1037
+ "Usage: curviate recruiter search <url>\n curviate recruiter search people [--keywords <k>]\n curviate recruiter search parameters --source <s> --type <t>\n"
1038
+ );
1039
+ return;
1040
+ }
1041
+ const cfg = await resolveEffectiveConfig({
1042
+ apiKey: flags["api-key"],
1043
+ baseUrl: flags["base-url"],
1044
+ timeout: flags.timeout,
1045
+ account: flags.account,
1046
+ profile: flags.profile
1047
+ });
1048
+ if (!cfg.apiKey) {
1049
+ process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
1050
+ process.exit(3);
1051
+ }
1052
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
1053
+ const out = buildOutputStreams();
1054
+ await runRecruiterSearchFromUrl(client, { ...flags, account: flags.account ?? cfg.account }, out);
748
1055
  }
749
1056
  });
750
1057
  var recruiterProjectsCommand = defineCommand({
@@ -768,12 +1075,21 @@ var recruiterProjectsCommand = defineCommand({
768
1075
  await runRecruiterListProjects(client, { ...flags, account: flags.account ?? cfg.account }, out);
769
1076
  }
770
1077
  });
771
- var recruiterProjectCommand = defineCommand({
772
- meta: { name: "project", description: "Get a Recruiter hiring project by ID." },
1078
+ var recruiterProjectUpdateCommand = defineCommand({
1079
+ meta: { name: "update", description: "Edit a Recruiter project's config. All fields optional \u2014 omitted fields are left unchanged." },
773
1080
  args: {
774
- // Single-object read: READ_SINGLE_FLAGS omits pagination flags, keeps --fields
775
- ...READ_SINGLE_FLAGS,
776
- projectId: { type: "positional", description: "Recruiter project ID." }
1081
+ // Write command: WRITE_SINGLE_FLAGS omits pagination flags, keeps --fields
1082
+ ...WRITE_SINGLE_FLAGS,
1083
+ projectId: { type: "positional", description: "Recruiter project ID." },
1084
+ name: { type: "string", description: "New project name." },
1085
+ visibility: { type: "string", description: "New project visibility: PRIVATE or PUBLIC." },
1086
+ description: { type: "string", description: "New project description." },
1087
+ "company-id": { type: "string", description: "Target company id." },
1088
+ "company-name": { type: "string", description: "Target company as free text (used when no id is given)." },
1089
+ "job-title-id": { type: "string", description: "Target job-title parameter id." },
1090
+ "job-title": { type: "string", description: "Target job-title display name." },
1091
+ location: { type: "string", description: "A LOCATION parameter id (resolve via search parameters)." },
1092
+ "seniority-level": { type: "string", description: "Target seniority level: INTERNSHIP|ENTRY_LEVEL|ASSOCIATE|MID_SENIOR_LEVEL|DIRECTOR|EXECUTIVE|NOT_APPLICABLE." }
777
1093
  },
778
1094
  async run({ args }) {
779
1095
  const flags = args;
@@ -790,20 +1106,27 @@ var recruiterProjectCommand = defineCommand({
790
1106
  }
791
1107
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
792
1108
  const out = buildOutputStreams();
793
- await runRecruiterGetProject(client, { ...flags, account: flags.account ?? cfg.account }, out);
1109
+ await runRecruiterUpdateProject(client, { ...flags, account: flags.account ?? cfg.account }, out);
794
1110
  }
795
1111
  });
796
- var recruiterAddCandidateCommand = defineCommand({
797
- meta: { name: "add-candidate", description: "Add a member as a candidate in a hiring project." },
1112
+ var recruiterProjectCommand = defineCommand({
1113
+ meta: { name: "project", description: "Get a Recruiter hiring project by ID." },
798
1114
  args: {
799
- // Write command: WRITE_FLAGS omits pagination/projection flags
800
- ...WRITE_FLAGS,
801
- userId: { type: "positional", description: "Member ID (AEM\u2026 format)." },
802
- "hiring-project-id": { type: "string", description: "Recruiter hiring project ID.", required: true },
803
- stage: { type: "string", description: "Pipeline stage (UNCONTACTED, CONTACTED, REPLIED)." }
1115
+ // Single-object read: READ_SINGLE_FLAGS omits pagination flags, keeps --fields
1116
+ ...READ_SINGLE_FLAGS,
1117
+ projectId: { type: "positional", description: "Recruiter project ID." }
1118
+ },
1119
+ subCommands: {
1120
+ update: recruiterProjectUpdateCommand
804
1121
  },
805
1122
  async run({ args }) {
806
1123
  const flags = args;
1124
+ if (!flags.projectId) {
1125
+ process.stderr.write(
1126
+ "Usage: curviate recruiter project <project_id>\n curviate recruiter project update <project_id> [flags\u2026]\n"
1127
+ );
1128
+ return;
1129
+ }
807
1130
  const cfg = await resolveEffectiveConfig({
808
1131
  apiKey: flags["api-key"],
809
1132
  baseUrl: flags["base-url"],
@@ -817,17 +1140,18 @@ var recruiterAddCandidateCommand = defineCommand({
817
1140
  }
818
1141
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
819
1142
  const out = buildOutputStreams();
820
- await runRecruiterAddCandidate(client, { ...flags, account: flags.account ?? cfg.account }, out);
1143
+ await runRecruiterGetProject(client, { ...flags, account: flags.account ?? cfg.account }, out);
821
1144
  }
822
1145
  });
823
- var recruiterAddApplicantCommand = defineCommand({
824
- meta: { name: "add-applicant", description: "Add a member as an applicant in a hiring project." },
1146
+ var recruiterPipelineCommand = defineCommand({
1147
+ meta: { name: "pipeline", description: "List candidates in a project's pipeline (POST-as-list)." },
825
1148
  args: {
826
- // Write command: WRITE_FLAGS omits pagination/projection flags
827
- ...WRITE_FLAGS,
828
- userId: { type: "positional", description: "Member ID (AEM\u2026 format)." },
829
- "hiring-project-id": { type: "string", description: "Recruiter hiring project ID.", required: true },
830
- stage: { type: "string", description: "Pipeline stage (UNCONTACTED, CONTACTED, REPLIED)." }
1149
+ ...GLOBAL_FLAGS,
1150
+ projectId: { type: "positional", description: "Recruiter project ID." },
1151
+ keywords: { type: "string", description: "Free-text keyword search." },
1152
+ "stage-id": { type: "string", description: "Filter to a single pipeline stage id." },
1153
+ "sort-by": { type: "string", description: "Sort field: LAST_MODIFIED or ALPHABETICAL." },
1154
+ spotlights: { type: "string", description: "Spotlight tags (comma-separated): OPEN_TO_WORK, ACTIVE_TALENT, MISSED_CANDIDATES." }
831
1155
  },
832
1156
  async run({ args }) {
833
1157
  const flags = args;
@@ -844,29 +1168,17 @@ var recruiterAddApplicantCommand = defineCommand({
844
1168
  }
845
1169
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
846
1170
  const out = buildOutputStreams();
847
- await runRecruiterAddApplicant(client, { ...flags, account: flags.account ?? cfg.account }, out);
1171
+ await runRecruiterListPipeline(client, { ...flags, account: flags.account ?? cfg.account }, out);
848
1172
  }
849
1173
  });
850
- var recruiterRejectApplicantCommand = defineCommand({
851
- meta: { name: "reject-applicant", description: "Reject an applicant from a hiring project." },
1174
+ var recruiterSaveCandidateCommand = defineCommand({
1175
+ meta: { name: "save-candidate", description: "Save a candidate to a project's pipeline at a given stage." },
852
1176
  args: {
853
1177
  // Write command: WRITE_FLAGS omits pagination/projection flags
854
1178
  ...WRITE_FLAGS,
855
- userId: { type: "positional", description: "Member ID (AEM\u2026 format)." },
856
- "hiring-project-id": { type: "string", description: "Recruiter hiring project ID.", required: true },
857
- reason: {
858
- type: "string",
859
- description: "Rejection reason (NOT_MEET_BASIC_QUALIFICATIONS, NOT_IN_DESIRED_LOCATION, MORE_QUALIFIED_CANDIDATES, WITHDREW_APPLICATION, NOT_CONSIDERED_OR_REASON_NOT_SPECIFIED).",
860
- required: true
861
- },
862
- message: {
863
- type: "string",
864
- description: "Rejection notification text. The applicant is only notified when --message is provided; omit it to reject silently."
865
- },
866
- "notify-at": {
867
- type: "string",
868
- description: "UNIX milliseconds timestamp to schedule the notification (default: now). Requires --message."
869
- }
1179
+ projectId: { type: "positional", description: "Recruiter project ID." },
1180
+ "stage-id": { type: "string", description: "Pipeline stage ID to save the candidate into.", required: true },
1181
+ "candidate-id": { type: "string", description: "Candidate id or user-profile id to save.", required: true }
870
1182
  },
871
1183
  async run({ args }) {
872
1184
  const flags = args;
@@ -883,7 +1195,7 @@ var recruiterRejectApplicantCommand = defineCommand({
883
1195
  }
884
1196
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
885
1197
  const out = buildOutputStreams();
886
- await runRecruiterRejectApplicant(client, { ...flags, account: flags.account ?? cfg.account }, out);
1198
+ await runRecruiterSaveCandidate(client, { ...flags, account: flags.account ?? cfg.account }, out);
887
1199
  }
888
1200
  });
889
1201
  var recruiterJobsCommand = defineCommand({
@@ -907,16 +1219,31 @@ var recruiterJobsCommand = defineCommand({
907
1219
  await runRecruiterListJobs(client, { ...flags, account: flags.account ?? cfg.account }, out);
908
1220
  }
909
1221
  });
1222
+ var RECRUITER_JOB_BODY_FLAGS = {
1223
+ "body-file": { type: "string", description: "Path to a JSON file with the full job body." },
1224
+ body: { type: "string", description: "Read the JSON job body from stdin (pass '-')." },
1225
+ "job-title-id": { type: "string", description: "Resolved job-title parameter id (merged with --job-title into job_title:{id,name})." },
1226
+ "job-title": { type: "string", description: "Job title display name (merged with --job-title-id into job_title:{id,name})." },
1227
+ "company-id": { type: "string", description: "Resolved company id (or use --company-name for free text)." },
1228
+ "company-name": { type: "string", description: "Company as free text (used when no resolved id is available)." },
1229
+ "workplace-type": { type: "string", description: "Workplace arrangement: ON_SITE|HYBRID|REMOTE." },
1230
+ location: { type: "string", description: "A resolved LOCATION parameter id." },
1231
+ "employment-status": { type: "string", description: "Employment type: FULL_TIME|PART_TIME|CONTRACT|TEMPORARY|OTHER|VOLUNTEER|INTERNSHIP." },
1232
+ "seniority-level": { type: "string", description: "Seniority level: INTERNSHIP|ENTRY_LEVEL|ASSOCIATE|MID_SENIOR_LEVEL|DIRECTOR|EXECUTIVE|NOT_APPLICABLE." },
1233
+ description: { type: "string", description: "Full job description (min 200 chars; merged over the JSON)." },
1234
+ industry: { type: "string", description: "Industry parameter ids, 1-3 (comma-separated)." },
1235
+ "job-function": { type: "string", description: "Job-function parameter ids, 1-3 (comma-separated)." },
1236
+ "apply-method": { type: "string", description: "How candidates apply: linkedin|external." },
1237
+ "notification-email": { type: "string", description: "Email notified of new applicants (used when --apply-method is linkedin)." },
1238
+ "website-url": { type: "string", description: "External apply URL (used when --apply-method is external)." }
1239
+ };
910
1240
  var recruiterJobCreateCommand = defineCommand({
911
- meta: { name: "create", description: "Create a Recruiter job posting draft." },
1241
+ meta: { name: "create", description: "Create a Recruiter job posting draft, opening a brand-new hiring project." },
912
1242
  args: {
913
1243
  // Write command: WRITE_FLAGS omits pagination/projection flags
914
1244
  ...WRITE_FLAGS,
915
- "body-file": { type: "string", description: "Path to a JSON file with the full job-create body." },
916
- body: { type: "string", description: "Read the JSON job-create body from stdin (pass '-')." },
917
- "job-title": { type: "string", description: "Job title text (merged over the JSON as job_title.text)." },
918
- description: { type: "string", description: "Job description (merged over the JSON)." },
919
- "employment-type": { type: "string", description: "Employment type, e.g. FULL_TIME (merged over the JSON)." }
1245
+ ...RECRUITER_JOB_BODY_FLAGS,
1246
+ "project-name": { type: "string", description: "Name for the new hiring project this job opens (required).", required: true }
920
1247
  },
921
1248
  async run({ args }) {
922
1249
  const flags = args;
@@ -937,12 +1264,16 @@ var recruiterJobCreateCommand = defineCommand({
937
1264
  }
938
1265
  });
939
1266
  var recruiterJobPublishCommand = defineCommand({
940
- meta: { name: "publish", description: "Publish a Recruiter job posting draft." },
1267
+ meta: { name: "publish", description: "Publish a Recruiter job posting draft. PROMOTED/PROMOTED_PLUS spend real money and require --budget-*." },
941
1268
  args: {
942
- // Write command: WRITE_FLAGS omits pagination/projection flags
943
- ...WRITE_FLAGS,
1269
+ // Write command: WRITE_SINGLE_FLAGS omits pagination flags, keeps --fields
1270
+ ...WRITE_SINGLE_FLAGS,
1271
+ projectId: { type: "positional", description: "Recruiter project ID." },
944
1272
  jobId: { type: "positional", description: "Job posting ID." },
945
- mode: { type: "string", description: "Publish mode: FREE (default), PROMOTED, or PROMOTED_PLUS." }
1273
+ mode: { type: "string", description: "Publish mode (required): FREE|PROMOTED|PROMOTED_PLUS.", required: true },
1274
+ "budget-currency": { type: "string", description: "ISO-4217 currency (required for a paid publish), e.g. EUR." },
1275
+ "budget-amount": { type: "string", description: "Budget amount (required for a paid publish)." },
1276
+ "budget-scope": { type: "string", description: "Budget scope (required for a paid publish): DAILY|TOTAL." }
946
1277
  },
947
1278
  async run({ args }) {
948
1279
  const flags = args;
@@ -962,13 +1293,12 @@ var recruiterJobPublishCommand = defineCommand({
962
1293
  await runRecruiterPublishJob(client, { ...flags, account: flags.account ?? cfg.account }, out);
963
1294
  }
964
1295
  });
965
- var recruiterJobCheckpointCommand = defineCommand({
966
- meta: { name: "checkpoint", description: "Solve a job posting publish verification checkpoint." },
1296
+ var recruiterApplicantsCommand = defineCommand({
1297
+ meta: { name: "applicants", description: "List applicants in a Recruiter project's talent pool." },
967
1298
  args: {
968
- // Write command: WRITE_FLAGS omits pagination/projection flags
969
- ...WRITE_FLAGS,
970
- jobId: { type: "positional", description: "Job posting ID." },
971
- input: { type: "string", description: "Verification value (OTP or email confirmation).", required: true }
1299
+ ...GLOBAL_FLAGS,
1300
+ projectId: { type: "positional", description: "Recruiter project ID." },
1301
+ "channel-id": { type: "string", description: "The project's JOB_POSTING talent-pool channel ID (required).", required: true }
972
1302
  },
973
1303
  async run({ args }) {
974
1304
  const flags = args;
@@ -985,14 +1315,14 @@ var recruiterJobCheckpointCommand = defineCommand({
985
1315
  }
986
1316
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
987
1317
  const out = buildOutputStreams();
988
- await runRecruiterJobCheckpoint(client, { ...flags, account: flags.account ?? cfg.account }, out);
1318
+ await runRecruiterListApplicants(client, { ...flags, account: flags.account ?? cfg.account }, out);
989
1319
  }
990
1320
  });
991
- var recruiterJobApplicantsCommand = defineCommand({
992
- meta: { name: "applicants", description: "List applicants for a Recruiter job posting." },
1321
+ var recruiterJobGetCommand = defineCommand({
1322
+ meta: { name: "get", description: "Get a job posting via the Recruiter lens (any public posting, not only your own)." },
993
1323
  args: {
994
- ...GLOBAL_FLAGS,
995
- jobId: { type: "positional", description: "Job posting ID." }
1324
+ ...READ_SINGLE_FLAGS,
1325
+ jobId: { type: "positional", description: "Job URL (e.g. https://www.linkedin.com/jobs/view/4428113858) or a bare numeric job id." }
996
1326
  },
997
1327
  async run({ args }) {
998
1328
  const flags = args;
@@ -1009,14 +1339,16 @@ var recruiterJobApplicantsCommand = defineCommand({
1009
1339
  }
1010
1340
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
1011
1341
  const out = buildOutputStreams();
1012
- await runRecruiterListApplicants(client, { ...flags, account: flags.account ?? cfg.account }, out);
1342
+ await runRecruiterGetJob(client, { ...flags, account: flags.account ?? cfg.account }, out);
1013
1343
  }
1014
1344
  });
1015
- var recruiterJobGetCommand = defineCommand({
1016
- meta: { name: "get", description: "Get a job posting via the Recruiter lens (any public posting, not only your own)." },
1345
+ var recruiterJobCloseCommand = defineCommand({
1346
+ meta: { name: "close", description: "Stop a project's job posting from accepting applications (irreversible once LISTED)." },
1017
1347
  args: {
1018
- ...READ_SINGLE_FLAGS,
1019
- jobId: { type: "positional", description: "Job URL (e.g. https://www.linkedin.com/jobs/view/4428113858) or a bare numeric job id." }
1348
+ // Write command: WRITE_SINGLE_FLAGS omits pagination flags, keeps --fields
1349
+ ...WRITE_SINGLE_FLAGS,
1350
+ projectId: { type: "positional", description: "Recruiter project ID." },
1351
+ jobId: { type: "positional", description: "Job posting ID." }
1020
1352
  },
1021
1353
  async run({ args }) {
1022
1354
  const flags = args;
@@ -1033,7 +1365,7 @@ var recruiterJobGetCommand = defineCommand({
1033
1365
  }
1034
1366
  const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
1035
1367
  const out = buildOutputStreams();
1036
- await runRecruiterGetJob(client, { ...flags, account: flags.account ?? cfg.account }, out);
1368
+ await runRecruiterCloseJob(client, { ...flags, account: flags.account ?? cfg.account }, out);
1037
1369
  }
1038
1370
  });
1039
1371
  var recruiterJobCommand = defineCommand({
@@ -1042,21 +1374,189 @@ var recruiterJobCommand = defineCommand({
1042
1374
  subCommands: {
1043
1375
  create: recruiterJobCreateCommand,
1044
1376
  publish: recruiterJobPublishCommand,
1045
- checkpoint: recruiterJobCheckpointCommand,
1046
- applicants: recruiterJobApplicantsCommand,
1377
+ close: recruiterJobCloseCommand,
1047
1378
  get: recruiterJobGetCommand
1048
1379
  },
1049
1380
  async run() {
1050
1381
  process.stderr.write(
1051
- "Usage: curviate recruiter job create [flags\u2026]\n curviate recruiter job publish <job_id> [--mode <m>]\n curviate recruiter job checkpoint <job_id> --input <v>\n curviate recruiter job applicants <job_id>\n curviate recruiter job get <url|id>\n"
1382
+ "Usage: curviate recruiter job create [flags\u2026]\n curviate recruiter job publish <project_id> <job_id> --mode <FREE|PROMOTED|PROMOTED_PLUS>\n curviate recruiter job close <project_id> <job_id>\n curviate recruiter job get <url|id>\n"
1052
1383
  );
1053
1384
  }
1054
1385
  });
1386
+ var recruiterProjectJobGetCommand = defineCommand({
1387
+ meta: { name: "get", description: "Get the single job posting attached to a project (404 when none is attached)." },
1388
+ args: {
1389
+ // Single-object read: READ_SINGLE_FLAGS omits pagination flags, keeps --fields
1390
+ ...READ_SINGLE_FLAGS,
1391
+ projectId: { type: "positional", description: "Recruiter project ID." }
1392
+ },
1393
+ async run({ args }) {
1394
+ const flags = args;
1395
+ const cfg = await resolveEffectiveConfig({
1396
+ apiKey: flags["api-key"],
1397
+ baseUrl: flags["base-url"],
1398
+ timeout: flags.timeout,
1399
+ account: flags.account,
1400
+ profile: flags.profile
1401
+ });
1402
+ if (!cfg.apiKey) {
1403
+ process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
1404
+ process.exit(3);
1405
+ }
1406
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
1407
+ const out = buildOutputStreams();
1408
+ await runRecruiterGetProjectJob(client, { ...flags, account: flags.account ?? cfg.account }, out);
1409
+ }
1410
+ });
1411
+ var recruiterProjectJobCreateCommand = defineCommand({
1412
+ meta: { name: "create", description: "Create a job-posting draft attached to an existing project." },
1413
+ args: {
1414
+ // Write command: WRITE_SINGLE_FLAGS omits pagination flags, keeps --fields
1415
+ ...WRITE_SINGLE_FLAGS,
1416
+ ...RECRUITER_JOB_BODY_FLAGS,
1417
+ projectId: { type: "positional", description: "Recruiter project ID." }
1418
+ },
1419
+ async run({ args }) {
1420
+ const flags = args;
1421
+ const cfg = await resolveEffectiveConfig({
1422
+ apiKey: flags["api-key"],
1423
+ baseUrl: flags["base-url"],
1424
+ timeout: flags.timeout,
1425
+ account: flags.account,
1426
+ profile: flags.profile
1427
+ });
1428
+ if (!cfg.apiKey) {
1429
+ process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
1430
+ process.exit(3);
1431
+ }
1432
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
1433
+ const out = buildOutputStreams();
1434
+ await runRecruiterCreateProjectJob(client, { ...flags, account: flags.account ?? cfg.account }, out);
1435
+ }
1436
+ });
1437
+ var recruiterProjectJobBudgetCommand = defineCommand({
1438
+ meta: { name: "budget", description: "Get pricing to publish a project's job posting." },
1439
+ args: {
1440
+ // Single-object read: READ_SINGLE_FLAGS omits pagination flags, keeps --fields
1441
+ ...READ_SINGLE_FLAGS,
1442
+ projectId: { type: "positional", description: "Recruiter project ID." },
1443
+ jobId: { type: "positional", description: "Job posting ID." }
1444
+ },
1445
+ async run({ args }) {
1446
+ const flags = args;
1447
+ const cfg = await resolveEffectiveConfig({
1448
+ apiKey: flags["api-key"],
1449
+ baseUrl: flags["base-url"],
1450
+ timeout: flags.timeout,
1451
+ account: flags.account,
1452
+ profile: flags.profile
1453
+ });
1454
+ if (!cfg.apiKey) {
1455
+ process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
1456
+ process.exit(3);
1457
+ }
1458
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
1459
+ const out = buildOutputStreams();
1460
+ await runRecruiterGetProjectJobBudget(client, { ...flags, account: flags.account ?? cfg.account }, out);
1461
+ }
1462
+ });
1463
+ var recruiterProjectJobUpdateCommand = defineCommand({
1464
+ meta: { name: "update", description: "Apply a partial update to a project's job posting." },
1465
+ args: {
1466
+ // Write command: WRITE_SINGLE_FLAGS omits pagination flags, keeps --fields
1467
+ ...WRITE_SINGLE_FLAGS,
1468
+ ...RECRUITER_JOB_BODY_FLAGS,
1469
+ projectId: { type: "positional", description: "Recruiter project ID." },
1470
+ jobId: { type: "positional", description: "Job posting ID." }
1471
+ },
1472
+ async run({ args }) {
1473
+ const flags = args;
1474
+ const cfg = await resolveEffectiveConfig({
1475
+ apiKey: flags["api-key"],
1476
+ baseUrl: flags["base-url"],
1477
+ timeout: flags.timeout,
1478
+ account: flags.account,
1479
+ profile: flags.profile
1480
+ });
1481
+ if (!cfg.apiKey) {
1482
+ process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
1483
+ process.exit(3);
1484
+ }
1485
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
1486
+ const out = buildOutputStreams();
1487
+ await runRecruiterUpdateProjectJob(client, { ...flags, account: flags.account ?? cfg.account }, out);
1488
+ }
1489
+ });
1490
+ var recruiterProjectJobCommand = defineCommand({
1491
+ meta: { name: "project-job", description: "The single job posting attached to a Recruiter project." },
1492
+ args: {
1493
+ ...READ_SINGLE_FLAGS,
1494
+ projectId: { type: "positional", description: "Recruiter project ID.", required: false }
1495
+ },
1496
+ subCommands: {
1497
+ get: recruiterProjectJobGetCommand,
1498
+ create: recruiterProjectJobCreateCommand,
1499
+ budget: recruiterProjectJobBudgetCommand,
1500
+ update: recruiterProjectJobUpdateCommand
1501
+ },
1502
+ async run({ args }) {
1503
+ const flags = args;
1504
+ if (!flags.projectId) {
1505
+ process.stderr.write(
1506
+ "Usage: curviate recruiter project-job get <project_id>\n curviate recruiter project-job create <project_id> [flags\u2026]\n curviate recruiter project-job budget <project_id> <job_id>\n curviate recruiter project-job update <project_id> <job_id> [flags\u2026]\n"
1507
+ );
1508
+ return;
1509
+ }
1510
+ const cfg = await resolveEffectiveConfig({
1511
+ apiKey: flags["api-key"],
1512
+ baseUrl: flags["base-url"],
1513
+ timeout: flags.timeout,
1514
+ account: flags.account,
1515
+ profile: flags.profile
1516
+ });
1517
+ if (!cfg.apiKey) {
1518
+ process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
1519
+ process.exit(3);
1520
+ }
1521
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
1522
+ const out = buildOutputStreams();
1523
+ await runRecruiterGetProjectJob(client, { ...flags, account: flags.account ?? cfg.account }, out);
1524
+ }
1525
+ });
1526
+ var recruiterTalentSearchCommand = defineCommand({
1527
+ meta: { name: "talent-search", description: "Search a project's talent pool." },
1528
+ args: {
1529
+ ...GLOBAL_FLAGS,
1530
+ projectId: { type: "positional", description: "Recruiter project ID." },
1531
+ "channel-id": { type: "string", description: "The project's RECRUITER_SEARCH talent-pool channel ID (required).", required: true },
1532
+ keywords: { type: "string", description: "Free-text keyword search." },
1533
+ filters: { type: "string", description: "Filter body as a JSON object (escape hatch for the full filter surface); '-' reads JSON from stdin." },
1534
+ "filters-file": { type: "string", description: "Path to a JSON file with the filter body." }
1535
+ },
1536
+ async run({ args }) {
1537
+ const flags = args;
1538
+ const cfg = await resolveEffectiveConfig({
1539
+ apiKey: flags["api-key"],
1540
+ baseUrl: flags["base-url"],
1541
+ timeout: flags.timeout,
1542
+ account: flags.account,
1543
+ profile: flags.profile
1544
+ });
1545
+ if (!cfg.apiKey) {
1546
+ process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
1547
+ process.exit(3);
1548
+ }
1549
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
1550
+ const out = buildOutputStreams();
1551
+ await runRecruiterSearchTalentPool(client, { ...flags, account: flags.account ?? cfg.account }, out);
1552
+ }
1553
+ });
1055
1554
  var recruiterApplicantResumeCommand = defineCommand({
1056
1555
  meta: { name: "resume", description: "Download a job applicant's resume." },
1057
1556
  args: {
1058
1557
  // Single-object read: READ_SINGLE_FLAGS omits pagination flags, keeps --fields
1059
1558
  ...READ_SINGLE_FLAGS,
1559
+ projectId: { type: "positional", description: "Recruiter project ID." },
1060
1560
  applicantId: { type: "positional", description: "Applicant ID." },
1061
1561
  output: { type: "string", alias: "o", description: "Path to write the resume file." }
1062
1562
  },
@@ -1088,6 +1588,7 @@ var recruiterApplicantCommand = defineCommand({
1088
1588
  args: {
1089
1589
  // Single-object read: READ_SINGLE_FLAGS omits pagination flags, keeps --fields
1090
1590
  ...READ_SINGLE_FLAGS,
1591
+ projectId: { type: "positional", description: "Recruiter project ID.", required: false },
1091
1592
  applicantId: { type: "positional", description: "Applicant ID.", required: false }
1092
1593
  },
1093
1594
  subCommands: {
@@ -1095,9 +1596,9 @@ var recruiterApplicantCommand = defineCommand({
1095
1596
  },
1096
1597
  async run({ args }) {
1097
1598
  const flags = args;
1098
- if (!flags.applicantId) {
1599
+ if (!flags.projectId || !flags.applicantId) {
1099
1600
  process.stderr.write(
1100
- "Usage: curviate recruiter applicant <applicant_id>\n curviate recruiter applicant resume <applicant_id> -o <file>\n"
1601
+ "Usage: curviate recruiter applicant <project_id> <applicant_id>\n curviate recruiter applicant resume <project_id> <applicant_id> -o <file>\n"
1101
1602
  );
1102
1603
  return;
1103
1604
  }
@@ -1121,43 +1622,49 @@ var recruiterCommand = defineCommand({
1121
1622
  meta: { name: "recruiter", description: "LinkedIn Recruiter operations (requires the Recruiter add-on)." },
1122
1623
  args: { ...GLOBAL_FLAGS },
1123
1624
  subCommands: {
1124
- sync: recruiterSyncCommand,
1125
1625
  message: recruiterMessageCommand,
1126
1626
  profile: recruiterProfileCommand,
1127
1627
  search: recruiterSearchCommand,
1128
1628
  projects: recruiterProjectsCommand,
1129
1629
  project: recruiterProjectCommand,
1130
- "add-candidate": recruiterAddCandidateCommand,
1131
- "add-applicant": recruiterAddApplicantCommand,
1132
- "reject-applicant": recruiterRejectApplicantCommand,
1630
+ pipeline: recruiterPipelineCommand,
1631
+ "project-job": recruiterProjectJobCommand,
1632
+ "talent-search": recruiterTalentSearchCommand,
1633
+ "save-candidate": recruiterSaveCandidateCommand,
1634
+ applicants: recruiterApplicantsCommand,
1133
1635
  jobs: recruiterJobsCommand,
1134
1636
  job: recruiterJobCommand,
1135
1637
  applicant: recruiterApplicantCommand
1136
1638
  },
1137
1639
  async run() {
1138
1640
  process.stderr.write(
1139
- 'Usage: curviate recruiter sync\n curviate recruiter message new --to <id> "<text>"\n curviate recruiter profile <identifier>\n curviate recruiter search people [--keywords <k>]\n curviate recruiter search parameters --type <t>\n curviate recruiter projects\n curviate recruiter project <project_id>\n curviate recruiter add-candidate <user_id> --hiring-project-id <id>\n curviate recruiter add-applicant <user_id> --hiring-project-id <id>\n curviate recruiter reject-applicant <user_id> --hiring-project-id <id> --reason <r>\n curviate recruiter jobs\n curviate recruiter job create [flags\u2026]\n curviate recruiter job publish <job_id> [--mode <m>]\n curviate recruiter job checkpoint <job_id> --input <v>\n curviate recruiter job applicants <job_id>\n curviate recruiter job get <url|id>\n curviate recruiter applicant <applicant_id>\n curviate recruiter applicant resume <applicant_id> -o <file>\n'
1641
+ 'Usage: curviate recruiter message new --to <id> "<text>"\n curviate recruiter profile <identifier>\n curviate recruiter search people [--keywords <k>]\n curviate recruiter search parameters --source <s> --type <t>\n curviate recruiter search <url>\n curviate recruiter projects\n curviate recruiter project <project_id>\n curviate recruiter project update <project_id> [flags\u2026]\n curviate recruiter pipeline <project_id>\n curviate recruiter project-job get <project_id>\n curviate recruiter project-job create <project_id> [flags\u2026]\n curviate recruiter project-job budget <project_id> <job_id>\n curviate recruiter project-job update <project_id> <job_id> [flags\u2026]\n curviate recruiter talent-search <project_id> --channel-id <id>\n curviate recruiter save-candidate <project_id> --stage-id <id> --candidate-id <id>\n curviate recruiter applicants <project_id> --channel-id <id>\n curviate recruiter jobs\n curviate recruiter job create [flags\u2026]\n curviate recruiter job publish <project_id> <job_id> --mode <FREE|PROMOTED|PROMOTED_PLUS>\n curviate recruiter job close <project_id> <job_id>\n curviate recruiter job get <url|id>\n curviate recruiter applicant <project_id> <applicant_id>\n curviate recruiter applicant resume <project_id> <applicant_id> -o <file>\n'
1140
1642
  );
1141
1643
  }
1142
1644
  });
1143
1645
  export {
1144
1646
  recruiterCommand,
1145
- runRecruiterAddApplicant,
1146
- runRecruiterAddCandidate,
1647
+ runRecruiterCloseJob,
1147
1648
  runRecruiterCreateJob,
1649
+ runRecruiterCreateProjectJob,
1148
1650
  runRecruiterDownloadResume,
1149
1651
  runRecruiterGetApplicant,
1150
1652
  runRecruiterGetJob,
1151
- runRecruiterGetParameters,
1152
1653
  runRecruiterGetProject,
1153
- runRecruiterJobCheckpoint,
1654
+ runRecruiterGetProjectJob,
1655
+ runRecruiterGetProjectJobBudget,
1154
1656
  runRecruiterListApplicants,
1155
1657
  runRecruiterListJobs,
1658
+ runRecruiterListPipeline,
1156
1659
  runRecruiterListProjects,
1157
1660
  runRecruiterMessageNew,
1158
1661
  runRecruiterProfile,
1159
1662
  runRecruiterPublishJob,
1160
- runRecruiterRejectApplicant,
1663
+ runRecruiterSaveCandidate,
1664
+ runRecruiterSearchFromUrl,
1665
+ runRecruiterSearchParameters,
1161
1666
  runRecruiterSearchPeople,
1162
- runRecruiterSync
1667
+ runRecruiterSearchTalentPool,
1668
+ runRecruiterUpdateProject,
1669
+ runRecruiterUpdateProjectJob
1163
1670
  };