@rolino/cli 0.7.0 → 0.7.1
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 +9 -0
- package/README.md +8 -4
- package/dist/bin.cjs +30 -34
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-PEJ2WA66.js → chunk-KSPZKKBG.js} +13 -17
- package/dist/chunk-KSPZKKBG.js.map +1 -0
- package/dist/index.cjs +30 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-PEJ2WA66.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @rolino/cli
|
|
2
2
|
|
|
3
|
+
## 0.7.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- c340405: Request the complete opt-in capability set during browser authorization so users can grant draft and scheduling access to local agents. Remote MCP setup now uses host-native configuration and standard OAuth client discovery instead of a fixed Rolino-managed client.
|
|
8
|
+
- @rolino/contracts@0.7.1
|
|
9
|
+
- @rolino/sdk@0.7.1
|
|
10
|
+
- @rolino/local-auth@0.7.1
|
|
11
|
+
|
|
3
12
|
## 0.7.0
|
|
4
13
|
|
|
5
14
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -116,8 +116,10 @@ page cannot restart the closed loopback listener.
|
|
|
116
116
|
|
|
117
117
|
`setup mcp` checks `/api/v1/meta` and prefers hosted Streamable HTTP when it is
|
|
118
118
|
available. Remote setup writes the `/mcp` URL and OAuth mode, does not start a
|
|
119
|
-
local MCP process, and does not reuse `rolino auth login`.
|
|
120
|
-
|
|
119
|
+
local MCP process, and does not reuse `rolino auth login`. For Codex, it leaves
|
|
120
|
+
OAuth client registration and the loopback callback to Codex so Codex can use
|
|
121
|
+
Rolino's advertised Client ID Metadata Document support. Run `codex mcp login
|
|
122
|
+
rolino` after remote Codex setup. Use `--transport http` to
|
|
121
123
|
require remote MCP or `--transport stdio` to require the local package and its
|
|
122
124
|
shared CLI OAuth session. The command previews the exact token-free
|
|
123
125
|
configuration and asks before changing anything. User scope is the default.
|
|
@@ -125,8 +127,10 @@ Codex configuration is written to `CODEX_HOME/config.toml` or
|
|
|
125
127
|
`~/.codex/config.toml`; Claude Code user scope is applied through its official
|
|
126
128
|
CLI. Project scope writes `.codex/config.toml` or `.mcp.json` in the current
|
|
127
129
|
directory. Existing file-backed configuration is backed up with a
|
|
128
|
-
`.rolino-backup` suffix. Use `--dry-run` to preview in scripts and `--yes` to
|
|
129
|
-
provide explicit non-interactive consent; `--agent` never implies consent.
|
|
130
|
+
`.rolino-backup` suffix. Use `--dry-run` to preview in scripts and `--yes` to
|
|
131
|
+
provide explicit non-interactive consent; `--agent` never implies consent.
|
|
132
|
+
An orphan Rolino-managed marker left by an earlier removal is repaired without
|
|
133
|
+
changing unrelated Codex settings.
|
|
130
134
|
|
|
131
135
|
Draft creation and update never schedule or publish. Updates change only the
|
|
132
136
|
fields supplied; omitted media, destinations, captions, and provider settings
|
package/dist/bin.cjs
CHANGED
|
@@ -34,7 +34,7 @@ var import_commander = require("commander");
|
|
|
34
34
|
// package.json
|
|
35
35
|
var package_default = {
|
|
36
36
|
name: "@rolino/cli",
|
|
37
|
-
version: "0.7.
|
|
37
|
+
version: "0.7.1",
|
|
38
38
|
description: "Agent-friendly command-line interface for Rolino",
|
|
39
39
|
type: "module",
|
|
40
40
|
license: "MIT",
|
|
@@ -91,9 +91,9 @@ var package_default = {
|
|
|
91
91
|
dev: "tsx src/bin.ts"
|
|
92
92
|
},
|
|
93
93
|
dependencies: {
|
|
94
|
-
"@rolino/contracts": "0.7.
|
|
95
|
-
"@rolino/local-auth": "0.7.
|
|
96
|
-
"@rolino/sdk": "0.7.
|
|
94
|
+
"@rolino/contracts": "0.7.1",
|
|
95
|
+
"@rolino/local-auth": "0.7.1",
|
|
96
|
+
"@rolino/sdk": "0.7.1",
|
|
97
97
|
commander: "^15.0.0",
|
|
98
98
|
open: "^11.0.0"
|
|
99
99
|
},
|
|
@@ -106,24 +106,21 @@ var package_default = {
|
|
|
106
106
|
};
|
|
107
107
|
|
|
108
108
|
// src/cli.ts
|
|
109
|
-
var
|
|
109
|
+
var import_contracts2 = require("@rolino/contracts");
|
|
110
110
|
var import_sdk = require("@rolino/sdk");
|
|
111
111
|
|
|
112
112
|
// src/browser-login.ts
|
|
113
113
|
var import_node_crypto = require("crypto");
|
|
114
114
|
var import_node_http = require("http");
|
|
115
|
+
var import_contracts = require("@rolino/contracts");
|
|
115
116
|
var import_local_auth = require("@rolino/local-auth");
|
|
116
117
|
var import_open = __toESM(require("open"), 1);
|
|
117
118
|
var OAUTH_CALLBACK_PORT = 48391;
|
|
118
119
|
var OAUTH_CALLBACK_PATH = "/oauth/callback";
|
|
119
120
|
var OAUTH_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
120
|
-
var
|
|
121
|
+
var AUTHORIZATION_REQUEST_SCOPES = [
|
|
121
122
|
"offline_access",
|
|
122
|
-
|
|
123
|
-
"projects:read",
|
|
124
|
-
"posts:read",
|
|
125
|
-
"integrations:read",
|
|
126
|
-
"calendar:read"
|
|
123
|
+
...import_contracts.AGENT_CAPABILITIES
|
|
127
124
|
];
|
|
128
125
|
function escapeHtml(value) {
|
|
129
126
|
return value.replace(/[&<>"']/g, (character) => ({
|
|
@@ -163,7 +160,7 @@ function createBrowserAuthorizationRequest(baseUrl) {
|
|
|
163
160
|
url.searchParams.set("response_type", "code");
|
|
164
161
|
url.searchParams.set("client_id", configuration.clientId);
|
|
165
162
|
url.searchParams.set("redirect_uri", redirectUri);
|
|
166
|
-
url.searchParams.set("scope",
|
|
163
|
+
url.searchParams.set("scope", AUTHORIZATION_REQUEST_SCOPES.join(" "));
|
|
167
164
|
url.searchParams.set("resource", configuration.resource);
|
|
168
165
|
url.searchParams.set("state", state);
|
|
169
166
|
url.searchParams.set("code_challenge", codeChallenge);
|
|
@@ -202,7 +199,7 @@ async function exchangeAuthorizationCode(options) {
|
|
|
202
199
|
accessTokenExpiresAt: new Date(Date.now() + expiresIn * 1e3).toISOString(),
|
|
203
200
|
refreshToken: payload.refresh_token,
|
|
204
201
|
refreshTokenExpiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1e3).toISOString(),
|
|
205
|
-
scopes: typeof payload.scope === "string" ? payload.scope.split(/\s+/).filter(Boolean) : [...
|
|
202
|
+
scopes: typeof payload.scope === "string" ? payload.scope.split(/\s+/).filter(Boolean) : [...AUTHORIZATION_REQUEST_SCOPES]
|
|
206
203
|
};
|
|
207
204
|
}
|
|
208
205
|
async function loginWithBrowser(options) {
|
|
@@ -669,13 +666,12 @@ function updateCodexConfig(source, server) {
|
|
|
669
666
|
const block = codexBlock(server, newline);
|
|
670
667
|
const begin = source.indexOf(CODEX_BEGIN);
|
|
671
668
|
const end = source.indexOf(CODEX_END);
|
|
672
|
-
if (begin === -1 !== (end === -1) || begin !== -1 && end < begin) {
|
|
673
|
-
throw new TypeError("Codex config contains an incomplete Rolino-managed block.");
|
|
674
|
-
}
|
|
675
669
|
let unmanagedSource = source;
|
|
676
|
-
if (begin !== -1) {
|
|
670
|
+
if (begin !== -1 && end !== -1 && end > begin) {
|
|
677
671
|
const after = end + CODEX_END.length;
|
|
678
672
|
unmanagedSource = `${source.slice(0, begin)}${source.slice(after)}`;
|
|
673
|
+
} else if (begin !== -1 || end !== -1) {
|
|
674
|
+
unmanagedSource = source.split(/\r?\n/).filter((line) => line.trim() !== CODEX_BEGIN && line.trim() !== CODEX_END).join(newline);
|
|
679
675
|
}
|
|
680
676
|
const withoutRolino = removeExistingCodexEntry(unmanagedSource, newline);
|
|
681
677
|
return `${withoutRolino ? `${withoutRolino}${newline}${newline}` : ""}${block}${newline}`;
|
|
@@ -881,40 +877,40 @@ function outputFormat(value) {
|
|
|
881
877
|
throw new import_commander.InvalidArgumentError("Output must be human, json, or jsonl.");
|
|
882
878
|
}
|
|
883
879
|
function postStatus(value) {
|
|
884
|
-
const parsed =
|
|
880
|
+
const parsed = import_contracts2.PostStatusSchema.safeParse(value.toUpperCase());
|
|
885
881
|
if (parsed.success) return parsed.data;
|
|
886
882
|
throw new import_commander.InvalidArgumentError(
|
|
887
|
-
`Status must be one of ${
|
|
883
|
+
`Status must be one of ${import_contracts2.PostStatusSchema.options.join(", ")}.`
|
|
888
884
|
);
|
|
889
885
|
}
|
|
890
886
|
function seoOpportunityKind(value) {
|
|
891
|
-
const parsed =
|
|
887
|
+
const parsed = import_contracts2.SeoOpportunityKindSchema.safeParse(value.toUpperCase());
|
|
892
888
|
if (parsed.success) return parsed.data;
|
|
893
|
-
throw new import_commander.InvalidArgumentError(`SEO kind must be one of ${
|
|
889
|
+
throw new import_commander.InvalidArgumentError(`SEO kind must be one of ${import_contracts2.SeoOpportunityKindSchema.options.join(", ")}.`);
|
|
894
890
|
}
|
|
895
891
|
function seoExpectedImpact(value) {
|
|
896
|
-
const parsed =
|
|
892
|
+
const parsed = import_contracts2.SeoExpectedImpactSchema.safeParse(value.toUpperCase());
|
|
897
893
|
if (parsed.success) return parsed.data;
|
|
898
894
|
throw new import_commander.InvalidArgumentError("SEO impact must be HIGH, MEDIUM, or LOW.");
|
|
899
895
|
}
|
|
900
896
|
function seoReportCompleteness(value) {
|
|
901
|
-
const parsed =
|
|
897
|
+
const parsed = import_contracts2.SeoReportCompletenessSchema.safeParse(value.toUpperCase());
|
|
902
898
|
if (parsed.success) return parsed.data;
|
|
903
899
|
throw new import_commander.InvalidArgumentError("Report status must be COMPLETE or PARTIAL.");
|
|
904
900
|
}
|
|
905
901
|
function projectType(value) {
|
|
906
|
-
const parsed =
|
|
902
|
+
const parsed = import_contracts2.ProjectTypeSchema.safeParse(value.toUpperCase());
|
|
907
903
|
if (parsed.success) return parsed.data;
|
|
908
904
|
throw new import_commander.InvalidArgumentError(
|
|
909
|
-
`Type must be one of ${
|
|
905
|
+
`Type must be one of ${import_contracts2.ProjectTypeSchema.options.join(", ")}.`
|
|
910
906
|
);
|
|
911
907
|
}
|
|
912
908
|
function publishingProvider(value) {
|
|
913
909
|
const normalized = value.toUpperCase();
|
|
914
|
-
const parsed =
|
|
910
|
+
const parsed = import_contracts2.PublishingProviderSchema.safeParse(normalized);
|
|
915
911
|
if (parsed.success) return parsed.data;
|
|
916
912
|
throw new import_commander.InvalidArgumentError(
|
|
917
|
-
`Platform must be one of ${
|
|
913
|
+
`Platform must be one of ${import_contracts2.PublishingProviderSchema.options.join(", ")}.`
|
|
918
914
|
);
|
|
919
915
|
}
|
|
920
916
|
function collectPublishingProvider(value, previous) {
|
|
@@ -925,10 +921,10 @@ function collectString(value, previous) {
|
|
|
925
921
|
}
|
|
926
922
|
function deliveryOptionsProvider(value) {
|
|
927
923
|
const normalized = value.toUpperCase();
|
|
928
|
-
const parsed =
|
|
924
|
+
const parsed = import_contracts2.ProviderDeliveryOptionsProviderSchema.safeParse(normalized);
|
|
929
925
|
if (parsed.success) return parsed.data;
|
|
930
926
|
throw new import_commander.InvalidArgumentError(
|
|
931
|
-
`Provider must be one of ${
|
|
927
|
+
`Provider must be one of ${import_contracts2.ProviderDeliveryOptionsProviderSchema.options.join(", ")}.`
|
|
932
928
|
);
|
|
933
929
|
}
|
|
934
930
|
function tiktokPostMode(value) {
|
|
@@ -966,7 +962,7 @@ function yesOrNo(value) {
|
|
|
966
962
|
function youtubeSettings(options) {
|
|
967
963
|
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;
|
|
968
964
|
if (!hasYouTubeOptions) return null;
|
|
969
|
-
return
|
|
965
|
+
return import_contracts2.YouTubePostSettingsSchema.parse({
|
|
970
966
|
title: options.youtubeTitle,
|
|
971
967
|
categoryId: options.youtubeCategoryId,
|
|
972
968
|
privacyStatus: options.youtubePrivacy,
|
|
@@ -1155,7 +1151,7 @@ function errorForOutput(error) {
|
|
|
1155
1151
|
function tiktokSettings(options) {
|
|
1156
1152
|
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;
|
|
1157
1153
|
if (!hasTikTokOptions) return void 0;
|
|
1158
|
-
return
|
|
1154
|
+
return import_contracts2.TikTokDraftSettingsSchema.parse({
|
|
1159
1155
|
postMode: options.tiktokMode,
|
|
1160
1156
|
privacyLevel: options.tiktokVisibility,
|
|
1161
1157
|
allowComment: options.tiktokComments,
|
|
@@ -1299,7 +1295,7 @@ async function runCli(argv = process.argv, overrides = {}) {
|
|
|
1299
1295
|
global,
|
|
1300
1296
|
runtime,
|
|
1301
1297
|
async action(context, client) {
|
|
1302
|
-
const parsed =
|
|
1298
|
+
const parsed = import_contracts2.ProjectCreateInputSchema.safeParse({
|
|
1303
1299
|
name: local.name,
|
|
1304
1300
|
type: local.type,
|
|
1305
1301
|
websiteUrl: local.website,
|
|
@@ -2175,7 +2171,7 @@ This moves eligible editorial dates only. It does not schedule, publish, or unpu
|
|
|
2175
2171
|
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) => {
|
|
2176
2172
|
const global = program.opts();
|
|
2177
2173
|
commandExitCode = await execute({ command: "blog articles update", global, runtime, async action(context, client) {
|
|
2178
|
-
const draft =
|
|
2174
|
+
const draft = import_contracts2.AgentBlogDraftUpdateSchema.parse(JSON.parse(await (0, import_promises2.readFile)((0, import_node_path2.resolve)(runtime.cwd, local.input), "utf8")));
|
|
2179
2175
|
await requireWriteConsent({ yes: local.yes, global, runtime, preview: `Save a new immutable Blog draft revision?
|
|
2180
2176
|
Project: ${local.project}
|
|
2181
2177
|
Article: ${articleId}
|
|
@@ -2352,7 +2348,7 @@ Revision: ${local.revision}` });
|
|
|
2352
2348
|
backlinkProspects.command("list").requiredOption("--project <project-id>").option("--stage <stage>").action(async (local) => {
|
|
2353
2349
|
const global = program.opts();
|
|
2354
2350
|
commandExitCode = await execute({ command: "backlinks prospects list", global, runtime, async action(context, client) {
|
|
2355
|
-
const stage = local.stage ?
|
|
2351
|
+
const stage = local.stage ? import_contracts2.BacklinkProspectStageSchema.parse(local.stage.toUpperCase()) : void 0;
|
|
2356
2352
|
const data = await client.backlinks.prospects.list(local.project, { stage }, { requestId: context.requestId });
|
|
2357
2353
|
writeSuccess(context, data, JSON.stringify(data, null, 2));
|
|
2358
2354
|
} });
|