@hintoai/cli 0.3.5 → 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/README.md CHANGED
@@ -368,6 +368,8 @@ When an error occurs with `--json`, stdout is always empty and the error message
368
368
 
369
369
  Commands that start background jobs — `generate start`, `publish now`, `publish republish`, `project retranslate` — default to fire-and-forget: they print the job metadata and return exit 0 immediately. Pass `--wait` to poll until the job completes (or fails) and print its output.
370
370
 
371
+ `hinto videos upload` also supports `--wait`: blocks until the uploaded video finishes server-side processing and reaches `ready` status (polls every 3s, 10 min timeout). Without `--wait`, the upload returns immediately with the `videoId` but the video may still be processing.
372
+
371
373
  ## Environment variables
372
374
 
373
375
  | Variable | Description |
@@ -62,6 +62,7 @@ export declare const articlesApi: (client: AxiosInstance) => {
62
62
  update: (id: string, body: {
63
63
  title?: string;
64
64
  slug?: string;
65
+ content?: string;
65
66
  metaDescription?: string;
66
67
  metaKeywords?: string[];
67
68
  }) => Promise<ArticleDetail>;
@@ -110,18 +110,24 @@ function registerArticles(program, client) {
110
110
  .description('Update an article')
111
111
  .option('--title <title>', 'New title')
112
112
  .option('--slug <slug>', 'New slug')
113
+ .option('--content <content>', 'New Markdown content (string or @filepath) — replaces the body')
113
114
  .option('--meta-description <text>', 'SEO meta description')
114
115
  .option('--meta-keywords <keywords>', 'Comma-separated SEO keywords')
115
116
  .option('--json', 'Output as JSON')
116
117
  .action(async (id, opts) => {
117
118
  try {
118
- if (!opts.title && !opts.slug && !opts.metaDescription && !opts.metaKeywords) {
119
- (0, errors_1.exitWithError)('Provide at least one field to update: --title, --slug, --meta-description, or --meta-keywords');
119
+ if (!opts.title &&
120
+ !opts.slug &&
121
+ !opts.content &&
122
+ !opts.metaDescription &&
123
+ !opts.metaKeywords) {
124
+ (0, errors_1.exitWithError)('Provide at least one field to update: --title, --slug, --content, --meta-description, or --meta-keywords');
120
125
  return;
121
126
  }
122
127
  const data = await api.update(id, {
123
128
  ...(opts.title !== undefined && { title: opts.title }),
124
129
  ...(opts.slug !== undefined && { slug: opts.slug }),
130
+ ...(opts.content !== undefined && { content: resolveContent(opts.content) }),
125
131
  ...(opts.metaDescription !== undefined && { metaDescription: opts.metaDescription }),
126
132
  ...(opts.metaKeywords !== undefined && {
127
133
  metaKeywords: opts.metaKeywords
@@ -43,6 +43,7 @@ const path = __importStar(require("path"));
43
43
  const videos_1 = require("../api/videos");
44
44
  const errors_1 = require("../errors");
45
45
  const output_1 = require("../output");
46
+ const poll_1 = require("../poll");
46
47
  function registerVideos(program, client) {
47
48
  const videos = program.command('videos').description('Manage videos');
48
49
  const api = (0, videos_1.videosApi)(client);
@@ -131,6 +132,7 @@ function registerVideos(program, client) {
131
132
  .command('upload')
132
133
  .description('Upload a video file from disk (3-step presigned flow)')
133
134
  .requiredOption('--file <path>', 'Path to the video file')
135
+ .option('--wait', 'Wait until the video is ready for generation')
134
136
  .option('--json', 'Output as JSON')
135
137
  .action(async (opts) => {
136
138
  try {
@@ -164,10 +166,14 @@ function registerVideos(program, client) {
164
166
  // Step 3: complete upload
165
167
  process.stderr.write('Completing upload...\n');
166
168
  const result = await api.uploadComplete(videoId, s3Key, filename);
169
+ if (opts.wait) {
170
+ await (0, poll_1.pollVideoReady)(client, result.videoId);
171
+ }
167
172
  if (opts.json)
168
173
  return (0, output_1.printJson)(result);
169
- process.stdout.write(`Uploaded: videoId=${result.videoId} status=pending\n`);
170
- process.stdout.write(`Track: hinto videos status ${result.videoId}\n`);
174
+ process.stdout.write(`Uploaded: videoId=${result.videoId} status=${opts.wait ? 'ready' : 'pending'}\n`);
175
+ if (!opts.wait)
176
+ process.stdout.write(`Track: hinto videos status ${result.videoId}\n`);
171
177
  }
172
178
  catch (e) {
173
179
  (0, errors_1.exitWithError)(e instanceof Error ? e.message : String(e));
package/dist/poll.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  import type { AxiosInstance } from 'axios';
2
2
  export declare function pollJob(client: AxiosInstance, jobId: string, intervalMs?: number, timeoutMs?: number): Promise<unknown>;
3
+ export declare function pollVideoReady(client: AxiosInstance, videoId: string, intervalMs?: number, timeoutMs?: number): Promise<void>;
package/dist/poll.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.pollJob = pollJob;
4
+ exports.pollVideoReady = pollVideoReady;
4
5
  async function pollJob(client, jobId, intervalMs = 2000, timeoutMs = 300000) {
5
6
  process.stderr.write(`Waiting for job ${jobId}…\n`);
6
7
  const deadline = Date.now() + timeoutMs;
@@ -18,6 +19,22 @@ async function pollJob(client, jobId, intervalMs = 2000, timeoutMs = 300000) {
18
19
  }
19
20
  throw new Error(`Job ${jobId} timed out after ${timeoutMs / 1000}s`);
20
21
  }
22
+ async function pollVideoReady(client, videoId, intervalMs = 3000, timeoutMs = 600000) {
23
+ process.stderr.write(`Waiting for video ${videoId} to be ready…\n`);
24
+ const deadline = Date.now() + timeoutMs;
25
+ while (Date.now() < deadline) {
26
+ const { data } = await client.get(`/videos/${videoId}/status`);
27
+ if (data.status === 'ready') {
28
+ process.stderr.write(`Video ${videoId} ready\n`);
29
+ return;
30
+ }
31
+ if (data.status === 'failed') {
32
+ throw new Error(`Video ${videoId} processing failed`);
33
+ }
34
+ await sleep(intervalMs);
35
+ }
36
+ throw new Error(`Video ${videoId} timed out after ${timeoutMs / 1000}s`);
37
+ }
21
38
  function sleep(ms) {
22
39
  return new Promise((resolve) => setTimeout(resolve, ms));
23
40
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hintoai/cli",
3
- "version": "0.3.5",
3
+ "version": "0.5.0",
4
4
  "description": "Hinto AI CLI — manage videos, articles, and publishing via the Hinto API",
5
5
  "main": "dist/index.js",
6
6
  "bin": {