@curviate/cli 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,49 @@ a new command or flag is a minor; a breaking command/flag/exit-code change is a
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [0.7.0] - 2026-07-01
12
+
13
+ ### Added
14
+
15
+ - `search` — named filter flags that previously required raw `--filters` JSON:
16
+ - **companies**: `--has-job-offers`, `--headcount <buckets>` (comma-separated
17
+ size buckets `1-10 … 5001-10000`; `10001+` reports a usage error).
18
+ - **jobs**: `--title <ids>`, `--presence`, `--benefits`, `--commitments`,
19
+ `--has-verifications`, `--under-10-applicants`, `--in-your-network`,
20
+ `--fair-chance-employer`, `--location-within-area <miles>`.
21
+ - **people**: `--connections-of`, `--followers-of` (comma-separated → array).
22
+ - **posts**: `--posted-by-member`, `--posted-by-company`, `--posted-by-me`,
23
+ `--mentioning-member`, `--mentioning-company`, `--author-industry`,
24
+ `--author-company`, `--author-keywords`.
25
+
26
+ ### Fixed
27
+
28
+ - `search jobs` slim `company_name` was always `null` — now derived from the
29
+ nested `company.name` (handles postings with no linked company). `--verbose`
30
+ still returns the raw response unchanged.
31
+ - `search parameters --type`, `search jobs --seniority`/`--job-type`, and
32
+ `search posts --content-type` help text now lists the correct/complete
33
+ enumerations (no behavior change).
34
+
35
+ ### Changed
36
+
37
+ - Updated `@curviate/sdk` dependency to `^0.5.0`.
38
+
39
+ ## [0.6.1] - 2026-07-01
40
+
41
+ ### Added
42
+
43
+ - `search people --title` (→ `advanced_keywords.title` keyword, nested-merged),
44
+ `--industry`, `--profile-language`; `--filters` deep-merge (named flags win).
45
+ - `search jobs --location` → `region` (single id) + `--region` alias +
46
+ `--date-posted <days>` (number).
47
+ - `search posts --date-posted` hyphen→underscore normalize.
48
+ - `--all` truncation emits `{"object":"stream_truncated",…}` JSON.
49
+
50
+ ### Changed
51
+
52
+ - Updated `@curviate/sdk` dependency to `^0.4.1`.
53
+
11
54
  ## [0.6.0] - 2026-06-30
12
55
 
13
56
  ### Added
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-R3VLWLVV.js";
5
5
  import {
6
6
  streamAll
7
- } from "./chunk-SND3NHCT.js";
7
+ } from "./chunk-GXTZION6.js";
8
8
  import {
9
9
  createClient,
10
10
  renderError,
@@ -68,7 +68,8 @@ async function runAccountList(client, flags, out) {
68
68
  const fn = (p) => client.accounts.list(p);
69
69
  for await (const item of streamAll(fn, params, {
70
70
  maxPages,
71
- onTruncated: (msg) => out.stderr.write(msg + "\n")
71
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
72
+ `)
72
73
  })) {
73
74
  out.stdout.write(JSON.stringify(item) + "\n");
74
75
  }
@@ -32,9 +32,8 @@ async function* streamAll(fn, params, opts = {}) {
32
32
  cursor = page.cursor;
33
33
  if (!cursor) break;
34
34
  if (pageCount >= maxPages) {
35
- const msg = `Streaming truncated at ${maxPages} page(s) \u2014 more results may exist. Increase --max-pages or use --cursor / --limit for manual paging.`;
36
35
  if (opts.onTruncated) {
37
- opts.onTruncated(msg);
36
+ opts.onTruncated(pageCount, cursor !== null && cursor !== void 0);
38
37
  }
39
38
  break;
40
39
  }
@@ -106,6 +106,79 @@ function slimInviteReceived(data) {
106
106
  cursor: d["cursor"] ?? null
107
107
  };
108
108
  }
109
+ function slimSearchPeopleItem(item) {
110
+ return {
111
+ id: item["id"] ?? null,
112
+ public_identifier: item["public_identifier"] ?? null,
113
+ full_name: item["full_name"] ?? null,
114
+ headline: item["headline"] ?? null,
115
+ location: item["location"] ?? null,
116
+ network_distance: item["network_distance"] ?? null
117
+ };
118
+ }
119
+ function slimSearchPeople(data) {
120
+ const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
121
+ const items = Array.isArray(d["items"]) ? d["items"].map(slimSearchPeopleItem) : [];
122
+ return { ...d, items };
123
+ }
124
+ function slimSearchCompaniesItem(item) {
125
+ const result = {
126
+ id: item["id"] ?? null,
127
+ name: item["name"] ?? null,
128
+ location: item["location"] ?? null,
129
+ followers_count: item["followers_count"] ?? null
130
+ };
131
+ if (Object.prototype.hasOwnProperty.call(item, "industry")) {
132
+ result["industry"] = item["industry"];
133
+ }
134
+ return result;
135
+ }
136
+ function slimSearchCompanies(data) {
137
+ const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
138
+ const items = Array.isArray(d["items"]) ? d["items"].map(slimSearchCompaniesItem) : [];
139
+ return { ...d, items };
140
+ }
141
+ function slimSearchJobsItem(item) {
142
+ const company = item["company"];
143
+ return {
144
+ job_urn: item["job_urn"] ?? null,
145
+ title: item["title"] ?? null,
146
+ location: item["location"] ?? null,
147
+ company_name: company?.["name"] ?? null,
148
+ posted_at: item["posted_at"] ?? null,
149
+ easy_apply: item["easy_apply"] ?? null
150
+ };
151
+ }
152
+ function slimSearchJobs(data) {
153
+ const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
154
+ const items = Array.isArray(d["items"]) ? d["items"].map(slimSearchJobsItem) : [];
155
+ return { ...d, items };
156
+ }
157
+ function slimSearchPostsItem(item) {
158
+ const rawAuthor = item["author"] !== null && item["author"] !== void 0 && typeof item["author"] === "object" ? item["author"] : null;
159
+ const author = rawAuthor !== null ? { name: rawAuthor["name"] ?? null } : null;
160
+ const rawText = item["text"];
161
+ let text;
162
+ if (rawText === null || rawText === void 0) {
163
+ text = null;
164
+ } else {
165
+ const s = String(rawText);
166
+ text = s.length > 200 ? s.slice(0, 200) : s;
167
+ }
168
+ return {
169
+ post_urn: item["post_urn"] ?? null,
170
+ posted_at: item["posted_at"] ?? null,
171
+ author,
172
+ text,
173
+ reaction_count: item["reaction_count"] ?? null,
174
+ comment_count: item["comment_count"] ?? null
175
+ };
176
+ }
177
+ function slimSearchPosts(data) {
178
+ const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
179
+ const items = Array.isArray(d["items"]) ? d["items"].map(slimSearchPostsItem) : [];
180
+ return { ...d, items };
181
+ }
109
182
  function slimCompany(data) {
110
183
  const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
111
184
  const rawMessaging = d["messaging"] !== null && d["messaging"] !== void 0 && typeof d["messaging"] === "object" ? d["messaging"] : null;
@@ -137,5 +210,13 @@ export {
137
210
  slimInviteSent,
138
211
  slimInviteReceivedItem,
139
212
  slimInviteReceived,
213
+ slimSearchPeopleItem,
214
+ slimSearchPeople,
215
+ slimSearchCompaniesItem,
216
+ slimSearchCompanies,
217
+ slimSearchJobsItem,
218
+ slimSearchJobs,
219
+ slimSearchPostsItem,
220
+ slimSearchPosts,
140
221
  slimCompany
141
222
  };
package/dist/cli.js CHANGED
@@ -143,17 +143,17 @@ var main = defineCommand({
143
143
  // ---------------------------------------------------------------------------
144
144
  // Noun groups — lazy-loaded on first invocation.
145
145
  // ---------------------------------------------------------------------------
146
- profile: () => import("./profile-NDDG26PL.js").then((m) => m.profileCommand),
147
- company: () => import("./company-SZPGJE3M.js").then((m) => m.companyCommand),
148
- connect: () => import("./connect-RMT7OS3I.js").then((m) => m.connectCommand),
149
- search: () => import("./search-QO237C4O.js").then((m) => m.searchCommand),
150
- inbox: () => import("./inbox-MIKI4HU3.js").then((m) => m.inboxCommand),
146
+ profile: () => import("./profile-GGUBDI3P.js").then((m) => m.profileCommand),
147
+ company: () => import("./company-HPHLJCKB.js").then((m) => m.companyCommand),
148
+ connect: () => import("./connect-EUJBSLNM.js").then((m) => m.connectCommand),
149
+ search: () => import("./search-RZYVGGMN.js").then((m) => m.searchCommand),
150
+ inbox: () => import("./inbox-YV6GPRG6.js").then((m) => m.inboxCommand),
151
151
  message: () => import("./message-YRMLMHK7.js").then((m) => m.messageCommand),
152
- post: () => import("./post-2FYHZAKC.js").then((m) => m.postCommand),
153
- account: () => import("./account-ZWBNNQKQ.js").then((m) => m.accountCommand),
154
- webhook: () => import("./webhook-FDIERREB.js").then((m) => m.webhookCommand),
155
- "sales-nav": () => import("./sales-nav-7WPN7BT4.js").then((m) => m.salesNavCommand),
156
- recruiter: () => import("./recruiter-3DRGDOVV.js").then((m) => m.recruiterCommand)
152
+ post: () => import("./post-KBSR3ADF.js").then((m) => m.postCommand),
153
+ account: () => import("./account-O5GZNE72.js").then((m) => m.accountCommand),
154
+ webhook: () => import("./webhook-F6CRIISR.js").then((m) => m.webhookCommand),
155
+ "sales-nav": () => import("./sales-nav-LSBARRGL.js").then((m) => m.salesNavCommand),
156
+ recruiter: () => import("./recruiter-7UEBT3JZ.js").then((m) => m.recruiterCommand)
157
157
  },
158
158
  async run() {
159
159
  const { runMain } = await import("citty");
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- slimCompany
4
- } from "./chunk-6VBOKOQJ.js";
5
2
  import {
6
3
  resolveIdentifier
7
4
  } from "./chunk-SZB3CFRZ.js";
5
+ import {
6
+ slimCompany
7
+ } from "./chunk-J5KGG2EE.js";
8
8
  import {
9
9
  createClient,
10
10
  renderError,
@@ -2,18 +2,18 @@
2
2
  import {
3
3
  buildPreviewOutput
4
4
  } from "./chunk-R3VLWLVV.js";
5
- import {
6
- slimInviteReceived,
7
- slimInviteReceivedItem,
8
- slimInviteSent,
9
- slimInviteSentItem
10
- } from "./chunk-6VBOKOQJ.js";
11
5
  import {
12
6
  resolveIdentifier
13
7
  } from "./chunk-SZB3CFRZ.js";
14
8
  import {
15
9
  streamAll
16
- } from "./chunk-SND3NHCT.js";
10
+ } from "./chunk-GXTZION6.js";
11
+ import {
12
+ slimInviteReceived,
13
+ slimInviteReceivedItem,
14
+ slimInviteSent,
15
+ slimInviteSentItem
16
+ } from "./chunk-J5KGG2EE.js";
17
17
  import {
18
18
  createClient,
19
19
  renderError,
@@ -104,7 +104,8 @@ async function runConnectSent(client, flags, out) {
104
104
  const fn = (p) => ns.invites.listSent(p);
105
105
  for await (const item of streamAll(fn, params, {
106
106
  maxPages,
107
- onTruncated: (msg) => out.stderr.write(msg + "\n")
107
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
108
+ `)
108
109
  })) {
109
110
  const projected = !flags.verbose ? slimInviteSentItem(item) : item;
110
111
  out.stdout.write(JSON.stringify(projected) + "\n");
@@ -141,7 +142,8 @@ async function runConnectReceived(client, flags, out) {
141
142
  const fn = (p) => ns.invites.listReceived(p);
142
143
  for await (const item of streamAll(fn, params, {
143
144
  maxPages,
144
- onTruncated: (msg) => out.stderr.write(msg + "\n")
145
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
146
+ `)
145
147
  })) {
146
148
  const projected = !flags.verbose ? slimInviteReceivedItem(item) : item;
147
149
  out.stdout.write(JSON.stringify(projected) + "\n");
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-SZB3CFRZ.js";
5
5
  import {
6
6
  streamAll
7
- } from "./chunk-SND3NHCT.js";
7
+ } from "./chunk-GXTZION6.js";
8
8
  import {
9
9
  createClient,
10
10
  renderError,
@@ -92,7 +92,8 @@ async function runInboxList(client, flags, out) {
92
92
  const fn = (p) => ns.messaging.listChats(p);
93
93
  for await (const item of streamAll(fn, params, {
94
94
  maxPages,
95
- onTruncated: (msg) => out.stderr.write(msg + "\n")
95
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
96
+ `)
96
97
  })) {
97
98
  out.stdout.write(JSON.stringify(item) + "\n");
98
99
  }
@@ -140,7 +141,8 @@ async function runInboxMessages(client, flags, out) {
140
141
  const fn = (p) => ns.messaging.listMessages(chatId, p);
141
142
  for await (const item of streamAll(fn, params, {
142
143
  maxPages,
143
- onTruncated: (msg) => out.stderr.write(msg + "\n")
144
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
145
+ `)
144
146
  })) {
145
147
  out.stdout.write(JSON.stringify(item) + "\n");
146
148
  }
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-R3VLWLVV.js";
12
12
  import {
13
13
  streamAll
14
- } from "./chunk-SND3NHCT.js";
14
+ } from "./chunk-GXTZION6.js";
15
15
  import {
16
16
  createClient,
17
17
  renderError,
@@ -92,7 +92,8 @@ async function runPostList(client, flags, out) {
92
92
  const fn = (p) => ns.posts.list(p);
93
93
  for await (const item of streamAll(fn, params, {
94
94
  maxPages,
95
- onTruncated: (msg) => out.stderr.write(msg + "\n")
95
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
96
+ `)
96
97
  })) {
97
98
  out.stdout.write(JSON.stringify(item) + "\n");
98
99
  }
@@ -246,7 +247,8 @@ async function runPostComments(client, flags, out) {
246
247
  const fn = (p) => ns.posts.listComments(postId, p);
247
248
  for await (const item of streamAll(fn, params, {
248
249
  maxPages,
249
- onTruncated: (msg) => out.stderr.write(msg + "\n")
250
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
251
+ `)
250
252
  })) {
251
253
  out.stdout.write(JSON.stringify(item) + "\n");
252
254
  }
@@ -308,7 +310,8 @@ async function runPostReactions(client, flags, out) {
308
310
  const fn = (p) => ns.posts.listReactions(postId, p);
309
311
  for await (const item of streamAll(fn, params, {
310
312
  maxPages,
311
- onTruncated: (msg) => out.stderr.write(msg + "\n")
313
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
314
+ `)
312
315
  })) {
313
316
  out.stdout.write(JSON.stringify(item) + "\n");
314
317
  }
@@ -2,16 +2,16 @@
2
2
  import {
3
3
  buildPreviewOutput
4
4
  } from "./chunk-R3VLWLVV.js";
5
- import {
6
- slimProfile,
7
- slimProfileMe
8
- } from "./chunk-6VBOKOQJ.js";
9
5
  import {
10
6
  resolveIdentifier
11
7
  } from "./chunk-SZB3CFRZ.js";
12
8
  import {
13
9
  streamAll
14
- } from "./chunk-SND3NHCT.js";
10
+ } from "./chunk-GXTZION6.js";
11
+ import {
12
+ slimProfile,
13
+ slimProfileMe
14
+ } from "./chunk-J5KGG2EE.js";
15
15
  import {
16
16
  createClient,
17
17
  renderError,
@@ -86,7 +86,8 @@ async function runProfileMe(client, flags, out) {
86
86
  const fn = (p) => ns.profiles.listPosts(ownSlug, p);
87
87
  for await (const item of streamAll(fn, params2, {
88
88
  maxPages,
89
- onTruncated: (msg) => out.stderr.write(msg + "\n")
89
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
90
+ `)
90
91
  })) {
91
92
  out.stdout.write(JSON.stringify(item) + "\n");
92
93
  }
@@ -99,7 +100,8 @@ async function runProfileMe(client, flags, out) {
99
100
  const fn = (p) => ns.profiles.listComments(ownSlug, p);
100
101
  for await (const item of streamAll(fn, params2, {
101
102
  maxPages,
102
- onTruncated: (msg) => out.stderr.write(msg + "\n")
103
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
104
+ `)
103
105
  })) {
104
106
  out.stdout.write(JSON.stringify(item) + "\n");
105
107
  }
@@ -112,7 +114,8 @@ async function runProfileMe(client, flags, out) {
112
114
  const fn = (p) => ns.profiles.listReactions(ownSlug, p);
113
115
  for await (const item of streamAll(fn, params2, {
114
116
  maxPages,
115
- onTruncated: (msg) => out.stderr.write(msg + "\n")
117
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
118
+ `)
116
119
  })) {
117
120
  out.stdout.write(JSON.stringify(item) + "\n");
118
121
  }
@@ -125,7 +128,8 @@ async function runProfileMe(client, flags, out) {
125
128
  const fn = (p) => ns.profiles.listFollowers(ownSlug, p);
126
129
  for await (const item of streamAll(fn, params2, {
127
130
  maxPages,
128
- onTruncated: (msg) => out.stderr.write(msg + "\n")
131
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
132
+ `)
129
133
  })) {
130
134
  out.stdout.write(JSON.stringify(item) + "\n");
131
135
  }
@@ -200,7 +204,8 @@ async function runProfileGet(client, flags, out) {
200
204
  const fn = (p) => ns.profiles.listPosts(postId, p);
201
205
  for await (const item of streamAll(fn, params, {
202
206
  maxPages,
203
- onTruncated: (msg) => out.stderr.write(msg + "\n")
207
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
208
+ `)
204
209
  })) {
205
210
  out.stdout.write(JSON.stringify(item) + "\n");
206
211
  }
@@ -216,7 +221,8 @@ async function runProfileGet(client, flags, out) {
216
221
  const fn = (p) => ns.profiles.listComments(resolvedId, p);
217
222
  for await (const item of streamAll(fn, params, {
218
223
  maxPages,
219
- onTruncated: (msg) => out.stderr.write(msg + "\n")
224
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
225
+ `)
220
226
  })) {
221
227
  out.stdout.write(JSON.stringify(item) + "\n");
222
228
  }
@@ -232,7 +238,8 @@ async function runProfileGet(client, flags, out) {
232
238
  const fn = (p) => ns.profiles.listReactions(resolvedId, p);
233
239
  for await (const item of streamAll(fn, params, {
234
240
  maxPages,
235
- onTruncated: (msg) => out.stderr.write(msg + "\n")
241
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
242
+ `)
236
243
  })) {
237
244
  out.stdout.write(JSON.stringify(item) + "\n");
238
245
  }
@@ -248,7 +255,8 @@ async function runProfileGet(client, flags, out) {
248
255
  const fn = (p) => ns.profiles.listFollowers(resolvedId, p);
249
256
  for await (const item of streamAll(fn, params, {
250
257
  maxPages,
251
- onTruncated: (msg) => out.stderr.write(msg + "\n")
258
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
259
+ `)
252
260
  })) {
253
261
  out.stdout.write(JSON.stringify(item) + "\n");
254
262
  }
@@ -295,7 +303,8 @@ async function runProfileConnections(client, flags, out) {
295
303
  const fn = (p) => ns.profiles.listConnections(p);
296
304
  for await (const item of streamAll(fn, params, {
297
305
  maxPages,
298
- onTruncated: (msg) => out.stderr.write(msg + "\n")
306
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
307
+ `)
299
308
  })) {
300
309
  out.stdout.write(JSON.stringify(item) + "\n");
301
310
  }
@@ -20,7 +20,7 @@ import {
20
20
  } from "./chunk-42VUUKQ3.js";
21
21
  import {
22
22
  streamAll
23
- } from "./chunk-SND3NHCT.js";
23
+ } from "./chunk-GXTZION6.js";
24
24
  import {
25
25
  createClient,
26
26
  renderError,
@@ -242,7 +242,8 @@ async function runRecruiterSearchPeople(client, flags, out, readers = DEFAULT_FI
242
242
  };
243
243
  for await (const item of streamAll(fn, params, {
244
244
  maxPages,
245
- onTruncated: (msg) => out.stderr.write(msg + "\n")
245
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
246
+ `)
246
247
  })) {
247
248
  out.stdout.write(JSON.stringify(item) + "\n");
248
249
  }
@@ -287,7 +288,8 @@ async function runRecruiterListProjects(client, flags, out) {
287
288
  const fn = (p) => ns.recruiter.listProjects(p);
288
289
  for await (const item of streamAll(fn, params, {
289
290
  maxPages,
290
- onTruncated: (msg) => out.stderr.write(msg + "\n")
291
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
292
+ `)
291
293
  })) {
292
294
  out.stdout.write(JSON.stringify(item) + "\n");
293
295
  }
@@ -404,7 +406,8 @@ async function runRecruiterListJobs(client, flags, out) {
404
406
  const fn = (p) => ns.recruiter.listJobs(p);
405
407
  for await (const item of streamAll(fn, params, {
406
408
  maxPages,
407
- onTruncated: (msg) => out.stderr.write(msg + "\n")
409
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
410
+ `)
408
411
  })) {
409
412
  out.stdout.write(JSON.stringify(item) + "\n");
410
413
  }
@@ -17,7 +17,7 @@ import {
17
17
  } from "./chunk-42VUUKQ3.js";
18
18
  import {
19
19
  streamAll
20
- } from "./chunk-SND3NHCT.js";
20
+ } from "./chunk-GXTZION6.js";
21
21
  import {
22
22
  createClient,
23
23
  renderError,
@@ -123,7 +123,8 @@ async function runSalesNavSearchPeople(client, flags, out, readers = DEFAULT_FIL
123
123
  };
124
124
  for await (const item of streamAll(fn, params, {
125
125
  maxPages,
126
- onTruncated: (msg) => out.stderr.write(msg + "\n")
126
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
127
+ `)
127
128
  })) {
128
129
  out.stdout.write(JSON.stringify(item) + "\n");
129
130
  }
@@ -171,7 +172,8 @@ async function runSalesNavSearchCompanies(client, flags, out, readers = DEFAULT_
171
172
  };
172
173
  for await (const item of streamAll(fn, params, {
173
174
  maxPages,
174
- onTruncated: (msg) => out.stderr.write(msg + "\n")
175
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
176
+ `)
175
177
  })) {
176
178
  out.stdout.write(JSON.stringify(item) + "\n");
177
179
  }
@@ -7,7 +7,17 @@ import {
7
7
  } from "./chunk-42VUUKQ3.js";
8
8
  import {
9
9
  streamAll
10
- } from "./chunk-SND3NHCT.js";
10
+ } from "./chunk-GXTZION6.js";
11
+ import {
12
+ slimSearchCompanies,
13
+ slimSearchCompaniesItem,
14
+ slimSearchJobs,
15
+ slimSearchJobsItem,
16
+ slimSearchPeople,
17
+ slimSearchPeopleItem,
18
+ slimSearchPosts,
19
+ slimSearchPostsItem
20
+ } from "./chunk-J5KGG2EE.js";
11
21
  import {
12
22
  createClient,
13
23
  renderError,
@@ -21,14 +31,24 @@ import {
21
31
 
22
32
  // src/commands/search.ts
23
33
  import { defineCommand } from "citty";
34
+ var HEADCOUNT_BUCKETS = {
35
+ "1-10": { min: 1, max: 10 },
36
+ "11-50": { min: 11, max: 50 },
37
+ "51-200": { min: 51, max: 200 },
38
+ "201-500": { min: 201, max: 500 },
39
+ "501-1000": { min: 501, max: 1e3 },
40
+ "1001-5000": { min: 1001, max: 5e3 },
41
+ "5001-10000": { min: 5001, max: 1e4 }
42
+ };
43
+ var PEOPLE_INVALID_FLAGS = ["seniority", "function", "employment-type", "sort-by"];
24
44
  var FILTER_FLAGS = {
25
45
  filters: {
26
46
  type: "string",
27
- description: "Filter body as a JSON object (escape hatch for the full filter surface); '-' reads JSON from stdin."
47
+ description: "Filter body as a JSON object (named flags win on conflict; server validates and strips unknown fields); '-' reads JSON from stdin."
28
48
  },
29
49
  "filters-file": {
30
50
  type: "string",
31
- description: "Path to a JSON file with the filter body."
51
+ description: "Path to a JSON file with the filter body (named flags win on conflict)."
32
52
  }
33
53
  };
34
54
  function buildOutputStreams() {
@@ -60,7 +80,8 @@ function resolveOutputOpts(flags) {
60
80
  return {
61
81
  json: (flags.json ?? false) || !process.stdout.isTTY,
62
82
  isTTY: process.stdout.isTTY ?? false,
63
- fields: flags.fields
83
+ fields: flags.fields,
84
+ verbose: flags.verbose ?? false
64
85
  };
65
86
  }
66
87
  function applyCommonSearchFlags(body, flags) {
@@ -69,6 +90,10 @@ function applyCommonSearchFlags(body, flags) {
69
90
  if (flags.cursor) body["cursor"] = flags.cursor;
70
91
  if (flags.limit) body["limit"] = parseInt(flags.limit, 10);
71
92
  }
93
+ function mergeNested(body, key, patch) {
94
+ const existing = body[key] !== null && body[key] !== void 0 && typeof body[key] === "object" && !Array.isArray(body[key]) ? body[key] : {};
95
+ body[key] = { ...existing, ...patch };
96
+ }
72
97
  var NAMED_FLAG_MAPPERS = {
73
98
  people(body, flags) {
74
99
  if (flags.industry) body["industry"] = splitCsv(flags.industry);
@@ -77,28 +102,71 @@ var NAMED_FLAG_MAPPERS = {
77
102
  if (flags["past-company"]) body["past_company"] = splitCsv(flags["past-company"]);
78
103
  if (flags.school) body["school"] = splitCsv(flags.school);
79
104
  if (flags["network-distance"]) body["network_distance"] = splitCsvNumbers(flags["network-distance"]);
80
- if (flags["connections-of"]) body["connections_of"] = flags["connections-of"];
81
- if (flags["followers-of"]) body["followers_of"] = flags["followers-of"];
105
+ if (flags["connections-of"]) body["connections_of"] = splitCsv(flags["connections-of"]);
106
+ if (flags["followers-of"]) body["followers_of"] = splitCsv(flags["followers-of"]);
107
+ if (flags.title) {
108
+ const existingAK = body["advanced_keywords"] !== null && body["advanced_keywords"] !== void 0 && typeof body["advanced_keywords"] === "object" && !Array.isArray(body["advanced_keywords"]) ? body["advanced_keywords"] : {};
109
+ body["advanced_keywords"] = { ...existingAK, title: flags.title };
110
+ }
111
+ if (flags["profile-language"]) body["profile_language"] = splitCsv(flags["profile-language"]);
82
112
  },
83
113
  companies(body, flags) {
84
114
  if (flags.industry) body["industry"] = splitCsv(flags.industry);
85
115
  if (flags.location) body["location"] = splitCsv(flags.location);
86
116
  if (flags["network-distance"]) body["network_distance"] = splitCsvNumbers(flags["network-distance"]);
117
+ if (flags["has-job-offers"]) body["has_job_offers"] = true;
118
+ if (flags.headcount) {
119
+ const buckets = splitCsv(flags.headcount);
120
+ const mapped = [];
121
+ for (const bucket of buckets) {
122
+ const range = HEADCOUNT_BUCKETS[bucket];
123
+ if (!range) return `--headcount: unrecognized bucket "${bucket}"`;
124
+ mapped.push(range);
125
+ }
126
+ body["headcount"] = mapped;
127
+ }
87
128
  },
88
129
  posts(body, flags) {
89
130
  if (flags["sort-by"]) body["sort_by"] = flags["sort-by"];
90
- if (flags["date-posted"]) body["date_posted"] = flags["date-posted"];
131
+ if (flags["date-posted"]) body["date_posted"] = flags["date-posted"].replace(/-/g, "_");
91
132
  if (flags["content-type"]) body["content_type"] = flags["content-type"];
133
+ if (flags["posted-by-member"]) mergeNested(body, "posted_by", { member: splitCsv(flags["posted-by-member"]) });
134
+ if (flags["posted-by-company"]) mergeNested(body, "posted_by", { company: splitCsv(flags["posted-by-company"]) });
135
+ if (flags["posted-by-me"]) mergeNested(body, "posted_by", { me: true });
136
+ if (flags["mentioning-member"]) mergeNested(body, "mentioning", { member: splitCsv(flags["mentioning-member"]) });
137
+ if (flags["mentioning-company"]) mergeNested(body, "mentioning", { company: splitCsv(flags["mentioning-company"]) });
138
+ if (flags["author-industry"]) mergeNested(body, "author", { industry: splitCsv(flags["author-industry"]) });
139
+ if (flags["author-company"]) mergeNested(body, "author", { company: splitCsv(flags["author-company"]) });
140
+ if (flags["author-keywords"]) mergeNested(body, "author", { keywords: flags["author-keywords"] });
92
141
  },
93
142
  jobs(body, flags) {
94
- if (flags.location) body["location"] = splitCsv(flags.location);
143
+ if (flags.location) body["region"] = flags.location;
95
144
  if (flags.industry) body["industry"] = splitCsv(flags.industry);
96
145
  if (flags.seniority) body["seniority"] = splitCsv(flags.seniority);
97
146
  if (flags.function) body["function"] = splitCsv(flags.function);
98
147
  if (flags["job-type"]) body["job_type"] = splitCsv(flags["job-type"]);
99
148
  if (flags.company) body["company"] = splitCsv(flags.company);
100
149
  if (flags["sort-by"]) body["sort_by"] = flags["sort-by"];
150
+ if (flags["date-posted"] !== void 0 && flags["date-posted"] !== "") {
151
+ body["date_posted"] = Number(flags["date-posted"]);
152
+ }
101
153
  if (flags.region) body["region"] = flags.region;
154
+ if (flags.title) body["role"] = splitCsv(flags.title);
155
+ if (flags.presence) body["presence"] = splitCsv(flags.presence);
156
+ if (flags.benefits) body["benefits"] = splitCsv(flags.benefits);
157
+ if (flags.commitments) body["commitments"] = splitCsv(flags.commitments);
158
+ if (flags["has-verifications"]) body["has_verifications"] = true;
159
+ if (flags["under-10-applicants"]) body["under_10_applicants"] = true;
160
+ if (flags["in-your-network"]) body["in_your_network"] = true;
161
+ if (flags["fair-chance-employer"]) body["fair_chance_employer"] = true;
162
+ if (flags["location-within-area"] !== void 0) {
163
+ const raw = flags["location-within-area"];
164
+ const n = Number(raw);
165
+ if (raw.trim() === "" || !Number.isFinite(n)) {
166
+ return `--location-within-area: must be a number (miles)`;
167
+ }
168
+ body["location_within_area"] = n;
169
+ }
102
170
  }
103
171
  };
104
172
  async function buildSearchBody(kind, flags, readers) {
@@ -106,14 +174,25 @@ async function buildSearchBody(kind, flags, readers) {
106
174
  if ("error" in assembled) return assembled;
107
175
  const body = assembled.body;
108
176
  applyCommonSearchFlags(body, flags);
109
- NAMED_FLAG_MAPPERS[kind](body, flags);
177
+ const mapperError = NAMED_FLAG_MAPPERS[kind](body, flags);
178
+ if (mapperError) return { error: mapperError };
110
179
  return { body };
111
180
  }
112
181
  async function runSearchPeople(client, flags, out, readers = DEFAULT_FILTER_READERS) {
113
182
  rejectPreviewOnRead(flags.preview, out);
183
+ for (const f of PEOPLE_INVALID_FLAGS) {
184
+ if (flags[f]) {
185
+ out.stderr.write(
186
+ `error: --${f} is not valid for \`search people\` (classic LinkedIn search). Use \`search jobs\` or \`sales-nav search people\` for this filter.
187
+ `
188
+ );
189
+ process.exit(2);
190
+ }
191
+ }
114
192
  const accountId = requireAccount(flags.account, out);
115
193
  const ns = client.account(accountId);
116
194
  const outOpts = resolveOutputOpts(flags);
195
+ const verbose = flags.verbose ?? false;
117
196
  const all = flags.all ?? false;
118
197
  const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
119
198
  const assembled = await buildSearchBody("people", flags, readers);
@@ -128,13 +207,17 @@ async function runSearchPeople(client, flags, out, readers = DEFAULT_FILTER_READ
128
207
  const fn = (p) => ns.search.people(p);
129
208
  for await (const item of streamAll(fn, body, {
130
209
  maxPages,
131
- onTruncated: (msg) => out.stderr.write(msg + "\n")
210
+ // Write JSON truncation sentinel to stdout as the last NDJSON line
211
+ onTruncated: (pagesFetched, hasMore) => out.stdout.write(
212
+ JSON.stringify({ object: "stream_truncated", pages_fetched: pagesFetched, has_more: hasMore }) + "\n"
213
+ )
132
214
  })) {
133
- out.stdout.write(JSON.stringify(item) + "\n");
215
+ const projected = verbose ? item : slimSearchPeopleItem(item);
216
+ out.stdout.write(JSON.stringify(projected) + "\n");
134
217
  }
135
218
  } else {
136
219
  const result = await ns.search.people(body);
137
- renderSuccess(result, outOpts, out);
220
+ renderSuccess(result, { ...outOpts, slim: slimSearchPeople }, out);
138
221
  }
139
222
  } catch (err) {
140
223
  const { CurviateError } = await import("@curviate/sdk");
@@ -152,6 +235,7 @@ async function runSearchCompanies(client, flags, out, readers = DEFAULT_FILTER_R
152
235
  const accountId = requireAccount(flags.account, out);
153
236
  const ns = client.account(accountId);
154
237
  const outOpts = resolveOutputOpts(flags);
238
+ const verbose = flags.verbose ?? false;
155
239
  const all = flags.all ?? false;
156
240
  const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
157
241
  const assembled = await buildSearchBody("companies", flags, readers);
@@ -166,13 +250,16 @@ async function runSearchCompanies(client, flags, out, readers = DEFAULT_FILTER_R
166
250
  const fn = (p) => ns.search.companies(p);
167
251
  for await (const item of streamAll(fn, body, {
168
252
  maxPages,
169
- onTruncated: (msg) => out.stderr.write(msg + "\n")
253
+ onTruncated: (pagesFetched, hasMore) => out.stdout.write(
254
+ JSON.stringify({ object: "stream_truncated", pages_fetched: pagesFetched, has_more: hasMore }) + "\n"
255
+ )
170
256
  })) {
171
- out.stdout.write(JSON.stringify(item) + "\n");
257
+ const projected = verbose ? item : slimSearchCompaniesItem(item);
258
+ out.stdout.write(JSON.stringify(projected) + "\n");
172
259
  }
173
260
  } else {
174
261
  const result = await ns.search.companies(body);
175
- renderSuccess(result, outOpts, out);
262
+ renderSuccess(result, { ...outOpts, slim: slimSearchCompanies }, out);
176
263
  }
177
264
  } catch (err) {
178
265
  const { CurviateError } = await import("@curviate/sdk");
@@ -190,6 +277,7 @@ async function runSearchPosts(client, flags, out, readers = DEFAULT_FILTER_READE
190
277
  const accountId = requireAccount(flags.account, out);
191
278
  const ns = client.account(accountId);
192
279
  const outOpts = resolveOutputOpts(flags);
280
+ const verbose = flags.verbose ?? false;
193
281
  const all = flags.all ?? false;
194
282
  const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
195
283
  const assembled = await buildSearchBody("posts", flags, readers);
@@ -204,13 +292,16 @@ async function runSearchPosts(client, flags, out, readers = DEFAULT_FILTER_READE
204
292
  const fn = (p) => ns.search.posts(p);
205
293
  for await (const item of streamAll(fn, body, {
206
294
  maxPages,
207
- onTruncated: (msg) => out.stderr.write(msg + "\n")
295
+ onTruncated: (pagesFetched, hasMore) => out.stdout.write(
296
+ JSON.stringify({ object: "stream_truncated", pages_fetched: pagesFetched, has_more: hasMore }) + "\n"
297
+ )
208
298
  })) {
209
- out.stdout.write(JSON.stringify(item) + "\n");
299
+ const projected = verbose ? item : slimSearchPostsItem(item);
300
+ out.stdout.write(JSON.stringify(projected) + "\n");
210
301
  }
211
302
  } else {
212
303
  const result = await ns.search.posts(body);
213
- renderSuccess(result, outOpts, out);
304
+ renderSuccess(result, { ...outOpts, slim: slimSearchPosts }, out);
214
305
  }
215
306
  } catch (err) {
216
307
  const { CurviateError } = await import("@curviate/sdk");
@@ -228,6 +319,7 @@ async function runSearchJobs(client, flags, out, readers = DEFAULT_FILTER_READER
228
319
  const accountId = requireAccount(flags.account, out);
229
320
  const ns = client.account(accountId);
230
321
  const outOpts = resolveOutputOpts(flags);
322
+ const verbose = flags.verbose ?? false;
231
323
  const all = flags.all ?? false;
232
324
  const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
233
325
  const assembled = await buildSearchBody("jobs", flags, readers);
@@ -242,13 +334,16 @@ async function runSearchJobs(client, flags, out, readers = DEFAULT_FILTER_READER
242
334
  const fn = (p) => ns.search.jobs(p);
243
335
  for await (const item of streamAll(fn, body, {
244
336
  maxPages,
245
- onTruncated: (msg) => out.stderr.write(msg + "\n")
337
+ onTruncated: (pagesFetched, hasMore) => out.stdout.write(
338
+ JSON.stringify({ object: "stream_truncated", pages_fetched: pagesFetched, has_more: hasMore }) + "\n"
339
+ )
246
340
  })) {
247
- out.stdout.write(JSON.stringify(item) + "\n");
341
+ const projected = verbose ? item : slimSearchJobsItem(item);
342
+ out.stdout.write(JSON.stringify(projected) + "\n");
248
343
  }
249
344
  } else {
250
345
  const result = await ns.search.jobs(body);
251
- renderSuccess(result, outOpts, out);
346
+ renderSuccess(result, { ...outOpts, slim: slimSearchJobs }, out);
252
347
  }
253
348
  } catch (err) {
254
349
  const { CurviateError } = await import("@curviate/sdk");
@@ -286,7 +381,7 @@ async function runSearchParameters(client, flags, out) {
286
381
  }
287
382
  }
288
383
  var searchPeopleCommand = defineCommand({
289
- meta: { name: "people", description: "Search LinkedIn members with structured filters." },
384
+ meta: { name: "people", description: "Search members with structured filters." },
290
385
  args: {
291
386
  ...GLOBAL_FLAGS,
292
387
  keywords: { type: "string", description: "Full-text keyword search." },
@@ -298,8 +393,11 @@ var searchPeopleCommand = defineCommand({
298
393
  "past-company": { type: "string", description: "Past company ids (comma-separated)." },
299
394
  school: { type: "string", description: "School ids (comma-separated)." },
300
395
  "network-distance": { type: "string", description: "Network distance, 1-3 (comma-separated)." },
301
- "connections-of": { type: "string", description: "Member id whose connections to search." },
302
- "followers-of": { type: "string", description: "Member id whose followers to search." }
396
+ "connections-of": { type: "string", description: 'member id(s), comma-separated (resolve: search parameters --type CONNECTIONS --keywords "<name>")' },
397
+ "followers-of": { type: "string", description: 'member id(s), comma-separated (resolve: search parameters --type PEOPLE --keywords "<name>")' },
398
+ // People-specific filter flags
399
+ title: { type: "string", description: "Job title keyword filter (maps to advanced_keywords.title)." },
400
+ "profile-language": { type: "string", description: "Profile language codes (comma-separated, e.g. en,de)." }
303
401
  },
304
402
  async run({ args }) {
305
403
  const flags = args;
@@ -320,7 +418,7 @@ var searchPeopleCommand = defineCommand({
320
418
  }
321
419
  });
322
420
  var searchCompaniesCommand = defineCommand({
323
- meta: { name: "companies", description: "Search LinkedIn companies." },
421
+ meta: { name: "companies", description: "Search companies." },
324
422
  args: {
325
423
  ...GLOBAL_FLAGS,
326
424
  keywords: { type: "string", description: "Full-text keyword search." },
@@ -328,7 +426,12 @@ var searchCompaniesCommand = defineCommand({
328
426
  ...FILTER_FLAGS,
329
427
  industry: { type: "string", description: "Industry ids (comma-separated)." },
330
428
  location: { type: "string", description: "Location ids (comma-separated)." },
331
- "network-distance": { type: "string", description: "Network distance, 1-3 (comma-separated)." }
429
+ "network-distance": { type: "string", description: "Network distance, 1-3 (comma-separated)." },
430
+ "has-job-offers": { type: "boolean", description: "only companies with active job listings" },
431
+ headcount: {
432
+ type: "string",
433
+ description: "company size, comma-separated: 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10001+ (10001+ not yet supported)"
434
+ }
332
435
  },
333
436
  async run({ args }) {
334
437
  const flags = args;
@@ -349,15 +452,23 @@ var searchCompaniesCommand = defineCommand({
349
452
  }
350
453
  });
351
454
  var searchPostsCommand = defineCommand({
352
- meta: { name: "posts", description: "Search LinkedIn posts." },
455
+ meta: { name: "posts", description: "Search posts." },
353
456
  args: {
354
457
  ...GLOBAL_FLAGS,
355
458
  keywords: { type: "string", description: "Full-text keyword search." },
356
459
  url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." },
357
460
  ...FILTER_FLAGS,
358
461
  "sort-by": { type: "string", description: "Sort order (e.g. relevance, date)." },
359
- "date-posted": { type: "string", description: "Date-posted window (e.g. past-day, past-week)." },
360
- "content-type": { type: "string", description: "Content type (e.g. videos, images, jobs)." }
462
+ "date-posted": { type: "string", description: "time window: past_day, past_week, or past_month (hyphens also accepted: past-day, past-week, past-month)" },
463
+ "content-type": { type: "string", description: "content type: videos, images, live_videos, collaborative_articles, documents" },
464
+ "posted-by-member": { type: "string", description: "member id(s), comma-separated (resolve: search parameters --type PEOPLE); merges into posted_by" },
465
+ "posted-by-company": { type: "string", description: "company id(s), comma-separated (resolve: search parameters --type COMPANY); merges into posted_by" },
466
+ "posted-by-me": { type: "boolean", description: "only posts authored by you; merges into posted_by" },
467
+ "mentioning-member": { type: "string", description: "member id(s) mentioned in the post, comma-separated (resolve: search parameters --type PEOPLE); merges into mentioning" },
468
+ "mentioning-company": { type: "string", description: "company id(s) mentioned in the post, comma-separated (resolve: search parameters --type COMPANY); merges into mentioning" },
469
+ "author-industry": { type: "string", description: "author's industry id(s), comma-separated (resolve: search parameters --type INDUSTRY); merges into author" },
470
+ "author-company": { type: "string", description: "author's company id(s), comma-separated (resolve: search parameters --type COMPANY); merges into author" },
471
+ "author-keywords": { type: "string", description: "author keyword filter (free text); merges into author" }
361
472
  },
362
473
  async run({ args }) {
363
474
  const flags = args;
@@ -378,20 +489,37 @@ var searchPostsCommand = defineCommand({
378
489
  }
379
490
  });
380
491
  var searchJobsCommand = defineCommand({
381
- meta: { name: "jobs", description: "Search LinkedIn jobs." },
492
+ meta: { name: "jobs", description: "Search jobs." },
382
493
  args: {
383
494
  ...GLOBAL_FLAGS,
384
495
  keywords: { type: "string", description: "Full-text keyword search." },
385
496
  url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." },
386
497
  ...FILTER_FLAGS,
387
- location: { type: "string", description: "Location ids (comma-separated)." },
498
+ // On jobs, --location maps to the geo region filter (not a location array — different API shape for jobs vs people)
499
+ location: { type: "string", description: "geo region id (single id; resolve via search parameters --type LOCATION); maps to region filter" },
388
500
  industry: { type: "string", description: "Industry ids (comma-separated)." },
389
- seniority: { type: "string", description: "Seniority ids (comma-separated)." },
501
+ seniority: { type: "string", description: "seniority level, closed enum: executive|director|mid_senior|associate|entry|intern (comma-separated)" },
390
502
  function: { type: "string", description: "Job function ids (comma-separated)." },
391
- "job-type": { type: "string", description: "Job type ids, e.g. F,P (comma-separated)." },
503
+ "job-type": { type: "string", description: "job type, independent 7-value enum: full_time|part_time|contract|temporary|volunteer|internship|other (comma-separated)" },
392
504
  company: { type: "string", description: "Company ids (comma-separated)." },
393
505
  "sort-by": { type: "string", description: "Sort order (e.g. relevance, recent)." },
394
- region: { type: "string", description: "Region id." }
506
+ "date-posted": { type: "string", description: "maximum job age in days (a number \u2014 e.g. 7, 14, 30; not an enum string)" },
507
+ region: { type: "string", description: "alias for --location (same body field: region)" },
508
+ title: {
509
+ type: "string",
510
+ description: "job title id(s), comma-separated (resolve: search parameters --type JOB_TITLE); ID-based targeting \u2014 unlike search people --title, which is free-text"
511
+ },
512
+ presence: { type: "string", description: "work presence, comma-separated: on_site, hybrid, remote" },
513
+ benefits: { type: "string", description: "benefit ids, comma-separated" },
514
+ commitments: { type: "string", description: "commitment/employment types, comma-separated" },
515
+ "has-verifications": { type: "boolean", description: "only jobs with verified details" },
516
+ "under-10-applicants": { type: "boolean", description: "only jobs with fewer than 10 applicants" },
517
+ "in-your-network": { type: "boolean", description: "only jobs where you have a connection at the company" },
518
+ "fair-chance-employer": { type: "boolean", description: "only fair-chance employer jobs" },
519
+ "location-within-area": {
520
+ type: "string",
521
+ description: "radius in miles from --location (requires --location; numeric only)"
522
+ }
395
523
  },
396
524
  async run({ args }) {
397
525
  const flags = args;
@@ -415,7 +543,11 @@ var searchParametersCommand = defineCommand({
415
543
  meta: { name: "parameters", description: "Resolve human-readable terms to opaque filter IDs." },
416
544
  args: {
417
545
  ...GLOBAL_FLAGS,
418
- type: { type: "string", description: "Parameter type (e.g. LOCATION, COMPANY, INDUSTRY).", required: true },
546
+ type: {
547
+ type: "string",
548
+ description: "Parameter type: LOCATION, PEOPLE, CONNECTIONS, COMPANY, SCHOOL, INDUSTRY, SERVICE, JOB_FUNCTION, JOB_TITLE, EMPLOYMENT_TYPE, SKILL.",
549
+ required: true
550
+ },
419
551
  keywords: { type: "string", description: "Human term to resolve (not required for EMPLOYMENT_TYPE)." }
420
552
  },
421
553
  async run({ args }) {
@@ -437,7 +569,7 @@ var searchParametersCommand = defineCommand({
437
569
  }
438
570
  });
439
571
  var searchCommand = defineCommand({
440
- meta: { name: "search", description: "Search LinkedIn members, companies, posts, and jobs." },
572
+ meta: { name: "search", description: "Search people, companies, posts, and jobs." },
441
573
  subCommands: {
442
574
  people: searchPeopleCommand,
443
575
  companies: searchCompaniesCommand,
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-R3VLWLVV.js";
5
5
  import {
6
6
  streamAll
7
- } from "./chunk-SND3NHCT.js";
7
+ } from "./chunk-GXTZION6.js";
8
8
  import {
9
9
  createClient,
10
10
  renderError,
@@ -110,7 +110,8 @@ async function runWebhookList(client, flags, out) {
110
110
  const fn = (p) => client.webhooks.list(p);
111
111
  for await (const item of streamAll(fn, params, {
112
112
  maxPages,
113
- onTruncated: (msg) => out.stderr.write(msg + "\n")
113
+ onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
114
+ `)
114
115
  })) {
115
116
  out.stdout.write(JSON.stringify(item) + "\n");
116
117
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curviate/cli",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "private": false,
5
5
  "description": "Official command-line interface for the Curviate API.",
6
6
  "license": "MIT",
@@ -40,7 +40,7 @@
40
40
  "clean": "rm -rf dist *.tsbuildinfo"
41
41
  },
42
42
  "dependencies": {
43
- "@curviate/sdk": "^0.4.0",
43
+ "@curviate/sdk": "^0.5.0",
44
44
  "citty": "^0.1.6"
45
45
  },
46
46
  "devDependencies": {