@chai-ui/core 0.6.0 → 0.7.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 (52) hide show
  1. package/README.md +10 -5
  2. package/dist/composer-view.d.ts +93 -0
  3. package/dist/composer-view.d.ts.map +1 -0
  4. package/dist/composer-view.js +142 -0
  5. package/dist/composer-view.js.map +1 -0
  6. package/dist/composer.d.ts +188 -0
  7. package/dist/composer.d.ts.map +1 -0
  8. package/dist/composer.js +326 -0
  9. package/dist/composer.js.map +1 -0
  10. package/dist/edit-card.d.ts +53 -0
  11. package/dist/edit-card.d.ts.map +1 -0
  12. package/dist/edit-card.js +119 -0
  13. package/dist/edit-card.js.map +1 -0
  14. package/dist/index.d.ts +7 -0
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +7 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/media-actions.d.ts +19 -0
  19. package/dist/media-actions.d.ts.map +1 -0
  20. package/dist/media-actions.js +57 -0
  21. package/dist/media-actions.js.map +1 -0
  22. package/dist/media-analyzer.d.ts +101 -0
  23. package/dist/media-analyzer.d.ts.map +1 -0
  24. package/dist/media-analyzer.js +215 -0
  25. package/dist/media-analyzer.js.map +1 -0
  26. package/dist/reasoning.d.ts +59 -0
  27. package/dist/reasoning.d.ts.map +1 -0
  28. package/dist/reasoning.js +55 -0
  29. package/dist/reasoning.js.map +1 -0
  30. package/dist/region-edit.d.ts +2 -0
  31. package/dist/region-edit.d.ts.map +1 -1
  32. package/dist/region-edit.js +6 -0
  33. package/dist/region-edit.js.map +1 -1
  34. package/dist/result-format.d.ts +11 -0
  35. package/dist/result-format.d.ts.map +1 -0
  36. package/dist/result-format.js +30 -0
  37. package/dist/result-format.js.map +1 -0
  38. package/dist/unique-id.d.ts +3 -0
  39. package/dist/unique-id.d.ts.map +1 -0
  40. package/dist/unique-id.js +7 -0
  41. package/dist/unique-id.js.map +1 -0
  42. package/package.json +2 -1
  43. package/src/composer-view.ts +222 -0
  44. package/src/composer.ts +525 -0
  45. package/src/edit-card.ts +138 -0
  46. package/src/index.ts +7 -0
  47. package/src/media-actions.ts +55 -0
  48. package/src/media-analyzer.ts +293 -0
  49. package/src/reasoning.ts +90 -0
  50. package/src/region-edit.ts +8 -0
  51. package/src/result-format.ts +34 -0
  52. package/src/unique-id.ts +6 -0
package/README.md CHANGED
@@ -14,9 +14,10 @@
14
14
 
15
15
  The headless core behind CHAI's components: the data types, the
16
16
  Request → Run → Result model a submitted prompt flows through, and the
17
- pluggable generation engines that actually call models. No framework, no
18
- rendering — `@chai-ui/react` is one binding of this; a future non-React
19
- binding would depend on this package the same way.
17
+ pluggable generation engines that actually call models, and the components'
18
+ behavior as small framework-free stores. No framework, no rendering:
19
+ `@chai-ui/react` wraps the stores in hooks, and a Vue binding will wrap the
20
+ same stores.
20
21
 
21
22
  ## Layout
22
23
 
@@ -29,6 +30,9 @@ binding would depend on this package the same way.
29
30
  - `suggested-models.ts` — the suggested model lists per use case (Fal for generation, OpenRouter for analysis), each model with its verified aspect ratios and Fal input format; `suggestedModels(useCase)`.
30
31
  - `check-suggested-models.ts` — `checkSuggestedModels()`: checks those lists against Fal's and OpenRouter's catalogs as they are today. No key, no model run.
31
32
  - `model-routing.ts` — auto-select: `buildModelRoutingPrompt`, `parseModelRoutingReply`, and `routeModel`, which falls back to the first listed model instead of throwing.
33
+ - `reasoning.ts` — the reasoning engine and models a `ChaiProvider` shares: `createReasoning`, `pickReasoning`, `reasoningModelFor` and the suggested defaults.
34
+ - `composer.ts` — `createComposerStore`, what `useComposer` wraps: submit payload → runs, auto-select routing, Enhance, cancel, and image edit versions. Plus the Composer's shared types (`ComposerSubmitPayload`, `EditVersion`, …).
35
+ - `media-analyzer.ts` — `createMediaAnalyzerStore`, what `useMediaAnalyzer` wraps.
32
36
  - `server/` — `createChaiHandler` and `toNodeHandler`, exported from `@chai-ui/core/server` (server-only).
33
37
 
34
38
  ## Suggested models, and checking them
@@ -73,8 +77,8 @@ Set `FAL_KEY` and `OPENROUTER_API_KEY` in the server's environment (never
73
77
  with a `VITE_` or `NEXT_PUBLIC_` prefix). A missing key comes back as a
74
78
  clear error, e.g. "FAL_KEY isn't set on the server."
75
79
 
76
- **Where it runs.** Chai's components are React-only, so the route lives in
77
- your React app's framework or on the API server behind it. Mount it at
80
+ **Where it runs.** The route lives in your app's framework (React or Vue)
81
+ or on the API server behind it. Mount it at
78
82
  `/api/chai`, where the components send their requests. `handle(request)`
79
83
  takes a standard web `Request` and returns a `Response`; `GET`, `POST` and
80
84
  `PUT` (Fal's cancel call) are the same function. When the browser
@@ -84,6 +88,7 @@ disconnects, the provider call is aborted too.
84
88
  |---|---|
85
89
  | Next.js (App Router) | `export const { GET, POST, PUT } = createChaiHandler();` in `app/api/chai/[...path]/route.ts` |
86
90
  | Remix / React Router | `export const loader = ({ request }) => chai.handle(request); export const action = loader;` in `app/routes/api.chai.$.ts` |
91
+ | Nuxt | `export default defineEventHandler((event) => chai.handle(toWebRequest(event)));` in `server/api/chai/[...path].ts` |
87
92
  | Hono | `app.all("/api/chai/*", (c) => chai.handle(c.req.raw))` |
88
93
  | Bun, Deno | route `/api/chai/*` to `chai.handle` in `Bun.serve` / `Deno.serve` |
89
94
  | Cloudflare Workers | `createChaiHandler({ falKey: env.FAL_KEY, openRouterKey: env.OPENROUTER_API_KEY }).handle(request)` |
@@ -0,0 +1,93 @@
1
+ /**
2
+ * What the Composer component shows and submits, worked out from its props:
3
+ * the same in every framework binding. Pure; nothing here renders.
4
+ */
5
+ import type { ComposerAttachment, ComposerSubmitPayload, ComposerUseCase } from "./composer.js";
6
+ import type { EditRegion } from "./region-edit.js";
7
+ import type { MediaKind, ModelOption, ParameterOption } from "./types.js";
8
+ export type ComposerAttachMenuAction = "add-media" | "create-image" | "create-video" | "edit-media";
9
+ /** The `+` menu, in order. "Add media" is the only item with a divider after it. */
10
+ export declare const COMPOSER_ATTACH_MENU_ITEMS: {
11
+ action: ComposerAttachMenuAction;
12
+ label: string;
13
+ divider?: boolean;
14
+ }[];
15
+ /**
16
+ * Past this length a rewritten prompt appears at once: a long reveal reads
17
+ * as sluggish, and a long prompt is when a person wants the result now.
18
+ */
19
+ export declare const MAX_ANIMATE_ENHANCE_LENGTH = 260;
20
+ /** How long the Enhance reveal takes: time-driven, between 300ms and 900ms. */
21
+ export declare function enhanceRevealDurationMs(charCount: number): number;
22
+ /** The Composer props `composerView` reads. Callbacks only matter by being there. */
23
+ export interface ComposerViewInput {
24
+ value: string;
25
+ placeholder?: string;
26
+ attachments?: ComposerAttachment[];
27
+ useCase?: ComposerUseCase | null;
28
+ defaultUseCase?: ComposerUseCase;
29
+ multiSelectUseCases?: boolean;
30
+ useCases?: ComposerUseCase[];
31
+ modelsByKind?: Partial<Record<MediaKind, ModelOption[]>>;
32
+ multiSelectModels?: boolean;
33
+ modelIds?: string[];
34
+ models?: ModelOption[];
35
+ modelId?: string | null;
36
+ onModelChange?: unknown;
37
+ onModelIdsChange?: unknown;
38
+ autoSelectModel?: boolean;
39
+ aspectRatios?: ParameterOption<string>[];
40
+ aspectRatio?: string | null;
41
+ submitError?: string | null;
42
+ submitDisabled?: boolean;
43
+ submitting?: boolean;
44
+ onAbort?: unknown;
45
+ regions?: EditRegion[];
46
+ disabled?: boolean;
47
+ }
48
+ export declare function composerView(props: ComposerViewInput): {
49
+ pickedUseCases: ComposerUseCase[];
50
+ activeUseCases: ComposerUseCase[];
51
+ editing: boolean;
52
+ isSubmitDisabled: boolean;
53
+ placeholder: string;
54
+ showStop: boolean;
55
+ multiModel: boolean;
56
+ modelSections: {
57
+ options: ModelOption[];
58
+ suggested: boolean;
59
+ label: string;
60
+ kind: MediaKind;
61
+ }[];
62
+ pickedModelIds: string[];
63
+ canPickModel: boolean;
64
+ modelTriggerLabel: string;
65
+ showAspectRatio: boolean;
66
+ aspectOptions: ParameterOption<string>[];
67
+ offeredAspect: string | null;
68
+ selectedAspect: ParameterOption<string> | null;
69
+ /** The model ids after a row click: the one picked, or with multi-select that one toggled. */
70
+ toggledModelIds: (id: string) => string[];
71
+ /** Everything a submit sends. */
72
+ payload: () => ComposerSubmitPayload;
73
+ };
74
+ export type ComposerView = ReturnType<typeof composerView>;
75
+ /** The `+` menu items that can work: "Add media" needs somewhere to put files, the use-case items a handler. */
76
+ export declare function composerAttachMenuItems(actions: ComposerAttachMenuAction[] | undefined, { canAddMedia, canSelect }: {
77
+ canAddMedia: boolean;
78
+ canSelect: boolean;
79
+ }): {
80
+ action: ComposerAttachMenuAction;
81
+ label: string;
82
+ divider?: boolean;
83
+ }[];
84
+ /**
85
+ * The attachments after picking files: each image, video or audio file
86
+ * added in the order picked. Editing works on one image, so its first image
87
+ * replaces what's there (and with none, every file is unsupported).
88
+ */
89
+ export declare function composerAttachmentsFromFiles(files: Iterable<File>, current: ComposerAttachment[], editing: boolean): Promise<{
90
+ attachments: ComposerAttachment[] | null;
91
+ unsupported: string[];
92
+ }>;
93
+ //# sourceMappingURL=composer-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composer-view.d.ts","sourceRoot":"","sources":["../src/composer-view.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ import { uniqueId } from "./unique-id.js";
2
+ import { TEXT_USE_CASE } from "./composer.js";
3
+ import { readMediaFiles } from "./media-analyzer.js";
4
+ import { deriveGenerationUseCase } from "./run.js";
5
+ import { suggestedModels } from "./suggested-models.js";
6
+ /** The `+` menu, in order. "Add media" is the only item with a divider after it. */
7
+ export const COMPOSER_ATTACH_MENU_ITEMS = [
8
+ { action: "add-media", label: "Add media", divider: true },
9
+ { action: "create-image", label: "Create image" },
10
+ { action: "create-video", label: "Create video" },
11
+ { action: "edit-media", label: "Edit image" },
12
+ ];
13
+ /**
14
+ * Past this length a rewritten prompt appears at once: a long reveal reads
15
+ * as sluggish, and a long prompt is when a person wants the result now.
16
+ */
17
+ export const MAX_ANIMATE_ENHANCE_LENGTH = 260;
18
+ /** How long the Enhance reveal takes: time-driven, between 300ms and 900ms. */
19
+ export function enhanceRevealDurationMs(charCount) {
20
+ return Math.min(900, Math.max(300, charCount * 6));
21
+ }
22
+ export function composerView(props) {
23
+ const { value, attachments = [], useCase = null, defaultUseCase = TEXT_USE_CASE, multiSelectUseCases = false, useCases = [], modelsByKind, multiSelectModels = false, modelIds = [], models, modelId = null, autoSelectModel = false, aspectRatios, aspectRatio = null, submitError = null, submitting = false, regions = [], disabled = false, } = props;
24
+ // What the person picked, and what actually runs: with nothing picked, the
25
+ // builder's default use case (a text request unless they chose otherwise).
26
+ const pickedUseCases = multiSelectUseCases ? useCases : useCase ? [useCase] : [];
27
+ const activeUseCases = pickedUseCases.length > 0 ? pickedUseCases : [defaultUseCase];
28
+ // An edit needs an image, then a change: a prompt for the whole image, a
29
+ // region with its own instruction, or both.
30
+ const editing = activeUseCases.some((u) => u.edit);
31
+ const hasImage = attachments.some((a) => a.kind === "image");
32
+ const hasContent = editing
33
+ ? hasImage && (value.trim().length > 0 || regions.length > 0)
34
+ : value.trim().length > 0 || attachments.length > 0;
35
+ const isSubmitDisabled = submitError ? disabled : (props.submitDisabled ?? (disabled || !hasContent));
36
+ const placeholder = props.placeholder ??
37
+ (editing
38
+ ? hasImage
39
+ ? "Describe a change across the whole image, or leave this empty"
40
+ : "Attach an image to edit"
41
+ : "Describe media to create");
42
+ // The stop icon only appears with somewhere for its click to go.
43
+ const showStop = submitting && Boolean(props.onAbort);
44
+ const multiModel = multiSelectModels || multiSelectUseCases;
45
+ const rawPickedIds = multiModel ? modelIds : modelId ? [modelId] : [];
46
+ // The app's list for a use case, or Chai's suggested models when it gave none.
47
+ const rosterFor = (u) => {
48
+ const given = multiSelectUseCases ? modelsByKind?.[u.kind] : models;
49
+ if (given)
50
+ return { options: given, suggested: false };
51
+ return { options: suggestedModels(u.edit ? "image-edit" : deriveGenerationUseCase(u, attachments)), suggested: true };
52
+ };
53
+ // One menu section per use case with multi-use-case select; otherwise one flat roster.
54
+ const modelSections = (multiSelectUseCases ? activeUseCases : activeUseCases.slice(0, 1))
55
+ .map((u) => ({ label: multiSelectUseCases ? u.label : "", kind: u.kind, ...rosterFor(u) }))
56
+ .filter((s) => s.options.length > 0);
57
+ const allModels = modelSections.flatMap((s) => s.options);
58
+ // A pick that isn't in the current list (e.g. the edit model after leaving
59
+ // edit mode) is shown as unpicked and never submitted. With no list at
60
+ // all, the app's pick is passed through as given. With nothing picked
61
+ // from a suggested list (and auto-select off), its first model is the pick.
62
+ const validPicks = allModels.length > 0 ? rawPickedIds.filter((id) => allModels.some((m) => m.id === id)) : rawPickedIds;
63
+ const pickedModelIds = validPicks.length > 0 || autoSelectModel ? validPicks : modelSections.filter((s) => s.suggested).map((s) => s.options[0].id);
64
+ const pickedModels = allModels.filter((m) => pickedModelIds.includes(m.id));
65
+ // No menu that can't change anything: without its handler, the Model menu hides (the default pick still runs).
66
+ const canPickModel = Boolean(multiModel ? props.onModelIdsChange : props.onModelChange);
67
+ const modelTriggerLabel = pickedModels.length > 1
68
+ ? `${pickedModels.length} models`
69
+ : (pickedModels[0]?.label ?? (autoSelectModel ? "Auto-select" : "Select models"));
70
+ // An edit keeps the source image's shape.
71
+ const showAspectRatio = activeUseCases.some((u) => !u.edit && (u.kind === "image" || u.kind === "video"));
72
+ // Only ratios every model that might run takes: the picked ones, or with
73
+ // none picked (or auto-select on) the whole list, so whichever runs can
74
+ // honor it. A model with no `aspectRatios` sets its own shape: no menu.
75
+ const ratioModels = pickedModels.length > 0 && !autoSelectModel ? pickedModels : allModels;
76
+ const sharedRatios = ratioModels.reduce((shared, m) => (shared ?? m.aspectRatios ?? []).filter((r) => m.aspectRatios?.includes(r)), null) ??
77
+ [];
78
+ const aspectOptions = aspectRatios
79
+ ? aspectRatios.filter((o) => sharedRatios.includes(o.value))
80
+ : sharedRatios.map((r) => ({ value: r, label: r }));
81
+ // A pick the current models don't take is shown as unpicked and never sent.
82
+ const offeredAspect = showAspectRatio && aspectOptions.some((o) => o.value === aspectRatio) ? aspectRatio : null;
83
+ const selectedAspect = aspectOptions.find((o) => o.value === offeredAspect) ?? null;
84
+ const selections = () => activeUseCases.map((u) => ({
85
+ useCase: u,
86
+ models: rosterFor(u).options,
87
+ modelIds: multiSelectUseCases ? pickedModelIds.filter((id) => rosterFor(u).options.some((m) => m.id === id)) : pickedModelIds,
88
+ }));
89
+ return {
90
+ pickedUseCases,
91
+ activeUseCases,
92
+ editing,
93
+ isSubmitDisabled,
94
+ placeholder,
95
+ showStop,
96
+ multiModel,
97
+ modelSections,
98
+ pickedModelIds,
99
+ canPickModel,
100
+ modelTriggerLabel,
101
+ showAspectRatio,
102
+ aspectOptions,
103
+ offeredAspect,
104
+ selectedAspect,
105
+ /** The model ids after a row click: the one picked, or with multi-select that one toggled. */
106
+ toggledModelIds: (id) => (modelIds.includes(id) ? modelIds.filter((m) => m !== id) : [...modelIds, id]),
107
+ /** Everything a submit sends. */
108
+ payload: () => ({
109
+ value,
110
+ attachments,
111
+ useCase: activeUseCases[0],
112
+ modelId: pickedModelIds[0] ?? null,
113
+ aspectRatio: offeredAspect,
114
+ selections: selections(),
115
+ autoSelectModel,
116
+ regions: editing ? regions : [],
117
+ }),
118
+ };
119
+ }
120
+ /** The `+` menu items that can work: "Add media" needs somewhere to put files, the use-case items a handler. */
121
+ export function composerAttachMenuItems(actions, { canAddMedia, canSelect }) {
122
+ return COMPOSER_ATTACH_MENU_ITEMS.filter((item) => (actions ?? COMPOSER_ATTACH_MENU_ITEMS.map((i) => i.action)).includes(item.action) &&
123
+ (item.action === "add-media" ? canAddMedia : canSelect));
124
+ }
125
+ /**
126
+ * The attachments after picking files: each image, video or audio file
127
+ * added in the order picked. Editing works on one image, so its first image
128
+ * replaces what's there (and with none, every file is unsupported).
129
+ */
130
+ export async function composerAttachmentsFromFiles(files, current, editing) {
131
+ const list = [...files];
132
+ if (editing) {
133
+ const image = list.find((f) => f.type.startsWith("image/"));
134
+ if (!image)
135
+ return { attachments: null, unsupported: list.map((f) => f.name) };
136
+ const { media, unsupported } = await readMediaFiles([image]);
137
+ return { attachments: media.length > 0 ? media.map((m) => ({ ...m, id: uniqueId() })) : null, unsupported };
138
+ }
139
+ const { media, unsupported } = await readMediaFiles(list);
140
+ return { attachments: [...current, ...media.map((m) => ({ ...m, id: uniqueId() }))], unsupported };
141
+ }
142
+ //# sourceMappingURL=composer-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composer-view.js","sourceRoot":"","sources":["../src/composer-view.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * The Composer's behavior with no framework: turns a submit payload into
3
+ * `Request` → `Run` → `Result` (§6), fanning out across `engine.generate`
4
+ * calls and folding each one back into state as it settles. A small store
5
+ * (`getState` + `subscribe`) that `useComposer` (React) and the Vue
6
+ * composable wrap; the pure transitions live in `run.ts`.
7
+ */
8
+ import { type GenerationEngine } from "./engine.js";
9
+ import { type ModelRoutingInput, type ModelRoutingResult } from "./model-routing.js";
10
+ import { type EditRegion } from "./region-edit.js";
11
+ import { type Reasoning } from "./reasoning.js";
12
+ import { type ResultStatus, type Run } from "./run.js";
13
+ import type { DroppedMedia, GenerationUseCase, MediaKind, ModelOption } from "./types.js";
14
+ export interface ComposerAttachment extends DroppedMedia {
15
+ id: string;
16
+ }
17
+ /**
18
+ * The selected generation use case, shown as a removable chip (reference:
19
+ * the mock's "Video"/"Image" chip) — deliberately independent of
20
+ * `attachments`: a use case can be picked from the attach menu with nothing
21
+ * attached yet (e.g. "Create video"). Composer never derives this from
22
+ * `attachments` itself (that's app-level policy, not a Composer opinion —
23
+ * the design). With none picked, `defaultUseCase` applies.
24
+ */
25
+ export interface ComposerUseCase {
26
+ kind: MediaKind;
27
+ label: string;
28
+ /**
29
+ * An edit of the attached image rather than a new one: no aspect ratio,
30
+ * region chips when `regions` is set, and a submit needs only an image and
31
+ * either a prompt or a region. Images only for now.
32
+ */
33
+ edit?: boolean;
34
+ }
35
+ /** A plain text request — what a submit means when no use case is picked, unless the builder sets `defaultUseCase`. */
36
+ export declare const TEXT_USE_CASE: ComposerUseCase;
37
+ /** Editing the attached image, the attach menu's "Edit image". Pair it with `useComposer`'s `editImage` and an `EditCard`. */
38
+ export declare const EDIT_IMAGE_USE_CASE: ComposerUseCase;
39
+ /** One use case to run and the models picked for it. Empty `modelIds` means the engine's default model. */
40
+ export interface ComposerSelection {
41
+ useCase: ComposerUseCase;
42
+ modelIds: string[];
43
+ /** The models offered for this use case: what auto-select routes among. */
44
+ models: ModelOption[];
45
+ }
46
+ /**
47
+ * Everything Composer itself tracks, assembled into one object at submit
48
+ * time — an honest snapshot of the component's own state, handed to
49
+ * `onSubmit` so a builder doesn't have to re-derive it from five
50
+ * separately-controlled props they already hold.
51
+ */
52
+ export interface ComposerSubmitPayload {
53
+ value: string;
54
+ attachments: ComposerAttachment[];
55
+ /** The use case to run — the picked one, or `defaultUseCase` when none is picked. The first one with `multiSelectUseCases`. */
56
+ useCase: ComposerUseCase;
57
+ /** The first picked model, or null for the engine's default. */
58
+ modelId: string | null;
59
+ aspectRatio: string | null;
60
+ /** Everything to run: one entry per use case with its picked models. A single entry unless `multiSelectUseCases` is on. */
61
+ selections: ComposerSelection[];
62
+ /** When true, the model is chosen at submit (`useComposer` routes among each selection's `models`), not by the picks. */
63
+ autoSelectModel: boolean;
64
+ /** An edit's marked regions, each with its own instruction. Empty unless the use case is an edit. */
65
+ regions?: EditRegion[];
66
+ }
67
+ /**
68
+ * One version of the image being edited: the original, or the result of an
69
+ * edit. The composer's `edit.versions` builds these from its runs.
70
+ */
71
+ export interface EditVersion {
72
+ id: string;
73
+ /** The image, once there is one. */
74
+ src?: string;
75
+ /** The image this version was edited from, shown under the progress spinner until `src` arrives. */
76
+ from?: string;
77
+ status: ResultStatus;
78
+ /** The regions this version was made with (none for the original). Shown faintly, for reference. */
79
+ regions: EditRegion[];
80
+ error?: string;
81
+ }
82
+ /** A result's `modelId` when nothing was picked: the engine runs its own default model. */
83
+ export declare const DEFAULT_MODEL_ID = "default";
84
+ export interface ComposerOptions {
85
+ /** The generation engine a submitted run actually calls. Defaults to `mockEngine`. */
86
+ engine?: GenerationEngine;
87
+ /**
88
+ * Engines per use-case kind, overriding `engine` for that kind — needed
89
+ * for multi-use-case select, since one Fal engine outputs one kind, e.g.
90
+ * `{ image: createFalEngine({ outputKind: "image" }), video: createFalEngine({ outputKind: "video" }) }`.
91
+ */
92
+ engineByKind?: Partial<Record<MediaKind, GenerationEngine>>;
93
+ /**
94
+ * The engine for text requests (a Composer with no use case picked, or a
95
+ * text use case). Defaults to `reasoningEngine`, and to a mock text engine
96
+ * when neither is set, so a text prompt always gets a reply.
97
+ */
98
+ textEngine?: GenerationEngine;
99
+ /** The model text requests use when none is picked. Defaults to the reasoning model for the attachments' kinds, then the text engine's own default. */
100
+ textModel?: string;
101
+ /**
102
+ * The reasoning engine Enhance calls — deliberately separate from
103
+ * `engine`: Fal's own text/vision access is itself an
104
+ * OpenRouter proxy, so defaulting Enhance to a Fal `engine` would
105
+ * silently double-proxy. Must return text. Set together with
106
+ * `reasoningModel` to override the nearest `ChaiProvider`'s pair; with
107
+ * neither set here nor a provider, `enhance` stays `undefined`, same
108
+ * shape as `Composer`'s own "omit `onEnhance` to hide the button" convention.
109
+ */
110
+ reasoningEngine?: GenerationEngine;
111
+ /** Set with `reasoningEngine` to override the provider's pair; used for every kind (§5.5). */
112
+ reasoningModel?: string;
113
+ /** Overrides the instruction wrapping a raw prompt for Enhance. Defaults to a generic still/video-aware rewrite instruction. */
114
+ enhancePrompt?: (value: string, mode?: GenerationUseCase) => string;
115
+ /**
116
+ * Auto-select: with `autoSelectModel` on in the payload, the reasoning
117
+ * model picks one model per use case at submit, then these fire with the
118
+ * pick so the Composer's trigger shows it. Wire them to the same state as
119
+ * Composer's `onModelChange` / `onModelIdsChange`.
120
+ */
121
+ onModelChange?: (modelId: string) => void;
122
+ onModelIdsChange?: (modelIds: string[]) => void;
123
+ /** Replaces the routing instruction (`buildModelRoutingPrompt`). */
124
+ routingPrompt?: (input: ModelRoutingInput) => string;
125
+ /**
126
+ * Fires when auto-select couldn't route and fell back to the first listed
127
+ * model: no reasoning model, a failed reasoning call (e.g. a bad key), or
128
+ * a reply naming no listed model. The request still runs.
129
+ */
130
+ onRoutingFallback?: (result: Extract<ModelRoutingResult, {
131
+ status: "fallback";
132
+ }>) => void;
133
+ /**
134
+ * The image to edit, when the Composer's use case is an edit (e.g.
135
+ * `EDIT_IMAGE_USE_CASE`) and an image is attached. While it's set, `edit`
136
+ * returns props for an `EditCard`, and each edit's results become new
137
+ * versions of the image. Changing it to another image starts over.
138
+ */
139
+ editImage?: DroppedMedia | null;
140
+ /** Replaces how an edit's prompt and regions become the model's prompt. Defaults to `buildRegionEditPrompt`, in the model's `regionFormat`. */
141
+ editPrompt?: (args: {
142
+ prompt: string;
143
+ regions: EditRegion[];
144
+ model?: ModelOption;
145
+ }) => string;
146
+ onRun?: (run: Run) => void;
147
+ onResult?: (run: Run, resultId: string) => void;
148
+ onError?: (run: Run, resultId: string) => void;
149
+ }
150
+ export interface ComposerState {
151
+ /** One run per use case submitted: a single run unless the Composer has `multiSelectUseCases` on. */
152
+ runs: Run[];
153
+ enhancing: boolean;
154
+ routing: boolean;
155
+ /** Edit mode. Each edit's runs are kept (not replaced by the next submit), since every result is a version of the image the person can page back to. */
156
+ editRuns: Run[];
157
+ regions: EditRegion[];
158
+ activeVersion: number;
159
+ /** The image the edit state belongs to. Another image starts over. */
160
+ editSource: string | null;
161
+ /** Numbers each image, so its original version has its own id and EditCard starts it clean. */
162
+ editImageCount: number;
163
+ }
164
+ /** Props for an `EditCard` (spread them in), and `regions` for `Composer`. */
165
+ export interface ComposerEdit {
166
+ versions: EditVersion[];
167
+ activeVersion: number;
168
+ onActiveVersionChange: (index: number) => void;
169
+ regions: EditRegion[];
170
+ onRegionsChange: (regions: EditRegion[]) => void;
171
+ }
172
+ /**
173
+ * `getOptions` is read on every call, so options can change between
174
+ * renders; `getProvided` is the nearest provider's reasoning, if any.
175
+ */
176
+ export declare function createComposerStore(getOptions: () => ComposerOptions, getProvided?: () => Reasoning | undefined): {
177
+ getState: () => ComposerState;
178
+ subscribe(listener: () => void): () => undefined;
179
+ submit: (payload: ComposerSubmitPayload) => void;
180
+ cancel: () => void;
181
+ enhance: (value: string) => Promise<string>;
182
+ edit: (s: ComposerState, editImage: DroppedMedia | null | undefined) => ComposerEdit | null;
183
+ reasoning: () => Reasoning | undefined;
184
+ };
185
+ export type ComposerStore = ReturnType<typeof createComposerStore>;
186
+ /** One console warning per message per page load: auto-select is on with no reasoning model to route with. */
187
+ export declare function warnNoReasoningOnce(consequence: string): void;
188
+ //# sourceMappingURL=composer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composer.d.ts","sourceRoot":"","sources":["../src/composer.ts"],"names":[],"mappings":"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"}