@felores/kie-cli 0.1.2 → 0.2.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.
Files changed (2) hide show
  1. package/dist/index.js +171 -0
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -624,6 +624,12 @@ var ListTasksSchema = z.object({
624
624
  limit: z.number().int().max(100).default(20).describe("Maximum number of tasks to return"),
625
625
  status: z.enum(["pending", "processing", "completed", "failed"]).optional().describe("Filter by status")
626
626
  });
627
+ var WaitForTaskSchema = z.object({
628
+ task_id: z.string().min(1).describe("Task ID returned by a generation tool to wait for"),
629
+ timeout_seconds: z.number().int().min(5).max(600).default(180).describe("Max seconds to wait before giving up"),
630
+ interval_seconds: z.number().int().min(1).max(60).default(5).describe("Seconds between status checks while waiting"),
631
+ rendezvous_url: z.string().url().optional().describe("Optional callback rendezvous result base URL (e.g. https://felo-workers.felo.workers.dev/kie/result). Omit to poll the Kie API directly (the default). When set, or when KIE_AI_RESULT_URL / a KIE_AI_CALLBACK_URL ending in /kie/callback is configured, it waits on the rendezvous instead")
632
+ });
627
633
  var Veo3Get1080pVideoSchema = z.object({
628
634
  task_id: z.string().min(1).describe("Veo3 task ID to get 1080p video for"),
629
635
  index: z.number().int().min(0).optional().describe("Video index (optional, for multiple video results)")
@@ -3433,6 +3439,170 @@ var veo3Get1080pVideoTool = {
3433
3439
  }
3434
3440
  };
3435
3441
 
3442
+ // ../core/dist/tools/wait_for_task.js
3443
+ function resolveResultBase(explicit, ctx) {
3444
+ const strip = (u) => u.replace(/\/+$/, "");
3445
+ if (explicit)
3446
+ return strip(explicit);
3447
+ if (process.env.KIE_AI_RESULT_URL)
3448
+ return strip(process.env.KIE_AI_RESULT_URL);
3449
+ const callback = ctx.getCallbackUrl();
3450
+ if (callback.endsWith("/kie/callback")) {
3451
+ return callback.slice(0, -"/kie/callback".length) + "/kie/result";
3452
+ }
3453
+ return null;
3454
+ }
3455
+ var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
3456
+ async function pollOnce(ctx, task_id) {
3457
+ try {
3458
+ const res = await getTaskStatusTool.run({ task_id }, ctx);
3459
+ return JSON.parse(res.content[0].text);
3460
+ } catch {
3461
+ return null;
3462
+ }
3463
+ }
3464
+ var waitForTaskTool = {
3465
+ name: "wait_for_task",
3466
+ description: "Wait for a generation task to complete in a single call, so you don't have to poll get_task_status repeatedly. Pass the task_id returned by any generation tool: it blocks until the result is ready (or the timeout) and returns the final URLs, streaming progress meanwhile. By default it polls the Kie API directly (no setup); if a callback rendezvous is configured (KIE_AI_RESULT_URL, rendezvous_url, or a KIE_AI_CALLBACK_URL ending in /kie/callback) it waits on that instead. Tip for long jobs: clients should enable resetTimeoutOnProgress with a generous maxTotalTimeout.",
3467
+ category: "utility",
3468
+ schema: WaitForTaskSchema,
3469
+ async run(args, ctx) {
3470
+ try {
3471
+ const { task_id, timeout_seconds = 180, interval_seconds = 5, rendezvous_url } = WaitForTaskSchema.parse(args);
3472
+ const base = resolveResultBase(rendezvous_url, ctx);
3473
+ const start = Date.now();
3474
+ const deadline = start + timeout_seconds * 1e3;
3475
+ const totalTicks = Math.max(1, Math.ceil(timeout_seconds / interval_seconds));
3476
+ let tick = 0;
3477
+ const elapsed = () => Math.round((Date.now() - start) / 1e3);
3478
+ if (base) {
3479
+ const url = `${base}/${encodeURIComponent(task_id)}`;
3480
+ while (Date.now() < deadline) {
3481
+ tick++;
3482
+ try {
3483
+ const res = await fetch(url);
3484
+ if (res.status === 200) {
3485
+ const data = await res.json();
3486
+ return {
3487
+ content: [
3488
+ {
3489
+ type: "text",
3490
+ text: JSON.stringify({
3491
+ success: true,
3492
+ task_id,
3493
+ status: data.status ?? "completed",
3494
+ elapsed_seconds: elapsed(),
3495
+ result_urls: data.urls ?? [],
3496
+ model: data.model ?? null,
3497
+ message: "Result received from rendezvous"
3498
+ }, null, 2)
3499
+ }
3500
+ ]
3501
+ };
3502
+ }
3503
+ } catch {
3504
+ }
3505
+ await ctx.onProgress?.({
3506
+ progress: tick,
3507
+ total: totalTicks,
3508
+ message: `Waiting on rendezvous\u2026 ${elapsed()}s elapsed`
3509
+ });
3510
+ await sleep(interval_seconds * 1e3);
3511
+ }
3512
+ return {
3513
+ isError: true,
3514
+ content: [
3515
+ {
3516
+ type: "text",
3517
+ text: JSON.stringify({
3518
+ success: false,
3519
+ task_id,
3520
+ status: "timed_out",
3521
+ error: "timeout",
3522
+ elapsed_seconds: elapsed(),
3523
+ message: `No result after ${timeout_seconds}s. The task may still be running; retry wait_for_task or check get_task_status.`
3524
+ }, null, 2)
3525
+ }
3526
+ ]
3527
+ };
3528
+ }
3529
+ while (Date.now() < deadline) {
3530
+ tick++;
3531
+ const details = await pollOnce(ctx, task_id);
3532
+ const task = await ctx.db.getTask(task_id);
3533
+ if (task?.status === "completed") {
3534
+ const fromDetails = details?.result_urls;
3535
+ const result_urls = fromDetails && fromDetails.length > 0 ? fromDetails : task.result_url ? [task.result_url] : [];
3536
+ return {
3537
+ content: [
3538
+ {
3539
+ type: "text",
3540
+ text: JSON.stringify({
3541
+ success: true,
3542
+ task_id,
3543
+ status: "completed",
3544
+ elapsed_seconds: elapsed(),
3545
+ result_urls,
3546
+ details,
3547
+ message: "Generation completed"
3548
+ }, null, 2)
3549
+ }
3550
+ ]
3551
+ };
3552
+ }
3553
+ if (task?.status === "failed") {
3554
+ return {
3555
+ isError: true,
3556
+ content: [
3557
+ {
3558
+ type: "text",
3559
+ text: JSON.stringify({
3560
+ success: false,
3561
+ task_id,
3562
+ status: "failed",
3563
+ elapsed_seconds: elapsed(),
3564
+ error: task.error_message ?? "Generation failed",
3565
+ details,
3566
+ message: "Generation failed"
3567
+ }, null, 2)
3568
+ }
3569
+ ]
3570
+ };
3571
+ }
3572
+ await ctx.onProgress?.({
3573
+ progress: tick,
3574
+ total: totalTicks,
3575
+ message: `Generating\u2026 ${elapsed()}s elapsed (status: ${task?.status ?? "pending"})`
3576
+ });
3577
+ await sleep(interval_seconds * 1e3);
3578
+ }
3579
+ return {
3580
+ isError: true,
3581
+ content: [
3582
+ {
3583
+ type: "text",
3584
+ text: JSON.stringify({
3585
+ success: false,
3586
+ task_id,
3587
+ status: "timed_out",
3588
+ error: "timeout",
3589
+ elapsed_seconds: elapsed(),
3590
+ message: `Still running after ${timeout_seconds}s. Call wait_for_task again with the same task_id, or check get_task_status.`
3591
+ }, null, 2)
3592
+ }
3593
+ ]
3594
+ };
3595
+ } catch (error) {
3596
+ return ctx.formatError("wait_for_task", error, {
3597
+ task_id: "Required: task ID returned by a generation tool",
3598
+ timeout_seconds: "Optional: max seconds to wait (5-600, default: 180)",
3599
+ interval_seconds: "Optional: seconds between status checks (1-60, default: 5)",
3600
+ rendezvous_url: "Optional: rendezvous result base URL (e.g. https://host/kie/result); omit to poll the Kie API directly"
3601
+ });
3602
+ }
3603
+ }
3604
+ };
3605
+
3436
3606
  // ../core/dist/tools/wan_animate.js
3437
3607
  import { z as z21 } from "zod";
3438
3608
  var wanAnimateTool = {
@@ -3651,6 +3821,7 @@ var TOOL_REGISTRY = [
3651
3821
  topazUpscaleImageTool,
3652
3822
  veo3GenerateVideoTool,
3653
3823
  veo3Get1080pVideoTool,
3824
+ waitForTaskTool,
3654
3825
  wanAnimateTool,
3655
3826
  wanVideoTool,
3656
3827
  zImageTool
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@felores/kie-cli",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Standalone CLI for Kie.ai APIs: generate images, video, music and speech from the terminal. Same models as the Kie.ai MCP server, no MCP client required.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {