@chai-ui/core 0.11.4 → 0.13.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 (42) hide show
  1. package/dist/composer-view.d.ts.map +1 -1
  2. package/dist/composer-view.js +4 -2
  3. package/dist/composer-view.js.map +1 -1
  4. package/dist/composer.d.ts +22 -1
  5. package/dist/composer.d.ts.map +1 -1
  6. package/dist/composer.js +64 -13
  7. package/dist/composer.js.map +1 -1
  8. package/dist/engines/fal.d.ts.map +1 -1
  9. package/dist/engines/fal.js +15 -6
  10. package/dist/engines/fal.js.map +1 -1
  11. package/dist/evaluation-judge.d.ts +33 -0
  12. package/dist/evaluation-judge.d.ts.map +1 -0
  13. package/dist/evaluation-judge.js +37 -0
  14. package/dist/evaluation-judge.js.map +1 -0
  15. package/dist/image-fit.d.ts +16 -0
  16. package/dist/image-fit.d.ts.map +1 -0
  17. package/dist/image-fit.js +54 -0
  18. package/dist/image-fit.js.map +1 -0
  19. package/dist/index.d.ts +2 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +2 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/run.d.ts +2 -0
  24. package/dist/run.d.ts.map +1 -1
  25. package/dist/run.js +4 -0
  26. package/dist/run.js.map +1 -1
  27. package/dist/suggested-models.d.ts +9 -2
  28. package/dist/suggested-models.d.ts.map +1 -1
  29. package/dist/suggested-models.js +42 -13
  30. package/dist/suggested-models.js.map +1 -1
  31. package/dist/types.d.ts +7 -0
  32. package/dist/types.d.ts.map +1 -1
  33. package/package.json +1 -1
  34. package/src/composer-view.ts +4 -2
  35. package/src/composer.ts +97 -20
  36. package/src/engines/fal.ts +15 -6
  37. package/src/evaluation-judge.ts +60 -0
  38. package/src/image-fit.ts +61 -0
  39. package/src/index.ts +2 -0
  40. package/src/run.ts +5 -0
  41. package/src/suggested-models.ts +43 -13
  42. package/src/types.ts +7 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The image redrawn at `ratio` (e.g. "16:9"), as a JPEG data URL. Returns
3
+ * `src` unchanged when it already has that shape, the ratio isn't "w:h",
4
+ * or there's no canvas to draw on (a server, or a test DOM).
5
+ */
6
+ export async function fitImageToRatio(src, ratio, fit) {
7
+ const [w, h] = ratio.split(":").map(Number);
8
+ if (!w || !h || typeof document === "undefined")
9
+ return src;
10
+ const canvas = document.createElement("canvas");
11
+ const ctx = canvas.getContext("2d");
12
+ if (!ctx)
13
+ return src;
14
+ const img = await loadImage(src).catch(() => null);
15
+ if (!img)
16
+ return src;
17
+ const iw = img.naturalWidth;
18
+ const ih = img.naturalHeight;
19
+ const target = w / h;
20
+ if (!iw || !ih || Math.abs(iw / ih - target) < 0.01)
21
+ return src;
22
+ // Crop keeps the image's short side and cuts the long one; pad keeps
23
+ // the whole image and grows the short side.
24
+ const wider = iw / ih > target;
25
+ const keepHeight = fit === "crop" ? wider : !wider;
26
+ canvas.width = keepHeight ? Math.round(ih * target) : iw;
27
+ canvas.height = keepHeight ? ih : Math.round(iw / target);
28
+ if (fit === "pad") {
29
+ ctx.fillStyle = "black";
30
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
31
+ }
32
+ ctx.drawImage(img, (canvas.width - iw) / 2, (canvas.height - ih) / 2);
33
+ try {
34
+ return canvas.toDataURL("image/jpeg", 0.92);
35
+ }
36
+ catch {
37
+ // A cross-origin image without CORS can't be read back: send it as is.
38
+ return src;
39
+ }
40
+ }
41
+ /** The attachments with each image fitted to `ratio`; other media unchanged. */
42
+ export function fitImagesToRatio(attachments, ratio, fit) {
43
+ return Promise.all(attachments.map(async (a) => (a.kind === "image" ? { ...a, src: await fitImageToRatio(a.src, ratio, fit) } : a)));
44
+ }
45
+ function loadImage(src) {
46
+ return new Promise((resolve, reject) => {
47
+ const img = new Image();
48
+ img.crossOrigin = "anonymous";
49
+ img.onload = () => resolve(img);
50
+ img.onerror = reject;
51
+ img.src = src;
52
+ });
53
+ }
54
+ //# sourceMappingURL=image-fit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-fit.js","sourceRoot":"","sources":["../src/image-fit.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAW,EAAE,KAAa,EAAE,GAAkB;IAClF,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO,GAAG,CAAC;IAC5D,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC;IACrB,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACnD,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC;IACrB,MAAM,EAAE,GAAG,GAAG,CAAC,YAAY,CAAC;IAC5B,MAAM,EAAE,GAAG,GAAG,CAAC,aAAa,CAAC;IAC7B,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,CAAC;IACrB,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC;IAChE,qEAAqE;IACrE,4CAA4C;IAC5C,MAAM,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;IAC/B,MAAM,UAAU,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnD,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzD,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC;IAC1D,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC;QACxB,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IACD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACtE,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,gBAAgB,CAAC,WAA2B,EAAE,KAAa,EAAE,GAAkB;IAC7F,OAAO,OAAO,CAAC,GAAG,CAChB,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CACjH,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,GAAG,CAAC,WAAW,GAAG,WAAW,CAAC;QAC9B,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC;QACrB,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC"}
package/dist/index.d.ts CHANGED
@@ -18,4 +18,6 @@ export * from "./composer-view.js";
18
18
  export * from "./edit-card.js";
19
19
  export * from "./voice-input.js";
20
20
  export * from "./menu-placement.js";
21
+ export * from "./image-fit.js";
22
+ export * from "./evaluation-judge.js";
21
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -18,4 +18,6 @@ export * from "./composer-view.js";
18
18
  export * from "./edit-card.js";
19
19
  export * from "./voice-input.js";
20
20
  export * from "./menu-placement.js";
21
+ export * from "./image-fit.js";
22
+ export * from "./evaluation-judge.js";
21
23
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,uBAAuB,CAAC"}
package/dist/run.d.ts CHANGED
@@ -63,6 +63,8 @@ export declare function startResult(run: Run, resultId: string): Run;
63
63
  */
64
64
  export declare function streamResult(run: Run, resultId: string, textSoFar: string): Run;
65
65
  export declare function resolveResult(run: Run, resultId: string, output: Result["output"], usage?: Usage, evaluations?: Evaluation[]): Run;
66
+ /** The result with `evaluations` added after any it already has (e.g. the judge's after the backend's). */
67
+ export declare function addEvaluations(run: Run, resultId: string, evaluations: Evaluation[]): Run;
66
68
  export declare function failResult(run: Run, resultId: string, error: Result["error"]): Run;
67
69
  /** Marks a queued or running result as stopped by the person. A settled result is left as it is. */
68
70
  export declare function cancelResult(run: Run, resultId: string): Run;
package/dist/run.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAE1H,MAAM,WAAW,OAAO;IACtB,+LAA+L;IAC/L,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,gGAAgG;AAChG,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,CAAC;AAEjF,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,SAAS,CAAA;KAAE,CAAC;IAC1C,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,wFAAwF;IACxF,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAChD,kKAAkK;IAClK,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4SAA4S;IAC5S,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAQ1C;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,GAAG,CAa/C;AAMD,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,GAAG,CAI/E;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,EACxB,KAAK,CAAC,EAAE,KAAK,EACb,WAAW,CAAC,EAAE,UAAU,EAAE,GACzB,GAAG,CASL;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,GAAG,CAOlF;AAED,oGAAoG;AACpG,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,CAM5D;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,CAAC,EAAE,YAAY,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,EACtE,WAAW,EAAE,YAAY,EAAE,GAC1B,iBAAiB,GAAG,SAAS,CAU/B"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
package/dist/run.js CHANGED
@@ -58,6 +58,10 @@ export function resolveResult(run, resultId, output, usage, evaluations) {
58
58
  durationMs: r.startedAt != null ? Date.now() - r.startedAt : undefined,
59
59
  }));
60
60
  }
61
+ /** The result with `evaluations` added after any it already has (e.g. the judge's after the backend's). */
62
+ export function addEvaluations(run, resultId, evaluations) {
63
+ return updateResult(run, resultId, (r) => ({ ...r, evaluations: [...(r.evaluations ?? []), ...evaluations] }));
64
+ }
61
65
  export function failResult(run, resultId, error) {
62
66
  return updateResult(run, resultId, (r) => ({
63
67
  ...r,
package/dist/run.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAwCH;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,SAAS,CAAC;AAE1C,IAAI,SAAS,GAAG,CAAC,CAAC;AAClB,SAAS,MAAM,CAAC,MAAc;IAC5B,SAAS,IAAI,CAAC,CAAC;IACf,OAAO,GAAG,MAAM,IAAI,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AAC5E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,OAAgB;IACxC,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACzB,OAAO;QACL,EAAE;QACF,OAAO;QACP,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC1C,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC;YACpB,KAAK,EAAE,EAAE;YACT,OAAO;YACP,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,GAAQ,EAAE,QAAgB,EAAE,EAA8B;IAC9E,OAAO,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAQ,EAAE,QAAgB;IACpD,OAAO,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;AAClG,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,GAAQ,EAAE,QAAgB,EAAE,SAAiB;IACxE,OAAO,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CACvC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAChF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,GAAQ,EACR,QAAgB,EAChB,MAAwB,EACxB,KAAa,EACb,WAA0B;IAE1B,OAAO,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzC,GAAG,CAAC;QACJ,MAAM,EAAE,MAAM;QACd,MAAM;QACN,KAAK;QACL,WAAW;QACX,UAAU,EAAE,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;KACvE,CAAC,CAAC,CAAC;AACN,CAAC;AAED,2GAA2G;AAC3G,MAAM,UAAU,cAAc,CAAC,GAAQ,EAAE,QAAgB,EAAE,WAAyB;IAClF,OAAO,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;AACjH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAQ,EAAE,QAAgB,EAAE,KAAsB;IAC3E,OAAO,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzC,GAAG,CAAC;QACJ,MAAM,EAAE,OAAO;QACf,KAAK;QACL,UAAU,EAAE,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;KACvE,CAAC,CAAC,CAAC;AACN,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,YAAY,CAAC,GAAQ,EAAE,QAAgB;IACrD,OAAO,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CACvC,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;QAC7C,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE;QACvG,CAAC,CAAC,CAAC,CACN,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAAsE,EACtE,WAA2B;IAE3B,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC7B,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC;IACjH,CAAC;IACD,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IACxC,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,eAAe,CAAC;IACnF,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe,CAAC;IAC/E,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC;IACzE,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -1,7 +1,14 @@
1
1
  import type { GenerationUseCase, MediaKind, ModelOption } from "./types.js";
2
- /** Create image, from a prompt. */
2
+ /**
3
+ * Create image. Each model's `withImages` endpoint takes attached images
4
+ * (as references) and still the picked aspect ratio.
5
+ */
3
6
  export declare const SUGGESTED_IMAGE_MODELS: ModelOption[];
4
- /** Create video, from a prompt alone. */
7
+ /**
8
+ * Create video. With an image attached, each runs as its `withImages`
9
+ * image-to-video endpoint, the image as the first frame; the image is
10
+ * fitted to the picked ratio first (`startImageFit`).
11
+ */
5
12
  export declare const SUGGESTED_TEXT_TO_VIDEO_MODELS: ModelOption[];
6
13
  /**
7
14
  * Create video, starting from an attached image. The video follows the
@@ -1 +1 @@
1
- {"version":3,"file":"suggested-models.d.ts","sourceRoot":"","sources":["../src/suggested-models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAwB5E,mCAAmC;AACnC,eAAO,MAAM,sBAAsB,EAAE,WAAW,EAa/C,CAAC;AAEF,yCAAyC;AACzC,eAAO,MAAM,8BAA8B,EAAE,WAAW,EAKvD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,EAAE,WAAW,EAKxD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,EAa9C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,CAAC,CAqB/E,CAAC;AAEF,2GAA2G;AAC3G,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,WAAW,EAAE,CAarF;AAED,oFAAoF;AACpF,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAEjE,CAAC"}
1
+ {"version":3,"file":"suggested-models.d.ts","sourceRoot":"","sources":["../src/suggested-models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAyB5E;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,EAsB/C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,EAAE,WAAW,EAKvD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,EAAE,WAAW,EAKxD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,EAa9C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE,CAAC,CAqB/E,CAAC;AAEF,2GAA2G;AAC3G,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,GAAG,WAAW,EAAE,CAarF;AAeD,oFAAoF;AACpF,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAEjE,CAAC"}
@@ -16,29 +16,46 @@ import { DEFAULT_MAX_REGIONS } from "./region-edit.js";
16
16
  */
17
17
  const NANO_BANANA_RATIOS = ["21:9", "16:9", "3:2", "4:3", "5:4", "1:1", "4:5", "3:4", "2:3", "9:16"];
18
18
  const FLUX_3_RATIOS = ["21:9", "2:1", "16:9", "3:2", "7:5", "4:3", "5:4", "1:1", "4:5", "3:4", "5:7", "2:3", "9:16", "1:2"];
19
- /** The ratios a named `image_size` covers (FLUX.1, GPT Image 2). */
19
+ const NANO_BANANA_2_RATIOS = [...NANO_BANANA_RATIOS, "4:1", "1:4", "8:1", "1:8"];
20
+ /** The ratios a named `image_size` covers (Flux 3 Klein, GPT Image 2). */
20
21
  const IMAGE_SIZE_RATIOS = ["1:1", "4:3", "16:9", "3:4", "9:16"];
21
- /** Create image, from a prompt. */
22
+ /**
23
+ * Create image. Each model's `withImages` endpoint takes attached images
24
+ * (as references) and still the picked aspect ratio.
25
+ */
22
26
  export const SUGGESTED_IMAGE_MODELS = [
23
- { id: "fal-ai/nano-banana-pro", label: "Nano Banana Pro", provider: "Google", speed: "standard", aspectRatios: NANO_BANANA_RATIOS, falInput: { aspectRatio: "aspect_ratio" } },
27
+ { id: "fal-ai/nano-banana-pro", label: "Nano Banana Pro", provider: "Google", speed: "standard", aspectRatios: NANO_BANANA_RATIOS, falInput: { aspectRatio: "aspect_ratio" }, withImages: "fal-ai/nano-banana-pro/edit" },
24
28
  {
25
29
  id: "fal-ai/nano-banana-2",
26
30
  label: "Nano Banana 2",
27
31
  provider: "Google",
28
32
  speed: "fast",
29
- aspectRatios: [...NANO_BANANA_RATIOS, "4:1", "1:4", "8:1", "1:8"],
33
+ aspectRatios: NANO_BANANA_2_RATIOS,
30
34
  falInput: { aspectRatio: "aspect_ratio" },
35
+ withImages: "fal-ai/nano-banana-2/edit",
36
+ },
37
+ { id: "blackforestlabs/flux-3/text-to-image", label: "Flux 3 Image", provider: "Black Forest Labs", speed: "standard", aspectRatios: FLUX_3_RATIOS, falInput: { aspectRatio: "aspect_ratio" }, withImages: "blackforestlabs/flux-3/edit-image" },
38
+ { id: "openai/gpt-image-2", label: "GPT Image 2", provider: "OpenAI", speed: "slow", aspectRatios: IMAGE_SIZE_RATIOS, falInput: { aspectRatio: "image_size" }, withImages: "openai/gpt-image-2/edit" },
39
+ {
40
+ id: "blackforestlabs/flux-3/klein/text-to-image",
41
+ label: "Flux 3 Klein",
42
+ provider: "Black Forest Labs",
43
+ speed: "fast",
44
+ aspectRatios: IMAGE_SIZE_RATIOS,
45
+ falInput: { aspectRatio: "image_size" },
46
+ withImages: "blackforestlabs/flux-3/klein/edit-image",
31
47
  },
32
- { id: "blackforestlabs/flux-3/text-to-image", label: "Flux 3 Image", provider: "Black Forest Labs", speed: "standard", aspectRatios: FLUX_3_RATIOS, falInput: { aspectRatio: "aspect_ratio" } },
33
- { id: "openai/gpt-image-2", label: "GPT Image 2", provider: "OpenAI", speed: "slow", aspectRatios: IMAGE_SIZE_RATIOS, falInput: { aspectRatio: "image_size" } },
34
- { id: "fal-ai/flux/schnell", label: "FLUX.1 schnell", provider: "Black Forest Labs", speed: "fast", aspectRatios: IMAGE_SIZE_RATIOS, falInput: { aspectRatio: "image_size" } },
35
48
  ];
36
- /** Create video, from a prompt alone. */
49
+ /**
50
+ * Create video. With an image attached, each runs as its `withImages`
51
+ * image-to-video endpoint, the image as the first frame; the image is
52
+ * fitted to the picked ratio first (`startImageFit`).
53
+ */
37
54
  export const SUGGESTED_TEXT_TO_VIDEO_MODELS = [
38
- { id: "minimax/h3-max/text-to-video", label: "MiniMax H3 Max", provider: "MiniMax", speed: "slow", aspectRatios: ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"], falInput: { aspectRatio: "aspect_ratio" } },
39
- { id: "bytedance/seedance-2.5/text-to-video", label: "Seedance 2.5", provider: "ByteDance", speed: "slow", aspectRatios: ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"], falInput: { aspectRatio: "aspect_ratio" } },
40
- { id: "fal-ai/kling-video/v3/pro/text-to-video", label: "Kling v3 Pro", provider: "Kling", speed: "slow", aspectRatios: ["16:9", "9:16", "1:1"], falInput: { aspectRatio: "aspect_ratio" } },
41
- { id: "fal-ai/veo3.1/fast", label: "Veo 3.1 Fast", provider: "Google", speed: "standard", aspectRatios: ["16:9", "9:16"], falInput: { aspectRatio: "aspect_ratio" } },
55
+ { id: "minimax/h3-max/text-to-video", label: "MiniMax H3 Max", provider: "MiniMax", speed: "slow", aspectRatios: ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"], falInput: { aspectRatio: "aspect_ratio" }, withImages: "minimax/h3-max/image-to-video" },
56
+ { id: "bytedance/seedance-2.5/text-to-video", label: "Seedance 2.5", provider: "ByteDance", speed: "slow", aspectRatios: ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"], falInput: { aspectRatio: "aspect_ratio" }, withImages: "bytedance/seedance-2.5/image-to-video" },
57
+ { id: "fal-ai/kling-video/v3/pro/text-to-video", label: "Kling v3 Pro", provider: "Kling", speed: "slow", aspectRatios: ["16:9", "9:16", "1:1"], falInput: { aspectRatio: "aspect_ratio" }, withImages: "fal-ai/kling-video/v3/pro/image-to-video" },
58
+ { id: "fal-ai/veo3.1/fast", label: "Veo 3.1 Fast", provider: "Google", speed: "standard", aspectRatios: ["16:9", "9:16"], falInput: { aspectRatio: "aspect_ratio" }, withImages: "fal-ai/veo3.1/fast/image-to-video" },
42
59
  ];
43
60
  /**
44
61
  * Create video, starting from an attached image. The video follows the
@@ -112,6 +129,18 @@ export function suggestedModels(useCase) {
112
129
  return [];
113
130
  }
114
131
  }
132
+ /** `withImages` endpoints in no menu of their own. */
133
+ const IMAGE_INPUT_ONLY = [
134
+ { id: "fal-ai/nano-banana-2/edit", label: "Nano Banana 2", provider: "Google", speed: "fast", aspectRatios: NANO_BANANA_2_RATIOS, falInput: { aspectRatio: "aspect_ratio", image: "image_urls" } },
135
+ {
136
+ id: "blackforestlabs/flux-3/klein/edit-image",
137
+ label: "Flux 3 Klein",
138
+ provider: "Black Forest Labs",
139
+ speed: "fast",
140
+ aspectRatios: IMAGE_SIZE_RATIOS,
141
+ falInput: { aspectRatio: "image_size", image: "image_urls" },
142
+ },
143
+ ];
115
144
  /** Every suggested Fal model, by id: how the Fal engine knows each one's inputs. */
116
- export const SUGGESTED_FAL_MODELS = new Map([...SUGGESTED_IMAGE_MODELS, ...SUGGESTED_TEXT_TO_VIDEO_MODELS, ...SUGGESTED_IMAGE_TO_VIDEO_MODELS, ...SUGGESTED_EDIT_MODELS].map((m) => [m.id, m]));
145
+ export const SUGGESTED_FAL_MODELS = new Map([...SUGGESTED_IMAGE_MODELS, ...SUGGESTED_TEXT_TO_VIDEO_MODELS, ...SUGGESTED_IMAGE_TO_VIDEO_MODELS, ...SUGGESTED_EDIT_MODELS, ...IMAGE_INPUT_ONLY].map((m) => [m.id, m]));
117
146
  //# sourceMappingURL=suggested-models.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"suggested-models.js","sourceRoot":"","sources":["../src/suggested-models.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"suggested-models.js","sourceRoot":"","sources":["../src/suggested-models.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -106,6 +106,13 @@ export interface ModelOption {
106
106
  * without it the Fal engine guesses from the id.
107
107
  */
108
108
  falInput?: FalInputFormat;
109
+ /**
110
+ * The Fal model to call instead when images are attached, for a model
111
+ * whose own endpoint takes a prompt only: e.g. Nano Banana Pro's edit
112
+ * endpoint, or a video model's image-to-video one. The Fal engine reads
113
+ * that model's inputs from the suggested lists or `FalEngineOptions.models`.
114
+ */
115
+ withImages?: string;
109
116
  /**
110
117
  * The output aspect ratios the model takes, e.g. `["1:1", "16:9", "9:16"]`.
111
118
  * Composer's Aspect ratio menu offers only ratios the selected models
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chai-ui/core",
3
- "version": "0.11.4",
3
+ "version": "0.13.0",
4
4
  "description": "Chai UI headless core — the Request/Run/Result data model and pluggable generation engines (Fal.ai, OpenRouter, Vercel AI Gateway, mock). No framework, no rendering.",
5
5
  "license": "MIT",
6
6
  "author": "kazarazat",
@@ -186,11 +186,13 @@ export function composerView(props: ComposerViewInput) {
186
186
 
187
187
  const multiModel = multiSelectModels || multiSelectUseCases;
188
188
  const rawPickedIds = multiModel ? modelIds : modelId ? [modelId] : [];
189
- // The app's list for a use case, or Chai's suggested models when it gave none.
189
+ // The app's list for a use case, or Chai's suggested models when it gave
190
+ // none. Attachments don't change the list: with images attached, the Fal
191
+ // engine runs each model as its `withImages` endpoint.
190
192
  const rosterFor = (u: ComposerUseCase): { options: ModelOption[]; suggested: boolean } => {
191
193
  const given = multiSelectUseCases ? modelsByKind?.[u.kind] : models;
192
194
  if (given) return { options: given, suggested: false };
193
- return { options: suggestedModels(u.edit ? "image-edit" : deriveGenerationUseCase(u, attachments)), suggested: true };
195
+ return { options: suggestedModels(u.edit ? "image-edit" : deriveGenerationUseCase(u, [])), suggested: true };
194
196
  };
195
197
  // One roster per use case with multi-use-case select (each gets its own menu); otherwise one.
196
198
  const modelSections = (multiSelectUseCases ? activeUseCases : activeUseCases.slice(0, 1))
package/src/composer.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  * composable wrap; the pure transitions live in `run.ts`.
7
7
  */
8
8
  import {
9
+ abortError,
9
10
  createMockEngine,
10
11
  isAbortError,
11
12
  mockEngine,
@@ -16,6 +17,7 @@ import { routeModel, type ModelRoutingInput, type ModelRoutingResult } from "./m
16
17
  import { buildRegionEditPrompt, PRECISE_EDIT_MODELS, type EditRegion } from "./region-edit.js";
17
18
  import { pickReasoning, reasoningModelFor, type Reasoning } from "./reasoning.js";
18
19
  import {
20
+ addEvaluations,
19
21
  cancelResult,
20
22
  createRun,
21
23
  deriveGenerationUseCase,
@@ -29,6 +31,14 @@ import {
29
31
  type Run,
30
32
  } from "./run.js";
31
33
  import type { ComposerPromptField } from "./composer-view.js";
34
+ import { fitImagesToRatio, type StartImageFit } from "./image-fit.js";
35
+ import {
36
+ buildJudgePrompt,
37
+ DEFAULT_EVALUATION_CHECKS,
38
+ parseJudgeReply,
39
+ type EvaluationCheck,
40
+ type JudgePromptInput,
41
+ } from "./evaluation-judge.js";
32
42
  import type { AudioUseCase, DroppedMedia, GenerationUseCase, MediaKind, ModelOption, OutputKind } from "./types.js";
33
43
 
34
44
  export interface ComposerAttachment extends DroppedMedia {
@@ -204,6 +214,25 @@ export interface ComposerOptions {
204
214
  * versions of the image. Changing it to another image starts over.
205
215
  */
206
216
  editImage?: DroppedMedia | null;
217
+ /**
218
+ * How a video's attached start image meets the picked aspect ratio:
219
+ * `"crop"` (the default) cuts it around its center, `"pad"` adds black
220
+ * bars. The ratio always wins, so the video comes out in it even on
221
+ * image-to-video models that otherwise take the image's shape.
222
+ */
223
+ startImageFit?: StartImageFit;
224
+ /**
225
+ * Opt-in, off by default: the model that checks each text or image
226
+ * result against `judgeChecks`, run on the reasoning engine (a
227
+ * `ChaiProvider`, or `reasoningEngine`). Each check becomes a pass or
228
+ * fail tag in the result's `evaluations`, after any your backend added.
229
+ * There's no default model: you name it. Video results aren't judged.
230
+ */
231
+ judgeModel?: string;
232
+ /** What the judge checks, in your words. Defaults to `DEFAULT_EVALUATION_CHECKS`, one "Matches prompt" check. */
233
+ judgeChecks?: EvaluationCheck[];
234
+ /** Replaces the judge's prompt. Defaults to `buildJudgePrompt`; call it to add to the default rather than rewrite it. */
235
+ judgePrompt?: (input: JudgePromptInput) => string;
207
236
  /** Replaces how an edit's prompt and regions become the model's prompt. Defaults to `buildRegionEditPrompt`, in the model's `regionFormat`. */
208
237
  editPrompt?: (args: { prompt: string; regions: EditRegion[]; model?: ModelOption }) => string;
209
238
  onRun?: (run: Run) => void;
@@ -405,6 +434,13 @@ export function createComposerStore(getOptions: () => ComposerOptions, getProvid
405
434
 
406
435
  for (const { run: newRun, engine, isEdit, models } of newRuns) {
407
436
  opts.onRun?.(newRun);
437
+ // A video's start image is fitted to the picked ratio first, so the
438
+ // ratio wins on models that otherwise take the image's shape.
439
+ const ratio = newRun.request.params.aspectRatio as string | undefined;
440
+ const fitting =
441
+ ratio && newRun.request.mode === "image-to-video"
442
+ ? fitImagesToRatio(newRun.request.attachments, ratio, opts.startImageFit ?? "crop")
443
+ : null;
408
444
  for (const result of newRun.results) {
409
445
  update(newRun.id, (r) => startResult(r, result.id));
410
446
  // An edit's prompt depends on the model: one with box support gets
@@ -415,34 +451,70 @@ export function createComposerStore(getOptions: () => ComposerOptions, getProvid
415
451
  const prompt = isEdit
416
452
  ? (opts.editPrompt ?? defaultEditPrompt)({ prompt: newRun.request.prompt, regions, model })
417
453
  : newRun.request.prompt;
418
- void engine
419
- .generate({
454
+ const generate = (attachments: DroppedMedia[]) =>
455
+ engine.generate({
420
456
  modelId: result.modelId === DEFAULT_MODEL_ID ? undefined : result.modelId,
421
457
  prompt,
422
- attachments: newRun.request.attachments,
423
- aspectRatio: newRun.request.params.aspectRatio as string | undefined,
458
+ attachments,
459
+ aspectRatio: ratio,
424
460
  character: newRun.request.params.character as string | undefined,
425
461
  frameRate: newRun.request.params.frameRate as number | undefined,
426
462
  voice: newRun.request.params.voice as string | undefined,
427
463
  // Text engines that stream fill `output` in while still "running".
428
464
  onText: (text) => update(newRun.id, (r) => streamResult(r, result.id, text)),
429
465
  signal,
430
- })
431
- .then(
432
- ({ src, kind, usage, evaluations }) => {
433
- update(newRun.id, (r) => resolveResult(r, result.id, { src, kind }, usage, evaluations));
434
- getOptions().onResult?.(newRun, result.id);
435
- },
436
- (err) => {
437
- if (isAbortError(err)) return update(newRun.id, (r) => cancelResult(r, result.id));
438
- update(newRun.id, (r) => failResult(r, result.id, normalizeGenerationError(err)));
439
- getOptions().onError?.(newRun, result.id);
440
- }
441
- );
466
+ });
467
+ // Straight to the engine unless a start image is being fitted.
468
+ void (
469
+ fitting
470
+ ? fitting.then((fitted) => {
471
+ if (signal.aborted) throw abortError();
472
+ return generate(fitted);
473
+ })
474
+ : generate(newRun.request.attachments)
475
+ ).then(
476
+ ({ src, kind, usage, evaluations }) => {
477
+ update(newRun.id, (r) => resolveResult(r, result.id, { src, kind }, usage, evaluations));
478
+ getOptions().onResult?.(newRun, result.id);
479
+ void judge(newRun, result.id, { src, kind }, signal);
480
+ },
481
+ (err) => {
482
+ if (isAbortError(err)) return update(newRun.id, (r) => cancelResult(r, result.id));
483
+ update(newRun.id, (r) => failResult(r, result.id, normalizeGenerationError(err)));
484
+ getOptions().onError?.(newRun, result.id);
485
+ }
486
+ );
442
487
  }
443
488
  }
444
489
  }
445
490
 
491
+ // The opt-in judge: checks a text or image result against the builder's
492
+ // criteria and adds a tag per check. A reply it can't read adds none.
493
+ async function judge(run: Run, resultId: string, output: { src: string; kind: MediaKind }, signal: AbortSignal) {
494
+ const { judgeModel, judgeChecks = DEFAULT_EVALUATION_CHECKS, judgePrompt = buildJudgePrompt } = getOptions();
495
+ if (!judgeModel || (output.kind !== "text" && output.kind !== "image")) return;
496
+ const checks = judgeChecks.filter((c) => !c.kind || c.kind === output.kind);
497
+ if (checks.length === 0) return;
498
+ const r = reasoning();
499
+ if (!r) return warnOnce("[chai-ui] judgeModel is set, but there's no reasoning engine to run it. Wrap your app in <ChaiProvider> or pass reasoningEngine.");
500
+ const prompt = judgePrompt({
501
+ prompt: run.request.prompt,
502
+ output: output.kind === "image" ? { kind: "image" } : { kind: "text", text: output.src },
503
+ checks,
504
+ });
505
+ try {
506
+ const attachments: DroppedMedia[] = output.kind === "image" ? [{ src: output.src, kind: "image" }] : [];
507
+ const reply = await r.engine.generate({ modelId: judgeModel, prompt, attachments, signal });
508
+ const verdicts = parseJudgeReply(reply.src, checks);
509
+ if (!verdicts) return warnOnce(`[chai-ui] The judge model "${judgeModel}" replied without verdicts Chai can read, so no evaluations were added.`);
510
+ // Only on a run still shown: a newer submit's runs are left alone.
511
+ const add = (runs: Run[]) => runs.map((x) => (x.id === run.id ? addEvaluations(x, resultId, verdicts) : x));
512
+ set((s) => ({ runs: add(s.runs), editRuns: add(s.editRuns) }));
513
+ } catch (err) {
514
+ if (!isAbortError(err)) warnOnce(`[chai-ui] The judge model "${judgeModel}" failed, so no evaluations were added: ${normalizeGenerationError(err).message}`);
515
+ }
516
+ }
517
+
446
518
  function submit(payload: ComposerSubmitPayload) {
447
519
  const id = ++submitId;
448
520
  controller?.abort();
@@ -584,11 +656,16 @@ export function createComposerStore(getOptions: () => ComposerOptions, getProvid
584
656
  export type ComposerStore = ReturnType<typeof createComposerStore>;
585
657
 
586
658
  const warned = new Set<string>();
587
- /** One console warning per message per page load: auto-select is on with no reasoning model to route with. */
659
+ /** One console warning per message per page load. */
660
+ function warnOnce(message: string) {
661
+ if (warned.has(message)) return;
662
+ warned.add(message);
663
+ console.warn(message);
664
+ }
665
+
666
+ /** Auto-select is on with no reasoning model to route with. */
588
667
  export function warnNoReasoningOnce(consequence: string) {
589
- if (warned.has(consequence)) return;
590
- warned.add(consequence);
591
- console.warn(
668
+ warnOnce(
592
669
  `[chai-ui] Auto-select model is on, but there's no reasoning model, so ${consequence}. Wrap your app in <ChaiProvider> to route with one.`
593
670
  );
594
671
  }
@@ -260,21 +260,30 @@ export function createFalEngine(options: FalEngineOptions = {}): GenerationEngin
260
260
  );
261
261
  }
262
262
 
263
- const input = options.models?.find((m) => m.id === model)?.falInput;
264
- const body = buildFalRequestBody({ prompt, attachments, model, aspectRatio, voice, input });
263
+ const known = (id: string) => options.models?.find((m) => m.id === id) ?? SUGGESTED_FAL_MODELS.get(id);
264
+ // With images attached, a model whose endpoint takes a prompt only
265
+ // runs as its `withImages` endpoint (an edit, or image-to-video).
266
+ const hasImages = attachments.some((a) => a.kind === "image");
267
+ const target = (hasImages && known(model)?.withImages) || model;
268
+ const info = known(target);
269
+ // An endpoint that lists its ratios gets only one it takes. With none
270
+ // listed (image-to-video that follows the image), the start image was
271
+ // already fitted to the ratio, so there's nothing to send.
272
+ const sendRatio = aspectRatio && (target === model || info?.aspectRatios?.includes(aspectRatio)) ? aspectRatio : undefined;
273
+ const body = buildFalRequestBody({ prompt, attachments, model: target, aspectRatio: sendRatio, voice, input: info?.falInput });
265
274
  if (signal?.aborted) throw abortError();
266
275
 
267
276
  try {
268
277
  // The submit itself isn't aborted mid-flight: without its request id
269
278
  // there'd be nothing to cancel at Fal.
270
- const { requestId, status } = await submitFalJob({ endpoint, model, body, fetchImpl });
279
+ const { requestId, status } = await submitFalJob({ endpoint, model: target, body, fetchImpl });
271
280
  if (signal?.aborted) {
272
- await cancelFalJob({ endpoint, model, requestId, fetchImpl });
281
+ await cancelFalJob({ endpoint, model: target, requestId, fetchImpl });
273
282
  throw abortError();
274
283
  }
275
284
  const result = await awaitFalJob({
276
285
  endpoint,
277
- model,
286
+ model: target,
278
287
  requestId,
279
288
  status,
280
289
  fetchImpl,
@@ -282,7 +291,7 @@ export function createFalEngine(options: FalEngineOptions = {}): GenerationEngin
282
291
  timeoutMs,
283
292
  signal,
284
293
  }).catch(async (err) => {
285
- if (isAbortError(err)) await cancelFalJob({ endpoint, model, requestId, fetchImpl });
294
+ if (isAbortError(err)) await cancelFalJob({ endpoint, model: target, requestId, fetchImpl });
286
295
  throw err;
287
296
  });
288
297
  const src = extractFalResultSrc(result, outputKind);
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The opt-in evaluation judge: after a text or image result arrives, a
3
+ * model the builder names checks it against the builder's own criteria,
4
+ * and each check becomes a pass or fail tag on the result. Chai writes the
5
+ * framing; what "good" means is the builder's, in `checks`.
6
+ */
7
+ import type { Evaluation } from "./types.js";
8
+
9
+ /** One thing the judge checks. `label` is the tag on the result; `criterion` says what passing means, in the builder's words. */
10
+ export interface EvaluationCheck {
11
+ id: string;
12
+ label: string;
13
+ criterion: string;
14
+ /** Only judge results of this kind, e.g. a look-and-feel check for images. Absent, text and image results both get it. */
15
+ kind?: "text" | "image";
16
+ }
17
+
18
+ /** What a judge prompt is built from. A text result's words are in `text`; an image result is attached to the judge's request. */
19
+ export interface JudgePromptInput {
20
+ prompt: string;
21
+ output: { kind: "text"; text: string } | { kind: "image" };
22
+ checks: EvaluationCheck[];
23
+ }
24
+
25
+ /** The checks when the builder gives none: one accuracy check. Replace or add to it for your app. */
26
+ export const DEFAULT_EVALUATION_CHECKS: EvaluationCheck[] = [
27
+ {
28
+ id: "matches-prompt",
29
+ label: "Matches prompt",
30
+ criterion: "The result does what the prompt asked for, with nothing important missing or wrong.",
31
+ },
32
+ ];
33
+
34
+ /** The prompt the judge model receives: the person's prompt, the result, and each check's criterion, answered as JSON. */
35
+ export function buildJudgePrompt({ prompt, output, checks }: JudgePromptInput): string {
36
+ return [
37
+ "You judge a result an AI app generated, against the app's own criteria. Be strict: pass a check only if the result clearly meets it.",
38
+ `The person's prompt:\n"""\n${prompt}\n"""`,
39
+ output.kind === "image" ? "The result is the attached image." : `The result:\n"""\n${output.text}\n"""`,
40
+ `Criteria, by id:\n${checks.map((c) => `- ${c.id}: ${c.criterion}`).join("\n")}`,
41
+ 'Reply with only a JSON object mapping each id to true (passes) or false (fails), e.g. {"first-id": true, "second-id": false}.',
42
+ ].join("\n\n");
43
+ }
44
+
45
+ /** The judge's verdicts as evaluations, in the checks' order: `null` when the reply has none it can read. */
46
+ export function parseJudgeReply(reply: string, checks: EvaluationCheck[]): Evaluation[] | null {
47
+ const json = reply.match(/\{[\s\S]*\}/)?.[0];
48
+ if (!json) return null;
49
+ let verdicts: Record<string, unknown>;
50
+ try {
51
+ verdicts = JSON.parse(json);
52
+ } catch {
53
+ return null;
54
+ }
55
+ const found = checks.flatMap((c) => {
56
+ const passed = verdicts[c.id];
57
+ return typeof passed === "boolean" ? [{ id: c.id, label: c.label, passed }] : [];
58
+ });
59
+ return found.length > 0 ? found : null;
60
+ }