@curviate/cli 0.5.0 → 0.6.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 +25 -0
- package/dist/{account-47TRPUKL.js → account-ZWBNNQKQ.js} +2 -2
- package/dist/{chunk-U6ACUNLU.js → chunk-47SYFQRF.js} +1 -1
- package/dist/{chunk-5NS2G4WQ.js → chunk-6VBOKOQJ.js} +46 -0
- package/dist/chunk-CHFKVAEI.js +32 -0
- package/dist/{chunk-BNUTM6KD.js → chunk-SZB3CFRZ.js} +8 -1
- package/dist/{chunk-52RZLSWP.js → chunk-TDYIQHQX.js} +13 -1
- package/dist/cli.js +18 -14
- package/dist/{company-4MUABENR.js → company-SZPGJE3M.js} +4 -4
- package/dist/{config-6PNGYL5E.js → config-2GBLD4GN.js} +1 -1
- package/dist/{connect-ZXD7P5CA.js → connect-RMT7OS3I.js} +45 -19
- package/dist/{inbox-ME4TXGFV.js → inbox-MIKI4HU3.js} +102 -19
- package/dist/{login-UJQGIP7S.js → login-POKHNDYX.js} +1 -1
- package/dist/{message-O7QN2L6Q.js → message-YRMLMHK7.js} +124 -39
- package/dist/{post-VDQF23WS.js → post-2FYHZAKC.js} +13 -8
- package/dist/{profile-CUVVESMY.js → profile-NDDG26PL.js} +7 -7
- package/dist/{recruiter-QKJKOWD7.js → recruiter-3DRGDOVV.js} +3 -3
- package/dist/{sales-nav-UL2H6J6V.js → sales-nav-7WPN7BT4.js} +3 -3
- package/dist/{search-M4WK3PDC.js → search-QO237C4O.js} +2 -2
- package/dist/{webhook-2SSNW25K.js → webhook-FDIERREB.js} +2 -2
- package/package.json +2 -2
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
|
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
renderSuccess,
|
|
12
12
|
renderUnexpectedError,
|
|
13
13
|
resolveEffectiveConfig
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-47SYFQRF.js";
|
|
15
15
|
import {
|
|
16
16
|
GLOBAL_FLAGS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-TDYIQHQX.js";
|
|
18
18
|
|
|
19
19
|
// src/commands/account.ts
|
|
20
20
|
import { defineCommand } from "citty";
|
|
@@ -64,6 +64,48 @@ function slimProfile(data) {
|
|
|
64
64
|
current_position: currentPosition
|
|
65
65
|
};
|
|
66
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
|
+
}
|
|
67
109
|
function slimCompany(data) {
|
|
68
110
|
const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
|
|
69
111
|
const rawMessaging = d["messaging"] !== null && d["messaging"] !== void 0 && typeof d["messaging"] === "object" ? d["messaging"] : null;
|
|
@@ -91,5 +133,9 @@ function slimCompany(data) {
|
|
|
91
133
|
export {
|
|
92
134
|
slimProfileMe,
|
|
93
135
|
slimProfile,
|
|
136
|
+
slimInviteSentItem,
|
|
137
|
+
slimInviteSent,
|
|
138
|
+
slimInviteReceivedItem,
|
|
139
|
+
slimInviteReceived,
|
|
94
140
|
slimCompany
|
|
95
141
|
};
|
|
@@ -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
|
+
};
|
|
@@ -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:
|
|
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-
|
|
138
|
-
config: () => import("./config-
|
|
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-
|
|
143
|
-
company: () => import("./company-
|
|
144
|
-
connect: () => import("./connect-
|
|
145
|
-
search: () => import("./search-
|
|
146
|
-
inbox: () => import("./inbox-
|
|
147
|
-
message: () => import("./message-
|
|
148
|
-
post: () => import("./post-
|
|
149
|
-
account: () => import("./account-
|
|
150
|
-
webhook: () => import("./webhook-
|
|
151
|
-
"sales-nav": () => import("./sales-nav-
|
|
152
|
-
recruiter: () => import("./recruiter-
|
|
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),
|
|
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)
|
|
153
157
|
},
|
|
154
158
|
async run() {
|
|
155
159
|
const { runMain } = await import("citty");
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
slimCompany
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6VBOKOQJ.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveIdentifier
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SZB3CFRZ.js";
|
|
8
8
|
import {
|
|
9
9
|
createClient,
|
|
10
10
|
renderError,
|
|
11
11
|
renderSuccess,
|
|
12
12
|
renderUnexpectedError,
|
|
13
13
|
resolveEffectiveConfig
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-47SYFQRF.js";
|
|
15
15
|
import {
|
|
16
16
|
GLOBAL_FLAGS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-TDYIQHQX.js";
|
|
18
18
|
|
|
19
19
|
// src/commands/company.ts
|
|
20
20
|
import { defineCommand } from "citty";
|
|
@@ -2,9 +2,15 @@
|
|
|
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";
|
|
5
11
|
import {
|
|
6
12
|
resolveIdentifier
|
|
7
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-SZB3CFRZ.js";
|
|
8
14
|
import {
|
|
9
15
|
streamAll
|
|
10
16
|
} from "./chunk-SND3NHCT.js";
|
|
@@ -14,10 +20,11 @@ import {
|
|
|
14
20
|
renderSuccess,
|
|
15
21
|
renderUnexpectedError,
|
|
16
22
|
resolveEffectiveConfig
|
|
17
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-47SYFQRF.js";
|
|
18
24
|
import {
|
|
19
|
-
GLOBAL_FLAGS
|
|
20
|
-
|
|
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) {
|
|
@@ -98,11 +106,12 @@ async function runConnectSent(client, flags, out) {
|
|
|
98
106
|
maxPages,
|
|
99
107
|
onTruncated: (msg) => out.stderr.write(msg + "\n")
|
|
100
108
|
})) {
|
|
101
|
-
|
|
109
|
+
const projected = !flags.verbose ? slimInviteSentItem(item) : item;
|
|
110
|
+
out.stdout.write(JSON.stringify(projected) + "\n");
|
|
102
111
|
}
|
|
103
112
|
} else {
|
|
104
113
|
const result = await ns.invites.listSent(params);
|
|
105
|
-
renderSuccess(result, outOpts, out);
|
|
114
|
+
renderSuccess(result, { ...outOpts, slim: slimInviteSent }, out);
|
|
106
115
|
}
|
|
107
116
|
} catch (err) {
|
|
108
117
|
const { CurviateError } = await import("@curviate/sdk");
|
|
@@ -134,11 +143,12 @@ async function runConnectReceived(client, flags, out) {
|
|
|
134
143
|
maxPages,
|
|
135
144
|
onTruncated: (msg) => out.stderr.write(msg + "\n")
|
|
136
145
|
})) {
|
|
137
|
-
|
|
146
|
+
const projected = !flags.verbose ? slimInviteReceivedItem(item) : item;
|
|
147
|
+
out.stdout.write(JSON.stringify(projected) + "\n");
|
|
138
148
|
}
|
|
139
149
|
} else {
|
|
140
150
|
const result = await ns.invites.listReceived(params);
|
|
141
|
-
renderSuccess(result, outOpts, out);
|
|
151
|
+
renderSuccess(result, { ...outOpts, slim: slimInviteReceived }, out);
|
|
142
152
|
}
|
|
143
153
|
} catch (err) {
|
|
144
154
|
const { CurviateError } = await import("@curviate/sdk");
|
|
@@ -219,7 +229,10 @@ async function runConnectCancel(client, flags, out) {
|
|
|
219
229
|
}
|
|
220
230
|
}
|
|
221
231
|
var connectSentCommand = defineCommand({
|
|
222
|
-
meta: {
|
|
232
|
+
meta: {
|
|
233
|
+
name: "sent",
|
|
234
|
+
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."
|
|
235
|
+
},
|
|
223
236
|
args: { ...GLOBAL_FLAGS },
|
|
224
237
|
async run({ args }) {
|
|
225
238
|
const flags = args;
|
|
@@ -242,7 +255,7 @@ var connectSentCommand = defineCommand({
|
|
|
242
255
|
var connectReceivedCommand = defineCommand({
|
|
243
256
|
meta: {
|
|
244
257
|
name: "received",
|
|
245
|
-
description: "
|
|
258
|
+
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
259
|
},
|
|
247
260
|
args: { ...GLOBAL_FLAGS },
|
|
248
261
|
async run({ args }) {
|
|
@@ -266,12 +279,15 @@ var connectReceivedCommand = defineCommand({
|
|
|
266
279
|
var connectRespondCommand = defineCommand({
|
|
267
280
|
meta: { name: "respond", description: "Accept or decline a received invitation." },
|
|
268
281
|
args: {
|
|
269
|
-
...
|
|
270
|
-
id: {
|
|
282
|
+
...WRITE_FLAGS,
|
|
283
|
+
id: {
|
|
284
|
+
type: "positional",
|
|
285
|
+
description: "Invitation id to respond to \u2014 use the `id` field from `connect received`."
|
|
286
|
+
},
|
|
271
287
|
action: { type: "string", description: "Response action: accept or decline.", required: true },
|
|
272
288
|
"shared-secret": {
|
|
273
289
|
type: "string",
|
|
274
|
-
description: "Per-invitation shared secret \u2014
|
|
290
|
+
description: "Per-invitation shared secret \u2014 use `specifics.shared_secret` from the same `connect received` item.",
|
|
275
291
|
required: true
|
|
276
292
|
}
|
|
277
293
|
},
|
|
@@ -296,7 +312,7 @@ var connectRespondCommand = defineCommand({
|
|
|
296
312
|
var connectCancelCommand = defineCommand({
|
|
297
313
|
meta: { name: "cancel", description: "Cancel a sent invitation." },
|
|
298
314
|
args: {
|
|
299
|
-
...
|
|
315
|
+
...WRITE_FLAGS,
|
|
300
316
|
id: { type: "positional", description: "Invitation id to cancel." }
|
|
301
317
|
},
|
|
302
318
|
async run({ args }) {
|
|
@@ -318,11 +334,21 @@ var connectCancelCommand = defineCommand({
|
|
|
318
334
|
}
|
|
319
335
|
});
|
|
320
336
|
var connectCommand = defineCommand({
|
|
321
|
-
meta: {
|
|
337
|
+
meta: {
|
|
338
|
+
name: "connect",
|
|
339
|
+
description: "Send or manage connection invitations. Connection requests may take 10\u201330 seconds to appear in the recipient's received list (LinkedIn propagation delay)."
|
|
340
|
+
},
|
|
322
341
|
args: {
|
|
323
|
-
...
|
|
324
|
-
id: {
|
|
325
|
-
|
|
342
|
+
...WRITE_FLAGS,
|
|
343
|
+
id: {
|
|
344
|
+
type: "positional",
|
|
345
|
+
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.",
|
|
346
|
+
required: false
|
|
347
|
+
},
|
|
348
|
+
note: {
|
|
349
|
+
type: "string",
|
|
350
|
+
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."
|
|
351
|
+
}
|
|
326
352
|
},
|
|
327
353
|
subCommands: {
|
|
328
354
|
sent: connectSentCommand,
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
normalizeChatId
|
|
4
|
+
} from "./chunk-SZB3CFRZ.js";
|
|
2
5
|
import {
|
|
3
6
|
streamAll
|
|
4
7
|
} from "./chunk-SND3NHCT.js";
|
|
@@ -8,10 +11,11 @@ import {
|
|
|
8
11
|
renderSuccess,
|
|
9
12
|
renderUnexpectedError,
|
|
10
13
|
resolveEffectiveConfig
|
|
11
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-47SYFQRF.js";
|
|
12
15
|
import {
|
|
13
|
-
GLOBAL_FLAGS
|
|
14
|
-
|
|
16
|
+
GLOBAL_FLAGS,
|
|
17
|
+
READ_SINGLE_FLAGS
|
|
18
|
+
} from "./chunk-TDYIQHQX.js";
|
|
15
19
|
|
|
16
20
|
// src/commands/inbox.ts
|
|
17
21
|
import { defineCommand } from "citty";
|
|
@@ -53,6 +57,15 @@ function buildPaginationParams(flags) {
|
|
|
53
57
|
if (flags.cursor) params["cursor"] = flags.cursor;
|
|
54
58
|
return params;
|
|
55
59
|
}
|
|
60
|
+
function validateIsoZTimestamp(value, flagName, out) {
|
|
61
|
+
if (Number.isNaN(new Date(value).getTime()) || !value.endsWith("Z")) {
|
|
62
|
+
out.stderr.write(
|
|
63
|
+
`error: --${flagName}: must be a UTC ISO-8601 timestamp ending in 'Z' (e.g. 2025-01-01T00:00:00Z).
|
|
64
|
+
`
|
|
65
|
+
);
|
|
66
|
+
process.exit(2);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
56
69
|
async function handleSdkError(err, outOpts, out) {
|
|
57
70
|
const { CurviateError } = await import("@curviate/sdk");
|
|
58
71
|
if (err instanceof CurviateError) {
|
|
@@ -71,6 +84,9 @@ async function runInboxList(client, flags, out) {
|
|
|
71
84
|
const all = flags.all ?? false;
|
|
72
85
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
73
86
|
const params = buildPaginationParams(flags);
|
|
87
|
+
if (flags.unread !== void 0) {
|
|
88
|
+
params.unread = flags.unread;
|
|
89
|
+
}
|
|
74
90
|
try {
|
|
75
91
|
if (all) {
|
|
76
92
|
const fn = (p) => ns.messaging.listChats(p);
|
|
@@ -92,7 +108,7 @@ async function runInboxGet(client, flags, out) {
|
|
|
92
108
|
rejectPreviewOnRead(flags.preview, out);
|
|
93
109
|
rejectAllOnNonPaginated(flags.all, out);
|
|
94
110
|
const accountId = requireAccount(flags.account, out);
|
|
95
|
-
const chatId = flags.chatId ?? "";
|
|
111
|
+
const chatId = normalizeChatId(flags.chatId ?? "");
|
|
96
112
|
const ns = client.account(accountId);
|
|
97
113
|
const outOpts = resolveOutputOpts(flags);
|
|
98
114
|
try {
|
|
@@ -105,12 +121,20 @@ async function runInboxGet(client, flags, out) {
|
|
|
105
121
|
async function runInboxMessages(client, flags, out) {
|
|
106
122
|
rejectPreviewOnRead(flags.preview, out);
|
|
107
123
|
const accountId = requireAccount(flags.account, out);
|
|
108
|
-
const chatId = flags.chatId ?? "";
|
|
124
|
+
const chatId = normalizeChatId(flags.chatId ?? "");
|
|
109
125
|
const ns = client.account(accountId);
|
|
110
126
|
const outOpts = resolveOutputOpts(flags);
|
|
111
127
|
const all = flags.all ?? false;
|
|
112
128
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
113
129
|
const params = buildPaginationParams(flags);
|
|
130
|
+
if (flags.before !== void 0) {
|
|
131
|
+
validateIsoZTimestamp(flags.before, "before", out);
|
|
132
|
+
params.before = flags.before;
|
|
133
|
+
}
|
|
134
|
+
if (flags.after !== void 0) {
|
|
135
|
+
validateIsoZTimestamp(flags.after, "after", out);
|
|
136
|
+
params.after = flags.after;
|
|
137
|
+
}
|
|
114
138
|
try {
|
|
115
139
|
if (all) {
|
|
116
140
|
const fn = (p) => ns.messaging.listMessages(chatId, p);
|
|
@@ -141,23 +165,58 @@ async function runInboxSync(client, flags, out) {
|
|
|
141
165
|
await handleSdkError(err, outOpts, out);
|
|
142
166
|
}
|
|
143
167
|
}
|
|
144
|
-
|
|
168
|
+
var SYNC_TERMINAL_STATUSES = /* @__PURE__ */ new Set(["done", "error", "chat_deleted"]);
|
|
169
|
+
var SYNC_POLL_INTERVAL_MS = 2e3;
|
|
170
|
+
async function runInboxSyncChat(client, flags, out, _sleep) {
|
|
145
171
|
rejectPreviewOnRead(flags.preview, out);
|
|
146
172
|
rejectAllOnNonPaginated(flags.all, out);
|
|
147
173
|
const accountId = requireAccount(flags.account, out);
|
|
148
|
-
const chatId = flags.chatId ?? "";
|
|
174
|
+
const chatId = normalizeChatId(flags.chatId ?? "");
|
|
149
175
|
const ns = client.account(accountId);
|
|
150
176
|
const outOpts = resolveOutputOpts(flags);
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
177
|
+
if (!flags.wait) {
|
|
178
|
+
try {
|
|
179
|
+
const result = await ns.messaging.syncChat(chatId);
|
|
180
|
+
renderSuccess(result, outOpts, out);
|
|
181
|
+
} catch (err) {
|
|
182
|
+
await handleSdkError(err, outOpts, out);
|
|
183
|
+
}
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const sleep = _sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
187
|
+
const timeoutSecs = parseInt(flags.timeout ?? "30", 10);
|
|
188
|
+
const timeoutMs = (Number.isNaN(timeoutSecs) ? 30 : timeoutSecs) * 1e3;
|
|
189
|
+
const startTime = Date.now();
|
|
190
|
+
while (true) {
|
|
191
|
+
let result;
|
|
192
|
+
try {
|
|
193
|
+
result = await ns.messaging.syncChat(chatId);
|
|
194
|
+
} catch (err) {
|
|
195
|
+
await handleSdkError(err, outOpts, out);
|
|
196
|
+
}
|
|
197
|
+
const resp = result;
|
|
198
|
+
if (resp.status !== void 0 && SYNC_TERMINAL_STATUSES.has(resp.status)) {
|
|
199
|
+
renderSuccess(result, outOpts, out);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (Date.now() - startTime >= timeoutMs) {
|
|
203
|
+
renderSuccess(result, outOpts, out);
|
|
204
|
+
process.exit(3);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
await sleep(SYNC_POLL_INTERVAL_MS);
|
|
156
208
|
}
|
|
157
209
|
}
|
|
158
210
|
var inboxListCommand = defineCommand({
|
|
159
211
|
meta: { name: "list", description: "List inbox chats." },
|
|
160
|
-
args: {
|
|
212
|
+
args: {
|
|
213
|
+
...GLOBAL_FLAGS,
|
|
214
|
+
unread: {
|
|
215
|
+
type: "boolean",
|
|
216
|
+
description: "Show unread chats only (--no-unread for read-only; omit for all)."
|
|
217
|
+
// No default → three-way semantics: undefined when omitted, true for --unread, false for --no-unread
|
|
218
|
+
}
|
|
219
|
+
},
|
|
161
220
|
async run({ args }) {
|
|
162
221
|
const flags = args;
|
|
163
222
|
const cfg = await resolveEffectiveConfig({
|
|
@@ -179,7 +238,8 @@ var inboxListCommand = defineCommand({
|
|
|
179
238
|
var inboxGetCommand = defineCommand({
|
|
180
239
|
meta: { name: "get", description: "Get details of a single chat." },
|
|
181
240
|
args: {
|
|
182
|
-
|
|
241
|
+
// Single-object read: READ_SINGLE_FLAGS omits pagination flags, keeps --fields
|
|
242
|
+
...READ_SINGLE_FLAGS,
|
|
183
243
|
chatId: { type: "positional", description: "Chat ID." }
|
|
184
244
|
},
|
|
185
245
|
async run({ args }) {
|
|
@@ -204,7 +264,15 @@ var inboxMessagesCommand = defineCommand({
|
|
|
204
264
|
meta: { name: "messages", description: "List messages in a chat." },
|
|
205
265
|
args: {
|
|
206
266
|
...GLOBAL_FLAGS,
|
|
207
|
-
chatId: { type: "positional", description: "Chat ID." }
|
|
267
|
+
chatId: { type: "positional", description: "Chat ID." },
|
|
268
|
+
before: {
|
|
269
|
+
type: "string",
|
|
270
|
+
description: "Return messages before this timestamp (ISO-8601, UTC \u2014 Z suffix required, e.g. 2025-01-01T00:00:00Z)."
|
|
271
|
+
},
|
|
272
|
+
after: {
|
|
273
|
+
type: "string",
|
|
274
|
+
description: "Return messages after this timestamp (ISO-8601, UTC \u2014 Z suffix required, e.g. 2025-01-01T00:00:00Z)."
|
|
275
|
+
}
|
|
208
276
|
},
|
|
209
277
|
async run({ args }) {
|
|
210
278
|
const flags = args;
|
|
@@ -226,7 +294,10 @@ var inboxMessagesCommand = defineCommand({
|
|
|
226
294
|
});
|
|
227
295
|
var inboxSyncCommand = defineCommand({
|
|
228
296
|
meta: { name: "sync", description: "Re-sync account message history." },
|
|
229
|
-
args: {
|
|
297
|
+
args: {
|
|
298
|
+
// Single-object read: READ_SINGLE_FLAGS omits pagination flags, keeps --fields
|
|
299
|
+
...READ_SINGLE_FLAGS
|
|
300
|
+
},
|
|
230
301
|
async run({ args }) {
|
|
231
302
|
const flags = args;
|
|
232
303
|
const cfg = await resolveEffectiveConfig({
|
|
@@ -248,15 +319,27 @@ var inboxSyncCommand = defineCommand({
|
|
|
248
319
|
var inboxSyncChatCommand = defineCommand({
|
|
249
320
|
meta: { name: "sync-chat", description: "Re-sync a specific chat's message history." },
|
|
250
321
|
args: {
|
|
251
|
-
|
|
252
|
-
|
|
322
|
+
// Single-object read: READ_SINGLE_FLAGS omits pagination flags, keeps --fields.
|
|
323
|
+
// The timeout below overrides READ_SINGLE_FLAGS.timeout with a command-specific description.
|
|
324
|
+
...READ_SINGLE_FLAGS,
|
|
325
|
+
chatId: { type: "positional", description: "Chat ID." },
|
|
326
|
+
wait: {
|
|
327
|
+
type: "boolean",
|
|
328
|
+
description: "Poll until sync completes (or --timeout elapses).",
|
|
329
|
+
default: false
|
|
330
|
+
},
|
|
331
|
+
// Override READ_SINGLE_FLAGS.timeout: here --timeout is the polling wait timeout
|
|
332
|
+
// in seconds (default: 30), not the SDK request timeout.
|
|
333
|
+
timeout: {
|
|
334
|
+
type: "string",
|
|
335
|
+
description: "Polling timeout in seconds (default: 30, requires --wait)."
|
|
336
|
+
}
|
|
253
337
|
},
|
|
254
338
|
async run({ args }) {
|
|
255
339
|
const flags = args;
|
|
256
340
|
const cfg = await resolveEffectiveConfig({
|
|
257
341
|
apiKey: flags["api-key"],
|
|
258
342
|
baseUrl: flags["base-url"],
|
|
259
|
-
timeout: flags.timeout,
|
|
260
343
|
account: flags.account,
|
|
261
344
|
profile: flags.profile
|
|
262
345
|
});
|
|
@@ -7,22 +7,27 @@ import {
|
|
|
7
7
|
AttachError,
|
|
8
8
|
readAttachment
|
|
9
9
|
} from "./chunk-Q43HZUN3.js";
|
|
10
|
+
import {
|
|
11
|
+
resolveTextOrStdin
|
|
12
|
+
} from "./chunk-CHFKVAEI.js";
|
|
10
13
|
import {
|
|
11
14
|
buildPreviewOutput
|
|
12
15
|
} from "./chunk-R3VLWLVV.js";
|
|
13
16
|
import {
|
|
17
|
+
normalizeChatId,
|
|
14
18
|
resolveIdentifier
|
|
15
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-SZB3CFRZ.js";
|
|
16
20
|
import {
|
|
17
21
|
createClient,
|
|
18
22
|
renderError,
|
|
19
23
|
renderSuccess,
|
|
20
24
|
renderUnexpectedError,
|
|
21
25
|
resolveEffectiveConfig
|
|
22
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-47SYFQRF.js";
|
|
23
27
|
import {
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
READ_SINGLE_FLAGS,
|
|
29
|
+
WRITE_FLAGS
|
|
30
|
+
} from "./chunk-TDYIQHQX.js";
|
|
26
31
|
|
|
27
32
|
// src/commands/message.ts
|
|
28
33
|
import { defineCommand } from "citty";
|
|
@@ -64,7 +69,7 @@ function normalizeAttachPaths(attach) {
|
|
|
64
69
|
}
|
|
65
70
|
var INMAIL_SURFACES = ["sales_nav", "recruiter", "classic"];
|
|
66
71
|
var MEMBER_URN_RE = /^urn:li:member:\d+$/;
|
|
67
|
-
var MEMBER_PROVIDER_ID_RE = /^A[CDE][A-Za-z0-9_-]{
|
|
72
|
+
var MEMBER_PROVIDER_ID_RE = /^A[CDE][A-Za-z0-9_-]{4,}$/;
|
|
68
73
|
async function handleSdkError(err, outOpts, out) {
|
|
69
74
|
const { CurviateError } = await import("@curviate/sdk");
|
|
70
75
|
if (err instanceof CurviateError) {
|
|
@@ -75,10 +80,10 @@ async function handleSdkError(err, outOpts, out) {
|
|
|
75
80
|
renderUnexpectedError(err, out);
|
|
76
81
|
process.exit(1);
|
|
77
82
|
}
|
|
78
|
-
async function runMessageNew(client, flags, out) {
|
|
83
|
+
async function runMessageNew(client, flags, out, _readStdin) {
|
|
79
84
|
const accountId = requireAccount(flags.account, out);
|
|
80
|
-
const
|
|
81
|
-
const
|
|
85
|
+
const rawTo = flags.to ?? "";
|
|
86
|
+
const rawText = flags.text ?? "";
|
|
82
87
|
const attachPaths = normalizeAttachPaths(flags.attach);
|
|
83
88
|
let attachBuffers = [];
|
|
84
89
|
try {
|
|
@@ -91,14 +96,30 @@ async function runMessageNew(client, flags, out) {
|
|
|
91
96
|
}
|
|
92
97
|
throw err;
|
|
93
98
|
}
|
|
99
|
+
const ns = client.account(accountId);
|
|
100
|
+
const outOpts = resolveOutputOpts(flags);
|
|
101
|
+
const text = await resolveTextOrStdin(rawText, out, _readStdin);
|
|
102
|
+
const resolvedSlugOrId = resolveIdentifier(rawTo);
|
|
103
|
+
let providerId;
|
|
104
|
+
if (MEMBER_PROVIDER_ID_RE.test(resolvedSlugOrId)) {
|
|
105
|
+
providerId = resolvedSlugOrId;
|
|
106
|
+
} else {
|
|
107
|
+
try {
|
|
108
|
+
const profileData = await ns.profiles.get(resolvedSlugOrId, {});
|
|
109
|
+
providerId = profileData["provider_id"];
|
|
110
|
+
} catch (err) {
|
|
111
|
+
await handleSdkError(err, outOpts, out);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
94
115
|
const body = {
|
|
95
|
-
attendees_ids: [
|
|
116
|
+
attendees_ids: [providerId],
|
|
96
117
|
text
|
|
97
118
|
};
|
|
98
119
|
if (flags.preview) {
|
|
99
120
|
const preview = buildPreviewOutput({
|
|
100
121
|
method: "messaging.startChat",
|
|
101
|
-
args: { attendees_ids: [
|
|
122
|
+
args: { attendees_ids: [providerId] },
|
|
102
123
|
body: { ...body },
|
|
103
124
|
account: accountId,
|
|
104
125
|
attachments: attachBuffers.map((buf, i) => ({
|
|
@@ -112,8 +133,6 @@ async function runMessageNew(client, flags, out) {
|
|
|
112
133
|
if (attachBuffers.length > 0) {
|
|
113
134
|
body["attachments"] = attachBuffers;
|
|
114
135
|
}
|
|
115
|
-
const ns = client.account(accountId);
|
|
116
|
-
const outOpts = resolveOutputOpts(flags);
|
|
117
136
|
try {
|
|
118
137
|
const result = await ns.messaging.startChat(body);
|
|
119
138
|
renderSuccess(result, outOpts, out);
|
|
@@ -121,11 +140,12 @@ async function runMessageNew(client, flags, out) {
|
|
|
121
140
|
await handleSdkError(err, outOpts, out);
|
|
122
141
|
}
|
|
123
142
|
}
|
|
124
|
-
async function runMessageSend(client, flags, out) {
|
|
143
|
+
async function runMessageSend(client, flags, out, _readStdin) {
|
|
125
144
|
const accountId = requireAccount(flags.account, out);
|
|
126
|
-
const chatId = flags.chatId ?? "";
|
|
127
|
-
const
|
|
145
|
+
const chatId = normalizeChatId(flags.chatId ?? "");
|
|
146
|
+
const rawText = flags.text ?? "";
|
|
128
147
|
const attachPaths = normalizeAttachPaths(flags.attach);
|
|
148
|
+
const text = await resolveTextOrStdin(rawText, out, _readStdin);
|
|
129
149
|
let attachBuffers = [];
|
|
130
150
|
try {
|
|
131
151
|
attachBuffers = await Promise.all(attachPaths.map((p) => readAttachment(p)));
|
|
@@ -178,10 +198,11 @@ async function runMessageGet(client, flags, out) {
|
|
|
178
198
|
await handleSdkError(err, outOpts, out);
|
|
179
199
|
}
|
|
180
200
|
}
|
|
181
|
-
async function runMessageEdit(client, flags, out) {
|
|
201
|
+
async function runMessageEdit(client, flags, out, _readStdin) {
|
|
182
202
|
const accountId = requireAccount(flags.account, out);
|
|
183
203
|
const messageId = flags.messageId ?? "";
|
|
184
|
-
const
|
|
204
|
+
const rawText = flags.text ?? "";
|
|
205
|
+
const text = await resolveTextOrStdin(rawText, out, _readStdin);
|
|
185
206
|
if (flags.preview) {
|
|
186
207
|
const preview = buildPreviewOutput({
|
|
187
208
|
method: "messaging.editMessage",
|
|
@@ -269,7 +290,7 @@ async function runMessageAttachment(client, flags, out, isTTY) {
|
|
|
269
290
|
await handleSdkError(err, outOpts, out);
|
|
270
291
|
}
|
|
271
292
|
}
|
|
272
|
-
async function runMessageInMail(client, flags, out) {
|
|
293
|
+
async function runMessageInMail(client, flags, out, _readStdin) {
|
|
273
294
|
const accountId = requireAccount(flags.account, out);
|
|
274
295
|
const surface = flags.surface ?? "";
|
|
275
296
|
if (!INMAIL_SURFACES.includes(surface)) {
|
|
@@ -279,15 +300,34 @@ async function runMessageInMail(client, flags, out) {
|
|
|
279
300
|
);
|
|
280
301
|
process.exit(2);
|
|
281
302
|
}
|
|
282
|
-
const
|
|
283
|
-
if (!
|
|
303
|
+
const rawTo = flags.to ?? "";
|
|
304
|
+
if (!rawTo) {
|
|
284
305
|
out.stderr.write(
|
|
285
|
-
"error: --to
|
|
306
|
+
"error: --to: not a valid LinkedIn URL, slug, provider-id, or URN.\n"
|
|
286
307
|
);
|
|
287
308
|
process.exit(2);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const ns = client.account(accountId);
|
|
312
|
+
const outOpts = resolveOutputOpts(flags);
|
|
313
|
+
const resolvedSlugOrId = resolveIdentifier(rawTo);
|
|
314
|
+
let recipientUrn;
|
|
315
|
+
if (MEMBER_URN_RE.test(resolvedSlugOrId)) {
|
|
316
|
+
recipientUrn = resolvedSlugOrId;
|
|
317
|
+
} else if (MEMBER_PROVIDER_ID_RE.test(resolvedSlugOrId)) {
|
|
318
|
+
recipientUrn = resolvedSlugOrId;
|
|
319
|
+
} else {
|
|
320
|
+
try {
|
|
321
|
+
const profileData = await ns.profiles.get(resolvedSlugOrId, {});
|
|
322
|
+
recipientUrn = profileData["provider_id"];
|
|
323
|
+
} catch (err) {
|
|
324
|
+
await handleSdkError(err, outOpts, out);
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
288
327
|
}
|
|
289
328
|
const subject = flags.subject ?? "";
|
|
290
|
-
const
|
|
329
|
+
const rawText = flags.text ?? "";
|
|
330
|
+
const text = await resolveTextOrStdin(rawText, out, _readStdin);
|
|
291
331
|
const body = {
|
|
292
332
|
recipient_urn: recipientUrn,
|
|
293
333
|
surface,
|
|
@@ -304,8 +344,6 @@ async function runMessageInMail(client, flags, out) {
|
|
|
304
344
|
out.stdout.write(JSON.stringify(preview) + "\n");
|
|
305
345
|
return;
|
|
306
346
|
}
|
|
307
|
-
const ns = client.account(accountId);
|
|
308
|
-
const outOpts = resolveOutputOpts(flags);
|
|
309
347
|
try {
|
|
310
348
|
const result = await ns.messaging.sendInMail(body);
|
|
311
349
|
renderSuccess(result, outOpts, out);
|
|
@@ -329,9 +367,14 @@ async function runMessageInMailBalance(client, flags, out) {
|
|
|
329
367
|
var messageNewCommand = defineCommand({
|
|
330
368
|
meta: { name: "new", description: "Start a new chat with one or more members." },
|
|
331
369
|
args: {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
370
|
+
// Write command: WRITE_FLAGS omits pagination/projection flags
|
|
371
|
+
...WRITE_FLAGS,
|
|
372
|
+
to: {
|
|
373
|
+
type: "string",
|
|
374
|
+
description: "Recipient: LinkedIn profile URL (e.g. https://www.linkedin.com/in/some-slug), bare slug (e.g. some-slug), or provider ID (e.g. ACoAAA\u2026). URL and slug inputs resolve the provider ID automatically.",
|
|
375
|
+
required: true
|
|
376
|
+
},
|
|
377
|
+
text: { type: "positional", description: "Opening message text. Pass - to read from stdin (e.g. via heredoc or pipe)." },
|
|
335
378
|
attach: { type: "string", description: "File to attach (repeatable)." }
|
|
336
379
|
},
|
|
337
380
|
async run({ args }) {
|
|
@@ -355,7 +398,8 @@ var messageNewCommand = defineCommand({
|
|
|
355
398
|
var messageGetCommand = defineCommand({
|
|
356
399
|
meta: { name: "get", description: "Get a message by ID." },
|
|
357
400
|
args: {
|
|
358
|
-
|
|
401
|
+
// Single-object read: READ_SINGLE_FLAGS omits pagination flags, keeps --fields
|
|
402
|
+
...READ_SINGLE_FLAGS,
|
|
359
403
|
messageId: { type: "positional", description: "Message ID." }
|
|
360
404
|
},
|
|
361
405
|
async run({ args }) {
|
|
@@ -379,9 +423,10 @@ var messageGetCommand = defineCommand({
|
|
|
379
423
|
var messageEditCommand = defineCommand({
|
|
380
424
|
meta: { name: "edit", description: "Edit a message (within the allowed window)." },
|
|
381
425
|
args: {
|
|
382
|
-
|
|
426
|
+
// Write command: WRITE_FLAGS omits pagination/projection flags
|
|
427
|
+
...WRITE_FLAGS,
|
|
383
428
|
messageId: { type: "positional", description: "Message ID." },
|
|
384
|
-
text: { type: "positional", description: "Replacement text." }
|
|
429
|
+
text: { type: "positional", description: "Replacement text. Pass - to read from stdin." }
|
|
385
430
|
},
|
|
386
431
|
async run({ args }) {
|
|
387
432
|
const flags = args;
|
|
@@ -404,7 +449,8 @@ var messageEditCommand = defineCommand({
|
|
|
404
449
|
var messageDeleteCommand = defineCommand({
|
|
405
450
|
meta: { name: "delete", description: "Delete a message." },
|
|
406
451
|
args: {
|
|
407
|
-
|
|
452
|
+
// Write command: WRITE_FLAGS omits pagination/projection flags
|
|
453
|
+
...WRITE_FLAGS,
|
|
408
454
|
messageId: { type: "positional", description: "Message ID." }
|
|
409
455
|
},
|
|
410
456
|
async run({ args }) {
|
|
@@ -428,7 +474,8 @@ var messageDeleteCommand = defineCommand({
|
|
|
428
474
|
var messageReactCommand = defineCommand({
|
|
429
475
|
meta: { name: "react", description: "Add an emoji reaction to a message." },
|
|
430
476
|
args: {
|
|
431
|
-
|
|
477
|
+
// Write command: WRITE_FLAGS omits pagination/projection flags
|
|
478
|
+
...WRITE_FLAGS,
|
|
432
479
|
messageId: { type: "positional", description: "Message ID." },
|
|
433
480
|
emoji: { type: "string", description: "Native emoji reaction value (e.g. \u{1F44D}).", required: true }
|
|
434
481
|
},
|
|
@@ -453,7 +500,8 @@ var messageReactCommand = defineCommand({
|
|
|
453
500
|
var messageAttachmentCommand = defineCommand({
|
|
454
501
|
meta: { name: "attachment", description: "Download a message attachment." },
|
|
455
502
|
args: {
|
|
456
|
-
|
|
503
|
+
// Single-object read: READ_SINGLE_FLAGS omits pagination flags, keeps --fields
|
|
504
|
+
...READ_SINGLE_FLAGS,
|
|
457
505
|
messageId: { type: "positional", description: "Message ID." },
|
|
458
506
|
attachmentId: { type: "positional", description: "Attachment ID." },
|
|
459
507
|
output: { type: "string", alias: "o", description: "Path to write the file to." }
|
|
@@ -484,11 +532,16 @@ var messageAttachmentCommand = defineCommand({
|
|
|
484
532
|
var messageInMailCommand = defineCommand({
|
|
485
533
|
meta: { name: "inmail", description: "Send an InMail to a member." },
|
|
486
534
|
args: {
|
|
487
|
-
|
|
488
|
-
|
|
535
|
+
// Write command: WRITE_FLAGS omits pagination/projection flags
|
|
536
|
+
...WRITE_FLAGS,
|
|
537
|
+
to: {
|
|
538
|
+
type: "string",
|
|
539
|
+
description: "Recipient: LinkedIn profile URL, bare slug, provider-id (ACoAAA\u2026), or member URN (urn:li:member:<id>). URL and slug inputs resolve the provider ID automatically.",
|
|
540
|
+
required: true
|
|
541
|
+
},
|
|
489
542
|
surface: { type: "string", description: "InMail surface: sales_nav, recruiter, or classic (classic uses the account's own premium InMail credits).", required: true },
|
|
490
543
|
subject: { type: "string", description: "InMail subject line.", required: true },
|
|
491
|
-
text: { type: "positional", description: "InMail body text." }
|
|
544
|
+
text: { type: "positional", description: "InMail body text. Pass - to read from stdin." }
|
|
492
545
|
},
|
|
493
546
|
async run({ args }) {
|
|
494
547
|
const flags = args;
|
|
@@ -508,9 +561,39 @@ var messageInMailCommand = defineCommand({
|
|
|
508
561
|
await runMessageInMail(client, { ...flags, account: flags.account ?? cfg.account }, out);
|
|
509
562
|
}
|
|
510
563
|
});
|
|
564
|
+
var messageSendCommand = defineCommand({
|
|
565
|
+
meta: { name: "send", description: "Send a message to an existing chat." },
|
|
566
|
+
args: {
|
|
567
|
+
// Write command: WRITE_FLAGS omits pagination/projection flags
|
|
568
|
+
...WRITE_FLAGS,
|
|
569
|
+
chatId: { type: "positional", description: "Chat ID or LinkedIn messaging thread URL." },
|
|
570
|
+
text: { type: "positional", description: "Message text. Pass - to read from stdin (e.g. via heredoc or pipe)." },
|
|
571
|
+
attach: { type: "string", description: "File to attach (repeatable)." }
|
|
572
|
+
},
|
|
573
|
+
async run({ args }) {
|
|
574
|
+
const flags = args;
|
|
575
|
+
const cfg = await resolveEffectiveConfig({
|
|
576
|
+
apiKey: flags["api-key"],
|
|
577
|
+
baseUrl: flags["base-url"],
|
|
578
|
+
timeout: flags.timeout,
|
|
579
|
+
account: flags.account,
|
|
580
|
+
profile: flags.profile
|
|
581
|
+
});
|
|
582
|
+
if (!cfg.apiKey) {
|
|
583
|
+
process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
|
|
584
|
+
process.exit(3);
|
|
585
|
+
}
|
|
586
|
+
const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
|
|
587
|
+
const out = buildOutputStreams();
|
|
588
|
+
await runMessageSend(client, { ...flags, account: flags.account ?? cfg.account }, out);
|
|
589
|
+
}
|
|
590
|
+
});
|
|
511
591
|
var messageInMailBalanceCommand = defineCommand({
|
|
512
592
|
meta: { name: "inmail-balance", description: "Get InMail credit balance." },
|
|
513
|
-
args: {
|
|
593
|
+
args: {
|
|
594
|
+
// Single-object read: READ_SINGLE_FLAGS omits pagination flags, keeps --fields
|
|
595
|
+
...READ_SINGLE_FLAGS
|
|
596
|
+
},
|
|
514
597
|
async run({ args }) {
|
|
515
598
|
const flags = args;
|
|
516
599
|
const cfg = await resolveEffectiveConfig({
|
|
@@ -532,13 +615,15 @@ var messageInMailBalanceCommand = defineCommand({
|
|
|
532
615
|
var messageCommand = defineCommand({
|
|
533
616
|
meta: { name: "message", description: "Send and manage LinkedIn messages." },
|
|
534
617
|
args: {
|
|
535
|
-
|
|
618
|
+
// Write command (message send): WRITE_FLAGS omits pagination/projection flags
|
|
619
|
+
...WRITE_FLAGS,
|
|
536
620
|
chatId: { type: "positional", description: "Chat ID to send a message to.", required: false },
|
|
537
|
-
text: { type: "positional", description: "Message text.", required: false },
|
|
621
|
+
text: { type: "positional", description: "Message text. Pass - to read from stdin.", required: false },
|
|
538
622
|
attach: { type: "string", description: "File to attach (repeatable)." }
|
|
539
623
|
},
|
|
540
624
|
subCommands: {
|
|
541
625
|
new: messageNewCommand,
|
|
626
|
+
send: messageSendCommand,
|
|
542
627
|
get: messageGetCommand,
|
|
543
628
|
edit: messageEditCommand,
|
|
544
629
|
delete: messageDeleteCommand,
|
|
@@ -3,6 +3,9 @@ import {
|
|
|
3
3
|
AttachError,
|
|
4
4
|
readAttachment
|
|
5
5
|
} from "./chunk-Q43HZUN3.js";
|
|
6
|
+
import {
|
|
7
|
+
resolveTextOrStdin
|
|
8
|
+
} from "./chunk-CHFKVAEI.js";
|
|
6
9
|
import {
|
|
7
10
|
buildPreviewOutput
|
|
8
11
|
} from "./chunk-R3VLWLVV.js";
|
|
@@ -15,11 +18,11 @@ import {
|
|
|
15
18
|
renderSuccess,
|
|
16
19
|
renderUnexpectedError,
|
|
17
20
|
resolveEffectiveConfig
|
|
18
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-47SYFQRF.js";
|
|
19
22
|
import {
|
|
20
23
|
GLOBAL_FLAGS,
|
|
21
24
|
WRITE_FLAGS
|
|
22
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-TDYIQHQX.js";
|
|
23
26
|
|
|
24
27
|
// src/commands/post.ts
|
|
25
28
|
import { defineCommand } from "citty";
|
|
@@ -115,11 +118,12 @@ async function runPostGet(client, flags, out) {
|
|
|
115
118
|
await handleSdkError(err, outOpts, out);
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
|
-
async function runPostCreate(client, flags, out) {
|
|
121
|
+
async function runPostCreate(client, flags, out, _readStdin) {
|
|
119
122
|
const accountId = requireAccount(flags.account, out);
|
|
120
|
-
const
|
|
123
|
+
const rawText = flags.text ?? "";
|
|
121
124
|
const attachPaths = normalizeAttachPaths(flags.attach);
|
|
122
125
|
const thumbPath = flags["video-thumbnail"];
|
|
126
|
+
const text = await resolveTextOrStdin(rawText, out, _readStdin);
|
|
123
127
|
let attachBuffers = [];
|
|
124
128
|
try {
|
|
125
129
|
attachBuffers = await Promise.all(attachPaths.map((p) => readAttachment(p)));
|
|
@@ -181,11 +185,12 @@ async function runPostCreate(client, flags, out) {
|
|
|
181
185
|
await handleSdkError(err, outOpts, out);
|
|
182
186
|
}
|
|
183
187
|
}
|
|
184
|
-
async function runPostComment(client, flags, out) {
|
|
188
|
+
async function runPostComment(client, flags, out, _readStdin) {
|
|
185
189
|
const accountId = requireAccount(flags.account, out);
|
|
186
190
|
const postId = flags.postId ?? "";
|
|
187
|
-
const
|
|
191
|
+
const rawText = flags.text ?? "";
|
|
188
192
|
const replyTo = flags["reply-to"];
|
|
193
|
+
const text = await resolveTextOrStdin(rawText, out, _readStdin);
|
|
189
194
|
const attachPaths = normalizeAttachPaths(flags.attach);
|
|
190
195
|
let attachBuffers = [];
|
|
191
196
|
try {
|
|
@@ -368,7 +373,7 @@ var postCreateCommand = defineCommand({
|
|
|
368
373
|
args: {
|
|
369
374
|
// Write command: WRITE_FLAGS omits pagination/projection flags
|
|
370
375
|
...WRITE_FLAGS,
|
|
371
|
-
text: { type: "positional", description: "Post body text." },
|
|
376
|
+
text: { type: "positional", description: "Post body text. Pass - to read from stdin (enables multiline via heredoc or pipe)." },
|
|
372
377
|
attach: {
|
|
373
378
|
type: "string",
|
|
374
379
|
description: "Image/video/document to attach (repeatable for images; use --video-thumbnail when attaching a video). Supported: jpg, png, gif, mp4, pdf."
|
|
@@ -405,7 +410,7 @@ var postCommentCommand = defineCommand({
|
|
|
405
410
|
type: "positional",
|
|
406
411
|
description: "Numeric post id, urn:li:activity:N, or full LinkedIn share URL (activity-<N>- extracted). POSTID is always the post's id; use --reply-to <comment_id> to reply to a specific comment within this post."
|
|
407
412
|
},
|
|
408
|
-
text: { type: "positional", description: "Comment text (max ~1,250 characters per LinkedIn limits)." },
|
|
413
|
+
text: { type: "positional", description: "Comment text (max ~1,250 characters per LinkedIn limits). Pass - to read from stdin." },
|
|
409
414
|
attach: { type: "string", description: "Image to attach to the comment (optional; one image per comment)." },
|
|
410
415
|
"reply-to": {
|
|
411
416
|
type: "string",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
slimProfile,
|
|
4
|
-
slimProfileMe
|
|
5
|
-
} from "./chunk-5NS2G4WQ.js";
|
|
6
2
|
import {
|
|
7
3
|
buildPreviewOutput
|
|
8
4
|
} from "./chunk-R3VLWLVV.js";
|
|
5
|
+
import {
|
|
6
|
+
slimProfile,
|
|
7
|
+
slimProfileMe
|
|
8
|
+
} from "./chunk-6VBOKOQJ.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveIdentifier
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-SZB3CFRZ.js";
|
|
12
12
|
import {
|
|
13
13
|
streamAll
|
|
14
14
|
} from "./chunk-SND3NHCT.js";
|
|
@@ -18,10 +18,10 @@ import {
|
|
|
18
18
|
renderSuccess,
|
|
19
19
|
renderUnexpectedError,
|
|
20
20
|
resolveEffectiveConfig
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-47SYFQRF.js";
|
|
22
22
|
import {
|
|
23
23
|
GLOBAL_FLAGS
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-TDYIQHQX.js";
|
|
25
25
|
|
|
26
26
|
// src/commands/profile.ts
|
|
27
27
|
import { defineCommand } from "citty";
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "./chunk-R3VLWLVV.js";
|
|
13
13
|
import {
|
|
14
14
|
resolveIdentifier
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-SZB3CFRZ.js";
|
|
16
16
|
import {
|
|
17
17
|
DEFAULT_FILTER_READERS,
|
|
18
18
|
assembleFilters,
|
|
@@ -27,10 +27,10 @@ import {
|
|
|
27
27
|
renderSuccess,
|
|
28
28
|
renderUnexpectedError,
|
|
29
29
|
resolveEffectiveConfig
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-47SYFQRF.js";
|
|
31
31
|
import {
|
|
32
32
|
GLOBAL_FLAGS
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-TDYIQHQX.js";
|
|
34
34
|
|
|
35
35
|
// src/commands/recruiter.ts
|
|
36
36
|
import { defineCommand } from "citty";
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-R3VLWLVV.js";
|
|
9
9
|
import {
|
|
10
10
|
resolveIdentifier
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-SZB3CFRZ.js";
|
|
12
12
|
import {
|
|
13
13
|
DEFAULT_FILTER_READERS,
|
|
14
14
|
assembleFilters,
|
|
@@ -24,10 +24,10 @@ import {
|
|
|
24
24
|
renderSuccess,
|
|
25
25
|
renderUnexpectedError,
|
|
26
26
|
resolveEffectiveConfig
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-47SYFQRF.js";
|
|
28
28
|
import {
|
|
29
29
|
GLOBAL_FLAGS
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-TDYIQHQX.js";
|
|
31
31
|
|
|
32
32
|
// src/commands/sales-nav.ts
|
|
33
33
|
import { defineCommand } from "citty";
|
|
@@ -14,10 +14,10 @@ import {
|
|
|
14
14
|
renderSuccess,
|
|
15
15
|
renderUnexpectedError,
|
|
16
16
|
resolveEffectiveConfig
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-47SYFQRF.js";
|
|
18
18
|
import {
|
|
19
19
|
GLOBAL_FLAGS
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-TDYIQHQX.js";
|
|
21
21
|
|
|
22
22
|
// src/commands/search.ts
|
|
23
23
|
import { defineCommand } from "citty";
|
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
renderSuccess,
|
|
12
12
|
renderUnexpectedError,
|
|
13
13
|
resolveEffectiveConfig
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-47SYFQRF.js";
|
|
15
15
|
import {
|
|
16
16
|
GLOBAL_FLAGS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-TDYIQHQX.js";
|
|
18
18
|
|
|
19
19
|
// src/commands/webhook.ts
|
|
20
20
|
import { defineCommand } from "citty";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@curviate/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.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.
|
|
43
|
+
"@curviate/sdk": "^0.4.0",
|
|
44
44
|
"citty": "^0.1.6"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|