@rolino/cli 0.3.0 → 0.5.0-beta.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 +54 -0
- package/README.md +76 -15
- package/dist/bin.cjs +360 -10
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-7BCIIFUB.js → chunk-TFNGSKT3.js} +366 -12
- package/dist/chunk-TFNGSKT3.js.map +1 -0
- package/dist/index.cjs +360 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-7BCIIFUB.js.map +0 -1
package/dist/bin.js
CHANGED
|
@@ -277,7 +277,7 @@ async function setupMcp(options) {
|
|
|
277
277
|
// src/cli.ts
|
|
278
278
|
import { randomUUID } from "crypto";
|
|
279
279
|
import { openAsBlob } from "fs";
|
|
280
|
-
import { stat } from "fs/promises";
|
|
280
|
+
import { readFile as readFile2, stat } from "fs/promises";
|
|
281
281
|
import { basename, extname, resolve as resolve2 } from "path";
|
|
282
282
|
import { createInterface } from "readline/promises";
|
|
283
283
|
import { Command, CommanderError, InvalidArgumentError } from "commander";
|
|
@@ -285,7 +285,7 @@ import { Command, CommanderError, InvalidArgumentError } from "commander";
|
|
|
285
285
|
// package.json
|
|
286
286
|
var package_default = {
|
|
287
287
|
name: "@rolino/cli",
|
|
288
|
-
version: "0.
|
|
288
|
+
version: "0.5.0-beta.0",
|
|
289
289
|
description: "Agent-friendly command-line interface for Rolino",
|
|
290
290
|
type: "module",
|
|
291
291
|
license: "MIT",
|
|
@@ -342,9 +342,9 @@ var package_default = {
|
|
|
342
342
|
dev: "tsx src/bin.ts"
|
|
343
343
|
},
|
|
344
344
|
dependencies: {
|
|
345
|
-
"@rolino/contracts": "0.
|
|
346
|
-
"@rolino/local-auth": "0.
|
|
347
|
-
"@rolino/sdk": "0.
|
|
345
|
+
"@rolino/contracts": "0.5.0-beta.0",
|
|
346
|
+
"@rolino/local-auth": "0.5.0-beta.0",
|
|
347
|
+
"@rolino/sdk": "0.5.0-beta.0",
|
|
348
348
|
commander: "^15.0.0",
|
|
349
349
|
open: "^11.0.0"
|
|
350
350
|
},
|
|
@@ -359,10 +359,14 @@ var package_default = {
|
|
|
359
359
|
// src/cli.ts
|
|
360
360
|
import {
|
|
361
361
|
PostStatusSchema,
|
|
362
|
+
AgentBlogDraftUpdateSchema,
|
|
362
363
|
ProjectCreateInputSchema,
|
|
363
364
|
ProjectTypeSchema,
|
|
364
365
|
ProviderDeliveryOptionsProviderSchema,
|
|
365
366
|
PublishingProviderSchema,
|
|
367
|
+
SeoOpportunityKindSchema,
|
|
368
|
+
SeoExpectedImpactSchema,
|
|
369
|
+
SeoReportCompletenessSchema,
|
|
366
370
|
TikTokDraftSettingsSchema,
|
|
367
371
|
YouTubePostSettingsSchema
|
|
368
372
|
} from "@rolino/contracts";
|
|
@@ -718,7 +722,6 @@ function formatPosts(data) {
|
|
|
718
722
|
return ["ID STATUS SCHEDULED CAPTION", ...rows].join("\n");
|
|
719
723
|
}
|
|
720
724
|
function formatPost(post) {
|
|
721
|
-
const queued = post.status === "PUBLISHING";
|
|
722
725
|
return [
|
|
723
726
|
`Post ${post.id}`,
|
|
724
727
|
`Project: ${post.projectId}`,
|
|
@@ -727,11 +730,11 @@ function formatPost(post) {
|
|
|
727
730
|
`Caption: ${post.caption || "-"}`,
|
|
728
731
|
...post.campaign ? [`Campaign: ${post.campaign.title} (${post.campaign.id})`] : [],
|
|
729
732
|
...post.scheduledAt ? [
|
|
730
|
-
|
|
733
|
+
`Scheduled: ${post.scheduledAt}${post.timezone ? ` (${post.timezone})` : ""}`
|
|
731
734
|
] : [],
|
|
732
735
|
...post.publishedAt ? [`Published: ${post.publishedAt}`] : [],
|
|
733
736
|
`Media: ${post.media.length}`,
|
|
734
|
-
`Destinations: ${post.destinations.map((destination) => `${destination.provider}:${
|
|
737
|
+
`Destinations: ${post.destinations.map((destination) => `${destination.provider}:${destination.deliveryMode}:${destination.stage}`).join(", ") || "none"}`,
|
|
735
738
|
...post.providerSettings?.TIKTOK ? [
|
|
736
739
|
`TikTok: ${post.providerSettings.TIKTOK.postMode}, ${post.providerSettings.TIKTOK.privacyLevel ?? "visibility not set"}, settings ${post.providerSettings.TIKTOK.consentedAt ? "reviewed" : "not reviewed"}`
|
|
737
740
|
] : [],
|
|
@@ -742,7 +745,8 @@ function formatPost(post) {
|
|
|
742
745
|
}
|
|
743
746
|
function formatPostSchedulePending(pending) {
|
|
744
747
|
return [
|
|
745
|
-
`YouTube
|
|
748
|
+
`YouTube publish-time confirmation pending for post ${pending.postId}.`,
|
|
749
|
+
"Video upload: complete (the video remains private).",
|
|
746
750
|
pending.message,
|
|
747
751
|
`Mutation: ${pending.mutationId}`
|
|
748
752
|
].join("\n");
|
|
@@ -769,7 +773,8 @@ function formatProviderDeliveryOptions(options) {
|
|
|
769
773
|
`Checked: ${options.checkedAt}`,
|
|
770
774
|
`Health: ${options.health.status} (${options.health.code}) ${options.health.message}`,
|
|
771
775
|
`Post types: ${options.supportedPostTypes.join(", ")}`,
|
|
772
|
-
`Images: up to ${options.image.maxItems}; ${options.image.mimeTypes.join(", ")}; under ${options.image.maxPixelsExclusive.toLocaleString()} pixels
|
|
776
|
+
`Images: up to ${options.image.maxItems}; ${options.image.mimeTypes.join(", ")}; under ${options.image.maxPixelsExclusive.toLocaleString()} pixels`,
|
|
777
|
+
`Video: one ${options.video.mimeTypes.join(", ")}; ${options.video.minDurationMs / 1e3}s to ${options.video.maxDurationMs / 6e4}m; ${options.video.minBytes.toLocaleString()} to ${options.video.maxBytes.toLocaleString()} bytes`
|
|
773
778
|
].join("\n");
|
|
774
779
|
}
|
|
775
780
|
}
|
|
@@ -787,8 +792,14 @@ function formatPostSchedulePreview(preview) {
|
|
|
787
792
|
return [
|
|
788
793
|
`Schedule preview for post ${preview.post.id}`,
|
|
789
794
|
`Current version: ${preview.post.version}`,
|
|
795
|
+
`Delivery mode: ${preview.deliveryMode}`,
|
|
790
796
|
`Publish at: ${preview.schedule.scheduledAt} (${preview.schedule.timezone})`,
|
|
791
797
|
`Destinations: ${preview.destinations.join(", ")}`,
|
|
798
|
+
...preview.youtube ? [
|
|
799
|
+
"YouTube preparation: starts immediately as PRIVATE.",
|
|
800
|
+
`YouTube scheduled visibility: ${preview.youtube.publishVisibility}.`,
|
|
801
|
+
`YouTube confirmation: ${preview.youtube.confirmationMeaning}`
|
|
802
|
+
] : [],
|
|
792
803
|
...preview.providerReconciliation ? [`Provider reconciliation: ${preview.providerReconciliation.message}`] : [],
|
|
793
804
|
`Confirmation expires: ${preview.confirmation.expiresAt}`,
|
|
794
805
|
`Confirmation token: ${preview.confirmation.token}`,
|
|
@@ -800,9 +811,10 @@ function formatPostPublishPreview(preview) {
|
|
|
800
811
|
return [
|
|
801
812
|
`Immediate publish preview for post ${preview.post.id}`,
|
|
802
813
|
`Current version: ${preview.post.version}`,
|
|
814
|
+
`Delivery mode: ${preview.deliveryMode}`,
|
|
803
815
|
`Destinations: ${preview.destinations.join(", ")}`,
|
|
804
816
|
"Effect: confirmed execution queues these destinations for immediate publishing.",
|
|
805
|
-
...preview.
|
|
817
|
+
...preview.youtube ? [`YouTube effect: execution starts a resumable upload using ${preview.youtube.visibility}; it does not create a schedule. PREPARING remains visible until upload, processing, and visibility are provider-confirmed.`] : [],
|
|
806
818
|
`Confirmation expires: ${preview.confirmation.expiresAt}`,
|
|
807
819
|
`Confirmation token: ${preview.confirmation.token}`,
|
|
808
820
|
...attention.length ? ["Readiness notes:", ...attention.map((check) => `${check.status.toUpperCase()} ${check.provider ?? "POST"} ${check.code} ${check.message}`)] : ["All required readiness checks passed."]
|
|
@@ -815,6 +827,65 @@ function formatCalendarEvents(data) {
|
|
|
815
827
|
const rows = data.items.map((event) => `${event.postId} ${event.scheduledAt} ${event.status} ${event.destinations.map((item) => item.provider).join(",") || "-"} ${event.title}`);
|
|
816
828
|
return ["POST ID SCHEDULED STATUS DESTINATIONS TITLE", ...rows].join("\n");
|
|
817
829
|
}
|
|
830
|
+
function formatSeoOpportunities(data) {
|
|
831
|
+
if (!data.items.length) return "No active SEO tasks found.";
|
|
832
|
+
return [
|
|
833
|
+
"ID DECISION FORMAT SCORE TOPIC RELEVANCE ACTION READINESS TITLE",
|
|
834
|
+
...data.items.map((item) => `${item.id} ${item.task.decision} ${item.task.primaryFormat} ${item.score} ${item.confidence.topicRelevance.label} ${item.confidence.actionReadiness.label} ${item.title}`)
|
|
835
|
+
].join("\n");
|
|
836
|
+
}
|
|
837
|
+
function formatSeoOpportunity(opportunity) {
|
|
838
|
+
return [
|
|
839
|
+
`${opportunity.title} (${opportunity.id})`,
|
|
840
|
+
`Project: ${opportunity.projectId}`,
|
|
841
|
+
`Decision: ${opportunity.task.decision}`,
|
|
842
|
+
`Primary format: ${opportunity.task.primaryFormat}`,
|
|
843
|
+
`Objective: ${opportunity.task.objective}`,
|
|
844
|
+
`Next step: ${opportunity.task.nextStep}`,
|
|
845
|
+
`Priority: ${opportunity.score}/100`,
|
|
846
|
+
`Topic relevance: ${opportunity.confidence.topicRelevance.label}${opportunity.confidence.topicRelevance.score === null ? "" : ` (${opportunity.confidence.topicRelevance.score}/100)`}`,
|
|
847
|
+
`Topic relevance explanation: ${opportunity.confidence.topicRelevance.explanation}`,
|
|
848
|
+
`Action readiness: ${opportunity.confidence.actionReadiness.label}${opportunity.confidence.actionReadiness.score === null ? "" : ` (${opportunity.confidence.actionReadiness.score}/100)`}`,
|
|
849
|
+
`Action readiness explanation: ${opportunity.confidence.actionReadiness.explanation}`,
|
|
850
|
+
"",
|
|
851
|
+
opportunity.brief
|
|
852
|
+
].join("\n");
|
|
853
|
+
}
|
|
854
|
+
function formatSeoReports(data) {
|
|
855
|
+
if (!data.items.length) return "No weekly SEO reports found.";
|
|
856
|
+
return [
|
|
857
|
+
"ID PERIOD START PERIOD END STATUS READY RESEARCH REJECTED LEGACY",
|
|
858
|
+
...data.items.map((item) => `${item.id} ${item.periodStart} ${item.periodEnd} ${item.completeness} ${item.readyTaskCount} ${item.researchTaskCount} ${item.rejectedFindingCount} ${item.legacy}`)
|
|
859
|
+
].join("\n");
|
|
860
|
+
}
|
|
861
|
+
function formatSeoReport(report) {
|
|
862
|
+
return [
|
|
863
|
+
`Weekly SEO report ${report.id}`,
|
|
864
|
+
`Project: ${report.projectId}`,
|
|
865
|
+
`Period: ${report.periodStart} to ${report.periodEnd}`,
|
|
866
|
+
`Schedule: day ${report.deliveryDay} in ${report.timeZone}`,
|
|
867
|
+
`Status: ${report.completeness}`,
|
|
868
|
+
...report.partialLabel ? [`Note: ${report.partialLabel}`] : [],
|
|
869
|
+
`Ready tasks: ${report.readyTaskCount}`,
|
|
870
|
+
`Research tasks: ${report.researchTaskCount}`,
|
|
871
|
+
`Rejected or filtered findings: ${report.rejectedFindingCount}`,
|
|
872
|
+
`Legacy report: ${report.legacy}`,
|
|
873
|
+
"",
|
|
874
|
+
...report.opportunities.flatMap((item, index) => [
|
|
875
|
+
`${index + 1}. ${item.title}`,
|
|
876
|
+
` Decision: ${item.task.decision}`,
|
|
877
|
+
` Format: ${item.task.primaryFormat}`,
|
|
878
|
+
` Objective: ${item.task.objective}`,
|
|
879
|
+
` Next step: ${item.task.nextStep}`,
|
|
880
|
+
` Topic relevance: ${item.confidence.topicRelevance.label}${item.confidence.topicRelevance.score === null ? "" : ` (${item.confidence.topicRelevance.score}/100)`}`,
|
|
881
|
+
` Action readiness: ${item.confidence.actionReadiness.label}${item.confidence.actionReadiness.score === null ? "" : ` (${item.confidence.actionReadiness.score}/100)`}`
|
|
882
|
+
]),
|
|
883
|
+
...report.rejectedFindings.flatMap((item, index) => [
|
|
884
|
+
`Rejected ${index + 1}: ${item.query}`,
|
|
885
|
+
` Reason: ${item.reason}`
|
|
886
|
+
])
|
|
887
|
+
].join("\n");
|
|
888
|
+
}
|
|
818
889
|
|
|
819
890
|
// src/cli.ts
|
|
820
891
|
var ROLINO_CLI_VERSION = package_default.version;
|
|
@@ -847,6 +918,21 @@ function postStatus(value) {
|
|
|
847
918
|
`Status must be one of ${PostStatusSchema.options.join(", ")}.`
|
|
848
919
|
);
|
|
849
920
|
}
|
|
921
|
+
function seoOpportunityKind(value) {
|
|
922
|
+
const parsed = SeoOpportunityKindSchema.safeParse(value.toUpperCase());
|
|
923
|
+
if (parsed.success) return parsed.data;
|
|
924
|
+
throw new InvalidArgumentError(`SEO kind must be one of ${SeoOpportunityKindSchema.options.join(", ")}.`);
|
|
925
|
+
}
|
|
926
|
+
function seoExpectedImpact(value) {
|
|
927
|
+
const parsed = SeoExpectedImpactSchema.safeParse(value.toUpperCase());
|
|
928
|
+
if (parsed.success) return parsed.data;
|
|
929
|
+
throw new InvalidArgumentError("SEO impact must be HIGH, MEDIUM, or LOW.");
|
|
930
|
+
}
|
|
931
|
+
function seoReportCompleteness(value) {
|
|
932
|
+
const parsed = SeoReportCompletenessSchema.safeParse(value.toUpperCase());
|
|
933
|
+
if (parsed.success) return parsed.data;
|
|
934
|
+
throw new InvalidArgumentError("Report status must be COMPLETE or PARTIAL.");
|
|
935
|
+
}
|
|
850
936
|
function projectType(value) {
|
|
851
937
|
const parsed = ProjectTypeSchema.safeParse(value.toUpperCase());
|
|
852
938
|
if (parsed.success) return parsed.data;
|
|
@@ -1864,6 +1950,274 @@ async function runCli(argv = process.argv, overrides = {}) {
|
|
|
1864
1950
|
}
|
|
1865
1951
|
});
|
|
1866
1952
|
});
|
|
1953
|
+
const blog = program.command("blog").description("Read and manage Blog Studio");
|
|
1954
|
+
const blogPublishing = blog.command("destinations").description("Inspect Blog publishing providers, destinations, and delivery attempts");
|
|
1955
|
+
blogPublishing.command("providers").requiredOption("--project <project-id>", "exact Rolino project ID").action(async (local) => {
|
|
1956
|
+
const global = program.opts();
|
|
1957
|
+
commandExitCode = await execute({ command: "blog destinations providers", global, runtime, async action(context, client) {
|
|
1958
|
+
const data = await client.blog.publishing.providers(local.project, { requestId: context.requestId });
|
|
1959
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
1960
|
+
} });
|
|
1961
|
+
});
|
|
1962
|
+
blogPublishing.command("list").requiredOption("--project <project-id>", "exact Rolino project ID").action(async (local) => {
|
|
1963
|
+
const global = program.opts();
|
|
1964
|
+
commandExitCode = await execute({ command: "blog destinations list", global, runtime, async action(context, client) {
|
|
1965
|
+
const data = await client.blog.publishing.destinations(local.project, { requestId: context.requestId });
|
|
1966
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
1967
|
+
} });
|
|
1968
|
+
});
|
|
1969
|
+
blogPublishing.command("deliveries").requiredOption("--project <project-id>", "exact Rolino project ID").option("--article <article-id>", "filter by exact Blog article ID").action(async (local) => {
|
|
1970
|
+
const global = program.opts();
|
|
1971
|
+
commandExitCode = await execute({ command: "blog destinations deliveries", global, runtime, async action(context, client) {
|
|
1972
|
+
const data = await client.blog.publishing.deliveries(local.project, local.article, { requestId: context.requestId });
|
|
1973
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
1974
|
+
} });
|
|
1975
|
+
});
|
|
1976
|
+
const blogSetup = blog.command("setup").description("Inspect agent-first Blog setup readiness");
|
|
1977
|
+
blogSetup.command("status").requiredOption("--project <project-id>", "exact Rolino project ID").action(async (local) => {
|
|
1978
|
+
const global = program.opts();
|
|
1979
|
+
commandExitCode = await execute({ command: "blog setup status", global, runtime, async action(context, client) {
|
|
1980
|
+
const data = await client.blog.setup.status(local.project, { requestId: context.requestId });
|
|
1981
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
1982
|
+
} });
|
|
1983
|
+
});
|
|
1984
|
+
const blogSite = blog.command("site").description("Initialize or retry the Blog website import");
|
|
1985
|
+
blogSite.command("import").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--idempotency-key <key>", "stable retry key").action(async (local) => {
|
|
1986
|
+
const global = program.opts();
|
|
1987
|
+
commandExitCode = await execute({ command: "blog site import", global, runtime, async action(context, client) {
|
|
1988
|
+
const data = await client.blog.site.import(local.project, local.idempotencyKey, { requestId: context.requestId });
|
|
1989
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2), [`rolino blog job ${data.id} --project ${local.project} --agent`]);
|
|
1990
|
+
} });
|
|
1991
|
+
});
|
|
1992
|
+
blogSite.command("retry").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--idempotency-key <key>", "stable retry key").action(async (local) => {
|
|
1993
|
+
const global = program.opts();
|
|
1994
|
+
commandExitCode = await execute({ command: "blog site retry", global, runtime, async action(context, client) {
|
|
1995
|
+
const data = await client.blog.site.retry(local.project, local.idempotencyKey, { requestId: context.requestId });
|
|
1996
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2), [`rolino blog job ${data.id} --project ${local.project} --agent`]);
|
|
1997
|
+
} });
|
|
1998
|
+
});
|
|
1999
|
+
blog.command("plans").description("List Blog Studio plans").requiredOption("--project <project-id>", "exact Rolino project ID").action(async (local) => {
|
|
2000
|
+
const global = program.opts();
|
|
2001
|
+
commandExitCode = await execute({ command: "blog plans", global, runtime, async action(context, client) {
|
|
2002
|
+
const data = await client.blog.plans.list(local.project, { requestId: context.requestId });
|
|
2003
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2004
|
+
} });
|
|
2005
|
+
});
|
|
2006
|
+
const blogPlan = blog.command("plan").description("Create, retry, and review a Blog cadence plan");
|
|
2007
|
+
blogPlan.command("create").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--start <date>", "local start date as YYYY-MM-DD").requiredOption("--weekdays <days>", "comma-separated weekday names such as mon,wed,fri").option("--time-zone <zone>", "IANA time zone", "UTC").requiredOption("--idempotency-key <key>", "stable retry key").action(async (local) => {
|
|
2008
|
+
const weekdayMap = { sun: 0, mon: 1, tue: 2, wed: 3, thu: 4, fri: 5, sat: 6 };
|
|
2009
|
+
const weekdays = local.weekdays.split(",").map((day) => weekdayMap[day.trim().toLowerCase()]).filter((day) => day !== void 0);
|
|
2010
|
+
if (!weekdays.length || weekdays.length !== local.weekdays.split(",").length) throw new TypeError("--weekdays must contain comma-separated sun,mon,tue,wed,thu,fri,sat values.");
|
|
2011
|
+
const global = program.opts();
|
|
2012
|
+
commandExitCode = await execute({ command: "blog plan create", global, runtime, async action(context, client) {
|
|
2013
|
+
const data = await client.blog.plans.create(local.project, { startsOn: local.start, weekdays, timeZone: local.timeZone }, local.idempotencyKey, { requestId: context.requestId });
|
|
2014
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2), [`rolino blog job ${data.job.id} --project ${local.project} --agent`]);
|
|
2015
|
+
} });
|
|
2016
|
+
});
|
|
2017
|
+
blogPlan.command("retry").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--plan <plan-id>", "exact Blog plan ID").requiredOption("--idempotency-key <key>", "stable retry key").action(async (local) => {
|
|
2018
|
+
const global = program.opts();
|
|
2019
|
+
commandExitCode = await execute({ command: "blog plan retry", global, runtime, async action(context, client) {
|
|
2020
|
+
const data = await client.blog.plans.retry(local.project, local.plan, local.idempotencyKey, { requestId: context.requestId });
|
|
2021
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2022
|
+
} });
|
|
2023
|
+
});
|
|
2024
|
+
blogPlan.command("items").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--plan <plan-id>", "exact Blog plan ID").action(async (local) => {
|
|
2025
|
+
const global = program.opts();
|
|
2026
|
+
commandExitCode = await execute({ command: "blog plan items", global, runtime, async action(context, client) {
|
|
2027
|
+
const data = await client.blog.plans.items.list(local.project, local.plan, { requestId: context.requestId });
|
|
2028
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2029
|
+
} });
|
|
2030
|
+
});
|
|
2031
|
+
const blogPlanItem = blogPlan.command("item").description("Accept or dismiss a reviewed Blog plan item");
|
|
2032
|
+
for (const state of ["accept", "dismiss"]) {
|
|
2033
|
+
blogPlanItem.command(state).requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--plan <plan-id>", "exact Blog plan ID").requiredOption("--item <item-id>", "exact plan item ID").requiredOption("--expected-state <state>", "state returned by the latest item read").requiredOption("--expected-version <version>", "version returned by the latest item read", Number).requiredOption("--idempotency-key <key>", "stable retry key").action(async (local) => {
|
|
2034
|
+
const global = program.opts();
|
|
2035
|
+
commandExitCode = await execute({ command: `blog plan item ${state}`, global, runtime, async action(context, client) {
|
|
2036
|
+
const data = await client.blog.plans.items.setState(local.project, local.plan, local.item, { state: state === "accept" ? "ACCEPTED" : "DISMISSED", expectedState: local.expectedState, expectedVersion: local.expectedVersion, idempotencyKey: local.idempotencyKey }, { requestId: context.requestId });
|
|
2037
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2038
|
+
} });
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
const blogArticle = blog.command("article").description("Create an editable Blog article from an accepted item");
|
|
2042
|
+
blogArticle.command("create").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--plan <plan-id>", "exact Blog plan ID").requiredOption("--item <item-id>", "exact accepted item ID").requiredOption("--expected-version <version>", "version returned by the latest item read", Number).requiredOption("--idempotency-key <key>", "stable retry key").action(async (local) => {
|
|
2043
|
+
const global = program.opts();
|
|
2044
|
+
commandExitCode = await execute({ command: "blog article create", global, runtime, async action(context, client) {
|
|
2045
|
+
const data = await client.blog.plans.items.createArticle(local.project, local.plan, local.item, { expectedState: "ACCEPTED", expectedVersion: local.expectedVersion, idempotencyKey: local.idempotencyKey }, { requestId: context.requestId });
|
|
2046
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2047
|
+
} });
|
|
2048
|
+
});
|
|
2049
|
+
const blogConnection = blog.command("connection").description("Configure and verify the server-only Next.js Blog connection");
|
|
2050
|
+
blogConnection.command("status").requiredOption("--project <project-id>", "exact Rolino project ID").action(async (local) => {
|
|
2051
|
+
const global = program.opts();
|
|
2052
|
+
commandExitCode = await execute({ command: "blog connection status", global, runtime, async action(context, client) {
|
|
2053
|
+
const data = await client.blog.connection.status(local.project, { requestId: context.requestId });
|
|
2054
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2055
|
+
} });
|
|
2056
|
+
});
|
|
2057
|
+
const addConnectionOptions = (command, execute2) => {
|
|
2058
|
+
command.requiredOption("--project <project-id>", "exact Rolino project ID").option("--endpoint <url>", "same-host signed revalidation endpoint").option("--credential-action <action>", "KEEP, CREATE, ROTATE, or REVOKE", "KEEP").option("--credential-id <id>", "credential to rotate or revoke").option("--secret-action <action>", "KEEP, CREATE, or ROTATE", "KEEP");
|
|
2059
|
+
if (execute2) command.requiredOption("--confirmation-token <token>", "short-lived token returned by preview").requiredOption("--idempotency-key <key>", "stable retry key").option("--yes", "confirm the exact connection change");
|
|
2060
|
+
return command;
|
|
2061
|
+
};
|
|
2062
|
+
addConnectionOptions(blogConnection.command("preview"), false).action(async (local) => {
|
|
2063
|
+
const input = { endpoint: local.endpoint ?? null, credentialAction: local.credentialAction.toUpperCase(), credentialId: local.credentialId ?? null, secretAction: local.secretAction.toUpperCase() };
|
|
2064
|
+
const global = program.opts();
|
|
2065
|
+
commandExitCode = await execute({ command: "blog connection preview", global, runtime, async action(context, client) {
|
|
2066
|
+
const data = await client.blog.connection.preview(local.project, input, { requestId: context.requestId });
|
|
2067
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2068
|
+
} });
|
|
2069
|
+
});
|
|
2070
|
+
addConnectionOptions(blogConnection.command("execute"), true).action(async (local) => {
|
|
2071
|
+
const input = { endpoint: local.endpoint ?? null, credentialAction: local.credentialAction.toUpperCase(), credentialId: local.credentialId ?? null, secretAction: local.secretAction.toUpperCase() };
|
|
2072
|
+
const global = program.opts();
|
|
2073
|
+
commandExitCode = await execute({ command: "blog connection execute", global, runtime, async action(context, client) {
|
|
2074
|
+
await requireWriteConsent({ yes: local.yes, global, runtime, preview: `Apply the previewed Blog connection change for project ${local.project}? One-time secrets may be returned and must stay server-only.` });
|
|
2075
|
+
const data = await client.blog.connection.execute(local.project, { ...input, confirmationToken: local.confirmationToken, idempotencyKey: local.idempotencyKey }, { requestId: context.requestId });
|
|
2076
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2077
|
+
} });
|
|
2078
|
+
});
|
|
2079
|
+
blogConnection.command("test").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--idempotency-key <key>", "stable retry key").action(async (local) => {
|
|
2080
|
+
const global = program.opts();
|
|
2081
|
+
commandExitCode = await execute({ command: "blog connection test", global, runtime, async action(context, client) {
|
|
2082
|
+
const data = await client.blog.connection.test(local.project, local.idempotencyKey, { requestId: context.requestId });
|
|
2083
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2084
|
+
} });
|
|
2085
|
+
});
|
|
2086
|
+
const blogArticles = blog.command("articles").description("Read and edit Blog Studio articles");
|
|
2087
|
+
blogArticles.command("list").requiredOption("--project <project-id>", "exact Rolino project ID").action(async (local) => {
|
|
2088
|
+
const global = program.opts();
|
|
2089
|
+
commandExitCode = await execute({ command: "blog articles list", global, runtime, async action(context, client) {
|
|
2090
|
+
const data = await client.blog.articles.list(local.project, { requestId: context.requestId });
|
|
2091
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2092
|
+
} });
|
|
2093
|
+
});
|
|
2094
|
+
blogArticles.command("show").argument("<article-id>").requiredOption("--project <project-id>", "exact Rolino project ID").action(async (articleId, local) => {
|
|
2095
|
+
const global = program.opts();
|
|
2096
|
+
commandExitCode = await execute({ command: "blog articles show", global, runtime, async action(context, client) {
|
|
2097
|
+
const data = await client.blog.articles.get(local.project, articleId, { requestId: context.requestId });
|
|
2098
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2099
|
+
} });
|
|
2100
|
+
});
|
|
2101
|
+
blogArticles.command("update").argument("<article-id>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--input <json-file>", "complete Blog draft JSON file").option("--yes", "confirm the draft save").action(async (articleId, local) => {
|
|
2102
|
+
const global = program.opts();
|
|
2103
|
+
commandExitCode = await execute({ command: "blog articles update", global, runtime, async action(context, client) {
|
|
2104
|
+
const draft = AgentBlogDraftUpdateSchema.parse(JSON.parse(await readFile2(resolve2(runtime.cwd, local.input), "utf8")));
|
|
2105
|
+
await requireWriteConsent({ yes: local.yes, global, runtime, preview: `Save a new immutable Blog draft revision?
|
|
2106
|
+
Project: ${local.project}
|
|
2107
|
+
Article: ${articleId}
|
|
2108
|
+
This will not publish.` });
|
|
2109
|
+
const data = await client.blog.articles.updateDraft(local.project, articleId, draft, { requestId: context.requestId });
|
|
2110
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2111
|
+
} });
|
|
2112
|
+
});
|
|
2113
|
+
blogArticles.command("generate").argument("<article-id>").requiredOption("--project <project-id>", "exact Rolino project ID").option("--idempotency-key <key>", "stable retry key; defaults to request ID").option("--yes", "confirm the generation request").action(async (articleId, local) => {
|
|
2114
|
+
const global = program.opts();
|
|
2115
|
+
commandExitCode = await execute({ command: "blog articles generate", global, runtime, async action(context, client) {
|
|
2116
|
+
await requireWriteConsent({ yes: local.yes, global, runtime, preview: `Queue durable Blog article generation?
|
|
2117
|
+
Project: ${local.project}
|
|
2118
|
+
Article: ${articleId}` });
|
|
2119
|
+
const data = await client.blog.articles.generate(local.project, articleId, local.idempotencyKey ?? context.requestId, { requestId: context.requestId });
|
|
2120
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2121
|
+
} });
|
|
2122
|
+
});
|
|
2123
|
+
blog.command("job").argument("<job-id>").requiredOption("--project <project-id>", "exact Rolino project ID").action(async (jobId, local) => {
|
|
2124
|
+
const global = program.opts();
|
|
2125
|
+
commandExitCode = await execute({ command: "blog job", global, runtime, async action(context, client) {
|
|
2126
|
+
const data = await client.blog.jobs.get(local.project, jobId, { requestId: context.requestId });
|
|
2127
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2128
|
+
} });
|
|
2129
|
+
});
|
|
2130
|
+
const blogPublish = blog.command("publish").description("Preview or execute exact approved Blog publication");
|
|
2131
|
+
blogPublish.command("preview").argument("<article-id>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--revision <revision-id>", "exact user-approved revision ID").option("--destination <destination-id...>", "exact destination IDs; defaults to the current primary").action(async (articleId, local) => {
|
|
2132
|
+
const global = program.opts();
|
|
2133
|
+
commandExitCode = await execute({ command: "blog publish preview", global, runtime, async action(context, client) {
|
|
2134
|
+
const data = await client.blog.articles.previewPublish(local.project, articleId, local.revision, { requestId: context.requestId }, local.destination);
|
|
2135
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2136
|
+
} });
|
|
2137
|
+
});
|
|
2138
|
+
blogPublish.command("execute").argument("<article-id>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--revision <revision-id>", "same exact revision used for preview").requiredOption("--confirmation-token <token>", "short-lived token returned by preview").option("--destination <destination-id...>", "same exact destination IDs used for preview").option("--idempotency-key <key>", "stable retry key; defaults to request ID").option("--yes", "confirm publication").action(async (articleId, local) => {
|
|
2139
|
+
const global = program.opts();
|
|
2140
|
+
commandExitCode = await execute({ command: "blog publish execute", global, runtime, async action(context, client) {
|
|
2141
|
+
await requireWriteConsent({ yes: local.yes, global, runtime, preview: `Publish the exact approved Blog revision?
|
|
2142
|
+
Project: ${local.project}
|
|
2143
|
+
Article: ${articleId}
|
|
2144
|
+
Revision: ${local.revision}` });
|
|
2145
|
+
const data = await client.blog.articles.executePublish(local.project, articleId, { revisionId: local.revision, destinationIds: local.destination, confirmationToken: local.confirmationToken, idempotencyKey: local.idempotencyKey ?? context.requestId }, { requestId: context.requestId });
|
|
2146
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2147
|
+
} });
|
|
2148
|
+
});
|
|
2149
|
+
const seo = program.command("seo").description("Read authorized SEO opportunities and weekly reports");
|
|
2150
|
+
const seoOpportunities = seo.command("opportunities").description("Read accepted SEO opportunities");
|
|
2151
|
+
seoOpportunities.command("list").description("List bounded SEO opportunities").requiredOption("--project <project-id>", "exact Rolino project ID").option("--limit <number>", "maximum opportunities to return", (value) => {
|
|
2152
|
+
const parsed = Number(value);
|
|
2153
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 50) {
|
|
2154
|
+
throw new InvalidArgumentError("Limit must be an integer from 1 to 50.");
|
|
2155
|
+
}
|
|
2156
|
+
return parsed;
|
|
2157
|
+
}).option("--cursor <cursor>", "continue from an SEO opportunity cursor").option("--kind <kind>", "filter by exact SEO opportunity kind", seoOpportunityKind).option("--impact <impact>", "filter by HIGH, MEDIUM, or LOW impact", seoExpectedImpact).action(async (local) => {
|
|
2158
|
+
const global = program.opts();
|
|
2159
|
+
commandExitCode = await execute({
|
|
2160
|
+
command: "seo opportunities list",
|
|
2161
|
+
global,
|
|
2162
|
+
runtime,
|
|
2163
|
+
async action(context, client) {
|
|
2164
|
+
const data = await client.seo.opportunities.list(local.project, {
|
|
2165
|
+
limit: local.limit,
|
|
2166
|
+
cursor: local.cursor,
|
|
2167
|
+
kind: local.kind,
|
|
2168
|
+
expectedImpact: local.impact
|
|
2169
|
+
}, { requestId: context.requestId });
|
|
2170
|
+
writeSuccess(context, data, formatSeoOpportunities(data), data.items.slice(0, 3).map((item) => `rolino seo opportunities show ${item.id} --project ${local.project} --agent`));
|
|
2171
|
+
}
|
|
2172
|
+
});
|
|
2173
|
+
});
|
|
2174
|
+
seoOpportunities.command("show").description("Show one canonical SEO opportunity task").argument("<opportunity-id>").requiredOption("--project <project-id>", "exact Rolino project ID").action(async (opportunityId, local) => {
|
|
2175
|
+
const global = program.opts();
|
|
2176
|
+
commandExitCode = await execute({
|
|
2177
|
+
command: "seo opportunities show",
|
|
2178
|
+
global,
|
|
2179
|
+
runtime,
|
|
2180
|
+
async action(context, client) {
|
|
2181
|
+
const opportunity = await client.seo.opportunities.get(local.project, opportunityId, { requestId: context.requestId });
|
|
2182
|
+
writeSuccess(context, opportunity, formatSeoOpportunity(opportunity));
|
|
2183
|
+
}
|
|
2184
|
+
});
|
|
2185
|
+
});
|
|
2186
|
+
const seoReports = seo.command("reports").description("Read immutable weekly SEO report snapshots");
|
|
2187
|
+
seoReports.command("list").description("List bounded weekly SEO reports").requiredOption("--project <project-id>", "exact Rolino project ID").option("--limit <number>", "maximum reports to return", (value) => {
|
|
2188
|
+
const parsed = Number(value);
|
|
2189
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 26) {
|
|
2190
|
+
throw new InvalidArgumentError("Limit must be an integer from 1 to 26.");
|
|
2191
|
+
}
|
|
2192
|
+
return parsed;
|
|
2193
|
+
}).option("--cursor <cursor>", "continue from an SEO report cursor").option("--status <status>", "filter by COMPLETE or PARTIAL", seoReportCompleteness).action(async (local) => {
|
|
2194
|
+
const global = program.opts();
|
|
2195
|
+
commandExitCode = await execute({
|
|
2196
|
+
command: "seo reports list",
|
|
2197
|
+
global,
|
|
2198
|
+
runtime,
|
|
2199
|
+
async action(context, client) {
|
|
2200
|
+
const data = await client.seo.reports.list(local.project, {
|
|
2201
|
+
limit: local.limit,
|
|
2202
|
+
cursor: local.cursor,
|
|
2203
|
+
completeness: local.status
|
|
2204
|
+
}, { requestId: context.requestId });
|
|
2205
|
+
writeSuccess(context, data, formatSeoReports(data), data.items.slice(0, 3).map((item) => `rolino seo reports show ${item.id} --project ${local.project} --agent`));
|
|
2206
|
+
}
|
|
2207
|
+
});
|
|
2208
|
+
});
|
|
2209
|
+
seoReports.command("show").description("Show one weekly SEO report snapshot").argument("<report-id>").requiredOption("--project <project-id>", "exact Rolino project ID").action(async (reportId, local) => {
|
|
2210
|
+
const global = program.opts();
|
|
2211
|
+
commandExitCode = await execute({
|
|
2212
|
+
command: "seo reports show",
|
|
2213
|
+
global,
|
|
2214
|
+
runtime,
|
|
2215
|
+
async action(context, client) {
|
|
2216
|
+
const report = await client.seo.reports.get(local.project, reportId, { requestId: context.requestId });
|
|
2217
|
+
writeSuccess(context, report, formatSeoReport(report));
|
|
2218
|
+
}
|
|
2219
|
+
});
|
|
2220
|
+
});
|
|
1867
2221
|
program.command("doctor").description("Check configuration, compatibility, and authentication").action(async () => {
|
|
1868
2222
|
const global = program.opts();
|
|
1869
2223
|
commandExitCode = await execute({
|
|
@@ -1957,4 +2311,4 @@ export {
|
|
|
1957
2311
|
ROLINO_CLI_VERSION,
|
|
1958
2312
|
runCli
|
|
1959
2313
|
};
|
|
1960
|
-
//# sourceMappingURL=chunk-
|
|
2314
|
+
//# sourceMappingURL=chunk-TFNGSKT3.js.map
|