@wport/cli 0.10.0 → 0.10.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/dist/index.js CHANGED
@@ -387,7 +387,7 @@ function registerJobsSearch(parent) {
387
387
  baseUrl: ctx.baseUrl,
388
388
  locale: ctx.locale,
389
389
  timeoutMs: ctx.timeoutMs,
390
- userAgent: (0, import_core2.buildUserAgent)("wport-cli", "0.10.0"),
390
+ userAgent: (0, import_core2.buildUserAgent)("wport-cli", "0.10.2"),
391
391
  source: CLI_SOURCE
392
392
  });
393
393
  const { data, error, response } = await client.GET("/api/jobs/search", {
@@ -632,7 +632,7 @@ function registerJobsView(parent) {
632
632
  baseUrl: ctx.baseUrl,
633
633
  locale: ctx.locale,
634
634
  timeoutMs: ctx.timeoutMs,
635
- userAgent: (0, import_core3.buildUserAgent)("wport-cli", "0.10.0"),
635
+ userAgent: (0, import_core3.buildUserAgent)("wport-cli", "0.10.2"),
636
636
  source: CLI_SOURCE
637
637
  });
638
638
  if (flags.batch) {
@@ -1073,7 +1073,7 @@ async function oauthPost(opts, path, body) {
1073
1073
  method: "POST",
1074
1074
  headers: {
1075
1075
  "Accept-Language": opts.locale,
1076
- "User-Agent": (0, import_core5.buildUserAgent)("wport-cli", "0.10.0"),
1076
+ "User-Agent": (0, import_core5.buildUserAgent)("wport-cli", "0.10.2"),
1077
1077
  "X-Source": CLI_SOURCE,
1078
1078
  Accept: "application/json",
1079
1079
  "Content-Type": "application/json"
@@ -1156,7 +1156,7 @@ function registerDoctorCommand(program2) {
1156
1156
  }
1157
1157
  async function runDoctor(ctx) {
1158
1158
  const line = (s = "") => process.stdout.write(s + "\n");
1159
- line(`wport-cli ${"0.10.0"}`);
1159
+ line(`wport-cli ${"0.10.2"}`);
1160
1160
  line(` bundled schema fingerprint: ${"839e8a891dfb"}`);
1161
1161
  line("");
1162
1162
  line("Resolved configuration:");
@@ -1216,7 +1216,7 @@ async function probeServer(ctx, line) {
1216
1216
  baseUrl: ctx.baseUrl,
1217
1217
  locale: ctx.locale,
1218
1218
  timeoutMs: ctx.timeoutMs,
1219
- userAgent: (0, import_core7.buildUserAgent)("wport-cli", "0.10.0"),
1219
+ userAgent: (0, import_core7.buildUserAgent)("wport-cli", "0.10.2"),
1220
1220
  source: CLI_SOURCE
1221
1221
  });
1222
1222
  const { response } = await client.GET("/api/jobs/search", { params: { query: { pageSize: 1 } } });
@@ -1246,7 +1246,7 @@ async function probeAuthServer(ctx, line) {
1246
1246
  var import_core8 = require("@wport/core");
1247
1247
  var transport = __toESM(require("@wport/core"));
1248
1248
  function withUserAgent(opts) {
1249
- return { ...opts, userAgent: (0, import_core8.buildUserAgent)("wport-cli", "0.10.0"), source: CLI_SOURCE };
1249
+ return { ...opts, userAgent: (0, import_core8.buildUserAgent)("wport-cli", "0.10.2"), source: CLI_SOURCE };
1250
1250
  }
1251
1251
  function extractErrorCodeBody(body) {
1252
1252
  if (!body || typeof body !== "object") return void 0;
@@ -1461,10 +1461,16 @@ async function runUsage(ctx, apiKey) {
1461
1461
  const rate = usage.rate_limit ?? {};
1462
1462
  const lines = [
1463
1463
  `period: ${usage.period ?? "\u2014"}`,
1464
- `monthly quota: ${num(quota.used)} / ${num(quota.limit)} used (${num(quota.remaining)} remaining)`,
1464
+ `monthly quota: ${num(quota.used)} / ${num(quota.limit)} calls used (${num(quota.remaining)} remaining)`,
1465
1465
  `rate limit: ${num(rate.limit)} requests / ${num(rate.window_seconds)}s per key`
1466
1466
  ];
1467
1467
  process.stdout.write(lines.join("\n") + "\n");
1468
+ process.stdout.write(
1469
+ dim(
1470
+ "Monthly quota meters every authenticated API call; whoami/usage and key rotate are exempt.",
1471
+ ctx.color
1472
+ ) + "\n"
1473
+ );
1468
1474
  process.stdout.write(
1469
1475
  dim("Live per-window rate-limit headroom is reported via response headers on write requests.", ctx.color) + "\n"
1470
1476
  );
@@ -2011,9 +2017,15 @@ function registerEnterpriseCompanyView(parent) {
2011
2017
 
2012
2018
  // src/commands/enterprise/company/update.ts
2013
2019
  var import_node_crypto5 = require("crypto");
2014
- var import_core19 = require("@wport/core");
2020
+ var import_core20 = require("@wport/core");
2015
2021
 
2016
2022
  // src/commands/enterprise/company/block-replace-shared.ts
2023
+ var import_core19 = require("@wport/core");
2024
+ function getEnterpriseErrorCode(err) {
2025
+ if (!(err instanceof import_core19.WportHttpError) || !err.body || typeof err.body !== "object") return void 0;
2026
+ const code = err.body.error_code;
2027
+ return typeof code === "string" ? code : void 0;
2028
+ }
2017
2029
  function assertValidSubmittedItems(value, label) {
2018
2030
  if (!Array.isArray(value)) {
2019
2031
  throw new InvalidArgumentError(
@@ -2128,7 +2140,7 @@ async function buildCompanyUpdatePayloads(input, ctx, apiKey) {
2128
2140
  { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey },
2129
2141
  "/company"
2130
2142
  );
2131
- const current = (0, import_core19.unwrapDataResponse)(body);
2143
+ const current = (0, import_core20.unwrapDataResponse)(body);
2132
2144
  const missingContractFields = CONTRACT_REQUIRED_GET_FIELDS.filter((f) => !(f in current));
2133
2145
  if (missingContractFields.length > 0) {
2134
2146
  throw new CliError(
@@ -2220,7 +2232,7 @@ async function runCompanyUpdate(ctx, apiKey, source, idempotencyFlags, options =
2220
2232
  const { body } = await enterprisePatch2(requestOpts, "/company/basic", payloads.basic, {
2221
2233
  idempotencyKey: basicKey
2222
2234
  });
2223
- basicResultCompany = (0, import_core19.unwrapDataResponse)(body);
2235
+ basicResultCompany = (0, import_core20.unwrapDataResponse)(body);
2224
2236
  }
2225
2237
  if (!needsDescriptions) {
2226
2238
  printCompanyResult(basicResultCompany, ctx.format);
@@ -2238,12 +2250,23 @@ async function runCompanyUpdate(ctx, apiKey, source, idempotencyFlags, options =
2238
2250
  ...needsVideoLinks ? { ifMatch: payloads.videoLinksRevision } : {}
2239
2251
  }
2240
2252
  );
2241
- const result = (0, import_core19.unwrapDataResponse)(body);
2253
+ const result = (0, import_core20.unwrapDataResponse)(body);
2242
2254
  printCompanyResult(result.company, ctx.format);
2243
2255
  } catch (err) {
2244
2256
  if (needsVideoLinks && err instanceof ServerClientHttpError && err.status === 409) {
2257
+ const errorCode = getEnterpriseErrorCode(err);
2258
+ if (errorCode === "idempotency_conflict") {
2259
+ throw new InvalidArgumentError(
2260
+ "This Idempotency-Key was already used for different request content; change the key (or omit --idempotency-key to let the CLI generate one)."
2261
+ );
2262
+ }
2263
+ if (errorCode !== "profile_revision_conflict") {
2264
+ throw new InvalidArgumentError(
2265
+ 'Request rejected with an unclassified 409 conflict while updating "video_links"; the CLI will not auto-retry.'
2266
+ );
2267
+ }
2245
2268
  const { body: freshBody } = await enterpriseGet2(requestOpts, "/company");
2246
- const freshCurrent = (0, import_core19.unwrapDataResponse)(freshBody);
2269
+ const freshCurrent = (0, import_core20.unwrapDataResponse)(freshBody);
2247
2270
  const freshVideoLinks = freshCurrent.video_links ?? [];
2248
2271
  const diff = summarizeItemsDiff(payloads.currentVideoLinks ?? [], freshVideoLinks);
2249
2272
  const partialBody = isDescriptionsPartialFailureBody(err.body) ? err.body : void 0;
@@ -2328,7 +2351,7 @@ function registerEnterpriseCompanyUpdate(parent) {
2328
2351
  var import_node_crypto6 = require("crypto");
2329
2352
  var import_node_fs7 = require("fs");
2330
2353
  var import_node_path3 = require("path");
2331
- var import_core20 = require("@wport/core");
2354
+ var import_core21 = require("@wport/core");
2332
2355
  var EXTENSION_TO_CONTENT_TYPE = {
2333
2356
  ".png": "image/png",
2334
2357
  ".jpg": "image/jpeg",
@@ -2386,13 +2409,13 @@ async function runCompanyLogoUpload(ctx, apiKey, path, idempotencyFlags) {
2386
2409
  { content_type: contentType, file_size: fileSize },
2387
2410
  { idempotencyKey: presignKey }
2388
2411
  );
2389
- const presign = (0, import_core20.unwrapDataResponse)(presignBody);
2412
+ const presign = (0, import_core21.unwrapDataResponse)(presignBody);
2390
2413
  const putRequest = new Request(presign.upload_url, {
2391
2414
  method: "PUT",
2392
2415
  headers: { "Content-Type": contentType },
2393
2416
  body: bytes
2394
2417
  });
2395
- const putResponse = await (0, import_core20.fetchWithTimeout)(putRequest, ctx.timeoutMs);
2418
+ const putResponse = await (0, import_core21.fetchWithTimeout)(putRequest, ctx.timeoutMs);
2396
2419
  if (!putResponse.ok) {
2397
2420
  throw new NetworkError(`Failed to upload file to S3: HTTP ${putResponse.status}`);
2398
2421
  }
@@ -2402,7 +2425,7 @@ async function runCompanyLogoUpload(ctx, apiKey, path, idempotencyFlags) {
2402
2425
  { s3_key: presign.s3_key },
2403
2426
  { idempotencyKey: confirmKey }
2404
2427
  );
2405
- const result = (0, import_core20.unwrapDataResponse)(confirmBody);
2428
+ const result = (0, import_core21.unwrapDataResponse)(confirmBody);
2406
2429
  printLogoResult(result, ctx.format);
2407
2430
  }
2408
2431
  function registerEnterpriseCompanyLogo(parent) {
@@ -2417,7 +2440,7 @@ function registerEnterpriseCompanyLogo(parent) {
2417
2440
 
2418
2441
  // src/commands/enterprise/company/replace.ts
2419
2442
  var import_node_crypto7 = require("crypto");
2420
- var import_core21 = require("@wport/core");
2443
+ var import_core22 = require("@wport/core");
2421
2444
  var REPLACE_SECTIONS = ["pain-points", "awards", "milestones", "qa-items"];
2422
2445
  var SECTION_CONFIG = {
2423
2446
  "pain-points": {
@@ -2472,7 +2495,7 @@ async function runCompanyReplace(ctx, apiKey, section, source, confirm, idempote
2472
2495
  const items = assertValidSubmittedItems(input.items, "items");
2473
2496
  const requestOpts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey };
2474
2497
  const { body: getBody } = await enterpriseGet2(requestOpts, "/company");
2475
- const current = (0, import_core21.unwrapDataResponse)(getBody);
2498
+ const current = (0, import_core22.unwrapDataResponse)(getBody);
2476
2499
  const currentItems = current[config.dataKey] ?? [];
2477
2500
  const revision = current.block_revisions?.[config.dataKey];
2478
2501
  if (!revision) {
@@ -2485,12 +2508,23 @@ async function runCompanyReplace(ctx, apiKey, section, source, confirm, idempote
2485
2508
  enforceDeletionConfirmation(section, deletions, confirm, ctx.color);
2486
2509
  try {
2487
2510
  const { body } = await enterprisePut2(requestOpts, config.path, { items }, { idempotencyKey, ifMatch: revision });
2488
- const result = (0, import_core21.unwrapDataResponse)(body);
2511
+ const result = (0, import_core22.unwrapDataResponse)(body);
2489
2512
  printReplaceResult(result, config, ctx.format, ctx.color);
2490
2513
  } catch (err) {
2491
- if (err instanceof import_core21.WportHttpError && err.status === 409) {
2514
+ if (err instanceof import_core22.WportHttpError && err.status === 409) {
2515
+ const errorCode = getEnterpriseErrorCode(err);
2516
+ if (errorCode === "idempotency_conflict") {
2517
+ throw new InvalidArgumentError(
2518
+ "This Idempotency-Key was already used for different request content; change the key (or omit --idempotency-key to let the CLI generate one)."
2519
+ );
2520
+ }
2521
+ if (errorCode !== "profile_revision_conflict") {
2522
+ throw new InvalidArgumentError(
2523
+ `Request rejected with an unclassified 409 conflict while replacing "${section}"; the CLI will not auto-retry.`
2524
+ );
2525
+ }
2492
2526
  const { body: freshBody } = await enterpriseGet2(requestOpts, "/company");
2493
- const freshCurrent = (0, import_core21.unwrapDataResponse)(freshBody);
2527
+ const freshCurrent = (0, import_core22.unwrapDataResponse)(freshBody);
2494
2528
  const freshItems = freshCurrent[config.dataKey] ?? [];
2495
2529
  const diff = summarizeItemsDiff(currentItems, freshItems);
2496
2530
  printWarn(`Server state for "${section}" changed since your read: ${diff}.`, ctx.color);
@@ -2503,7 +2537,7 @@ async function runCompanyReplace(ctx, apiKey, section, source, confirm, idempote
2503
2537
  }
2504
2538
  function registerEnterpriseCompanyReplace(parent) {
2505
2539
  parent.command("replace <section>").description(
2506
- `Replace an entire company profile block from a JSON file. <section> is one of: ${REPLACE_SECTIONS.join("|")}. This is a full replacement, not an add/update: any existing item not listed in the input is deleted.`
2540
+ `Replace an entire company profile block from a JSON file. <section> is one of: ${REPLACE_SECTIONS.join("|")}. This is a full replacement, not an add/update: any existing item not listed in the input is hard-deleted. A \`company view --output json\` backup cannot be restored as-is after deletion: strip every \`enc_id\` first to recreate items with new IDs. Example: \`jq '{items: [.awards[] | del(.enc_id)]}' company-backup.json > awards-restore.json\`.`
2507
2541
  ).requiredOption("--file <path>", 'path to a JSON body { "items": [...] }, or "-" for stdin').option("--confirm", "confirm deletion of existing items that are not present in the input").option("--idempotency-key <key>", "reuse across retries (default: a fresh UUID)").action(async (section, flags, command) => {
2508
2542
  const ctx = resolveContext(command);
2509
2543
  const globals = command.optsWithGlobals();
@@ -2530,7 +2564,7 @@ function registerEnterpriseCompanyCommand(parent) {
2530
2564
  }
2531
2565
 
2532
2566
  // src/commands/enterprise/talents/list.ts
2533
- var import_core22 = require("@wport/core");
2567
+ var import_core23 = require("@wport/core");
2534
2568
  var DEFAULT_PAGE_SIZE = 20;
2535
2569
  var MINIMAL_LIST_FIELDS2 = ["enc_resume_id", "candidate_name", "applied_job_title", "applied_at"];
2536
2570
  function formatDate4(value) {
@@ -2553,7 +2587,7 @@ async function runEnterpriseTalentsList(ctx, apiKey, flags) {
2553
2587
  pageSize: flags.pageSize ?? DEFAULT_PAGE_SIZE
2554
2588
  }
2555
2589
  );
2556
- const paged = (0, import_core22.asPaginatedBody)(body);
2590
+ const paged = (0, import_core23.asPaginatedBody)(body);
2557
2591
  const projection = flags.minimal ? MINIMAL_LIST_FIELDS2 : flags.fields ? parseFieldsList(flags.fields) : void 0;
2558
2592
  if (projection || ctx.format === "json") {
2559
2593
  printJson(projection ? { ...paged, data: paged.data.map((row) => pickPaths(row, projection)) } : paged);
@@ -2586,7 +2620,7 @@ function registerEnterpriseTalentsList(parent) {
2586
2620
  }
2587
2621
 
2588
2622
  // src/commands/enterprise/talents/view.ts
2589
- var import_core23 = require("@wport/core");
2623
+ var import_core24 = require("@wport/core");
2590
2624
  async function runEnterpriseTalentsView(ctx, apiKey, encResumeId, flags) {
2591
2625
  const trimmed = encResumeId.trim();
2592
2626
  if (!trimmed) {
@@ -2596,7 +2630,7 @@ async function runEnterpriseTalentsView(ctx, apiKey, encResumeId, flags) {
2596
2630
  { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey },
2597
2631
  `/talents/${encodeURIComponent(trimmed)}`
2598
2632
  );
2599
- const resume = (0, import_core23.unwrapDataResponse)(body);
2633
+ const resume = (0, import_core24.unwrapDataResponse)(body);
2600
2634
  if (flags.fields) {
2601
2635
  printJson(pickPaths(resume, parseFieldsList(flags.fields)));
2602
2636
  return;
@@ -2614,7 +2648,7 @@ function registerEnterpriseTalentsView(parent) {
2614
2648
 
2615
2649
  // src/commands/enterprise/talents/respond.ts
2616
2650
  var import_node_crypto8 = require("crypto");
2617
- var import_core24 = require("@wport/core");
2651
+ var import_core25 = require("@wport/core");
2618
2652
  function resolveRespondBody(flags, options = {}) {
2619
2653
  const hasBody = flags.body !== void 0;
2620
2654
  const hasBodyFile = flags.bodyFile !== void 0;
@@ -2646,7 +2680,7 @@ async function runEnterpriseTalentsRespond(ctx, apiKey, encResumeId, flags, idem
2646
2680
  payload,
2647
2681
  { idempotencyKey }
2648
2682
  );
2649
- const result = (0, import_core24.unwrapDataResponse)(respBody);
2683
+ const result = (0, import_core25.unwrapDataResponse)(respBody);
2650
2684
  if (ctx.format === "json") {
2651
2685
  printJson(result);
2652
2686
  return;
@@ -2675,7 +2709,7 @@ function registerEnterpriseTalentsCommand(parent) {
2675
2709
 
2676
2710
  // src/commands/enterprise/campaigns/create.ts
2677
2711
  var import_node_crypto9 = require("crypto");
2678
- var import_core25 = require("@wport/core");
2712
+ var import_core26 = require("@wport/core");
2679
2713
  async function runCampaignCreate(ctx, apiKey, source, idempotencyKey) {
2680
2714
  const campaignBody = readJsonObject(source, { timeoutMs: ctx.timeoutMs });
2681
2715
  const { body } = await enterprisePost2(
@@ -2684,7 +2718,7 @@ async function runCampaignCreate(ctx, apiKey, source, idempotencyKey) {
2684
2718
  campaignBody,
2685
2719
  { idempotencyKey }
2686
2720
  );
2687
- const created = (0, import_core25.unwrapDataResponse)(body);
2721
+ const created = (0, import_core26.unwrapDataResponse)(body);
2688
2722
  if (ctx.format === "json") {
2689
2723
  printJson(created);
2690
2724
  return;
@@ -2702,7 +2736,7 @@ function registerEnterpriseCampaignsCreate(parent) {
2702
2736
  }
2703
2737
 
2704
2738
  // src/commands/enterprise/campaigns/list.ts
2705
- var import_core26 = require("@wport/core");
2739
+ var import_core27 = require("@wport/core");
2706
2740
  var STATUS_MAP2 = { open: 1, closed: 0 };
2707
2741
  var MINIMAL_LIST_FIELDS3 = ["enc_id", "name", "status", "job_count"];
2708
2742
  function mapStatusFlag2(raw) {
@@ -2732,7 +2766,7 @@ async function runEnterpriseCampaignsList(ctx, apiKey, flags) {
2732
2766
  status: mapStatusFlag2(flags.status)
2733
2767
  }
2734
2768
  );
2735
- const paged = (0, import_core26.asPaginatedBody)(body);
2769
+ const paged = (0, import_core27.asPaginatedBody)(body);
2736
2770
  const projection = flags.minimal ? MINIMAL_LIST_FIELDS3 : flags.fields ? parseFieldsList(flags.fields) : void 0;
2737
2771
  if (projection || ctx.format === "json") {
2738
2772
  printJson(projection ? { ...paged, data: paged.data.map((row) => pickPaths(row, projection)) } : paged);
@@ -2765,7 +2799,7 @@ function registerEnterpriseCampaignsList(parent) {
2765
2799
 
2766
2800
  // src/commands/enterprise/campaigns/lifecycle.ts
2767
2801
  var import_node_crypto10 = require("crypto");
2768
- var import_core27 = require("@wport/core");
2802
+ var import_core28 = require("@wport/core");
2769
2803
  async function runCampaignTransition(ctx, apiKey, encId, action, idempotencyKey) {
2770
2804
  const trimmed = requireEncId(encId);
2771
2805
  const { body } = await enterprisePatch2(
@@ -2774,7 +2808,7 @@ async function runCampaignTransition(ctx, apiKey, encId, action, idempotencyKey)
2774
2808
  {},
2775
2809
  { idempotencyKey }
2776
2810
  );
2777
- const result = (0, import_core27.unwrapDataResponse)(body);
2811
+ const result = (0, import_core28.unwrapDataResponse)(body);
2778
2812
  if (ctx.format === "json") {
2779
2813
  printJson(result);
2780
2814
  return;
@@ -2800,7 +2834,7 @@ function registerEnterpriseCampaignsUnpublish(parent) {
2800
2834
 
2801
2835
  // src/commands/enterprise/campaigns/update.ts
2802
2836
  var import_node_crypto11 = require("crypto");
2803
- var import_core28 = require("@wport/core");
2837
+ var import_core29 = require("@wport/core");
2804
2838
  async function runCampaignUpdate(ctx, apiKey, encId, source, idempotencyKey) {
2805
2839
  const trimmed = requireEncId(encId);
2806
2840
  const campaignBody = readJsonObject(source, { timeoutMs: ctx.timeoutMs });
@@ -2810,7 +2844,7 @@ async function runCampaignUpdate(ctx, apiKey, encId, source, idempotencyKey) {
2810
2844
  campaignBody,
2811
2845
  { idempotencyKey }
2812
2846
  );
2813
- const updated = (0, import_core28.unwrapDataResponse)(body);
2847
+ const updated = (0, import_core29.unwrapDataResponse)(body);
2814
2848
  if (ctx.format === "json") {
2815
2849
  printJson(updated);
2816
2850
  return;
@@ -2828,7 +2862,7 @@ function registerEnterpriseCampaignsUpdate(parent) {
2828
2862
  }
2829
2863
 
2830
2864
  // src/commands/enterprise/campaigns/view.ts
2831
- var import_core29 = require("@wport/core");
2865
+ var import_core30 = require("@wport/core");
2832
2866
  async function runEnterpriseCampaignsView(ctx, apiKey, encId, flags) {
2833
2867
  const trimmed = encId.trim();
2834
2868
  if (!trimmed) {
@@ -2838,7 +2872,7 @@ async function runEnterpriseCampaignsView(ctx, apiKey, encId, flags) {
2838
2872
  { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey },
2839
2873
  `/campaigns/${encodeURIComponent(trimmed)}`
2840
2874
  );
2841
- const campaign = (0, import_core29.unwrapDataResponse)(body);
2875
+ const campaign = (0, import_core30.unwrapDataResponse)(body);
2842
2876
  if (flags.fields) {
2843
2877
  printJson(pickPaths(campaign, parseFieldsList(flags.fields)));
2844
2878
  return;
@@ -2983,10 +3017,10 @@ function registerLoginCommand(program2) {
2983
3017
  }
2984
3018
 
2985
3019
  // src/commands/auth/whoami.ts
2986
- var import_core31 = require("@wport/core");
3020
+ var import_core32 = require("@wport/core");
2987
3021
 
2988
3022
  // src/lib/personal-client.ts
2989
- var import_core30 = require("@wport/core");
3023
+ var import_core31 = require("@wport/core");
2990
3024
  var EXPIRY_SKEW_MS = 3e4;
2991
3025
  var NOT_LOGGED_IN_MESSAGE = "Not logged in. Run `wport login`.";
2992
3026
  async function ensureFreshCredentials(opts) {
@@ -3015,7 +3049,7 @@ async function attemptRequest(opts, method, path, accessToken, body, query, extr
3015
3049
  const headers = {
3016
3050
  Authorization: `Bearer ${accessToken}`,
3017
3051
  "Accept-Language": opts.locale,
3018
- "User-Agent": (0, import_core30.buildUserAgent)("wport-cli", "0.10.0"),
3052
+ "User-Agent": (0, import_core31.buildUserAgent)("wport-cli", "0.10.2"),
3019
3053
  "X-Source": CLI_SOURCE,
3020
3054
  Accept: "application/json"
3021
3055
  };
@@ -3026,7 +3060,7 @@ async function attemptRequest(opts, method, path, accessToken, body, query, extr
3026
3060
  headers,
3027
3061
  body: body !== void 0 ? JSON.stringify(body) : void 0
3028
3062
  });
3029
- const res = await (0, import_core30.fetchWithTimeout)(request, opts.timeoutMs);
3063
+ const res = await (0, import_core31.fetchWithTimeout)(request, opts.timeoutMs);
3030
3064
  const respBody = await res.json().catch(() => null);
3031
3065
  return { status: res.status, body: respBody, headers: res.headers };
3032
3066
  }
@@ -3058,13 +3092,13 @@ function personalDelete(opts, path, extra) {
3058
3092
  }
3059
3093
  function throwPersonalHttpError(status, body) {
3060
3094
  if (status === 401) {
3061
- const base = (0, import_core30.extractErrorMessage)(body) ?? `HTTP ${status}`;
3095
+ const base = (0, import_core31.extractErrorMessage)(body) ?? `HTTP ${status}`;
3062
3096
  throw new CliError(
3063
3097
  `${base} \u2014 Your session may have expired or the request was rejected. Run \`wport login\` to sign in again.`,
3064
3098
  ExitCode.ServerClientError
3065
3099
  );
3066
3100
  }
3067
- (0, import_core30.throwForHttpStatus)(status, body);
3101
+ (0, import_core31.throwForHttpStatus)(status, body);
3068
3102
  }
3069
3103
  function warnIfRateLimitLow2(headers) {
3070
3104
  const remaining = Number(headers.get("x-ratelimit-remaining"));
@@ -3075,7 +3109,7 @@ function warnIfRateLimitLow2(headers) {
3075
3109
  }
3076
3110
 
3077
3111
  // src/commands/auth/whoami.ts
3078
- var import_core32 = require("@wport/core");
3112
+ var import_core33 = require("@wport/core");
3079
3113
  var PLACEHOLDER = "\u2014";
3080
3114
  function display(value) {
3081
3115
  const clean = sanitizeForTerminal(value ?? "");
@@ -3083,8 +3117,8 @@ function display(value) {
3083
3117
  }
3084
3118
  async function performWhoami(ctx) {
3085
3119
  const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
3086
- const { body } = await personalGet(opts, import_core32.OAUTH_SESSIONS_BASE);
3087
- const sessions = (0, import_core31.unwrapDataArray)(body);
3120
+ const { body } = await personalGet(opts, import_core33.OAUTH_SESSIONS_BASE);
3121
+ const sessions = (0, import_core32.unwrapDataArray)(body);
3088
3122
  const current = sessions.find((s) => s.is_current);
3089
3123
  const localLoginAt = loadPersonalCredentials()?.session_created_at ?? null;
3090
3124
  if (ctx.format === "json") {
@@ -3136,15 +3170,15 @@ function registerLogoutCommand(program2) {
3136
3170
  }
3137
3171
 
3138
3172
  // src/commands/sessions/list.ts
3139
- var import_core33 = require("@wport/core");
3140
3173
  var import_core34 = require("@wport/core");
3174
+ var import_core35 = require("@wport/core");
3141
3175
  function formatDate5(value) {
3142
3176
  return value ? String(value).slice(0, 10) : "";
3143
3177
  }
3144
3178
  async function runSessionsList(ctx) {
3145
3179
  const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
3146
- const { body } = await personalGet(opts, import_core34.OAUTH_SESSIONS_BASE);
3147
- const sessions = (0, import_core33.unwrapDataArray)(body);
3180
+ const { body } = await personalGet(opts, import_core35.OAUTH_SESSIONS_BASE);
3181
+ const sessions = (0, import_core34.unwrapDataArray)(body);
3148
3182
  if (ctx.format === "json") {
3149
3183
  printJson(sessions);
3150
3184
  return;
@@ -3168,8 +3202,8 @@ function registerSessionsList(parent) {
3168
3202
  }
3169
3203
 
3170
3204
  // src/commands/sessions/revoke.ts
3171
- var import_core35 = require("@wport/core");
3172
3205
  var import_core36 = require("@wport/core");
3206
+ var import_core37 = require("@wport/core");
3173
3207
  async function runSessionsRevoke(ctx, encId, allOthers) {
3174
3208
  const hasEncId = encId !== void 0;
3175
3209
  if (hasEncId === allOthers) {
@@ -3177,8 +3211,8 @@ async function runSessionsRevoke(ctx, encId, allOthers) {
3177
3211
  }
3178
3212
  const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
3179
3213
  if (allOthers) {
3180
- const { body } = await personalDelete(opts, `${import_core35.OAUTH_SESSIONS_BASE}/others`);
3181
- const result = (0, import_core36.unwrapDataResponse)(body);
3214
+ const { body } = await personalDelete(opts, `${import_core36.OAUTH_SESSIONS_BASE}/others`);
3215
+ const result = (0, import_core37.unwrapDataResponse)(body);
3182
3216
  if (ctx.format === "json") {
3183
3217
  printJson(result);
3184
3218
  return;
@@ -3189,7 +3223,7 @@ async function runSessionsRevoke(ctx, encId, allOthers) {
3189
3223
  }
3190
3224
  const trimmed = encId.trim();
3191
3225
  if (!trimmed) throw new CliError("enc_id must not be empty", ExitCode.InvalidArgument);
3192
- await personalDelete(opts, `${import_core35.OAUTH_SESSIONS_BASE}/${encodeURIComponent(trimmed)}`);
3226
+ await personalDelete(opts, `${import_core36.OAUTH_SESSIONS_BASE}/${encodeURIComponent(trimmed)}`);
3193
3227
  if (ctx.format === "json") {
3194
3228
  printJson({ enc_id: trimmed, revoked: true });
3195
3229
  return;
@@ -3212,18 +3246,18 @@ function registerSessionsCommand(program2) {
3212
3246
  }
3213
3247
 
3214
3248
  // src/commands/personal/resumes/schema.ts
3215
- var import_core37 = require("@wport/core");
3249
+ var import_core38 = require("@wport/core");
3216
3250
  function registerPersonalResumesSchema(parent) {
3217
3251
  parent.command("schema").description("Print the resume aggregate JSON Schema (offline, no login required)").option("--section <name>", "print only the given section (e.g. education, work_experience)").action((opts) => {
3218
- printJson((0, import_core37.buildAggregateJsonSchema)(opts.section));
3252
+ printJson((0, import_core38.buildAggregateJsonSchema)(opts.section));
3219
3253
  });
3220
3254
  }
3221
3255
 
3222
3256
  // src/commands/personal/resumes/validate.ts
3223
- var import_core38 = require("@wport/core");
3257
+ var import_core39 = require("@wport/core");
3224
3258
  function runResumesValidate(ctx, filePath) {
3225
3259
  const input = readJsonInput(filePath, { timeoutMs: ctx.timeoutMs });
3226
- const issues = (0, import_core38.validateAggregate)(input);
3260
+ const issues = (0, import_core39.validateAggregate)(input);
3227
3261
  if (issues.length === 0) {
3228
3262
  if (ctx.format === "json") {
3229
3263
  printJson({ valid: true });
@@ -3251,9 +3285,9 @@ function registerPersonalResumesValidate(parent) {
3251
3285
 
3252
3286
  // src/commands/personal/resumes/template.ts
3253
3287
  var import_node_fs8 = require("fs");
3254
- var import_core39 = require("@wport/core");
3288
+ var import_core40 = require("@wport/core");
3255
3289
  function runResumesTemplate(outPath) {
3256
- const template = (0, import_core39.buildTemplate)();
3290
+ const template = (0, import_core40.buildTemplate)();
3257
3291
  if (outPath === void 0) {
3258
3292
  printJson(template);
3259
3293
  return;
@@ -3277,8 +3311,8 @@ function registerPersonalResumesTemplate(parent) {
3277
3311
  }
3278
3312
 
3279
3313
  // src/commands/personal/resumes/list.ts
3280
- var import_core40 = require("@wport/core");
3281
3314
  var import_core41 = require("@wport/core");
3315
+ var import_core42 = require("@wport/core");
3282
3316
  var MINIMAL_LIST_FIELDS4 = ["enc_id", "name", "updated_at", "is_complete", "is_published"];
3283
3317
  function formatDate6(value) {
3284
3318
  return value ? String(value).slice(0, 10) : "";
@@ -3288,8 +3322,8 @@ function formatQuotaLine(quota) {
3288
3322
  return `${quota.used}/${quota.max_resumes} used, ${status}.`;
3289
3323
  }
3290
3324
  async function fetchResumeList(opts) {
3291
- const { body } = await personalGet(opts, import_core41.PERSONAL_RESUMES_BASE);
3292
- return (0, import_core40.unwrapDataResponse)(body);
3325
+ const { body } = await personalGet(opts, import_core42.PERSONAL_RESUMES_BASE);
3326
+ return (0, import_core41.unwrapDataResponse)(body);
3293
3327
  }
3294
3328
  async function runResumesList(ctx, flags) {
3295
3329
  if (flags.fields && flags.minimal) {
@@ -3322,20 +3356,20 @@ function registerPersonalResumesList(parent) {
3322
3356
  }
3323
3357
 
3324
3358
  // src/commands/personal/resumes/view.ts
3325
- var import_core42 = require("@wport/core");
3326
3359
  var import_core43 = require("@wport/core");
3327
3360
  var import_core44 = require("@wport/core");
3361
+ var import_core45 = require("@wport/core");
3328
3362
  async function fetchResumeAggregate(opts, encId) {
3329
3363
  const trimmed = encId.trim();
3330
3364
  if (!trimmed) {
3331
3365
  throw new CliError("enc_id must not be empty", ExitCode.InvalidArgument);
3332
3366
  }
3333
- const { body } = await personalGet(opts, `${import_core43.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}`);
3334
- return (0, import_core42.unwrapDataResponse)(body);
3367
+ const { body } = await personalGet(opts, `${import_core44.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}`);
3368
+ return (0, import_core43.unwrapDataResponse)(body);
3335
3369
  }
3336
3370
  function summarizeSections(resume) {
3337
3371
  const rows = [{ section: "name", summary: resume.name }];
3338
- for (const def of import_core44.SECTIONS) {
3372
+ for (const def of import_core45.SECTIONS) {
3339
3373
  rows.push({ section: def.key, summary: summarizeSection(def, resume) });
3340
3374
  }
3341
3375
  return rows;
@@ -3413,13 +3447,13 @@ function registerPersonalResumesExport(parent) {
3413
3447
  }
3414
3448
 
3415
3449
  // src/commands/personal/resumes/create.ts
3416
- var import_core48 = require("@wport/core");
3450
+ var import_core49 = require("@wport/core");
3417
3451
 
3418
3452
  // src/lib/resume-orchestrator.ts
3419
3453
  var import_node_crypto12 = require("crypto");
3420
- var import_core45 = require("@wport/core");
3421
3454
  var import_core46 = require("@wport/core");
3422
3455
  var import_core47 = require("@wport/core");
3456
+ var import_core48 = require("@wport/core");
3423
3457
  function freshIdempotencyKey() {
3424
3458
  return { idempotencyKey: (0, import_node_crypto12.randomUUID)() };
3425
3459
  }
@@ -3434,8 +3468,8 @@ function extractErrorCode(body) {
3434
3468
  }
3435
3469
  async function createShell(opts) {
3436
3470
  try {
3437
- const { body } = await personalPost(opts, import_core46.PERSONAL_RESUMES_BASE, {}, freshIdempotencyKey());
3438
- return (0, import_core45.unwrapDataResponse)(body).enc_id;
3471
+ const { body } = await personalPost(opts, import_core47.PERSONAL_RESUMES_BASE, {}, freshIdempotencyKey());
3472
+ return (0, import_core46.unwrapDataResponse)(body).enc_id;
3439
3473
  } catch (err) {
3440
3474
  if (err instanceof ServerClientHttpError) {
3441
3475
  const code = extractErrorCode(err.body);
@@ -3456,7 +3490,7 @@ async function createShell(opts) {
3456
3490
  }
3457
3491
  }
3458
3492
  async function renameResume(opts, encId, name) {
3459
- await personalPut(opts, `${import_core46.PERSONAL_RESUMES_BASE}/${encodeURIComponent(encId)}/name`, { name }, freshIdempotencyKey());
3493
+ await personalPut(opts, `${import_core47.PERSONAL_RESUMES_BASE}/${encodeURIComponent(encId)}/name`, { name }, freshIdempotencyKey());
3460
3494
  }
3461
3495
  function toWorkExperienceWriteItem(item) {
3462
3496
  const { is_current, ...rest } = item;
@@ -3468,8 +3502,8 @@ function splitItemEncId(item) {
3468
3502
  return [valid, rest];
3469
3503
  }
3470
3504
  async function writeSection(opts, encId, key, value, mode) {
3471
- const plan = import_core46.SECTION_WRITE_PLAN[key];
3472
- const base = `${import_core46.PERSONAL_RESUMES_BASE}/${encodeURIComponent(encId)}`;
3505
+ const plan = import_core47.SECTION_WRITE_PLAN[key];
3506
+ const base = `${import_core47.PERSONAL_RESUMES_BASE}/${encodeURIComponent(encId)}`;
3473
3507
  switch (plan.kind) {
3474
3508
  case "per-item-post": {
3475
3509
  for (const item of value) {
@@ -3536,7 +3570,7 @@ async function createAggregate(opts, aggregate) {
3536
3570
  if (aggregate.name !== void 0) {
3537
3571
  reports.push(await attemptStep("name", () => renameResume(opts, encId, aggregate.name)));
3538
3572
  }
3539
- for (const section of import_core47.SECTIONS) {
3573
+ for (const section of import_core48.SECTIONS) {
3540
3574
  const value = aggregate[section.key];
3541
3575
  if (value === void 0) continue;
3542
3576
  reports.push(await attemptStep(section.key, () => writeSection(opts, encId, section.key, value, "create")));
@@ -3546,9 +3580,9 @@ async function createAggregate(opts, aggregate) {
3546
3580
  async function updateAggregate(opts, encId, aggregate, onlySection) {
3547
3581
  const reports = [];
3548
3582
  if (onlySection !== void 0) {
3549
- const section = (0, import_core47.getSection)(onlySection);
3583
+ const section = (0, import_core48.getSection)(onlySection);
3550
3584
  if (!section) {
3551
- const allowed = import_core47.SECTIONS.map((s) => s.key).join(", ");
3585
+ const allowed = import_core48.SECTIONS.map((s) => s.key).join(", ");
3552
3586
  throw new CliError(`Unknown section "${onlySection}". Allowed: ${allowed}`, ExitCode.InvalidArgument);
3553
3587
  }
3554
3588
  const value = aggregate[onlySection];
@@ -3561,7 +3595,7 @@ async function updateAggregate(opts, encId, aggregate, onlySection) {
3561
3595
  if (aggregate.name !== void 0) {
3562
3596
  reports.push(await attemptStep("name", () => renameResume(opts, encId, aggregate.name)));
3563
3597
  }
3564
- for (const section of import_core47.SECTIONS) {
3598
+ for (const section of import_core48.SECTIONS) {
3565
3599
  const value = aggregate[section.key];
3566
3600
  if (value === void 0) continue;
3567
3601
  reports.push(await attemptStep(section.key, () => writeSection(opts, encId, section.key, value, "update")));
@@ -3572,7 +3606,7 @@ async function updateAggregate(opts, encId, aggregate, onlySection) {
3572
3606
  // src/commands/personal/resumes/create.ts
3573
3607
  async function runResumesCreate(ctx, filePath) {
3574
3608
  const input = readJsonObject(filePath, { timeoutMs: ctx.timeoutMs });
3575
- const issues = (0, import_core48.validateAggregate)(input);
3609
+ const issues = (0, import_core49.validateAggregate)(input);
3576
3610
  if (issues.length > 0) {
3577
3611
  if (ctx.format === "json") {
3578
3612
  printJson({ valid: false, issues });
@@ -3665,8 +3699,8 @@ function registerPersonalResumesUpdate(parent) {
3665
3699
 
3666
3700
  // src/commands/personal/resumes/copy.ts
3667
3701
  var import_node_crypto13 = require("crypto");
3668
- var import_core49 = require("@wport/core");
3669
3702
  var import_core50 = require("@wport/core");
3703
+ var import_core51 = require("@wport/core");
3670
3704
  function requireEncId3(encId) {
3671
3705
  const trimmed = encId.trim();
3672
3706
  if (!trimmed) {
@@ -3685,12 +3719,12 @@ function printCopyResult(ctx, sourceEncId, newEncId) {
3685
3719
  async function runResumesCopy(ctx, encId, name) {
3686
3720
  const trimmed = requireEncId3(encId);
3687
3721
  const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
3688
- const { body } = await personalPost(opts, `${import_core50.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}/duplicate`, {}, { idempotencyKey: (0, import_node_crypto13.randomUUID)() });
3689
- const { enc_id: newEncId } = (0, import_core49.unwrapDataResponse)(body);
3722
+ const { body } = await personalPost(opts, `${import_core51.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}/duplicate`, {}, { idempotencyKey: (0, import_node_crypto13.randomUUID)() });
3723
+ const { enc_id: newEncId } = (0, import_core50.unwrapDataResponse)(body);
3690
3724
  printCopyResult(ctx, trimmed, newEncId);
3691
3725
  if (name === void 0) return;
3692
3726
  try {
3693
- await personalPut(opts, `${import_core50.PERSONAL_RESUMES_BASE}/${encodeURIComponent(newEncId)}/name`, { name }, { idempotencyKey: (0, import_node_crypto13.randomUUID)() });
3727
+ await personalPut(opts, `${import_core51.PERSONAL_RESUMES_BASE}/${encodeURIComponent(newEncId)}/name`, { name }, { idempotencyKey: (0, import_node_crypto13.randomUUID)() });
3694
3728
  } catch (err) {
3695
3729
  const reason = err instanceof Error ? err.message : String(err);
3696
3730
  throw new CliError(
@@ -3707,8 +3741,8 @@ function registerPersonalResumesCopy(parent) {
3707
3741
 
3708
3742
  // src/commands/personal/resumes/publish.ts
3709
3743
  var import_node_crypto14 = require("crypto");
3710
- var import_core51 = require("@wport/core");
3711
3744
  var import_core52 = require("@wport/core");
3745
+ var import_core53 = require("@wport/core");
3712
3746
  function requireEncId4(encId) {
3713
3747
  const trimmed = encId.trim();
3714
3748
  if (!trimmed) {
@@ -3722,11 +3756,11 @@ async function runResumesPublishTransition(ctx, encId, action) {
3722
3756
  const targetStatus = action === "publish";
3723
3757
  const { body } = await personalPatch(
3724
3758
  opts,
3725
- `${import_core52.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}/published-status`,
3759
+ `${import_core53.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}/published-status`,
3726
3760
  { target_status: targetStatus },
3727
3761
  { idempotencyKey: (0, import_node_crypto14.randomUUID)() }
3728
3762
  );
3729
- const result = (0, import_core51.unwrapDataResponse)(body);
3763
+ const result = (0, import_core52.unwrapDataResponse)(body);
3730
3764
  if (ctx.format === "json") {
3731
3765
  printJson({ enc_id: trimmed, is_published: result.is_published });
3732
3766
  return;
@@ -3748,7 +3782,7 @@ function registerPersonalResumesUnpublish(parent) {
3748
3782
 
3749
3783
  // src/commands/personal/resumes/delete.ts
3750
3784
  var import_node_crypto15 = require("crypto");
3751
- var import_core53 = require("@wport/core");
3785
+ var import_core54 = require("@wport/core");
3752
3786
  function requireEncId5(encId) {
3753
3787
  const trimmed = encId.trim();
3754
3788
  if (!trimmed) {
@@ -3762,7 +3796,7 @@ async function runResumesDelete(ctx, encId, confirm) {
3762
3796
  }
3763
3797
  const trimmed = requireEncId5(encId);
3764
3798
  const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
3765
- await personalDelete(opts, `${import_core53.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}`, { idempotencyKey: (0, import_node_crypto15.randomUUID)() });
3799
+ await personalDelete(opts, `${import_core54.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}`, { idempotencyKey: (0, import_node_crypto15.randomUUID)() });
3766
3800
  if (ctx.format === "json") {
3767
3801
  printJson({ enc_id: trimmed, deleted: true });
3768
3802
  return;
@@ -3796,7 +3830,7 @@ function registerPersonalResumesCommand(parent) {
3796
3830
  // src/commands/personal/apply/index.ts
3797
3831
  var import_node_crypto16 = require("crypto");
3798
3832
  var import_node_fs11 = require("fs");
3799
- var import_core54 = require("@wport/core");
3833
+ var import_core55 = require("@wport/core");
3800
3834
 
3801
3835
  // src/commands/personal/apply/message-input.ts
3802
3836
  var import_node_fs10 = require("fs");
@@ -3878,7 +3912,7 @@ async function runPersonalApply(ctx, args) {
3878
3912
  const body = { enc_job_id: args.encJobId, enc_resume_id: args.encResumeId, application_message: args.message };
3879
3913
  let result;
3880
3914
  try {
3881
- result = await personalPost(opts, import_core54.PERSONAL_APPLICATIONS_BASE, body, { idempotencyKey: (0, import_node_crypto16.randomUUID)() });
3915
+ result = await personalPost(opts, import_core55.PERSONAL_APPLICATIONS_BASE, body, { idempotencyKey: (0, import_node_crypto16.randomUUID)() });
3882
3916
  } catch (err) {
3883
3917
  rethrowApplyError(err);
3884
3918
  }
@@ -3929,7 +3963,7 @@ async function runPersonalApplyBatch(ctx, args) {
3929
3963
  const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
3930
3964
  let result;
3931
3965
  try {
3932
- result = await personalPost(opts, `${import_core54.PERSONAL_APPLICATIONS_BASE}/batch`, { applications: items }, { idempotencyKey: (0, import_node_crypto16.randomUUID)() });
3966
+ result = await personalPost(opts, `${import_core55.PERSONAL_APPLICATIONS_BASE}/batch`, { applications: items }, { idempotencyKey: (0, import_node_crypto16.randomUUID)() });
3933
3967
  } catch (err) {
3934
3968
  rethrowApplyError(err);
3935
3969
  }
@@ -3957,7 +3991,7 @@ function registerPersonalCommand(program2) {
3957
3991
 
3958
3992
  // src/index.ts
3959
3993
  var program = new import_commander.Command();
3960
- program.name("wport").description("wport CLI \u2014 terminal interface to the W101 Talent Search Hub public API").version("0.10.0", "-v, --version", "output the CLI version").option("--lang <locale>", "Accept-Language locale: zh-TW | en-US | vi-VN | th-TH | id-ID").option("--api <url>", "override API base URL").option("--output <fmt>", "output format: table | json").option("--no-color", "disable color output").option("--timeout <ms>", "HTTP timeout in milliseconds", (v) => Number(v));
3994
+ program.name("wport").description("wport CLI \u2014 terminal interface to the W101 Talent Search Hub public API").version("0.10.2", "-v, --version", "output the CLI version").option("--lang <locale>", "Accept-Language locale: zh-TW | en-US | vi-VN | th-TH | id-ID").option("--api <url>", "override API base URL").option("--output <fmt>", "output format: table | json").option("--no-color", "disable color output").option("--timeout <ms>", "HTTP timeout in milliseconds", (v) => Number(v));
3961
3995
  registerJobsCommand(program);
3962
3996
  registerConfigCommand(program);
3963
3997
  registerDoctorCommand(program);