@curviate/cli 0.15.1 → 0.16.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
@@ -6,6 +6,70 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6
6
  Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html):
7
7
  a new command or flag is a minor; a breaking command/flag/exit-code change is a major; a fix is a patch.
8
8
 
9
+ ## [0.16.0] - 2026-07-17
10
+
11
+ A minor release adding the `inboxes` command group. No breaking changes,
12
+ built against `@curviate/sdk` 0.16.0.
13
+
14
+ ### Added
15
+
16
+ - **New `inboxes` command group (Beta), the reply-as-a-page workflow.**
17
+ `inboxes list [--kind personal|company] [--company-id <id>]` discovers the
18
+ account's personal inbox plus, when the company product is attached, one
19
+ entry per company page (id like `COMPANY_83734124_PRIMARY`), a flat,
20
+ non-paginated read (rejects `--all`). `inboxes chats <inbox_id> [--limit]
21
+ [--cursor] [--all]` lists a single inbox's conversations, cursor-paginated
22
+ like every other list command. Every returned chat id is send-ready: reply
23
+ with the existing `message send <chat_id> "<text>"`. A company inbox's
24
+ chat id (e.g. `COMPANY_83734124_2-…`) sends AS THE PAGE, no separate flag
25
+ needed. Company inboxes are reply-only and cannot start a new conversation.
26
+ Distinct from the existing `inbox` command group (a friendlier front door
27
+ to the account's own message-thread inbox: `messaging.listChats`/`getChat`/
28
+ `markChatRead`/`messages`). `inboxes` (plural) wraps the newer
29
+ inbox-*discovery* resource, so both groups coexist without a naming
30
+ collision.
31
+ - **`PREMIUM_CONFLICT` and `REAUTH_REQUIRED` mapped to exit code 8**
32
+ (account/connection state) in the error to exit table, the two new SDK
33
+ error codes surfacing from `account link`'s underlying `auth.intent` call:
34
+ a seat resolving to both individual-Premium tiers at once, and a
35
+ scope-changing reconnect attempted with a cookie instead of credentials.
36
+ - **`message send` names the acting identity on a company-page reply.**
37
+ When the response's `sent_as.kind` is `"company"`, the default output
38
+ (not just `--verbose --json`) now prints `Sent as <name> (company page)`
39
+ to stderr right after the send (the data itself was already on the
40
+ response; this makes it visible without inspecting raw JSON). A personal
41
+ send prints nothing new.
42
+ - **`message send --preview` echoes the acting identity for a `COMPANY_`
43
+ chat id.** Prints `Will send as a company page` to stderr, derived purely
44
+ from the chat id's own prefix so `--preview` still makes zero network
45
+ calls. A personal chat id prints nothing new.
46
+ - **`--limit` on `inbox list`, `inbox messages`, and `inboxes chats` is now
47
+ validated client-side against the server's accepted range (1-25).** A
48
+ value outside that range now exits 2 with `error: --limit must be
49
+ between 1 and 25 (default 20); got <value>.` before any network call,
50
+ instead of round-tripping to the server for the same 400. `--help` on
51
+ all three now states the range explicitly.
52
+
53
+ ## [0.15.2] - 2026-07-12
54
+
55
+ A patch release fixing an interactive-terminal hang on `account link`.
56
+
57
+ ### Fixed
58
+
59
+ - **`account link --password-stdin` / `--li-at-stdin` no longer hang on an
60
+ interactive terminal.** These flags previously read stdin to EOF, which a
61
+ human paste + Enter never produces on a TTY — the command hung
62
+ indefinitely and the pasted secret echoed on-screen. The read is now
63
+ mode-aware: piped/redirected stdin (non-TTY) is unchanged (read to EOF,
64
+ trimmed); an interactive TTY now prints a single cue line, then reads one
65
+ no-echo line — paste + Enter resolves immediately, including a paste whose
66
+ clipboard content ends in a trailing newline. An empty line still falls
67
+ through to the normal resolution order (env var, then the password
68
+ prompt / `li_at` fail-fast).
69
+ - **`--preview` never blocks on a terminal read.** Under `--preview`, the
70
+ interactive stdin read is suppressed entirely, matching every other
71
+ preview-mode command.
72
+
9
73
  ## [0.15.1] - 2026-07-11
10
74
 
11
75
  A patch release of agent-experience (AX) and developer-experience (DX)
@@ -4,10 +4,10 @@ import {
4
4
  } from "./chunk-U7Y4EXHT.js";
5
5
  import {
6
6
  readlineSync
7
- } from "./chunk-MKXA2LAR.js";
7
+ } from "./chunk-H4KV7MIN.js";
8
8
  import {
9
9
  AUTH_NEEDED
10
- } from "./chunk-ZE7QGR3F.js";
10
+ } from "./chunk-M6UDWFHX.js";
11
11
  import {
12
12
  buildPreviewOutput
13
13
  } from "./chunk-R3VLWLVV.js";
@@ -37,16 +37,33 @@ import {
37
37
  import { defineCommand } from "citty";
38
38
 
39
39
  // src/lib/credential-resolve.ts
40
+ var STDIN_TTY_CUE = "Reading secret from stdin (paste + Enter): ";
41
+ function defaultReadSingleLine() {
42
+ return readlineSync("", { mask: true });
43
+ }
40
44
  async function resolveSecret(params) {
41
45
  if (params.flagValue !== void 0 && params.flagValue !== "") {
42
46
  return params.flagValue;
43
47
  }
44
48
  if (params.stdinRequested) {
45
- const reader = params.readStdin ?? defaultReadStdin;
46
- const raw = await reader();
47
- const trimmed = raw.trim();
48
- if (trimmed !== "") {
49
- return trimmed;
49
+ if (params.isTTY) {
50
+ const stdinReadAllowed = params.allowInteractiveStdinRead ?? params.allowInteractive;
51
+ if (stdinReadAllowed !== false) {
52
+ params.out.stderr.write(STDIN_TTY_CUE);
53
+ const reader = params.readSingleLine ?? defaultReadSingleLine;
54
+ const raw = await reader(STDIN_TTY_CUE);
55
+ const trimmed = raw.trim();
56
+ if (trimmed !== "") {
57
+ return trimmed;
58
+ }
59
+ }
60
+ } else {
61
+ const reader = params.readStdin ?? defaultReadStdin;
62
+ const raw = await reader();
63
+ const trimmed = raw.trim();
64
+ if (trimmed !== "") {
65
+ return trimmed;
66
+ }
50
67
  }
51
68
  }
52
69
  const envValue = process.env[params.envVar];
@@ -204,7 +221,7 @@ function resolveOutputOpts(flags) {
204
221
  async function handleError(err, outOpts, out) {
205
222
  const { CurviateError } = await import("@curviate/sdk");
206
223
  if (err instanceof CurviateError) {
207
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
224
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
208
225
  renderError(err, outOpts, out);
209
226
  process.exit(getExitCode(err.code));
210
227
  }
@@ -262,12 +279,20 @@ async function buildAuthBody(flags, ctx) {
262
279
  flagValue: flags.password,
263
280
  stdinRequested: flags["password-stdin"],
264
281
  envVar: "CURVIATE_LINKEDIN_PASSWORD",
282
+ isTTY: ctx.isTTY,
265
283
  readStdin: ctx.readStdin,
284
+ readSingleLine: ctx.readSingleLine,
266
285
  required: true,
267
- // The interactive prompt/fail-fast only engages once --email is present
268
- // (nothing meaningful to prompt toward yet otherwise) — and never
269
- // under --preview (a client-side render must not prompt or exit).
286
+ // The masked-prompt/fail-fast tiers (3/4) only engage once --email is
287
+ // present (nothing meaningful to prompt toward yet otherwise) — and
288
+ // never under --preview (a client-side render must not prompt or
289
+ // exit).
270
290
  allowInteractive: !ctx.previewMode && Boolean(flags.email),
291
+ // Tier-1b's own gate is preview-only, deliberately NOT email-gated: a
292
+ // user who passed --password-stdin on a TTY gets the read regardless
293
+ // of --email — an email-less body still fails downstream validation,
294
+ // as expected, rather than the flag being silently ignored.
295
+ allowInteractiveStdinRead: !ctx.previewMode,
271
296
  failMessage: "no password \u2014 pass --password, --password-stdin, or set CURVIATE_LINKEDIN_PASSWORD",
272
297
  prompt: { isTTY: ctx.isTTY, readline: ctx.readline, promptText: "LinkedIn password: " },
273
298
  out: ctx.out
@@ -284,7 +309,9 @@ async function buildAuthBody(flags, ctx) {
284
309
  flagValue: flags["li-at"],
285
310
  stdinRequested: flags["li-at-stdin"],
286
311
  envVar: "CURVIATE_LINKEDIN_LI_AT",
312
+ isTTY: ctx.isTTY,
287
313
  readStdin: ctx.readStdin,
314
+ readSingleLine: ctx.readSingleLine,
288
315
  required: true,
289
316
  allowInteractive: !ctx.previewMode,
290
317
  failMessage: "no li_at \u2014 pass --li-at, --li-at-stdin, or set CURVIATE_LINKEDIN_LI_AT",
@@ -330,6 +357,13 @@ function resolveCredentialIO(io) {
330
357
  isOutputTTY: io.isOutputTTY ?? (process.stdout.isTTY ?? false),
331
358
  readline: io.readline ?? readlineSync,
332
359
  readStdin: io.readStdin ?? defaultReadStdin,
360
+ // Always the masked, no-echo raw-mode branch — never a bare readlineSync
361
+ // pass-through, which would default mask to false and echo the secret.
362
+ // Prompt is deliberately EMPTY, not `cue`: credential-resolve.ts already
363
+ // wrote STDIN_TTY_CUE to out.stderr before calling this reader, and
364
+ // readlineSync itself writes its `prompt` argument to stderr too — the
365
+ // cue text would otherwise print twice on a real terminal.
366
+ readSingleLine: io.readSingleLine ?? (() => readlineSync("", { mask: true })),
333
367
  sleep: io.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms))),
334
368
  now: io.now ?? (() => Date.now()),
335
369
  open: io.open ?? defaultOpen
@@ -464,6 +498,7 @@ async function runAccountLink(client, flags, out, io = {}) {
464
498
  isTTY: resolvedIo.isTTY,
465
499
  readline: resolvedIo.readline,
466
500
  readStdin: resolvedIo.readStdin,
501
+ readSingleLine: resolvedIo.readSingleLine,
467
502
  previewMode: flags.preview ?? false
468
503
  });
469
504
  const body = {
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/lib/readline.ts
4
+ import { createInterface } from "readline";
5
+ async function readlineSync(prompt, opts = {}) {
6
+ const stdin = opts.stdin ?? process.stdin;
7
+ return new Promise((resolve, reject) => {
8
+ process.stderr.write(prompt);
9
+ if (opts.mask && typeof stdin.setRawMode === "function") {
10
+ stdin.setRawMode(true);
11
+ stdin.resume();
12
+ stdin.setEncoding("utf8");
13
+ let input = "";
14
+ const onData = (chunk) => {
15
+ for (let i = 0; i < chunk.length; i++) {
16
+ const char = chunk[i];
17
+ if (char === "\r" || char === "\n") {
18
+ stdin.setRawMode?.(false);
19
+ stdin.pause();
20
+ stdin.removeListener("data", onData);
21
+ process.stderr.write("\n");
22
+ resolve(input);
23
+ return;
24
+ } else if (char === "") {
25
+ stdin.setRawMode?.(false);
26
+ stdin.pause();
27
+ stdin.removeListener("data", onData);
28
+ reject(new Error("Interrupted."));
29
+ return;
30
+ } else if (char === "\x7F" || char === "\b") {
31
+ input = input.slice(0, -1);
32
+ } else {
33
+ input += char;
34
+ }
35
+ }
36
+ };
37
+ stdin.on("data", onData);
38
+ } else {
39
+ const rl = createInterface({
40
+ input: stdin,
41
+ output: void 0,
42
+ // suppress default echo (prompt already on stderr)
43
+ terminal: false
44
+ });
45
+ rl.once("line", (line) => {
46
+ rl.close();
47
+ resolve(line.trim());
48
+ });
49
+ rl.once("error", reject);
50
+ rl.once("close", () => resolve(""));
51
+ }
52
+ });
53
+ }
54
+
55
+ export {
56
+ readlineSync
57
+ };
@@ -34,6 +34,8 @@ var EXIT_CODE_MAP = {
34
34
  ACCOUNT_ALREADY_LINKED: 8,
35
35
  LINKEDIN_OPERATION_NOT_SUPPORTED: 8,
36
36
  CONNECTION_REQUEST_CONFLICT: 8,
37
+ PREMIUM_CONFLICT: 8,
38
+ REAUTH_REQUIRED: 8,
37
39
  // Checkpoint flow (9)
38
40
  CHECKPOINT_NOT_FOUND: 9,
39
41
  CHECKPOINT_EXPIRED: 9,
package/dist/cli.js CHANGED
@@ -250,24 +250,25 @@ var main = defineCommand({
250
250
  // Subcommand registry — names and descriptions are static for help rendering;
251
251
  // the handler implementation is loaded lazily on first invocation.
252
252
  subCommands: {
253
- login: () => import("./login-MFB45PVZ.js").then((m) => m.loginCommand),
253
+ login: () => import("./login-GDLWR542.js").then((m) => m.loginCommand),
254
254
  config: () => import("./config-P5CPF5WC.js").then((m) => m.configCommand),
255
255
  // ---------------------------------------------------------------------------
256
256
  // Noun groups — lazy-loaded on first invocation.
257
257
  // ---------------------------------------------------------------------------
258
- profile: () => import("./profile-57RJEL7H.js").then((m) => m.profileCommand),
259
- company: () => import("./company-IYTMW64G.js").then((m) => m.companyCommand),
260
- job: () => import("./job-YARGTHUY.js").then((m) => m.jobCommand),
261
- connect: () => import("./connect-TTJHMBUP.js").then((m) => m.connectCommand),
262
- search: () => import("./search-RD4TXNV7.js").then((m) => m.searchCommand),
263
- inbox: () => import("./inbox-EOOGJ3ZN.js").then((m) => m.inboxCommand),
264
- message: () => import("./message-2DLIQIE6.js").then((m) => m.messageCommand),
265
- post: () => import("./post-GRIJ7X52.js").then((m) => m.postCommand),
266
- comment: () => import("./comment-NCDXERSI.js").then((m) => m.commentCommand),
267
- account: () => import("./account-FM473HEK.js").then((m) => m.accountCommand),
268
- webhook: () => import("./webhook-CEP7SGP5.js").then((m) => m.webhookCommand),
269
- "sales-nav": () => import("./sales-nav-NUMEYOEO.js").then((m) => m.salesNavCommand),
270
- recruiter: () => import("./recruiter-CTYH7AYG.js").then((m) => m.recruiterCommand)
258
+ profile: () => import("./profile-JUTGTPES.js").then((m) => m.profileCommand),
259
+ company: () => import("./company-XU7TZ66L.js").then((m) => m.companyCommand),
260
+ job: () => import("./job-QLSGNDGW.js").then((m) => m.jobCommand),
261
+ connect: () => import("./connect-7OWBNGHU.js").then((m) => m.connectCommand),
262
+ search: () => import("./search-5U5U5MTT.js").then((m) => m.searchCommand),
263
+ inbox: () => import("./inbox-VVRQ7SOX.js").then((m) => m.inboxCommand),
264
+ inboxes: () => import("./inboxes-MTPWLP5F.js").then((m) => m.inboxesCommand),
265
+ message: () => import("./message-IKKOI6CZ.js").then((m) => m.messageCommand),
266
+ post: () => import("./post-DH4RDYKZ.js").then((m) => m.postCommand),
267
+ comment: () => import("./comment-COJY6HQP.js").then((m) => m.commentCommand),
268
+ account: () => import("./account-ZDIZAXVI.js").then((m) => m.accountCommand),
269
+ webhook: () => import("./webhook-UWIOVWVV.js").then((m) => m.webhookCommand),
270
+ "sales-nav": () => import("./sales-nav-NUCYJ4S3.js").then((m) => m.salesNavCommand),
271
+ recruiter: () => import("./recruiter-WEZZVZN3.js").then((m) => m.recruiterCommand)
271
272
  },
272
273
  async run() {
273
274
  const { runMain } = await import("citty");
@@ -70,7 +70,7 @@ function buildListQuery(flags) {
70
70
  async function handleSdkError(err, outOpts, out) {
71
71
  const { CurviateError } = await import("@curviate/sdk");
72
72
  if (err instanceof CurviateError) {
73
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
73
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
74
74
  renderError(err, outOpts, out);
75
75
  process.exit(getExitCode(err.code));
76
76
  }
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ resolveIdentifier
4
+ } from "./chunk-DMQZEPQE.js";
2
5
  import {
3
6
  slimCompany,
4
7
  slimSearchJobs,
5
8
  slimSearchPeople,
6
9
  slimSearchPosts
7
10
  } from "./chunk-45KHSWCV.js";
8
- import {
9
- resolveIdentifier
10
- } from "./chunk-DMQZEPQE.js";
11
11
  import {
12
12
  pageDelayFromFlags,
13
13
  streamAll
@@ -61,7 +61,7 @@ async function resolveCompanyId(ns, raw) {
61
61
  async function handleSdkError(err, outOpts, out) {
62
62
  const { CurviateError } = await import("@curviate/sdk");
63
63
  if (err instanceof CurviateError) {
64
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
64
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
65
65
  renderError(err, outOpts, out);
66
66
  process.exit(getExitCode(err.code));
67
67
  }
@@ -2,15 +2,15 @@
2
2
  import {
3
3
  buildPreviewOutput
4
4
  } from "./chunk-R3VLWLVV.js";
5
+ import {
6
+ resolveIdentifier
7
+ } from "./chunk-DMQZEPQE.js";
5
8
  import {
6
9
  slimInviteReceived,
7
10
  slimInviteReceivedItem,
8
11
  slimInviteSent,
9
12
  slimInviteSentItem
10
13
  } from "./chunk-45KHSWCV.js";
11
- import {
12
- resolveIdentifier
13
- } from "./chunk-DMQZEPQE.js";
14
14
  import {
15
15
  pageDelayFromFlags,
16
16
  streamAll
@@ -82,7 +82,7 @@ async function runConnectSend(client, flags, out) {
82
82
  } catch (err) {
83
83
  const { CurviateError } = await import("@curviate/sdk");
84
84
  if (err instanceof CurviateError) {
85
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
85
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
86
86
  renderError(err, outOpts, out);
87
87
  process.exit(getExitCode(err.code));
88
88
  }
@@ -120,7 +120,7 @@ async function runConnectSent(client, flags, out) {
120
120
  } catch (err) {
121
121
  const { CurviateError } = await import("@curviate/sdk");
122
122
  if (err instanceof CurviateError) {
123
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
123
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
124
124
  renderError(err, outOpts, out);
125
125
  process.exit(getExitCode(err.code));
126
126
  }
@@ -158,7 +158,7 @@ async function runConnectReceived(client, flags, out) {
158
158
  } catch (err) {
159
159
  const { CurviateError } = await import("@curviate/sdk");
160
160
  if (err instanceof CurviateError) {
161
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
161
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
162
162
  renderError(err, outOpts, out);
163
163
  process.exit(getExitCode(err.code));
164
164
  }
@@ -187,7 +187,7 @@ async function runConnectAccept(client, flags, out) {
187
187
  } catch (err) {
188
188
  const { CurviateError } = await import("@curviate/sdk");
189
189
  if (err instanceof CurviateError) {
190
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
190
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
191
191
  renderError(err, outOpts, out);
192
192
  process.exit(getExitCode(err.code));
193
193
  }
@@ -216,7 +216,7 @@ async function runConnectDecline(client, flags, out) {
216
216
  } catch (err) {
217
217
  const { CurviateError } = await import("@curviate/sdk");
218
218
  if (err instanceof CurviateError) {
219
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
219
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
220
220
  renderError(err, outOpts, out);
221
221
  process.exit(getExitCode(err.code));
222
222
  }
@@ -245,7 +245,7 @@ async function runConnectCancel(client, flags, out) {
245
245
  } catch (err) {
246
246
  const { CurviateError } = await import("@curviate/sdk");
247
247
  if (err instanceof CurviateError) {
248
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
248
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
249
249
  renderError(err, outOpts, out);
250
250
  process.exit(getExitCode(err.code));
251
251
  }
@@ -3,7 +3,7 @@ import {
3
3
  AUTH_NEEDED,
4
4
  EXIT_CODE_MAP,
5
5
  getExitCode
6
- } from "./chunk-ZE7QGR3F.js";
6
+ } from "./chunk-M6UDWFHX.js";
7
7
  export {
8
8
  AUTH_NEEDED,
9
9
  EXIT_CODE_MAP,
@@ -71,10 +71,20 @@ function validateIsoZTimestamp(value, flagName, out) {
71
71
  process.exit(2);
72
72
  }
73
73
  }
74
+ function validateLimitRange(raw, out) {
75
+ if (raw === void 0) return;
76
+ const n = Number(raw);
77
+ if (!Number.isFinite(n)) return;
78
+ if (n < 1 || n > 25) {
79
+ out.stderr.write(`error: --limit must be between 1 and 25 (default 20); got ${raw}.
80
+ `);
81
+ process.exit(2);
82
+ }
83
+ }
74
84
  async function handleSdkError(err, outOpts, out) {
75
85
  const { CurviateError } = await import("@curviate/sdk");
76
86
  if (err instanceof CurviateError) {
77
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
87
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
78
88
  renderError(err, outOpts, out);
79
89
  process.exit(getExitCode(err.code));
80
90
  }
@@ -89,6 +99,7 @@ async function runInboxList(client, flags, out) {
89
99
  const all = flags.all ?? false;
90
100
  const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
91
101
  const params = buildPaginationParams(flags);
102
+ validateLimitRange(flags.limit, out);
92
103
  if (flags.unread !== void 0) {
93
104
  params.unread = flags.unread;
94
105
  }
@@ -151,6 +162,7 @@ async function runInboxMessages(client, flags, out) {
151
162
  const all = flags.all ?? false;
152
163
  const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
153
164
  const params = buildPaginationParams(flags);
165
+ validateLimitRange(flags.limit, out);
154
166
  if (flags.before !== void 0) {
155
167
  validateIsoZTimestamp(flags.before, "before", out);
156
168
  params.before = flags.before;
@@ -181,6 +193,7 @@ var inboxListCommand = defineCommand({
181
193
  meta: { name: "list", description: "List inbox chats." },
182
194
  args: {
183
195
  ...GLOBAL_FLAGS,
196
+ limit: { type: "string", description: "Number of items to return per page (1-25, default 20)." },
184
197
  unread: {
185
198
  type: "boolean",
186
199
  description: "Show unread chats only (--no-unread for read-only; omit for all)."
@@ -259,6 +272,7 @@ var inboxMessagesCommand = defineCommand({
259
272
  meta: { name: "messages", description: "List messages in a chat. A very recent send/delete may take a few minutes to appear or clear here (LinkedIn-side indexing); `message get <chat_id> <message_id>` reflects it immediately." },
260
273
  args: {
261
274
  ...GLOBAL_FLAGS,
275
+ limit: { type: "string", description: "Number of items to return per page (1-25, default 20)." },
262
276
  chatId: { type: "positional", description: "Chat ID." },
263
277
  before: {
264
278
  type: "string",
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ pageDelayFromFlags,
4
+ streamAll
5
+ } from "./chunk-EEMJDJ4W.js";
6
+ import {
7
+ createClient,
8
+ renderError,
9
+ renderSuccess,
10
+ renderUnexpectedError,
11
+ resolveEffectiveConfig
12
+ } from "./chunk-M33MI53G.js";
13
+ import {
14
+ GLOBAL_FLAGS,
15
+ READ_SINGLE_FLAGS
16
+ } from "./chunk-TMU3CSPR.js";
17
+
18
+ // src/commands/inboxes.ts
19
+ import { defineCommand } from "citty";
20
+ function buildOutputStreams() {
21
+ return {
22
+ stdout: { write: (s) => process.stdout.write(s) },
23
+ stderr: { write: (s) => process.stderr.write(s) }
24
+ };
25
+ }
26
+ function requireAccount(account, out) {
27
+ if (!account) {
28
+ out.stderr.write("error: --account is required for this command. Set it via --account, CURVIATE_ACCOUNT, or `curviate config set-account`.\n");
29
+ process.exit(2);
30
+ }
31
+ return account;
32
+ }
33
+ function rejectPreviewOnRead(preview, out) {
34
+ if (preview) {
35
+ out.stderr.write("error: --preview is only valid on write commands (mutations). Reads just run.\n");
36
+ process.exit(2);
37
+ }
38
+ }
39
+ function rejectAllOnNonPaginated(all, out) {
40
+ if (all) {
41
+ out.stderr.write("error: --all is not supported on non-paginated commands.\n");
42
+ process.exit(2);
43
+ }
44
+ }
45
+ function resolveOutputOpts(flags) {
46
+ return {
47
+ json: (flags.json ?? false) || !process.stdout.isTTY,
48
+ isTTY: process.stdout.isTTY ?? false,
49
+ fields: flags.fields,
50
+ verbose: flags.verbose ?? false
51
+ };
52
+ }
53
+ async function handleSdkError(err, outOpts, out) {
54
+ const { CurviateError } = await import("@curviate/sdk");
55
+ if (err instanceof CurviateError) {
56
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
57
+ renderError(err, outOpts, out);
58
+ process.exit(getExitCode(err.code));
59
+ }
60
+ renderUnexpectedError(err, out);
61
+ process.exit(1);
62
+ }
63
+ function validateLimitRange(raw, out) {
64
+ if (raw === void 0) return;
65
+ const n = Number(raw);
66
+ if (!Number.isFinite(n)) return;
67
+ if (n < 1 || n > 25) {
68
+ out.stderr.write(`error: --limit must be between 1 and 25 (default 20); got ${raw}.
69
+ `);
70
+ process.exit(2);
71
+ }
72
+ }
73
+ async function runInboxesList(client, flags, out) {
74
+ rejectPreviewOnRead(flags.preview, out);
75
+ rejectAllOnNonPaginated(flags.all, out);
76
+ const accountId = requireAccount(flags.account, out);
77
+ const ns = client.account(accountId);
78
+ const outOpts = resolveOutputOpts(flags);
79
+ const params = {};
80
+ if (flags.kind) params["kind"] = flags.kind;
81
+ if (flags["company-id"]) params["company_id"] = flags["company-id"];
82
+ try {
83
+ const result = await ns.inboxes.list(params);
84
+ renderSuccess(result, outOpts, out);
85
+ } catch (err) {
86
+ await handleSdkError(err, outOpts, out);
87
+ }
88
+ }
89
+ async function runInboxesChats(client, flags, out) {
90
+ rejectPreviewOnRead(flags.preview, out);
91
+ const accountId = requireAccount(flags.account, out);
92
+ const inboxId = flags.inboxId ?? "";
93
+ const ns = client.account(accountId);
94
+ const outOpts = resolveOutputOpts(flags);
95
+ const all = flags.all ?? false;
96
+ const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
97
+ validateLimitRange(flags.limit, out);
98
+ const params = {};
99
+ if (flags.limit) params["limit"] = parseInt(flags.limit, 10);
100
+ if (flags.cursor) params["cursor"] = flags.cursor;
101
+ try {
102
+ if (all) {
103
+ const fn = (p) => ns.inboxes.listChats(inboxId, p);
104
+ for await (const item of streamAll(fn, params, {
105
+ maxPages,
106
+ out,
107
+ pageDelayMs: pageDelayFromFlags(flags)
108
+ })) {
109
+ out.stdout.write(JSON.stringify(item) + "\n");
110
+ }
111
+ } else {
112
+ const result = await ns.inboxes.listChats(inboxId, params);
113
+ renderSuccess(result, outOpts, out);
114
+ }
115
+ } catch (err) {
116
+ await handleSdkError(err, outOpts, out);
117
+ }
118
+ }
119
+ var inboxesListCommand = defineCommand({
120
+ meta: { name: "list", description: "Discover the account's inboxes (personal + company pages)." },
121
+ args: {
122
+ // Single-object-shaped read: READ_SINGLE_FLAGS omits pagination flags
123
+ // (this response carries no cursor — every inbox comes back in one call).
124
+ ...READ_SINGLE_FLAGS,
125
+ kind: {
126
+ type: "string",
127
+ description: "Filter to only personal or only company inboxes: personal | company. Omit to list both."
128
+ },
129
+ "company-id": {
130
+ type: "string",
131
+ description: "Filter to the one company inbox correlated to this managed-company id (e.g. 112013061)."
132
+ }
133
+ },
134
+ async run({ args }) {
135
+ const flags = args;
136
+ const cfg = await resolveEffectiveConfig({
137
+ apiKey: flags["api-key"],
138
+ baseUrl: flags["base-url"],
139
+ timeout: flags.timeout,
140
+ account: flags.account,
141
+ profile: flags.profile
142
+ });
143
+ if (!cfg.apiKey) {
144
+ process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
145
+ process.exit(3);
146
+ }
147
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
148
+ const out = buildOutputStreams();
149
+ await runInboxesList(client, { ...flags, account: flags.account ?? cfg.account }, out);
150
+ }
151
+ });
152
+ var inboxesChatsCommand = defineCommand({
153
+ meta: {
154
+ name: "chats",
155
+ description: "List an inbox's conversations. Each chat id is send-ready: reply with `message send <chat_id> \"<text>\"`. A company inbox's chat id (e.g. COMPANY_83734124_2-\u2026) sends AS THE PAGE, no separate flag needed. Company inboxes are reply-only and cannot start a new conversation."
156
+ },
157
+ args: {
158
+ ...GLOBAL_FLAGS,
159
+ limit: { type: "string", description: "Number of items to return per page (1-25, default 20)." },
160
+ inboxId: { type: "positional", description: "Inbox id from `inboxes list` (e.g. CLASSIC_PRIMARY or COMPANY_83734124_PRIMARY)." }
161
+ },
162
+ async run({ args }) {
163
+ const flags = args;
164
+ const cfg = await resolveEffectiveConfig({
165
+ apiKey: flags["api-key"],
166
+ baseUrl: flags["base-url"],
167
+ timeout: flags.timeout,
168
+ account: flags.account,
169
+ profile: flags.profile
170
+ });
171
+ if (!cfg.apiKey) {
172
+ process.stderr.write("error: no API key \u2014 run `curviate login` or pass --api-key.\n");
173
+ process.exit(3);
174
+ }
175
+ const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl, timeout: cfg.timeout });
176
+ const out = buildOutputStreams();
177
+ await runInboxesChats(client, { ...flags, account: flags.account ?? cfg.account }, out);
178
+ }
179
+ });
180
+ var inboxesCommand = defineCommand({
181
+ meta: {
182
+ name: "inboxes",
183
+ description: "Discover LinkedIn inboxes (personal + company pages) and list their conversations. Beta. See also: `inbox` (the account's own message-thread inbox), `message send` (reply to a chat)."
184
+ },
185
+ subCommands: {
186
+ list: inboxesListCommand,
187
+ chats: inboxesChatsCommand
188
+ },
189
+ async run() {
190
+ process.stderr.write(
191
+ "Usage: curviate inboxes <subcommand>\n list [--kind personal|company] [--company-id <id>]\n chats <inbox_id> [--limit] [--cursor] [--all]\n"
192
+ );
193
+ }
194
+ });
195
+ export {
196
+ inboxesCommand,
197
+ runInboxesChats,
198
+ runInboxesList
199
+ };
@@ -6,12 +6,12 @@ import {
6
6
  import {
7
7
  buildPreviewOutput
8
8
  } from "./chunk-R3VLWLVV.js";
9
- import {
10
- slimJob
11
- } from "./chunk-45KHSWCV.js";
12
9
  import {
13
10
  resolveJobIdentifier
14
11
  } from "./chunk-DMQZEPQE.js";
12
+ import {
13
+ slimJob
14
+ } from "./chunk-45KHSWCV.js";
15
15
  import {
16
16
  DEFAULT_PAGE_DELAY_MS,
17
17
  ndjsonModeNotice,
@@ -98,7 +98,7 @@ function requireEnum(value, allowed, flag, out) {
98
98
  async function handleSdkError(err, outOpts, out) {
99
99
  const { CurviateError } = await import("@curviate/sdk");
100
100
  if (err instanceof CurviateError) {
101
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
101
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
102
102
  renderError(err, outOpts, out);
103
103
  process.exit(getExitCode(err.code));
104
104
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  readlineSync
4
- } from "./chunk-MKXA2LAR.js";
4
+ } from "./chunk-H4KV7MIN.js";
5
5
  import {
6
6
  GLOBAL_FLAGS,
7
7
  writeProfile
@@ -73,13 +73,23 @@ var MEMBER_PROVIDER_ID_RE = /^A[CDE][A-Za-z0-9_-]{4,}$/;
73
73
  async function handleSdkError(err, outOpts, out) {
74
74
  const { CurviateError } = await import("@curviate/sdk");
75
75
  if (err instanceof CurviateError) {
76
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
76
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
77
77
  renderError(err, outOpts, out);
78
78
  process.exit(getExitCode(err.code));
79
79
  }
80
80
  renderUnexpectedError(err, out);
81
81
  process.exit(1);
82
82
  }
83
+ function sentAsNotice(sentAs) {
84
+ if (!sentAs || typeof sentAs !== "object") return null;
85
+ const s = sentAs;
86
+ if (s.kind !== "company") return null;
87
+ return s.name ? `Sent as ${s.name} (company page)
88
+ ` : "Sent as a company page\n";
89
+ }
90
+ function willSendAsNotice(chatId) {
91
+ return chatId.startsWith("COMPANY_") ? "Will send as a company page\n" : null;
92
+ }
83
93
  async function runMessageNew(client, flags, out, _readStdin) {
84
94
  const accountId = requireAccount(flags.account, out);
85
95
  const rawTo = flags.to ?? "";
@@ -168,6 +178,8 @@ async function runMessageSend(client, flags, out, _readStdin) {
168
178
  }))
169
179
  });
170
180
  out.stdout.write(JSON.stringify(preview) + "\n");
181
+ const willSendAs = willSendAsNotice(chatId);
182
+ if (willSendAs) out.stderr.write(willSendAs);
171
183
  return;
172
184
  }
173
185
  const attachmentPayloads = attachBuffers.map((buf, i) => toAttachmentPayload(attachPaths[i], buf));
@@ -180,6 +192,8 @@ async function runMessageSend(client, flags, out, _readStdin) {
180
192
  try {
181
193
  const result = await ns.messaging.sendMessage(chatId, body);
182
194
  renderSuccess(result, outOpts, out);
195
+ const notice = sentAsNotice(result?.["sent_as"]);
196
+ if (notice) out.stderr.write(notice);
183
197
  } catch (err) {
184
198
  await handleSdkError(err, outOpts, out);
185
199
  }
@@ -572,11 +586,17 @@ var messageInMailCommand = defineCommand({
572
586
  }
573
587
  });
574
588
  var messageSendCommand = defineCommand({
575
- meta: { name: "send", description: "Send a message to an existing chat." },
589
+ meta: {
590
+ name: "send",
591
+ description: 'Send a message to an existing chat. Pass a COMPANY_ chat id (from `inboxes chats`) to send as that company page instead of yourself, no separate flag needed. The output shows the acting identity: a company-page send prints "Sent as <name> (company page)", a personal send prints nothing new. See also: `inboxes chats` (discover a COMPANY_ chat id) and the Reply as a company page guide.'
592
+ },
576
593
  args: {
577
594
  // Write command: WRITE_FLAGS omits pagination/projection flags
578
595
  ...WRITE_FLAGS,
579
- chatId: { type: "positional", description: "Chat ID or LinkedIn messaging thread URL." },
596
+ chatId: {
597
+ type: "positional",
598
+ description: "Chat ID or LinkedIn messaging thread URL. A COMPANY_ chat id sends as the company page; any other chat id sends as the connected member."
599
+ },
580
600
  text: { type: "positional", description: "Message text. Pass - to read from stdin (e.g. via heredoc or pipe)." },
581
601
  attach: { type: "string", description: "File to attach (repeatable)." }
582
602
  },
@@ -623,11 +643,18 @@ var messageInMailBalanceCommand = defineCommand({
623
643
  }
624
644
  });
625
645
  var messageCommand = defineCommand({
626
- meta: { name: "message", description: "Send and manage LinkedIn messages." },
646
+ meta: {
647
+ name: "message",
648
+ description: "Send and manage LinkedIn messages. A COMPANY_ chat id (from `inboxes chats`) sends as that company page instead of yourself; see `message send --help`."
649
+ },
627
650
  args: {
628
651
  // Write command (message send): WRITE_FLAGS omits pagination/projection flags
629
652
  ...WRITE_FLAGS,
630
- chatId: { type: "positional", description: "Chat ID to send a message to.", required: false },
653
+ chatId: {
654
+ type: "positional",
655
+ description: "Chat ID to send a message to. A COMPANY_ chat id sends as the company page.",
656
+ required: false
657
+ },
631
658
  text: { type: "positional", description: "Message text. Pass - to read from stdin.", required: false },
632
659
  attach: { type: "string", description: "File to attach (repeatable)." }
633
660
  },
@@ -79,7 +79,7 @@ function normalizeAttachPaths(attach) {
79
79
  async function handleSdkError(err, outOpts, out) {
80
80
  const { CurviateError } = await import("@curviate/sdk");
81
81
  if (err instanceof CurviateError) {
82
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
82
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
83
83
  renderError(err, outOpts, out);
84
84
  process.exit(getExitCode(err.code));
85
85
  }
@@ -11,13 +11,13 @@ import {
11
11
  import {
12
12
  buildPreviewOutput
13
13
  } from "./chunk-R3VLWLVV.js";
14
+ import {
15
+ resolveIdentifier
16
+ } from "./chunk-DMQZEPQE.js";
14
17
  import {
15
18
  slimProfile,
16
19
  slimProfileMe
17
20
  } from "./chunk-45KHSWCV.js";
18
- import {
19
- resolveIdentifier
20
- } from "./chunk-DMQZEPQE.js";
21
21
  import {
22
22
  pageDelayFromFlags,
23
23
  streamAll
@@ -189,7 +189,7 @@ async function runProfileMe(client, flags, out) {
189
189
  } catch (err) {
190
190
  const { CurviateError } = await import("@curviate/sdk");
191
191
  if (err instanceof CurviateError) {
192
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
192
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
193
193
  renderError(err, outOpts, out);
194
194
  process.exit(getExitCode(err.code));
195
195
  }
@@ -215,7 +215,7 @@ async function runProfileMe(client, flags, out) {
215
215
  } catch (err) {
216
216
  const { CurviateError } = await import("@curviate/sdk");
217
217
  if (err instanceof CurviateError) {
218
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
218
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
219
219
  renderError(err, outOpts, out);
220
220
  process.exit(getExitCode(err.code));
221
221
  }
@@ -341,7 +341,7 @@ async function runProfileGet(client, flags, out) {
341
341
  } catch (err) {
342
342
  const { CurviateError } = await import("@curviate/sdk");
343
343
  if (err instanceof CurviateError) {
344
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
344
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
345
345
  renderError(err, outOpts, out);
346
346
  process.exit(getExitCode(err.code));
347
347
  }
@@ -378,7 +378,7 @@ async function runProfileRelations(client, flags, out) {
378
378
  } catch (err) {
379
379
  const { CurviateError } = await import("@curviate/sdk");
380
380
  if (err instanceof CurviateError) {
381
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
381
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
382
382
  renderError(err, outOpts, out);
383
383
  process.exit(getExitCode(err.code));
384
384
  }
@@ -418,7 +418,7 @@ async function runProfileEndorse(client, flags, out) {
418
418
  async function handleSdkError(err, outOpts, out) {
419
419
  const { CurviateError } = await import("@curviate/sdk");
420
420
  if (err instanceof CurviateError) {
421
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
421
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
422
422
  renderError(err, outOpts, out);
423
423
  process.exit(getExitCode(err.code));
424
424
  }
@@ -16,13 +16,13 @@ import {
16
16
  import {
17
17
  buildPreviewOutput
18
18
  } from "./chunk-R3VLWLVV.js";
19
- import {
20
- slimJob
21
- } from "./chunk-45KHSWCV.js";
22
19
  import {
23
20
  resolveIdentifier,
24
21
  resolveJobIdentifier
25
22
  } from "./chunk-DMQZEPQE.js";
23
+ import {
24
+ slimJob
25
+ } from "./chunk-45KHSWCV.js";
26
26
  import {
27
27
  pageDelayFromFlags,
28
28
  streamAll
@@ -78,7 +78,7 @@ function normalizeAttachPaths(attach) {
78
78
  async function handleSdkError(err, outOpts, out) {
79
79
  const { CurviateError } = await import("@curviate/sdk");
80
80
  if (err instanceof CurviateError) {
81
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
81
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
82
82
  renderError(err, outOpts, out);
83
83
  process.exit(getExitCode(err.code));
84
84
  }
@@ -68,7 +68,7 @@ function normalizeAttachPaths(attach) {
68
68
  async function handleSdkError(err, outOpts, out) {
69
69
  const { CurviateError } = await import("@curviate/sdk");
70
70
  if (err instanceof CurviateError) {
71
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
71
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
72
72
  renderError(err, outOpts, out);
73
73
  process.exit(getExitCode(err.code));
74
74
  }
@@ -220,7 +220,7 @@ async function runSearchPeople(client, flags, out, readers = DEFAULT_FILTER_READ
220
220
  } catch (err) {
221
221
  const { CurviateError } = await import("@curviate/sdk");
222
222
  if (err instanceof CurviateError) {
223
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
223
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
224
224
  renderError(err, outOpts, out);
225
225
  process.exit(getExitCode(err.code));
226
226
  }
@@ -261,7 +261,7 @@ async function runSearchCompanies(client, flags, out, readers = DEFAULT_FILTER_R
261
261
  } catch (err) {
262
262
  const { CurviateError } = await import("@curviate/sdk");
263
263
  if (err instanceof CurviateError) {
264
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
264
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
265
265
  renderError(err, outOpts, out);
266
266
  process.exit(getExitCode(err.code));
267
267
  }
@@ -302,7 +302,7 @@ async function runSearchPosts(client, flags, out, readers = DEFAULT_FILTER_READE
302
302
  } catch (err) {
303
303
  const { CurviateError } = await import("@curviate/sdk");
304
304
  if (err instanceof CurviateError) {
305
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
305
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
306
306
  renderError(err, outOpts, out);
307
307
  process.exit(getExitCode(err.code));
308
308
  }
@@ -343,7 +343,7 @@ async function runSearchJobs(client, flags, out, readers = DEFAULT_FILTER_READER
343
343
  } catch (err) {
344
344
  const { CurviateError } = await import("@curviate/sdk");
345
345
  if (err instanceof CurviateError) {
346
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
346
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
347
347
  renderError(err, outOpts, out);
348
348
  process.exit(getExitCode(err.code));
349
349
  }
@@ -376,7 +376,7 @@ async function runSearchParameters(client, flags, out) {
376
376
  } catch (err) {
377
377
  const { CurviateError } = await import("@curviate/sdk");
378
378
  if (err instanceof CurviateError) {
379
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
379
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
380
380
  renderError(err, outOpts, out);
381
381
  process.exit(getExitCode(err.code));
382
382
  }
@@ -413,7 +413,7 @@ async function runSearchFromUrl(client, flags, out) {
413
413
  } catch (err) {
414
414
  const { CurviateError } = await import("@curviate/sdk");
415
415
  if (err instanceof CurviateError) {
416
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
416
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
417
417
  renderError(err, outOpts, out);
418
418
  process.exit(getExitCode(err.code));
419
419
  }
@@ -48,7 +48,7 @@ function resolveOutputOpts(flags) {
48
48
  async function handleError(err, outOpts, out) {
49
49
  const { CurviateError } = await import("@curviate/sdk");
50
50
  if (err instanceof CurviateError) {
51
- const { getExitCode } = await import("./exit-codes-SL3GQF7W.js");
51
+ const { getExitCode } = await import("./exit-codes-63JE5GM5.js");
52
52
  renderError(err, outOpts, out);
53
53
  process.exit(getExitCode(err.code));
54
54
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curviate/cli",
3
- "version": "0.15.1",
3
+ "version": "0.16.0",
4
4
  "private": false,
5
5
  "description": "Official command-line interface for the Curviate API.",
6
6
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  "clean": "rm -rf dist *.tsbuildinfo"
42
42
  },
43
43
  "dependencies": {
44
- "@curviate/sdk": "^0.15.0",
44
+ "@curviate/sdk": "^0.16.0",
45
45
  "citty": "^0.1.6",
46
46
  "open": "^10.1.0"
47
47
  },
@@ -1,51 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/lib/readline.ts
4
- import { createInterface } from "readline";
5
- async function readlineSync(prompt, opts = {}) {
6
- return new Promise((resolve, reject) => {
7
- process.stderr.write(prompt);
8
- if (opts.mask && typeof process.stdin.setRawMode === "function") {
9
- process.stdin.setRawMode(true);
10
- process.stdin.resume();
11
- process.stdin.setEncoding("utf8");
12
- let input = "";
13
- const onData = (char) => {
14
- if (char === "\r" || char === "\n") {
15
- process.stdin.setRawMode(false);
16
- process.stdin.pause();
17
- process.stdin.removeListener("data", onData);
18
- process.stderr.write("\n");
19
- resolve(input);
20
- } else if (char === "") {
21
- process.stdin.setRawMode(false);
22
- process.stdin.pause();
23
- process.stdin.removeListener("data", onData);
24
- reject(new Error("Interrupted."));
25
- } else if (char === "\x7F" || char === "\b") {
26
- input = input.slice(0, -1);
27
- } else {
28
- input += char;
29
- }
30
- };
31
- process.stdin.on("data", onData);
32
- } else {
33
- const rl = createInterface({
34
- input: process.stdin,
35
- output: void 0,
36
- // suppress default echo (prompt already on stderr)
37
- terminal: false
38
- });
39
- rl.once("line", (line) => {
40
- rl.close();
41
- resolve(line.trim());
42
- });
43
- rl.once("error", reject);
44
- rl.once("close", () => resolve(""));
45
- }
46
- });
47
- }
48
-
49
- export {
50
- readlineSync
51
- };