@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/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.7.0",
53
+ version: "0.7.1",
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.7.0",
111
- "@rolino/local-auth": "0.7.0",
112
- "@rolino/sdk": "0.7.0",
110
+ "@rolino/contracts": "0.7.1",
111
+ "@rolino/local-auth": "0.7.1",
112
+ "@rolino/sdk": "0.7.1",
113
113
  commander: "^15.0.0",
114
114
  open: "^11.0.0"
115
115
  },
@@ -122,24 +122,21 @@ var package_default = {
122
122
  };
123
123
 
124
124
  // src/cli.ts
125
- var import_contracts = require("@rolino/contracts");
125
+ var import_contracts2 = require("@rolino/contracts");
126
126
  var import_sdk = require("@rolino/sdk");
127
127
 
128
128
  // src/browser-login.ts
129
129
  var import_node_crypto = require("crypto");
130
130
  var import_node_http = require("http");
131
+ var import_contracts = require("@rolino/contracts");
131
132
  var import_local_auth = require("@rolino/local-auth");
132
133
  var import_open = __toESM(require("open"), 1);
133
134
  var OAUTH_CALLBACK_PORT = 48391;
134
135
  var OAUTH_CALLBACK_PATH = "/oauth/callback";
135
136
  var OAUTH_TIMEOUT_MS = 5 * 60 * 1e3;
136
- var DEFAULT_SCOPES = [
137
+ var AUTHORIZATION_REQUEST_SCOPES = [
137
138
  "offline_access",
138
- "identity:read",
139
- "projects:read",
140
- "posts:read",
141
- "integrations:read",
142
- "calendar:read"
139
+ ...import_contracts.AGENT_CAPABILITIES
143
140
  ];
144
141
  function escapeHtml(value) {
145
142
  return value.replace(/[&<>"']/g, (character) => ({
@@ -179,7 +176,7 @@ function createBrowserAuthorizationRequest(baseUrl) {
179
176
  url.searchParams.set("response_type", "code");
180
177
  url.searchParams.set("client_id", configuration.clientId);
181
178
  url.searchParams.set("redirect_uri", redirectUri);
182
- url.searchParams.set("scope", DEFAULT_SCOPES.join(" "));
179
+ url.searchParams.set("scope", AUTHORIZATION_REQUEST_SCOPES.join(" "));
183
180
  url.searchParams.set("resource", configuration.resource);
184
181
  url.searchParams.set("state", state);
185
182
  url.searchParams.set("code_challenge", codeChallenge);
@@ -218,7 +215,7 @@ async function exchangeAuthorizationCode(options) {
218
215
  accessTokenExpiresAt: new Date(Date.now() + expiresIn * 1e3).toISOString(),
219
216
  refreshToken: payload.refresh_token,
220
217
  refreshTokenExpiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1e3).toISOString(),
221
- scopes: typeof payload.scope === "string" ? payload.scope.split(/\s+/).filter(Boolean) : [...DEFAULT_SCOPES]
218
+ scopes: typeof payload.scope === "string" ? payload.scope.split(/\s+/).filter(Boolean) : [...AUTHORIZATION_REQUEST_SCOPES]
222
219
  };
223
220
  }
224
221
  async function loginWithBrowser(options) {
@@ -685,13 +682,12 @@ function updateCodexConfig(source, server) {
685
682
  const block = codexBlock(server, newline);
686
683
  const begin = source.indexOf(CODEX_BEGIN);
687
684
  const end = source.indexOf(CODEX_END);
688
- if (begin === -1 !== (end === -1) || begin !== -1 && end < begin) {
689
- throw new TypeError("Codex config contains an incomplete Rolino-managed block.");
690
- }
691
685
  let unmanagedSource = source;
692
- if (begin !== -1) {
686
+ if (begin !== -1 && end !== -1 && end > begin) {
693
687
  const after = end + CODEX_END.length;
694
688
  unmanagedSource = `${source.slice(0, begin)}${source.slice(after)}`;
689
+ } else if (begin !== -1 || end !== -1) {
690
+ unmanagedSource = source.split(/\r?\n/).filter((line) => line.trim() !== CODEX_BEGIN && line.trim() !== CODEX_END).join(newline);
695
691
  }
696
692
  const withoutRolino = removeExistingCodexEntry(unmanagedSource, newline);
697
693
  return `${withoutRolino ? `${withoutRolino}${newline}${newline}` : ""}${block}${newline}`;
@@ -897,40 +893,40 @@ function outputFormat(value) {
897
893
  throw new import_commander.InvalidArgumentError("Output must be human, json, or jsonl.");
898
894
  }
899
895
  function postStatus(value) {
900
- const parsed = import_contracts.PostStatusSchema.safeParse(value.toUpperCase());
896
+ const parsed = import_contracts2.PostStatusSchema.safeParse(value.toUpperCase());
901
897
  if (parsed.success) return parsed.data;
902
898
  throw new import_commander.InvalidArgumentError(
903
- `Status must be one of ${import_contracts.PostStatusSchema.options.join(", ")}.`
899
+ `Status must be one of ${import_contracts2.PostStatusSchema.options.join(", ")}.`
904
900
  );
905
901
  }
906
902
  function seoOpportunityKind(value) {
907
- const parsed = import_contracts.SeoOpportunityKindSchema.safeParse(value.toUpperCase());
903
+ const parsed = import_contracts2.SeoOpportunityKindSchema.safeParse(value.toUpperCase());
908
904
  if (parsed.success) return parsed.data;
909
- throw new import_commander.InvalidArgumentError(`SEO kind must be one of ${import_contracts.SeoOpportunityKindSchema.options.join(", ")}.`);
905
+ throw new import_commander.InvalidArgumentError(`SEO kind must be one of ${import_contracts2.SeoOpportunityKindSchema.options.join(", ")}.`);
910
906
  }
911
907
  function seoExpectedImpact(value) {
912
- const parsed = import_contracts.SeoExpectedImpactSchema.safeParse(value.toUpperCase());
908
+ const parsed = import_contracts2.SeoExpectedImpactSchema.safeParse(value.toUpperCase());
913
909
  if (parsed.success) return parsed.data;
914
910
  throw new import_commander.InvalidArgumentError("SEO impact must be HIGH, MEDIUM, or LOW.");
915
911
  }
916
912
  function seoReportCompleteness(value) {
917
- const parsed = import_contracts.SeoReportCompletenessSchema.safeParse(value.toUpperCase());
913
+ const parsed = import_contracts2.SeoReportCompletenessSchema.safeParse(value.toUpperCase());
918
914
  if (parsed.success) return parsed.data;
919
915
  throw new import_commander.InvalidArgumentError("Report status must be COMPLETE or PARTIAL.");
920
916
  }
921
917
  function projectType(value) {
922
- const parsed = import_contracts.ProjectTypeSchema.safeParse(value.toUpperCase());
918
+ const parsed = import_contracts2.ProjectTypeSchema.safeParse(value.toUpperCase());
923
919
  if (parsed.success) return parsed.data;
924
920
  throw new import_commander.InvalidArgumentError(
925
- `Type must be one of ${import_contracts.ProjectTypeSchema.options.join(", ")}.`
921
+ `Type must be one of ${import_contracts2.ProjectTypeSchema.options.join(", ")}.`
926
922
  );
927
923
  }
928
924
  function publishingProvider(value) {
929
925
  const normalized = value.toUpperCase();
930
- const parsed = import_contracts.PublishingProviderSchema.safeParse(normalized);
926
+ const parsed = import_contracts2.PublishingProviderSchema.safeParse(normalized);
931
927
  if (parsed.success) return parsed.data;
932
928
  throw new import_commander.InvalidArgumentError(
933
- `Platform must be one of ${import_contracts.PublishingProviderSchema.options.join(", ")}.`
929
+ `Platform must be one of ${import_contracts2.PublishingProviderSchema.options.join(", ")}.`
934
930
  );
935
931
  }
936
932
  function collectPublishingProvider(value, previous) {
@@ -941,10 +937,10 @@ function collectString(value, previous) {
941
937
  }
942
938
  function deliveryOptionsProvider(value) {
943
939
  const normalized = value.toUpperCase();
944
- const parsed = import_contracts.ProviderDeliveryOptionsProviderSchema.safeParse(normalized);
940
+ const parsed = import_contracts2.ProviderDeliveryOptionsProviderSchema.safeParse(normalized);
945
941
  if (parsed.success) return parsed.data;
946
942
  throw new import_commander.InvalidArgumentError(
947
- `Provider must be one of ${import_contracts.ProviderDeliveryOptionsProviderSchema.options.join(", ")}.`
943
+ `Provider must be one of ${import_contracts2.ProviderDeliveryOptionsProviderSchema.options.join(", ")}.`
948
944
  );
949
945
  }
950
946
  function tiktokPostMode(value) {
@@ -982,7 +978,7 @@ function yesOrNo(value) {
982
978
  function youtubeSettings(options) {
983
979
  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;
984
980
  if (!hasYouTubeOptions) return null;
985
- return import_contracts.YouTubePostSettingsSchema.parse({
981
+ return import_contracts2.YouTubePostSettingsSchema.parse({
986
982
  title: options.youtubeTitle,
987
983
  categoryId: options.youtubeCategoryId,
988
984
  privacyStatus: options.youtubePrivacy,
@@ -1171,7 +1167,7 @@ function errorForOutput(error) {
1171
1167
  function tiktokSettings(options) {
1172
1168
  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;
1173
1169
  if (!hasTikTokOptions) return void 0;
1174
- return import_contracts.TikTokDraftSettingsSchema.parse({
1170
+ return import_contracts2.TikTokDraftSettingsSchema.parse({
1175
1171
  postMode: options.tiktokMode,
1176
1172
  privacyLevel: options.tiktokVisibility,
1177
1173
  allowComment: options.tiktokComments,
@@ -1315,7 +1311,7 @@ async function runCli(argv = process.argv, overrides = {}) {
1315
1311
  global,
1316
1312
  runtime,
1317
1313
  async action(context, client) {
1318
- const parsed = import_contracts.ProjectCreateInputSchema.safeParse({
1314
+ const parsed = import_contracts2.ProjectCreateInputSchema.safeParse({
1319
1315
  name: local.name,
1320
1316
  type: local.type,
1321
1317
  websiteUrl: local.website,
@@ -2191,7 +2187,7 @@ This moves eligible editorial dates only. It does not schedule, publish, or unpu
2191
2187
  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) => {
2192
2188
  const global = program.opts();
2193
2189
  commandExitCode = await execute({ command: "blog articles update", global, runtime, async action(context, client) {
2194
- const draft = import_contracts.AgentBlogDraftUpdateSchema.parse(JSON.parse(await (0, import_promises2.readFile)((0, import_node_path2.resolve)(runtime.cwd, local.input), "utf8")));
2190
+ const draft = import_contracts2.AgentBlogDraftUpdateSchema.parse(JSON.parse(await (0, import_promises2.readFile)((0, import_node_path2.resolve)(runtime.cwd, local.input), "utf8")));
2195
2191
  await requireWriteConsent({ yes: local.yes, global, runtime, preview: `Save a new immutable Blog draft revision?
2196
2192
  Project: ${local.project}
2197
2193
  Article: ${articleId}
@@ -2368,7 +2364,7 @@ Revision: ${local.revision}` });
2368
2364
  backlinkProspects.command("list").requiredOption("--project <project-id>").option("--stage <stage>").action(async (local) => {
2369
2365
  const global = program.opts();
2370
2366
  commandExitCode = await execute({ command: "backlinks prospects list", global, runtime, async action(context, client) {
2371
- const stage = local.stage ? import_contracts.BacklinkProspectStageSchema.parse(local.stage.toUpperCase()) : void 0;
2367
+ const stage = local.stage ? import_contracts2.BacklinkProspectStageSchema.parse(local.stage.toUpperCase()) : void 0;
2372
2368
  const data = await client.backlinks.prospects.list(local.project, { stage }, { requestId: context.requestId });
2373
2369
  writeSuccess(context, data, JSON.stringify(data, null, 2));
2374
2370
  } });