@curviate/cli 0.5.0 → 0.6.1

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,31 @@ 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.6.0] - 2026-06-30
12
+
13
+ ### Added
14
+
15
+ - `inbox list --unread` — filter the inbox to chats with unread messages.
16
+ - `messages` now accepts `--before` and `--after` to page a conversation by
17
+ timestamp window.
18
+ - `sync-chat --wait` — poll until a chat sync completes instead of returning
19
+ immediately.
20
+ - `message new --to` and `message inmail --to` now resolve a **LinkedIn profile
21
+ URL or vanity slug** (e.g. `linkedin.com/in/<slug>`) to the recipient, in
22
+ addition to provider ids and member URNs.
23
+ - Thread-URL `chat_id` normalization — a pasted conversation URL is normalized to
24
+ the underlying chat id wherever a `chat_id` is accepted.
25
+ - Write commands that take a TEXT positional accept `-` to read the value from
26
+ stdin (pipe message bodies in).
27
+ - `connect`: slim default projection + write-flag suppression + help text
28
+ (Invites-AX co-release).
29
+
30
+ ### Changed
31
+
32
+ - Pagination flags are suppressed from the help output of non-list commands.
33
+ - Updated `@curviate/sdk` dependency to `^0.4.0` (regenerated types:
34
+ `primary_locale` on profile, account-sync `status` field).
35
+
11
36
  ## [0.5.0] - 2026-06-29
12
37
 
13
38
  ### Added
@@ -4,17 +4,17 @@ 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,
11
11
  renderSuccess,
12
12
  renderUnexpectedError,
13
13
  resolveEffectiveConfig
14
- } from "./chunk-U6ACUNLU.js";
14
+ } from "./chunk-47SYFQRF.js";
15
15
  import {
16
16
  GLOBAL_FLAGS
17
- } from "./chunk-52RZLSWP.js";
17
+ } from "./chunk-TDYIQHQX.js";
18
18
 
19
19
  // src/commands/account.ts
20
20
  import { defineCommand } from "citty";
@@ -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
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  readConfig
4
- } from "./chunk-52RZLSWP.js";
4
+ } from "./chunk-TDYIQHQX.js";
5
5
 
6
6
  // src/lib/resolve.ts
7
7
  var DEFAULT_BASE_URL = "https://api.curviate.com";
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/lib/stdin.ts
4
+ var STDIN_SENTINEL = "__curviate_stdin__";
5
+ async function defaultReadStdin() {
6
+ return new Promise((resolve, reject) => {
7
+ const chunks = [];
8
+ process.stdin.on("data", (chunk) => {
9
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
10
+ });
11
+ process.stdin.on("end", () => {
12
+ const full = Buffer.concat(chunks).toString("utf8");
13
+ resolve(full.replace(/\n+$/, ""));
14
+ });
15
+ process.stdin.on("error", reject);
16
+ });
17
+ }
18
+ async function resolveTextOrStdin(rawText, out, readStdin) {
19
+ if (rawText !== "-" && rawText !== STDIN_SENTINEL) return rawText;
20
+ const reader = readStdin ?? defaultReadStdin;
21
+ const text = await reader();
22
+ if (!text) {
23
+ out.stderr.write("error: stdin: empty input\n");
24
+ process.exit(2);
25
+ }
26
+ return text;
27
+ }
28
+
29
+ export {
30
+ STDIN_SENTINEL,
31
+ resolveTextOrStdin
32
+ };
@@ -0,0 +1,221 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/lib/slim.ts
4
+ function synthesizeCurrentPosition(workExperience) {
5
+ if (!Array.isArray(workExperience) || workExperience.length === 0) {
6
+ return null;
7
+ }
8
+ const entry = workExperience[0];
9
+ return {
10
+ title: entry["position"] ?? null,
11
+ company_name: entry["company"] ?? null,
12
+ company_id: null,
13
+ is_current: entry["end"] == null
14
+ };
15
+ }
16
+ function synthesizeHeadquarters(locations) {
17
+ if (!Array.isArray(locations)) return null;
18
+ const hq = locations.find(
19
+ (l) => l["is_headquarter"] === true
20
+ );
21
+ if (!hq) return null;
22
+ return {
23
+ city: hq["city"] ?? null,
24
+ country: hq["country"] ?? null,
25
+ area: hq["area"] ?? null
26
+ };
27
+ }
28
+ function slimProfileMe(data) {
29
+ const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
30
+ const rawOrgs = Array.isArray(d["organizations"]) ? d["organizations"] : [];
31
+ const organizations = rawOrgs.map((org) => ({
32
+ id: org["id"] ?? null,
33
+ mailbox_id: org["mailbox_id"] ?? null,
34
+ name: org["name"] ?? null
35
+ }));
36
+ const rawWE = Array.isArray(d["work_experience"]) ? d["work_experience"] : [];
37
+ const currentPosition = synthesizeCurrentPosition(rawWE);
38
+ return {
39
+ provider_id: d["provider_id"] ?? null,
40
+ first_name: d["first_name"] ?? null,
41
+ last_name: d["last_name"] ?? null,
42
+ public_identifier: d["public_identifier"] ?? null,
43
+ location: d["location"] ?? null,
44
+ email: d["email"] ?? null,
45
+ occupation: d["occupation"] ?? null,
46
+ is_premium: d["is_premium"] ?? null,
47
+ organizations,
48
+ current_position: currentPosition
49
+ };
50
+ }
51
+ function slimProfile(data) {
52
+ const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
53
+ const rawWE = Array.isArray(d["work_experience"]) ? d["work_experience"] : [];
54
+ const currentPosition = synthesizeCurrentPosition(rawWE);
55
+ return {
56
+ provider_id: d["provider_id"] ?? null,
57
+ first_name: d["first_name"] ?? null,
58
+ last_name: d["last_name"] ?? null,
59
+ headline: d["headline"] ?? null,
60
+ location: d["location"] ?? null,
61
+ occupation: d["occupation"] ?? null,
62
+ network_distance: d["network_distance"] ?? null,
63
+ public_identifier: d["public_identifier"] ?? null,
64
+ current_position: currentPosition
65
+ };
66
+ }
67
+ function slimInviteSentItem(item) {
68
+ return {
69
+ id: item["id"] ?? null,
70
+ invited_user: item["invited_user"] ?? null,
71
+ invited_user_id: item["invited_user_id"] ?? null,
72
+ invited_user_public_id: item["invited_user_public_id"] ?? null,
73
+ invited_user_description: item["invited_user_description"] ?? null,
74
+ date: item["date"] ?? null,
75
+ parsed_datetime: item["parsed_datetime"] ?? null,
76
+ invitation_text: item["invitation_text"] ?? null
77
+ };
78
+ }
79
+ function slimInviteSent(data) {
80
+ const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
81
+ const items = Array.isArray(d["items"]) ? d["items"].map(slimInviteSentItem) : [];
82
+ return {
83
+ object: d["object"] ?? null,
84
+ items,
85
+ cursor: d["cursor"] ?? null
86
+ };
87
+ }
88
+ function slimInviteReceivedItem(item) {
89
+ const rawSpecifics = item["specifics"] !== null && item["specifics"] !== void 0 && typeof item["specifics"] === "object" ? item["specifics"] : null;
90
+ const specifics = rawSpecifics !== null ? { shared_secret: rawSpecifics["shared_secret"] ?? null } : null;
91
+ return {
92
+ id: item["id"] ?? null,
93
+ inviter: item["inviter"] ?? null,
94
+ date: item["date"] ?? null,
95
+ parsed_datetime: item["parsed_datetime"] ?? null,
96
+ invitation_text: item["invitation_text"] ?? null,
97
+ specifics
98
+ };
99
+ }
100
+ function slimInviteReceived(data) {
101
+ const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
102
+ const items = Array.isArray(d["items"]) ? d["items"].map(slimInviteReceivedItem) : [];
103
+ return {
104
+ object: d["object"] ?? null,
105
+ items,
106
+ cursor: d["cursor"] ?? null
107
+ };
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
+ return {
143
+ job_urn: item["job_urn"] ?? null,
144
+ title: item["title"] ?? null,
145
+ location: item["location"] ?? null,
146
+ company_name: item["company_name"] ?? null,
147
+ posted_at: item["posted_at"] ?? null,
148
+ easy_apply: item["easy_apply"] ?? null
149
+ };
150
+ }
151
+ function slimSearchJobs(data) {
152
+ const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
153
+ const items = Array.isArray(d["items"]) ? d["items"].map(slimSearchJobsItem) : [];
154
+ return { ...d, items };
155
+ }
156
+ function slimSearchPostsItem(item) {
157
+ const rawAuthor = item["author"] !== null && item["author"] !== void 0 && typeof item["author"] === "object" ? item["author"] : null;
158
+ const author = rawAuthor !== null ? { name: rawAuthor["name"] ?? null } : null;
159
+ const rawText = item["text"];
160
+ let text;
161
+ if (rawText === null || rawText === void 0) {
162
+ text = null;
163
+ } else {
164
+ const s = String(rawText);
165
+ text = s.length > 200 ? s.slice(0, 200) : s;
166
+ }
167
+ return {
168
+ post_urn: item["post_urn"] ?? null,
169
+ posted_at: item["posted_at"] ?? null,
170
+ author,
171
+ text,
172
+ reaction_count: item["reaction_count"] ?? null,
173
+ comment_count: item["comment_count"] ?? null
174
+ };
175
+ }
176
+ function slimSearchPosts(data) {
177
+ const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
178
+ const items = Array.isArray(d["items"]) ? d["items"].map(slimSearchPostsItem) : [];
179
+ return { ...d, items };
180
+ }
181
+ function slimCompany(data) {
182
+ const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
183
+ const rawMessaging = d["messaging"] !== null && d["messaging"] !== void 0 && typeof d["messaging"] === "object" ? d["messaging"] : null;
184
+ const messaging = {
185
+ is_enabled: rawMessaging?.["is_enabled"] ?? false
186
+ };
187
+ const rawLocations = Array.isArray(d["locations"]) ? d["locations"] : [];
188
+ const headquarters = synthesizeHeadquarters(rawLocations);
189
+ return {
190
+ id: d["id"] ?? null,
191
+ name: d["name"] ?? null,
192
+ public_identifier: d["public_identifier"] ?? null,
193
+ profile_url: d["profile_url"] ?? null,
194
+ industry: d["industry"] ?? null,
195
+ employee_count: d["employee_count"] ?? null,
196
+ employee_count_range: d["employee_count_range"] ?? null,
197
+ website: d["website"] ?? null,
198
+ foundation_date: d["foundation_date"] ?? null,
199
+ messaging,
200
+ headquarters,
201
+ followers_count: d["followers_count"] ?? null
202
+ };
203
+ }
204
+
205
+ export {
206
+ slimProfileMe,
207
+ slimProfile,
208
+ slimInviteSentItem,
209
+ slimInviteSent,
210
+ slimInviteReceivedItem,
211
+ slimInviteReceived,
212
+ slimSearchPeopleItem,
213
+ slimSearchPeople,
214
+ slimSearchCompaniesItem,
215
+ slimSearchCompanies,
216
+ slimSearchJobsItem,
217
+ slimSearchJobs,
218
+ slimSearchPostsItem,
219
+ slimSearchPosts,
220
+ slimCompany
221
+ };
@@ -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
  }
@@ -27,7 +27,14 @@ function resolveIdentifier(raw) {
27
27
  function stripTrailingSlash(s) {
28
28
  return s.endsWith("/") ? s.slice(0, -1) : s;
29
29
  }
30
+ var MESSAGING_THREAD_URL_RE = /messaging\/thread\/([^/?]+)/;
31
+ function normalizeChatId(raw) {
32
+ const match = MESSAGING_THREAD_URL_RE.exec(raw);
33
+ if (match?.[1]) return match[1];
34
+ return raw;
35
+ }
30
36
 
31
37
  export {
32
- resolveIdentifier
38
+ resolveIdentifier,
39
+ normalizeChatId
33
40
  };
@@ -197,6 +197,17 @@ var WRITE_FLAGS = {
197
197
  preview: GLOBAL_FLAGS.preview,
198
198
  verbose: GLOBAL_FLAGS.verbose
199
199
  };
200
+ var READ_SINGLE_FLAGS = {
201
+ "api-key": GLOBAL_FLAGS["api-key"],
202
+ profile: GLOBAL_FLAGS.profile,
203
+ account: GLOBAL_FLAGS.account,
204
+ "base-url": GLOBAL_FLAGS["base-url"],
205
+ timeout: GLOBAL_FLAGS.timeout,
206
+ json: GLOBAL_FLAGS.json,
207
+ fields: GLOBAL_FLAGS.fields,
208
+ preview: GLOBAL_FLAGS.preview,
209
+ verbose: GLOBAL_FLAGS.verbose
210
+ };
200
211
 
201
212
  export {
202
213
  getConfigPath,
@@ -207,5 +218,6 @@ export {
207
218
  removeProfile,
208
219
  updateProfileField,
209
220
  GLOBAL_FLAGS,
210
- WRITE_FLAGS
221
+ WRITE_FLAGS,
222
+ READ_SINGLE_FLAGS
211
223
  };
package/dist/cli.js CHANGED
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ STDIN_SENTINEL
4
+ } from "./chunk-CHFKVAEI.js";
2
5
 
3
6
  // src/cli.ts
4
7
  import { defineCommand } from "citty";
@@ -108,8 +111,9 @@ async function dispatch(root, rawArgs) {
108
111
  if (unknown !== null) {
109
112
  usageError(`unknown flag \`${unknown}\`.`);
110
113
  }
114
+ const processedLeafArgs = leafArgs.map((a) => a === "-" ? STDIN_SENTINEL : a);
111
115
  const leafToRun = { ...leaf, subCommands: void 0 };
112
- await runCommand(leafToRun, { rawArgs: leafArgs });
116
+ await runCommand(leafToRun, { rawArgs: processedLeafArgs });
113
117
  } catch (err) {
114
118
  const message = err instanceof Error ? err.message : String(err);
115
119
  const code = err?.code;
@@ -134,22 +138,22 @@ var main = defineCommand({
134
138
  // Subcommand registry — names and descriptions are static for help rendering;
135
139
  // the handler implementation is loaded lazily on first invocation.
136
140
  subCommands: {
137
- login: () => import("./login-UJQGIP7S.js").then((m) => m.loginCommand),
138
- config: () => import("./config-6PNGYL5E.js").then((m) => m.configCommand),
141
+ login: () => import("./login-POKHNDYX.js").then((m) => m.loginCommand),
142
+ config: () => import("./config-2GBLD4GN.js").then((m) => m.configCommand),
139
143
  // ---------------------------------------------------------------------------
140
144
  // Noun groups — lazy-loaded on first invocation.
141
145
  // ---------------------------------------------------------------------------
142
- profile: () => import("./profile-CUVVESMY.js").then((m) => m.profileCommand),
143
- company: () => import("./company-4MUABENR.js").then((m) => m.companyCommand),
144
- connect: () => import("./connect-ZXD7P5CA.js").then((m) => m.connectCommand),
145
- search: () => import("./search-M4WK3PDC.js").then((m) => m.searchCommand),
146
- inbox: () => import("./inbox-ME4TXGFV.js").then((m) => m.inboxCommand),
147
- message: () => import("./message-O7QN2L6Q.js").then((m) => m.messageCommand),
148
- post: () => import("./post-VDQF23WS.js").then((m) => m.postCommand),
149
- account: () => import("./account-47TRPUKL.js").then((m) => m.accountCommand),
150
- webhook: () => import("./webhook-2SSNW25K.js").then((m) => m.webhookCommand),
151
- "sales-nav": () => import("./sales-nav-UL2H6J6V.js").then((m) => m.salesNavCommand),
152
- recruiter: () => import("./recruiter-QKJKOWD7.js").then((m) => m.recruiterCommand)
146
+ profile: () => import("./profile-4IPEB7MN.js").then((m) => m.profileCommand),
147
+ company: () => import("./company-WH2ZETTP.js").then((m) => m.companyCommand),
148
+ connect: () => import("./connect-YUJ2T5CN.js").then((m) => m.connectCommand),
149
+ search: () => import("./search-ONCNS43D.js").then((m) => m.searchCommand),
150
+ inbox: () => import("./inbox-YV6GPRG6.js").then((m) => m.inboxCommand),
151
+ message: () => import("./message-YRMLMHK7.js").then((m) => m.messageCommand),
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)
153
157
  },
154
158
  async run() {
155
159
  const { runMain } = await import("citty");
@@ -1,20 +1,20 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- slimCompany
4
- } from "./chunk-5NS2G4WQ.js";
5
2
  import {
6
3
  resolveIdentifier
7
- } from "./chunk-BNUTM6KD.js";
4
+ } from "./chunk-SZB3CFRZ.js";
5
+ import {
6
+ slimCompany
7
+ } from "./chunk-FX6VBI43.js";
8
8
  import {
9
9
  createClient,
10
10
  renderError,
11
11
  renderSuccess,
12
12
  renderUnexpectedError,
13
13
  resolveEffectiveConfig
14
- } from "./chunk-U6ACUNLU.js";
14
+ } from "./chunk-47SYFQRF.js";
15
15
  import {
16
16
  GLOBAL_FLAGS
17
- } from "./chunk-52RZLSWP.js";
17
+ } from "./chunk-TDYIQHQX.js";
18
18
 
19
19
  // src/commands/company.ts
20
20
  import { defineCommand } from "citty";
@@ -7,7 +7,7 @@ import {
7
7
  renameProfile,
8
8
  setActiveProfile,
9
9
  updateProfileField
10
- } from "./chunk-52RZLSWP.js";
10
+ } from "./chunk-TDYIQHQX.js";
11
11
 
12
12
  // src/commands/config.ts
13
13
  import { defineCommand } from "citty";
@@ -4,20 +4,27 @@ import {
4
4
  } from "./chunk-R3VLWLVV.js";
5
5
  import {
6
6
  resolveIdentifier
7
- } from "./chunk-BNUTM6KD.js";
7
+ } from "./chunk-SZB3CFRZ.js";
8
8
  import {
9
9
  streamAll
10
- } from "./chunk-SND3NHCT.js";
10
+ } from "./chunk-GXTZION6.js";
11
+ import {
12
+ slimInviteReceived,
13
+ slimInviteReceivedItem,
14
+ slimInviteSent,
15
+ slimInviteSentItem
16
+ } from "./chunk-FX6VBI43.js";
11
17
  import {
12
18
  createClient,
13
19
  renderError,
14
20
  renderSuccess,
15
21
  renderUnexpectedError,
16
22
  resolveEffectiveConfig
17
- } from "./chunk-U6ACUNLU.js";
23
+ } from "./chunk-47SYFQRF.js";
18
24
  import {
19
- GLOBAL_FLAGS
20
- } from "./chunk-52RZLSWP.js";
25
+ GLOBAL_FLAGS,
26
+ WRITE_FLAGS
27
+ } from "./chunk-TDYIQHQX.js";
21
28
 
22
29
  // src/commands/connect.ts
23
30
  import { defineCommand } from "citty";
@@ -44,7 +51,8 @@ function resolveOutputOpts(flags) {
44
51
  return {
45
52
  json: (flags.json ?? false) || !process.stdout.isTTY,
46
53
  isTTY: process.stdout.isTTY ?? false,
47
- fields: flags.fields
54
+ fields: flags.fields,
55
+ verbose: flags.verbose ?? false
48
56
  };
49
57
  }
50
58
  async function runConnectSend(client, flags, out) {
@@ -96,13 +104,15 @@ async function runConnectSent(client, flags, out) {
96
104
  const fn = (p) => ns.invites.listSent(p);
97
105
  for await (const item of streamAll(fn, params, {
98
106
  maxPages,
99
- 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
+ `)
100
109
  })) {
101
- out.stdout.write(JSON.stringify(item) + "\n");
110
+ const projected = !flags.verbose ? slimInviteSentItem(item) : item;
111
+ out.stdout.write(JSON.stringify(projected) + "\n");
102
112
  }
103
113
  } else {
104
114
  const result = await ns.invites.listSent(params);
105
- renderSuccess(result, outOpts, out);
115
+ renderSuccess(result, { ...outOpts, slim: slimInviteSent }, out);
106
116
  }
107
117
  } catch (err) {
108
118
  const { CurviateError } = await import("@curviate/sdk");
@@ -132,13 +142,15 @@ async function runConnectReceived(client, flags, out) {
132
142
  const fn = (p) => ns.invites.listReceived(p);
133
143
  for await (const item of streamAll(fn, params, {
134
144
  maxPages,
135
- 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
+ `)
136
147
  })) {
137
- out.stdout.write(JSON.stringify(item) + "\n");
148
+ const projected = !flags.verbose ? slimInviteReceivedItem(item) : item;
149
+ out.stdout.write(JSON.stringify(projected) + "\n");
138
150
  }
139
151
  } else {
140
152
  const result = await ns.invites.listReceived(params);
141
- renderSuccess(result, outOpts, out);
153
+ renderSuccess(result, { ...outOpts, slim: slimInviteReceived }, out);
142
154
  }
143
155
  } catch (err) {
144
156
  const { CurviateError } = await import("@curviate/sdk");
@@ -219,7 +231,10 @@ async function runConnectCancel(client, flags, out) {
219
231
  }
220
232
  }
221
233
  var connectSentCommand = defineCommand({
222
- meta: { name: "sent", description: "List sent connection invitations." },
234
+ meta: {
235
+ name: "sent",
236
+ description: "Returns pending sent invitations only \u2014 accepted and declined invitations are not returned (LinkedIn API limitation). Use `id` with `connect cancel`; use `invited_user_public_id` or `invited_user_id` with `curviate profile`. `parsed_datetime` is approximate \u2014 derived from LinkedIn's relative date label; invitations sharing a label get the same computed time. No total count is available; use `connect sent --all` and count client-side."
237
+ },
223
238
  args: { ...GLOBAL_FLAGS },
224
239
  async run({ args }) {
225
240
  const flags = args;
@@ -242,7 +257,7 @@ var connectSentCommand = defineCommand({
242
257
  var connectReceivedCommand = defineCommand({
243
258
  meta: {
244
259
  name: "received",
245
- description: "List received connection invitations. Each item carries a shared_secret \u2014 pass it to `connect respond --shared-secret`."
260
+ description: "Returns pending received invitations only \u2014 already-handled invitations are not returned. The `inviter.*` fields identify who sent the request. `specifics.shared_secret` is required for `connect respond`."
246
261
  },
247
262
  args: { ...GLOBAL_FLAGS },
248
263
  async run({ args }) {
@@ -266,12 +281,15 @@ var connectReceivedCommand = defineCommand({
266
281
  var connectRespondCommand = defineCommand({
267
282
  meta: { name: "respond", description: "Accept or decline a received invitation." },
268
283
  args: {
269
- ...GLOBAL_FLAGS,
270
- id: { type: "positional", description: "Invitation id to respond to." },
284
+ ...WRITE_FLAGS,
285
+ id: {
286
+ type: "positional",
287
+ description: "Invitation id to respond to \u2014 use the `id` field from `connect received`."
288
+ },
271
289
  action: { type: "string", description: "Response action: accept or decline.", required: true },
272
290
  "shared-secret": {
273
291
  type: "string",
274
- description: "Per-invitation shared secret \u2014 read it from `connect received`.",
292
+ description: "Per-invitation shared secret \u2014 use `specifics.shared_secret` from the same `connect received` item.",
275
293
  required: true
276
294
  }
277
295
  },
@@ -296,7 +314,7 @@ var connectRespondCommand = defineCommand({
296
314
  var connectCancelCommand = defineCommand({
297
315
  meta: { name: "cancel", description: "Cancel a sent invitation." },
298
316
  args: {
299
- ...GLOBAL_FLAGS,
317
+ ...WRITE_FLAGS,
300
318
  id: { type: "positional", description: "Invitation id to cancel." }
301
319
  },
302
320
  async run({ args }) {
@@ -318,11 +336,21 @@ var connectCancelCommand = defineCommand({
318
336
  }
319
337
  });
320
338
  var connectCommand = defineCommand({
321
- meta: { name: "connect", description: "Send or manage connection invitations." },
339
+ meta: {
340
+ name: "connect",
341
+ description: "Send or manage connection invitations. Connection requests may take 10\u201330 seconds to appear in the recipient's received list (LinkedIn propagation delay)."
342
+ },
322
343
  args: {
323
- ...GLOBAL_FLAGS,
324
- id: { type: "positional", description: "Member identifier (URL, slug, or URN).", required: false },
325
- note: { type: "string", description: "Optional invitation note (\u2264300 characters)." }
344
+ ...WRITE_FLAGS,
345
+ id: {
346
+ type: "positional",
347
+ description: "Recipient's LinkedIn URL, public slug, or provider_id (ACoAAA\u2026 from `curviate profile`). LinkedIn URN (`urn:li:member:N`) also accepted but the numeric member ID is not exposed by this API.",
348
+ required: false
349
+ },
350
+ note: {
351
+ type: "string",
352
+ description: "Personalized message shown to the recipient alongside the connection request (\u2264300 chars; LinkedIn cap). Omit to send a generic note. Personalized messages increase acceptance rates."
353
+ }
326
354
  },
327
355
  subCommands: {
328
356
  sent: connectSentCommand,