@koda-sl/baker-cli 0.81.1 → 0.82.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
@@ -3263,6 +3263,8 @@ Reverse-engineer a video into a replication-grade blueprint: scene boundaries, t
3263
3263
 
3264
3264
  Over-length runs fail with a message that includes ready-to-use suggested windows, so the loop is self-correcting.
3265
3265
 
3266
+ > **Async execution.** Full-mode `video_deconstruct` is a multi-minute job, so the backend runs it as a durable background workflow rather than over a single long-lived HTTP request: the exec call returns immediately and the CLI transparently polls the job to completion. This is invisible to callers — the node's inputs, params, and outputs are unchanged — but it means a stalled provider can no longer drop the connection and cause a whole-node retry storm. (`mode:"index"` stays synchronous.)
3267
+
3266
3268
  **Inputs**
3267
3269
 
3268
3270
  | Slot | Kind | Required | Accepted MIMEs |
@@ -770,13 +770,48 @@ function shouldRetry(err) {
770
770
  }
771
771
 
772
772
  // src/engine/client/backend-client.ts
773
+ function isAsyncJob(res) {
774
+ return typeof res.job_id === "string";
775
+ }
776
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
777
+ var JOB_POLL_INTERVAL_MS = 3e3;
778
+ var JOB_POLL_MAX_MS = 20 * 60 * 1e3;
773
779
  var BackendClient = class {
774
780
  http;
775
781
  constructor(opts) {
776
782
  this.http = new HttpClient(opts);
777
783
  }
778
- exec(req, signal) {
779
- return this.http.postJson("/api/canvas/nodes/exec", req, signal);
784
+ async exec(req, signal) {
785
+ const res = await this.http.postJson("/api/canvas/nodes/exec", req, signal);
786
+ if (isAsyncJob(res)) {
787
+ return await this.pollJob(res.job_id, signal);
788
+ }
789
+ return res;
790
+ }
791
+ async pollJob(jobId, signal) {
792
+ const deadline = Date.now() + JOB_POLL_MAX_MS;
793
+ const path16 = `/api/canvas/jobs/${encodeURIComponent(jobId)}`;
794
+ while (true) {
795
+ if (signal?.aborted) {
796
+ throw new BackendHttpError({ kind: "network", cause: signal.reason ?? new Error("aborted") });
797
+ }
798
+ const job = await this.http.getJson(path16, signal);
799
+ if (job.status === "completed") return job.result;
800
+ if (job.status === "failed") {
801
+ throw new BackendHttpError({
802
+ kind: "provider",
803
+ status: job.error.status ?? 502,
804
+ provider: job.error.provider,
805
+ code: job.error.code ?? "provider_error",
806
+ message: job.error.message ?? "deconstruct failed",
807
+ retryable: job.error.retryable ?? false
808
+ });
809
+ }
810
+ if (Date.now() > deadline) {
811
+ throw new BackendHttpError({ kind: "timeout", message: `job ${jobId} did not finish in time` });
812
+ }
813
+ await sleep(JOB_POLL_INTERVAL_MS);
814
+ }
780
815
  }
781
816
  presignAssetUpload(sha256, mime, signal) {
782
817
  return this.http.postJson(
@@ -5970,4 +6005,4 @@ export {
5970
6005
  defaultRegistry,
5971
6006
  createEngineFromEnv
5972
6007
  };
5973
- //# sourceMappingURL=chunk-NBNUNCY7.js.map
6008
+ //# sourceMappingURL=chunk-KIL2ZJST.js.map