@rolino/cli 0.1.0 → 0.3.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/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runCli
4
- } from "./chunk-YTEWMNSV.js";
4
+ } from "./chunk-7BCIIFUB.js";
5
5
 
6
6
  // src/bin.ts
7
7
  void runCli().then(
@@ -276,7 +276,8 @@ async function setupMcp(options) {
276
276
 
277
277
  // src/cli.ts
278
278
  import { randomUUID } from "crypto";
279
- import { readFile as readFile2, stat } from "fs/promises";
279
+ import { openAsBlob } from "fs";
280
+ import { stat } from "fs/promises";
280
281
  import { basename, extname, resolve as resolve2 } from "path";
281
282
  import { createInterface } from "readline/promises";
282
283
  import { Command, CommanderError, InvalidArgumentError } from "commander";
@@ -284,7 +285,7 @@ import { Command, CommanderError, InvalidArgumentError } from "commander";
284
285
  // package.json
285
286
  var package_default = {
286
287
  name: "@rolino/cli",
287
- version: "0.1.0",
288
+ version: "0.3.0",
288
289
  description: "Agent-friendly command-line interface for Rolino",
289
290
  type: "module",
290
291
  license: "MIT",
@@ -341,9 +342,9 @@ var package_default = {
341
342
  dev: "tsx src/bin.ts"
342
343
  },
343
344
  dependencies: {
344
- "@rolino/contracts": "0.1.0",
345
- "@rolino/local-auth": "0.1.0",
346
- "@rolino/sdk": "0.1.0",
345
+ "@rolino/contracts": "0.3.0",
346
+ "@rolino/local-auth": "0.3.0",
347
+ "@rolino/sdk": "0.3.0",
347
348
  commander: "^15.0.0",
348
349
  open: "^11.0.0"
349
350
  },
@@ -360,7 +361,9 @@ import {
360
361
  PostStatusSchema,
361
362
  ProjectCreateInputSchema,
362
363
  ProjectTypeSchema,
364
+ ProviderDeliveryOptionsProviderSchema,
363
365
  PublishingProviderSchema,
366
+ TikTokDraftSettingsSchema,
364
367
  YouTubePostSettingsSchema
365
368
  } from "@rolino/contracts";
366
369
  import {
@@ -728,7 +731,13 @@ function formatPost(post) {
728
731
  ] : [],
729
732
  ...post.publishedAt ? [`Published: ${post.publishedAt}`] : [],
730
733
  `Media: ${post.media.length}`,
731
- `Destinations: ${post.destinations.map((destination) => `${destination.provider}:${queued && destination.status === "SCHEDULED" ? "QUEUED" : destination.status}`).join(", ") || "none"}`
734
+ `Destinations: ${post.destinations.map((destination) => `${destination.provider}:${queued && destination.status === "SCHEDULED" ? "QUEUED" : destination.status}`).join(", ") || "none"}`,
735
+ ...post.providerSettings?.TIKTOK ? [
736
+ `TikTok: ${post.providerSettings.TIKTOK.postMode}, ${post.providerSettings.TIKTOK.privacyLevel ?? "visibility not set"}, settings ${post.providerSettings.TIKTOK.consentedAt ? "reviewed" : "not reviewed"}`
737
+ ] : [],
738
+ ...post.providerSettings?.YOUTUBE ? [
739
+ `YouTube: ${post.providerSettings.YOUTUBE.privacyStatus}, ${post.providerSettings.YOUTUBE.title}`
740
+ ] : []
732
741
  ].join("\n");
733
742
  }
734
743
  function formatPostSchedulePending(pending) {
@@ -742,6 +751,28 @@ function formatIntegrationHealth(data) {
742
751
  const rows = data.items.map((item) => `${item.provider} ${item.connected ? "connected" : "disconnected"} ${item.health.status} ${item.health.isStale ? "stale" : "current"} ${item.health.message}`);
743
752
  return ["PROVIDER CONNECTION HEALTH FRESHNESS DETAIL", ...rows].join("\n");
744
753
  }
754
+ function formatProviderDeliveryOptions(options) {
755
+ switch (options.provider) {
756
+ case "TIKTOK":
757
+ return [
758
+ `TikTok delivery options for ${options.account.displayName ?? options.account.username ?? "connected account"}`,
759
+ `Checked: ${options.checkedAt}`,
760
+ `Health: ${options.health.status} (${options.health.code}) ${options.health.message}`,
761
+ `Modes: ${options.allowedPostModes.join(", ") || "none"}`,
762
+ `Visibility: ${options.visibilityOptions.join(", ") || "none"}`,
763
+ `Interactions: comments ${options.interactions.comment.available ? "available" : "disabled"}, duet ${options.interactions.duet.available ? "available" : "disabled"}, stitch ${options.interactions.stitch.available ? "available" : "disabled"}`,
764
+ `Maximum video duration: ${options.maxVideoDurationMs === null ? "unknown" : `${options.maxVideoDurationMs} ms`}`
765
+ ].join("\n");
766
+ case "LINKEDIN":
767
+ return [
768
+ `LinkedIn delivery options for ${options.account.displayName ?? "connected member"}`,
769
+ `Checked: ${options.checkedAt}`,
770
+ `Health: ${options.health.status} (${options.health.code}) ${options.health.message}`,
771
+ `Post types: ${options.supportedPostTypes.join(", ")}`,
772
+ `Images: up to ${options.image.maxItems}; ${options.image.mimeTypes.join(", ")}; under ${options.image.maxPixelsExclusive.toLocaleString()} pixels`
773
+ ].join("\n");
774
+ }
775
+ }
745
776
  function formatPostReadiness(readiness) {
746
777
  const attention = readiness.checks.filter((check) => check.status !== "pass");
747
778
  const summary = readiness.hasBlockingChecks ? "Post is not ready to publish." : readiness.requiresLiveRefresh.length ? "Local checks passed; live provider health must be refreshed." : "Post is ready to publish.";
@@ -835,7 +866,32 @@ function collectPublishingProvider(value, previous) {
835
866
  return [...previous ?? [], publishingProvider(value)];
836
867
  }
837
868
  function collectString(value, previous) {
838
- return [...previous, value];
869
+ return [...previous ?? [], value];
870
+ }
871
+ function deliveryOptionsProvider(value) {
872
+ const normalized = value.toUpperCase();
873
+ const parsed = ProviderDeliveryOptionsProviderSchema.safeParse(normalized);
874
+ if (parsed.success) return parsed.data;
875
+ throw new InvalidArgumentError(
876
+ `Provider must be one of ${ProviderDeliveryOptionsProviderSchema.options.join(", ")}.`
877
+ );
878
+ }
879
+ function tiktokPostMode(value) {
880
+ const normalized = value.trim().toLowerCase();
881
+ if (normalized === "direct" || normalized === "direct_post") {
882
+ return "DIRECT_POST";
883
+ }
884
+ if (normalized === "inbox" || normalized === "media_upload") {
885
+ return "MEDIA_UPLOAD";
886
+ }
887
+ throw new InvalidArgumentError("TikTok mode must be direct or inbox.");
888
+ }
889
+ function nonnegativeInteger(value) {
890
+ const parsed = Number(value);
891
+ if (!Number.isSafeInteger(parsed) || parsed < 0) {
892
+ throw new InvalidArgumentError("Expected a nonnegative integer.");
893
+ }
894
+ return parsed;
839
895
  }
840
896
  function youtubePrivacy(value) {
841
897
  const normalized = value.toUpperCase();
@@ -853,7 +909,7 @@ function yesOrNo(value) {
853
909
  throw new InvalidArgumentError("Expected yes or no.");
854
910
  }
855
911
  function youtubeSettings(options) {
856
- const hasYouTubeOptions = options.youtubeTitle !== void 0 || options.youtubeCategoryId !== void 0 || options.youtubePrivacy !== void 0 || options.youtubeMadeForKids !== void 0 || options.youtubeSyntheticMedia === true || options.youtubeNotifySubscribers === false || options.youtubeTag.length > 0;
912
+ const hasYouTubeOptions = options.youtubeTitle !== void 0 || options.youtubeCategoryId !== void 0 || options.youtubePrivacy !== void 0 || options.youtubeMadeForKids !== void 0 || options.youtubeSyntheticMedia === true || options.youtubeNotifySubscribers === false || (options.youtubeTag?.length ?? 0) > 0;
857
913
  if (!hasYouTubeOptions) return null;
858
914
  return YouTubePostSettingsSchema.parse({
859
915
  title: options.youtubeTitle,
@@ -862,7 +918,7 @@ function youtubeSettings(options) {
862
918
  madeForKids: options.youtubeMadeForKids,
863
919
  containsSyntheticMedia: options.youtubeSyntheticMedia ?? false,
864
920
  notifySubscribers: options.youtubeNotifySubscribers ?? true,
865
- tags: options.youtubeTag
921
+ tags: options.youtubeTag ?? []
866
922
  });
867
923
  }
868
924
  function positiveInteger(value) {
@@ -1008,6 +1064,23 @@ function errorForOutput(error) {
1008
1064
  }
1009
1065
  return { code: "CLI_ERROR", message: "The command failed unexpectedly." };
1010
1066
  }
1067
+ function tiktokSettings(options) {
1068
+ const hasTikTokOptions = options.tiktokMode !== void 0 || options.tiktokVisibility !== void 0 || options.tiktokComments !== void 0 || options.tiktokDuet !== void 0 || options.tiktokStitch !== void 0 || options.tiktokCommercialContent !== void 0 || options.tiktokPromotesOwnBrand !== void 0 || options.tiktokPromotesThirdParty !== void 0 || options.tiktokAiGenerated !== void 0 || options.tiktokCoverTimestampMs !== void 0 || options.tiktokSettingsReviewed === true;
1069
+ if (!hasTikTokOptions) return void 0;
1070
+ return TikTokDraftSettingsSchema.parse({
1071
+ postMode: options.tiktokMode,
1072
+ privacyLevel: options.tiktokVisibility,
1073
+ allowComment: options.tiktokComments,
1074
+ allowDuet: options.tiktokDuet,
1075
+ allowStitch: options.tiktokStitch,
1076
+ commercialContentEnabled: options.tiktokCommercialContent,
1077
+ promotesOwnBrand: options.tiktokPromotesOwnBrand,
1078
+ promotesThirdParty: options.tiktokPromotesThirdParty,
1079
+ isAiGenerated: options.tiktokAiGenerated,
1080
+ videoCoverTimestampMs: options.tiktokCoverTimestampMs,
1081
+ reviewed: options.tiktokSettingsReviewed === true
1082
+ });
1083
+ }
1011
1084
  function recoverySuggestions(code, command) {
1012
1085
  switch (code) {
1013
1086
  case "AUTH_REQUIRED":
@@ -1211,8 +1284,8 @@ async function runCli(argv = process.argv, overrides = {}) {
1211
1284
  const contentType = contentTypes[extname(absolutePath).toLowerCase()];
1212
1285
  if (!contentType) throw new TypeError("Use a JPEG, PNG, WebP, MP4, or MOV file.");
1213
1286
  await requireWriteConsent({ yes: local.yes, global, runtime, subject: "media", preview: [`Upload ${basename(absolutePath)} to Rolino?`, `Project: ${local.project}`, `Size: ${details.size} bytes`, "This adds a reusable media asset but does not create, schedule, or publish a post."].join("\n") });
1214
- const bytes = await readFile2(absolutePath);
1215
- const asset = await client.media.upload(local.project, { fileName: basename(absolutePath), contentType, fileSize: details.size, body: new Blob([bytes], { type: contentType }) }, { requestId: context.requestId });
1287
+ const body = await openAsBlob(absolutePath, { type: contentType });
1288
+ const asset = await client.media.upload(local.project, { fileName: basename(absolutePath), contentType, fileSize: details.size, body }, { requestId: context.requestId });
1216
1289
  writeSuccess(context, asset, formatMediaAsset(asset), [`rolino posts create --project ${local.project} --caption <text> --media ${asset.id} --agent --yes`]);
1217
1290
  }
1218
1291
  });
@@ -1435,7 +1508,7 @@ async function runCli(argv = process.argv, overrides = {}) {
1435
1508
  });
1436
1509
  });
1437
1510
  const posts = program.command("posts").description("Read and prepare posts in a Rolino project");
1438
- posts.command("create").description("Create a draft post without scheduling or publishing it").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--caption <text>", "draft caption; use an empty string for media-only drafts").option("--platform <provider>", "INSTAGRAM, TIKTOK, YOUTUBE, or BLUESKY; repeat as needed", collectPublishingProvider, []).option("--media <asset-id>", "existing project media asset ID; repeat for multiple", collectString, []).option("--instagram-caption <text>", "Instagram-specific caption override").option("--tiktok-caption <text>", "TikTok-specific caption override").option("--youtube-caption <text>", "YouTube description override; otherwise the shared caption is used").option("--bluesky-caption <text>", "Bluesky-specific caption override; limited to 300 graphemes").option("--youtube-title <text>", "required YouTube video title").option("--youtube-category-id <id>", "required numeric YouTube video category ID").option("--youtube-privacy <status>", "required PUBLIC, UNLISTED, or PRIVATE visibility", youtubePrivacy).option("--youtube-made-for-kids <yes|no>", "required explicit YouTube audience declaration", yesOrNo).option("--youtube-synthetic-media", "declare realistic altered or synthetic media to YouTube").option("--no-youtube-notify-subscribers", "disable eligible YouTube subscriber notifications").option("--youtube-tag <tag>", "YouTube tag; repeat as needed", collectString, []).option("--idempotency-key <key>", "stable retry key; defaults to the request ID").option("--yes", "confirm creation without an interactive prompt").action(async (local) => {
1511
+ posts.command("create").description("Create a draft post without scheduling or publishing it").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--caption <text>", "draft caption; use an empty string for media-only drafts").option("--platform <provider>", "INSTAGRAM, TIKTOK, YOUTUBE, BLUESKY, or LINKEDIN; repeat as needed", collectPublishingProvider, []).option("--media <asset-id>", "existing project media asset ID; repeat for multiple", collectString, []).option("--instagram-caption <text>", "Instagram-specific caption override").option("--tiktok-caption <text>", "TikTok-specific caption override").option("--tiktok-mode <mode>", "direct publishing or inbox draft delivery", tiktokPostMode).option("--tiktok-visibility <value>", "exact visibility returned by integrations delivery-options").option("--tiktok-comments <yes|no>", "allow TikTok comments", yesOrNo).option("--tiktok-duet <yes|no>", "allow TikTok duets", yesOrNo).option("--tiktok-stitch <yes|no>", "allow TikTok stitches", yesOrNo).option("--tiktok-commercial-content <yes|no>", "declare commercial TikTok content", yesOrNo).option("--tiktok-promotes-own-brand <yes|no>", "declare own-brand promotion", yesOrNo).option("--tiktok-promotes-third-party <yes|no>", "declare third-party promotion", yesOrNo).option("--tiktok-ai-generated <yes|no>", "declare AI-generated TikTok content", yesOrNo).option("--tiktok-cover-timestamp-ms <number>", "video cover timestamp in milliseconds", nonnegativeInteger).option("--tiktok-settings-reviewed", "confirm the TikTok account choices were reviewed; separate from --yes").option("--youtube-caption <text>", "YouTube description override; otherwise the shared caption is used").option("--bluesky-caption <text>", "Bluesky-specific caption override; limited to 300 graphemes").option("--linkedin-caption <text>", "LinkedIn-specific caption override; limited to 3,000 characters").option("--youtube-title <text>", "required YouTube video title").option("--youtube-category-id <id>", "required numeric YouTube video category ID").option("--youtube-privacy <status>", "required PUBLIC, UNLISTED, or PRIVATE visibility", youtubePrivacy).option("--youtube-made-for-kids <yes|no>", "required explicit YouTube audience declaration", yesOrNo).option("--youtube-synthetic-media", "declare realistic altered or synthetic media to YouTube").option("--no-youtube-notify-subscribers", "disable eligible YouTube subscriber notifications").option("--youtube-tag <tag>", "YouTube tag; repeat as needed", collectString, []).option("--idempotency-key <key>", "stable retry key; defaults to the request ID").option("--yes", "confirm creation without an interactive prompt").action(async (local) => {
1439
1512
  const global = program.opts();
1440
1513
  commandExitCode = await execute({
1441
1514
  command: "posts create",
@@ -1461,9 +1534,10 @@ async function runCli(argv = process.argv, overrides = {}) {
1461
1534
  ...local.instagramCaption === void 0 ? {} : { INSTAGRAM: local.instagramCaption },
1462
1535
  ...local.tiktokCaption === void 0 ? {} : { TIKTOK: local.tiktokCaption },
1463
1536
  ...local.youtubeCaption === void 0 ? {} : { YOUTUBE: local.youtubeCaption },
1464
- ...local.blueskyCaption === void 0 ? {} : { BLUESKY: local.blueskyCaption }
1537
+ ...local.blueskyCaption === void 0 ? {} : { BLUESKY: local.blueskyCaption },
1538
+ ...local.linkedinCaption === void 0 ? {} : { LINKEDIN: local.linkedinCaption }
1465
1539
  },
1466
- tiktokSettings: null,
1540
+ tiktokSettings: tiktokSettings(local) ?? null,
1467
1541
  youtubeSettings: youtubeSettings(local)
1468
1542
  };
1469
1543
  const post = await client.posts.create(local.project, input, {
@@ -1479,7 +1553,7 @@ async function runCli(argv = process.argv, overrides = {}) {
1479
1553
  }
1480
1554
  });
1481
1555
  });
1482
- posts.command("update").description("Replace an existing draft using optimistic concurrency").argument("<post-id>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--expected-version <number>", "current post version from posts show", positiveInteger).requiredOption("--caption <text>", "replacement draft caption").option("--platform <provider>", "INSTAGRAM, TIKTOK, YOUTUBE, or BLUESKY; repeat as needed", collectPublishingProvider, []).option("--media <asset-id>", "replacement media asset ID; repeat for multiple", collectString, []).option("--instagram-caption <text>", "Instagram-specific caption override").option("--tiktok-caption <text>", "TikTok-specific caption override").option("--youtube-caption <text>", "YouTube description override; otherwise the shared caption is used").option("--bluesky-caption <text>", "Bluesky-specific caption override; limited to 300 graphemes").option("--youtube-title <text>", "required YouTube video title").option("--youtube-category-id <id>", "required numeric YouTube video category ID").option("--youtube-privacy <status>", "required PUBLIC, UNLISTED, or PRIVATE visibility", youtubePrivacy).option("--youtube-made-for-kids <yes|no>", "required explicit YouTube audience declaration", yesOrNo).option("--youtube-synthetic-media", "declare realistic altered or synthetic media to YouTube").option("--no-youtube-notify-subscribers", "disable eligible YouTube subscriber notifications").option("--youtube-tag <tag>", "YouTube tag; repeat as needed", collectString, []).option("--idempotency-key <key>", "stable retry key; defaults to the request ID").option("--yes", "confirm the update without an interactive prompt").action(async (postId, local) => {
1556
+ posts.command("update").description("Update selected draft fields using optimistic concurrency").argument("<post-id>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--expected-version <number>", "current post version from posts show", positiveInteger).option("--caption <text>", "replacement draft caption; omitted fields are preserved").option("--platform <provider>", "replacement destinations; repeat as needed", collectPublishingProvider).option("--clear-platforms", "remove every draft destination").option("--media <asset-id>", "replacement media asset ID; repeat for multiple", collectString).option("--clear-media", "remove every media asset from the draft").option("--instagram-caption <text>", "Instagram-specific caption override").option("--tiktok-caption <text>", "TikTok-specific caption override").option("--tiktok-mode <mode>", "direct publishing or inbox draft delivery", tiktokPostMode).option("--tiktok-visibility <value>", "exact visibility returned by integrations delivery-options").option("--tiktok-comments <yes|no>", "allow TikTok comments", yesOrNo).option("--tiktok-duet <yes|no>", "allow TikTok duets", yesOrNo).option("--tiktok-stitch <yes|no>", "allow TikTok stitches", yesOrNo).option("--tiktok-commercial-content <yes|no>", "declare commercial TikTok content", yesOrNo).option("--tiktok-promotes-own-brand <yes|no>", "declare own-brand promotion", yesOrNo).option("--tiktok-promotes-third-party <yes|no>", "declare third-party promotion", yesOrNo).option("--tiktok-ai-generated <yes|no>", "declare AI-generated TikTok content", yesOrNo).option("--tiktok-cover-timestamp-ms <number>", "video cover timestamp in milliseconds", nonnegativeInteger).option("--tiktok-settings-reviewed", "confirm the TikTok account choices were reviewed; separate from --yes").option("--youtube-caption <text>", "YouTube description override; otherwise the shared caption is used").option("--bluesky-caption <text>", "Bluesky-specific caption override; limited to 300 graphemes").option("--linkedin-caption <text>", "LinkedIn-specific caption override; limited to 3,000 characters").option("--youtube-title <text>", "required YouTube video title").option("--youtube-category-id <id>", "required numeric YouTube video category ID").option("--youtube-privacy <status>", "required PUBLIC, UNLISTED, or PRIVATE visibility", youtubePrivacy).option("--youtube-made-for-kids <yes|no>", "required explicit YouTube audience declaration", yesOrNo).option("--youtube-synthetic-media", "declare realistic altered or synthetic media to YouTube").option("--no-youtube-notify-subscribers", "disable eligible YouTube subscriber notifications").option("--youtube-tag <tag>", "replacement YouTube tag; repeat as needed", collectString).option("--idempotency-key <key>", "stable retry key; defaults to the request ID").option("--yes", "confirm the update without an interactive prompt").action(async (postId, local) => {
1483
1557
  const global = program.opts();
1484
1558
  commandExitCode = await execute({
1485
1559
  command: "posts update",
@@ -1491,24 +1565,34 @@ async function runCli(argv = process.argv, overrides = {}) {
1491
1565
  global,
1492
1566
  runtime,
1493
1567
  preview: [
1494
- `Replace draft ${postId}?`,
1568
+ `Update draft ${postId}?`,
1495
1569
  `Project: ${local.project}`,
1496
1570
  `Expected version: ${local.expectedVersion}`,
1497
1571
  "This will not schedule or publish the post."
1498
1572
  ].join("\n")
1499
1573
  });
1574
+ if (local.clearPlatforms && local.platform !== void 0) {
1575
+ throw new TypeError("Use either --platform or --clear-platforms, not both.");
1576
+ }
1577
+ if (local.clearMedia && local.media !== void 0) {
1578
+ throw new TypeError("Use either --media or --clear-media, not both.");
1579
+ }
1580
+ const captionOverrides = {
1581
+ ...local.instagramCaption === void 0 ? {} : { INSTAGRAM: local.instagramCaption },
1582
+ ...local.tiktokCaption === void 0 ? {} : { TIKTOK: local.tiktokCaption },
1583
+ ...local.youtubeCaption === void 0 ? {} : { YOUTUBE: local.youtubeCaption },
1584
+ ...local.blueskyCaption === void 0 ? {} : { BLUESKY: local.blueskyCaption },
1585
+ ...local.linkedinCaption === void 0 ? {} : { LINKEDIN: local.linkedinCaption }
1586
+ };
1587
+ const resolvedTikTokSettings = tiktokSettings(local);
1588
+ const resolvedYouTubeSettings = youtubeSettings(local);
1500
1589
  const input = {
1501
- caption: local.caption,
1502
- platforms: local.platform,
1503
- mediaAssetIds: local.media,
1504
- captionOverrides: {
1505
- ...local.instagramCaption === void 0 ? {} : { INSTAGRAM: local.instagramCaption },
1506
- ...local.tiktokCaption === void 0 ? {} : { TIKTOK: local.tiktokCaption },
1507
- ...local.youtubeCaption === void 0 ? {} : { YOUTUBE: local.youtubeCaption },
1508
- ...local.blueskyCaption === void 0 ? {} : { BLUESKY: local.blueskyCaption }
1509
- },
1510
- tiktokSettings: null,
1511
- youtubeSettings: youtubeSettings(local)
1590
+ ...local.caption === void 0 ? {} : { caption: local.caption },
1591
+ ...local.platform === void 0 && !local.clearPlatforms ? {} : { platforms: local.clearPlatforms ? [] : local.platform },
1592
+ ...local.media === void 0 && !local.clearMedia ? {} : { mediaAssetIds: local.clearMedia ? [] : local.media },
1593
+ ...Object.keys(captionOverrides).length ? { captionOverrides } : {},
1594
+ ...resolvedTikTokSettings === void 0 ? {} : { tiktokSettings: resolvedTikTokSettings },
1595
+ ...resolvedYouTubeSettings === null ? {} : { youtubeSettings: resolvedYouTubeSettings }
1512
1596
  };
1513
1597
  const post = await client.posts.update(local.project, postId, input, {
1514
1598
  requestId: context.requestId,
@@ -1646,7 +1730,7 @@ async function runCli(argv = process.argv, overrides = {}) {
1646
1730
  });
1647
1731
  });
1648
1732
  const publish = posts.command("publish").description("Preview and queue server-confirmed immediate publishing");
1649
- publish.command("preview").description("Validate exact destinations and issue a five-minute confirmation").argument("<post-id>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--expected-version <number>", "current post version from posts show", positiveInteger).requiredOption("--platform <provider>", "INSTAGRAM, TIKTOK, YOUTUBE, or BLUESKY; repeat as needed", collectPublishingProvider).action(async (postId, local) => {
1733
+ publish.command("preview").description("Validate exact destinations and issue a five-minute confirmation").argument("<post-id>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--expected-version <number>", "current post version from posts show", positiveInteger).requiredOption("--platform <provider>", "INSTAGRAM, TIKTOK, YOUTUBE, BLUESKY, or LINKEDIN; repeat as needed", collectPublishingProvider).action(async (postId, local) => {
1650
1734
  const global = program.opts();
1651
1735
  commandExitCode = await execute({
1652
1736
  command: "posts publish preview",
@@ -1729,6 +1813,27 @@ async function runCli(argv = process.argv, overrides = {}) {
1729
1813
  }
1730
1814
  });
1731
1815
  });
1816
+ integrations.command("delivery-options").description("Refresh secret-safe creator delivery choices for one provider").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--provider <provider>", "publishing provider; TIKTOK or LINKEDIN", deliveryOptionsProvider).action(async (local) => {
1817
+ const global = program.opts();
1818
+ commandExitCode = await execute({
1819
+ command: "integrations delivery-options",
1820
+ global,
1821
+ runtime,
1822
+ async action(context, client) {
1823
+ const options = await client.integrations.deliveryOptions(
1824
+ local.project,
1825
+ local.provider,
1826
+ { requestId: context.requestId }
1827
+ );
1828
+ writeSuccess(
1829
+ context,
1830
+ options,
1831
+ formatProviderDeliveryOptions(options),
1832
+ [`rolino posts create --project ${local.project} --caption <text> --platform ${local.provider} --agent --yes`]
1833
+ );
1834
+ }
1835
+ });
1836
+ });
1732
1837
  const calendar = program.command("calendar").description("Read scheduled publishing events");
1733
1838
  calendar.command("list").description("List scheduled posts in a bounded calendar window").requiredOption("--project <project-id>", "exact Rolino project ID").option("--from <datetime>", "inclusive ISO-8601 window start", isoDateTime).option("--to <datetime>", "exclusive ISO-8601 window end", isoDateTime).option("--limit <number>", "maximum events to return", (value) => {
1734
1839
  const parsed = Number(value);
@@ -1852,4 +1957,4 @@ export {
1852
1957
  ROLINO_CLI_VERSION,
1853
1958
  runCli
1854
1959
  };
1855
- //# sourceMappingURL=chunk-YTEWMNSV.js.map
1960
+ //# sourceMappingURL=chunk-7BCIIFUB.js.map