@rolino/cli 0.5.0-beta.0 → 0.5.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 +41 -0
- package/README.md +63 -26
- package/dist/bin.cjs +105 -4
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-TFNGSKT3.js → chunk-MBZL2CK6.js} +106 -5
- package/dist/chunk-MBZL2CK6.js.map +1 -0
- package/dist/index.cjs +105 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-TFNGSKT3.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -50,7 +50,7 @@ var import_commander = require("commander");
|
|
|
50
50
|
// package.json
|
|
51
51
|
var package_default = {
|
|
52
52
|
name: "@rolino/cli",
|
|
53
|
-
version: "0.5.0
|
|
53
|
+
version: "0.5.0",
|
|
54
54
|
description: "Agent-friendly command-line interface for Rolino",
|
|
55
55
|
type: "module",
|
|
56
56
|
license: "MIT",
|
|
@@ -107,9 +107,9 @@ var package_default = {
|
|
|
107
107
|
dev: "tsx src/bin.ts"
|
|
108
108
|
},
|
|
109
109
|
dependencies: {
|
|
110
|
-
"@rolino/contracts": "0.5.0
|
|
111
|
-
"@rolino/local-auth": "0.5.0
|
|
112
|
-
"@rolino/sdk": "0.5.0
|
|
110
|
+
"@rolino/contracts": "0.5.0",
|
|
111
|
+
"@rolino/local-auth": "0.5.0",
|
|
112
|
+
"@rolino/sdk": "0.5.0",
|
|
113
113
|
commander: "^15.0.0",
|
|
114
114
|
open: "^11.0.0"
|
|
115
115
|
},
|
|
@@ -1069,6 +1069,10 @@ async function requireWriteConsent(options) {
|
|
|
1069
1069
|
);
|
|
1070
1070
|
}
|
|
1071
1071
|
}
|
|
1072
|
+
function requireBlogExecutionConsent(options) {
|
|
1073
|
+
if (options.yes || resolveFormat(options.global, options.runtime) !== "human") return;
|
|
1074
|
+
throw new TypeError("This Blog execute command requires explicit consent. Review the confirmed operation and pass --yes.");
|
|
1075
|
+
}
|
|
1072
1076
|
function formatMcpSetupPreview(result) {
|
|
1073
1077
|
return [
|
|
1074
1078
|
`Client: ${result.client === "codex" ? "Codex" : "Claude Code"}`,
|
|
@@ -2129,6 +2133,103 @@ Article: ${articleId}` });
|
|
|
2129
2133
|
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2130
2134
|
} });
|
|
2131
2135
|
});
|
|
2136
|
+
const blogImages = blog.command("images").description("Create and review Blog images with blog:write; cannot approve or publish");
|
|
2137
|
+
blogImages.command("generate").description("Queue one exact-revision featured image with blog:write; cannot approve or publish").argument("<article-id>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--revision <revision-id>", "exact Blog revision ID").option("--editorial-brief <text>", "bounded visual direction; provider controls stay on the server").option("--idempotency-key <key>", "stable retry key; defaults to request ID").action(async (articleId, local) => {
|
|
2138
|
+
const global = program.opts();
|
|
2139
|
+
commandExitCode = await execute({ command: "blog images generate", global, runtime, async action(context, client) {
|
|
2140
|
+
const data = await client.blog.articles.generateImage(local.project, articleId, { revisionId: local.revision, idempotencyKey: local.idempotencyKey ?? context.requestId, editorialBrief: local.editorialBrief }, { requestId: context.requestId });
|
|
2141
|
+
writeSuccess(context, data, `Blog image generation queued.
|
|
2142
|
+
Image: ${data.image.id}
|
|
2143
|
+
Job: ${data.job.id}`);
|
|
2144
|
+
} });
|
|
2145
|
+
});
|
|
2146
|
+
blogImages.command("upload").description("Upload one JPEG, PNG, or WebP for an exact Blog revision with blog:write; cannot approve or publish").argument("<article-id>").argument("<file-path>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--revision <revision-id>", "exact Blog revision ID").requiredOption("--alt-text <text>", "reviewable image alt text").action(async (articleId, filePath, local) => {
|
|
2147
|
+
const global = program.opts();
|
|
2148
|
+
commandExitCode = await execute({ command: "blog images upload", global, runtime, async action(context, client) {
|
|
2149
|
+
const absolutePath = (0, import_node_path2.resolve)(runtime.cwd, filePath);
|
|
2150
|
+
const details = await (0, import_promises2.stat)(absolutePath).catch(() => null);
|
|
2151
|
+
if (!details?.isFile()) throw new TypeError("The Blog image path must point to a readable file.");
|
|
2152
|
+
const contentTypes = { ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".png": "image/png", ".webp": "image/webp" };
|
|
2153
|
+
const extension = (0, import_node_path2.extname)(absolutePath).toLowerCase();
|
|
2154
|
+
const contentType = contentTypes[extension];
|
|
2155
|
+
if (!contentType) throw new TypeError("Use a JPEG, PNG, or WebP Blog image.");
|
|
2156
|
+
const body = await (0, import_node_fs2.openAsBlob)(absolutePath, { type: contentType });
|
|
2157
|
+
const data = await client.blog.articles.uploadImage(local.project, articleId, { revisionId: local.revision, fileName: (0, import_node_path2.basename)(absolutePath), contentType, fileSize: details.size, altText: local.altText, body }, { requestId: context.requestId });
|
|
2158
|
+
writeSuccess(context, data, `Blog image uploaded for review.
|
|
2159
|
+
Image: ${data.id}
|
|
2160
|
+
State: ${data.state}`);
|
|
2161
|
+
} });
|
|
2162
|
+
});
|
|
2163
|
+
blogImages.command("review").description("Review one exact Blog image with blog:write; does not approve the article or publish").argument("<article-id>").argument("<image-id>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--decision <decision>", "APPROVED or REJECTED").requiredOption("--expected-version <version>", "current image version", positiveInteger).option("--alt-text <text>", "final image alt text; required by the server for approval").option("--idempotency-key <key>", "stable retry key; defaults to request ID").action(async (articleId, imageId, local) => {
|
|
2164
|
+
const decision = local.decision.toUpperCase();
|
|
2165
|
+
if (decision !== "APPROVED" && decision !== "REJECTED") throw new TypeError("--decision must be APPROVED or REJECTED.");
|
|
2166
|
+
const global = program.opts();
|
|
2167
|
+
commandExitCode = await execute({ command: "blog images review", global, runtime, async action(context, client) {
|
|
2168
|
+
const data = await client.blog.articles.reviewImage(local.project, articleId, imageId, { decision, expectedVersion: local.expectedVersion, altText: local.altText ?? "", idempotencyKey: local.idempotencyKey ?? context.requestId }, { requestId: context.requestId });
|
|
2169
|
+
writeSuccess(context, data, `Blog image review saved.
|
|
2170
|
+
Image: ${data.id}
|
|
2171
|
+
State: ${data.state}`);
|
|
2172
|
+
} });
|
|
2173
|
+
});
|
|
2174
|
+
const blogApprove = blog.command("approve").description("Approve one exact Blog bundle with blog:approve; cannot publish");
|
|
2175
|
+
blogApprove.command("preview").description("Preview one exact approval bundle with blog:approve; creates a confirmation but cannot publish").argument("<article-id>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--revision <revision-id>", "exact Blog revision ID").action(async (articleId, local) => {
|
|
2176
|
+
const global = program.opts();
|
|
2177
|
+
commandExitCode = await execute({ command: "blog approve preview", global, runtime, async action(context, client) {
|
|
2178
|
+
const data = await client.blog.articles.previewApproval(local.project, articleId, { revisionId: local.revision }, { requestId: context.requestId });
|
|
2179
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2180
|
+
} });
|
|
2181
|
+
});
|
|
2182
|
+
blogApprove.command("execute").description("Approve the confirmed exact bundle with blog:approve; separate blog:publish access is still required").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").requiredOption("--idempotency-key <key>", "stable retry key").option("--yes", "confirm exact bundle approval").action(async (articleId, local) => {
|
|
2183
|
+
const global = program.opts();
|
|
2184
|
+
commandExitCode = await execute({ command: "blog approve execute", global, runtime, async action(context, client) {
|
|
2185
|
+
requireBlogExecutionConsent({ yes: local.yes, global, runtime });
|
|
2186
|
+
const data = await client.blog.articles.executeApproval(local.project, articleId, { revisionId: local.revision, confirmationToken: local.confirmationToken, idempotencyKey: local.idempotencyKey }, { requestId: context.requestId });
|
|
2187
|
+
writeSuccess(context, data, `Exact Blog bundle approved.
|
|
2188
|
+
Revision: ${data.revisionId}
|
|
2189
|
+
Publishing still requires blog:publish.`);
|
|
2190
|
+
} });
|
|
2191
|
+
});
|
|
2192
|
+
const blogSchedule = blog.command("schedule").description("Schedule exact approved Blog bundles with blog:publish; does not grant approval");
|
|
2193
|
+
const addScheduleOptions = (command, executeSchedule) => {
|
|
2194
|
+
command.argument("<article-id>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--revision <revision-id>", "exact approved Blog revision ID").requiredOption("--at <iso>", "future ISO date-time with UTC offset").requiredOption("--timezone <iana>", "explicit IANA timezone").option("--destination <destination-id...>", "exact destination IDs; defaults to the current primary");
|
|
2195
|
+
if (executeSchedule) command.requiredOption("--confirmation-token <token>", "short-lived token returned by preview").requiredOption("--idempotency-key <key>", "stable retry key").option("--yes", "confirm future external publication");
|
|
2196
|
+
return command;
|
|
2197
|
+
};
|
|
2198
|
+
addScheduleOptions(blogSchedule.command("preview").description("Preview an exact future Blog schedule with blog:publish; does not publish now"), false).action(async (articleId, local) => {
|
|
2199
|
+
const global = program.opts();
|
|
2200
|
+
commandExitCode = await execute({ command: "blog schedule preview", global, runtime, async action(context, client) {
|
|
2201
|
+
const data = await client.blog.articles.previewSchedule(local.project, articleId, { revisionId: local.revision, scheduledAt: local.at, timezone: local.timezone, destinationIds: local.destination }, { requestId: context.requestId });
|
|
2202
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2203
|
+
} });
|
|
2204
|
+
});
|
|
2205
|
+
addScheduleOptions(blogSchedule.command("execute").description("Execute a confirmed future Blog schedule with blog:publish; causes future external publication"), true).action(async (articleId, local) => {
|
|
2206
|
+
const global = program.opts();
|
|
2207
|
+
commandExitCode = await execute({ command: "blog schedule execute", global, runtime, async action(context, client) {
|
|
2208
|
+
requireBlogExecutionConsent({ yes: local.yes, global, runtime });
|
|
2209
|
+
const data = await client.blog.articles.executeSchedule(local.project, articleId, { revisionId: local.revision, scheduledAt: local.at, timezone: local.timezone, destinationIds: local.destination, confirmationToken: local.confirmationToken, idempotencyKey: local.idempotencyKey }, { requestId: context.requestId });
|
|
2210
|
+
writeSuccess(context, data, `Blog article scheduled.
|
|
2211
|
+
Time: ${data.scheduledAt}
|
|
2212
|
+
Timezone: ${data.timezone}`);
|
|
2213
|
+
} });
|
|
2214
|
+
});
|
|
2215
|
+
const blogScheduleCancel = blogSchedule.command("cancel").description("Cancel one future Blog schedule with blog:publish; never unpublishes a live article");
|
|
2216
|
+
blogScheduleCancel.command("preview").description("Preview exact schedule cancellation with blog:publish; does not unpublish").argument("<article-id>").requiredOption("--project <project-id>", "exact Rolino project ID").action(async (articleId, local) => {
|
|
2217
|
+
const global = program.opts();
|
|
2218
|
+
commandExitCode = await execute({ command: "blog schedule cancel preview", global, runtime, async action(context, client) {
|
|
2219
|
+
const data = await client.blog.articles.previewScheduleCancellation(local.project, articleId, { requestId: context.requestId });
|
|
2220
|
+
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2221
|
+
} });
|
|
2222
|
+
});
|
|
2223
|
+
blogScheduleCancel.command("execute").description("Cancel the confirmed future schedule with blog:publish; never unpublishes a live article").argument("<article-id>").requiredOption("--project <project-id>", "exact Rolino project ID").requiredOption("--confirmation-token <token>", "short-lived token returned by preview").requiredOption("--idempotency-key <key>", "stable retry key").option("--yes", "confirm schedule cancellation").action(async (articleId, local) => {
|
|
2224
|
+
const global = program.opts();
|
|
2225
|
+
commandExitCode = await execute({ command: "blog schedule cancel execute", global, runtime, async action(context, client) {
|
|
2226
|
+
requireBlogExecutionConsent({ yes: local.yes, global, runtime });
|
|
2227
|
+
const data = await client.blog.articles.executeScheduleCancellation(local.project, articleId, { confirmationToken: local.confirmationToken, idempotencyKey: local.idempotencyKey }, { requestId: context.requestId });
|
|
2228
|
+
writeSuccess(context, data, `Future Blog schedule canceled.
|
|
2229
|
+
Article: ${data.articleId}
|
|
2230
|
+
A live article was not unpublished.`);
|
|
2231
|
+
} });
|
|
2232
|
+
});
|
|
2132
2233
|
blog.command("job").argument("<job-id>").requiredOption("--project <project-id>", "exact Rolino project ID").action(async (jobId, local) => {
|
|
2133
2234
|
const global = program.opts();
|
|
2134
2235
|
commandExitCode = await execute({ command: "blog job", global, runtime, async action(context, client) {
|