@civitai/app-sdk 0.65.1 → 0.67.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 +106 -1
- package/dist/blocks/index.d.ts +8 -1
- package/dist/blocks/index.js +7 -0
- package/dist/blocks/messages.d.ts +15 -2
- package/dist/blocks/messages.js +1 -0
- package/dist/blocks/types.d.ts +492 -4
- package/dist/blocks/types.js +32 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -140,7 +140,7 @@ interface BlockInitPayload {
|
|
|
140
140
|
| `isModelSlotContext(ctx)` / `isPageSlotContext(ctx)` | Runtime narrowing for the `slotId`-discriminated `BlockContext` union. Real checks on a value that crossed a `postMessage` boundary — they verify every field they assert, not just `slotId`. |
|
|
141
141
|
| `fetchNestedDocument(opts)` | Embed one of your OWN bundled documents as an iframe `srcdoc`, because a nested `<iframe src>` of your own content **cannot load** — see [Nested documents](#nested-documents) below. `NestedDocumentError` carries a `.code` of `'invalid-url' \| 'http-error' \| 'network-error'`. |
|
|
142
142
|
| `isSignedIn(viewer)` | **The sign-in gate.** `isSignedIn(useBlockContext().viewer)` — do not open-code it as `viewer !== null` or `viewer?.signedIn === true`. Which of those is correct has already changed once with the host contract, and this is the one place it is decided. It reads neither `viewer.id` nor `viewer.username` (both `@deprecated`), so nothing written through it changes when those are removed. Need the identity rather than the presence? `useViewer()` — scope-gated and audited per call. |
|
|
143
|
-
| types | `BlockManifestV1`, `ManifestSettings` (+ field types), `BlockContext`, `ModelSlotContext`, `BlockCheckpointInfo`, `ShowcaseImage`, `BlockToken`, `WrappedToken`, `BlockSettings`, `ViewerInfo`, `Theme`, `WorkflowBody`, `BlockTextToImageParams`, `WorkflowBodyCustomComfy` (+ its two arms `WorkflowBodyCustomComfyRecipe` / `WorkflowBodyCustomComfyInline`, and `InlineComfyNode`), `WorkflowBodyStep` / `WorkflowBodyPassThroughStep` (the two arms of `kind: 'step'`), `WorkflowBodyTraining` (+ `AiToolkitTrainingParams`, `BlockTrainingQuote`, `BlockTrainingDatasetItem`, `BlockTrainingDatasetResult` and the `BLOCK_TRAINING_*` bounds), `BlockWorkflowSnapshot`, `WorkflowStatus`, `BlockInitPayload`, `ParentToBlockMessage`, `BlockToParentMessage`. |
|
|
143
|
+
| types | `BlockManifestV1`, `ManifestSettings` (+ field types), `BlockContext`, `ModelSlotContext`, `BlockCheckpointInfo`, `ShowcaseImage`, `BlockToken`, `WrappedToken`, `BlockSettings`, `ViewerInfo`, `Theme`, `WorkflowBody`, `BlockTextToImageParams`, `WorkflowBodyCustomComfy` (+ its two arms `WorkflowBodyCustomComfyRecipe` / `WorkflowBodyCustomComfyInline`, and `InlineComfyNode`), `WorkflowBodyStep` / `WorkflowBodyPassThroughStep` (the two arms of `kind: 'step'`), `WorkflowBodyTraining` (+ `AiToolkitTrainingParams`, `BlockTrainingQuote`, `BlockTrainingDatasetItem`, `BlockTrainingDatasetResult` and the `BLOCK_TRAINING_*` bounds), `WorkflowBodyWorkflow` (+ `WorkflowBodyWorkflowStep`, `WorkflowStepRef`, `WithWorkflowStepRefs`, `BlockWorkflowStepSnapshot` and `BLOCK_WORKFLOW_MAX_STEPS`), `BlockStepQuote` / `BlockRunConfirmedStepHostError` (+ `BLOCK_CONFIRMED_STEP_MAX_BUZZ_PER_JOB`, `BLOCK_STEP_QUOTE_ID_REGEX`), `BlockModel3dOutput`, `BlockWorkflowSnapshot`, `WorkflowStatus`, `BlockInitPayload`, `ParentToBlockMessage`, `BlockToParentMessage`. |
|
|
144
144
|
|
|
145
145
|
`WorkflowBody`'s `customComfy` member is a discriminated union on `mode`, mirroring
|
|
146
146
|
the host's `blockCustomComfyMemberSchema`. Narrow on the VALUE (`body.mode === 'inline'`),
|
|
@@ -209,6 +209,46 @@ const body: WorkflowBody = {
|
|
|
209
209
|
};
|
|
210
210
|
```
|
|
211
211
|
|
|
212
|
+
**Above the per-call budget: a confirmed step.** A pass-through job the per-call budget refuses
|
|
213
|
+
can still run when the **viewer confirms its exact price** in Civitai's own dialog
|
|
214
|
+
(civitai/civitai#5786). When the orchestrator quotes a **fixed** price (positive, not variable
|
|
215
|
+
or metered) above the token's per-call budget and at most `BLOCK_CONFIRMED_STEP_MAX_BUZZ_PER_JOB`
|
|
216
|
+
(5,000), the `estimate` reply carries `snapshot.stepQuote` (`quoteId`, `total`, `stepType`,
|
|
217
|
+
`expiresAt`). Send the same body back with that `quoteId` on the `RUN_CONFIRMED_STEP` bridge
|
|
218
|
+
(`CONFIRMED_STEP_RESULT`); a `quoteId` body sent as an ordinary submit is refused. A quote is
|
|
219
|
+
single-use and expires after 15 minutes. Only a **single** estimate carries `stepQuote` — a
|
|
220
|
+
batch estimate stores nothing, so its cells never do. Where a quote would be granted, the
|
|
221
|
+
estimate **fails instead** (`{ workflowId: 'failed', status: 'failed', error }`) for a training
|
|
222
|
+
`$type` in any casing (`a training step type cannot run as a confirmed step — use kind:'training'`) and for an
|
|
223
|
+
`input` that is not plain JSON (`a confirmed step needs plain JSON input (objects, arrays,
|
|
224
|
+
strings, finite numbers, booleans, null) — <path> is <what>`; the suffix varies, so match on
|
|
225
|
+
the text before the dash). Each confirmation is its own job, so a
|
|
226
|
+
`submission-unconfirmed` result — the outcome is unknown — must never be retried automatically:
|
|
227
|
+
a retry is a new, separately charged job. Page apps only, `ai:write:budgeted`, behind the host
|
|
228
|
+
flag `app-blocks-confirmed-step` (off by default), and refused for development, dev-tunnel and
|
|
229
|
+
review tokens — so it is exercised against the mock host, not `dev:live`. Use it through
|
|
230
|
+
`@civitai/blocks-react`'s `useRunConfirmedStep()`.
|
|
231
|
+
|
|
232
|
+
**3D outputs.** A step that produces 3D models (`polyGen`) still lists every model url in
|
|
233
|
+
`snapshot.imageUrls`; `snapshot.model3dOutputs` (and the same field on an `AppWorkflow` row)
|
|
234
|
+
labels them. Omitted when there are none.
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
import type { BlockModel3dOutput, BlockWorkflowSnapshot } from '@civitai/app-sdk/blocks';
|
|
238
|
+
|
|
239
|
+
// `format` is the model's file format; `variant` is the output it came from.
|
|
240
|
+
function pickModel(
|
|
241
|
+
snapshot: BlockWorkflowSnapshot,
|
|
242
|
+
format: string,
|
|
243
|
+
variant: string,
|
|
244
|
+
): BlockModel3dOutput | undefined {
|
|
245
|
+
return snapshot.model3dOutputs?.find((m) => m.format === format && m.variant === variant);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const mesh = pickModel(snapshot, 'glb', 'model');
|
|
249
|
+
const rigged = pickModel(snapshot, 'fbx', 'riggedFbxModel');
|
|
250
|
+
```
|
|
251
|
+
|
|
212
252
|
`WorkflowBodyTraining` (`kind: 'training'`) is the **quoted** way to train: an ai-toolkit LoRA
|
|
213
253
|
run on a dataset Civitai prepared from the viewer's own images, mirroring the host's
|
|
214
254
|
`blockTrainingBodySchema` (civitai/civitai#5434). There is no `maxBuzz` and no timeout — the
|
|
@@ -221,6 +261,71 @@ and review sessions. The dataset is prepared over `PREPARE_TRAINING_DATASET`
|
|
|
221
261
|
(civitai/civitai#5438). Use it through `@civitai/blocks-react`'s `usePrepareTrainingDataset()`
|
|
222
262
|
and `useRunTraining()`.
|
|
223
263
|
|
|
264
|
+
`WorkflowBodyWorkflow` (`kind: 'workflow'`) submits **several orchestrator steps as one
|
|
265
|
+
workflow**, 1 to `BLOCK_WORKFLOW_MAX_STEPS` (8), through the same messages as every other kind.
|
|
266
|
+
A value anywhere in a step's `input` may be a `WorkflowStepRef`
|
|
267
|
+
(`{ $ref, path, default?, format? }`) naming `'$arguments'`, an **earlier** step's `name`, or an
|
|
268
|
+
earlier **unnamed** step by position (`'$0'`). A `name` starts with a lowercase
|
|
269
|
+
letter, uses only lowercase letters, digits, `_` and `-`, and is unique (the exact rule is on
|
|
270
|
+
`WorkflowBodyWorkflowStep.name`). `suppressOutput: true` marks an intermediate step whose
|
|
271
|
+
blobs are not surfaced. There is no `maxBuzz`: the ceiling is the app's per-generation budget × the
|
|
272
|
+
number of steps.
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
import type { WorkflowBody } from '@civitai/app-sdk/blocks';
|
|
276
|
+
|
|
277
|
+
const body: WorkflowBody = {
|
|
278
|
+
kind: 'workflow',
|
|
279
|
+
arguments: { prompt: 'a lighthouse at dusk' },
|
|
280
|
+
steps: [
|
|
281
|
+
{
|
|
282
|
+
name: 'draw',
|
|
283
|
+
$type: 'imageGen',
|
|
284
|
+
input: {
|
|
285
|
+
engine: 'google',
|
|
286
|
+
model: 'nano-banana-2',
|
|
287
|
+
prompt: { $ref: '$arguments', path: 'prompt' },
|
|
288
|
+
},
|
|
289
|
+
suppressOutput: true,
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
name: 'cutout',
|
|
293
|
+
$type: 'imageBackgroundRemoval',
|
|
294
|
+
input: { image: { $ref: 'draw', path: 'output.images[0].url' } },
|
|
295
|
+
},
|
|
296
|
+
],
|
|
297
|
+
};
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
- 🔴 **The estimate is not a maximum.** The orchestrator re-prices a step once the values it
|
|
301
|
+
references are known and charges the difference.
|
|
302
|
+
- **A workflow the host cannot price has no estimate, but its submit still proceeds.** The
|
|
303
|
+
estimate (and a batch-estimate cell) fails with no `cost` and `snapshot.errorCode`
|
|
304
|
+
`workflow_quote_rejected` (the orchestrator refused the body; the same body will fail again),
|
|
305
|
+
`workflow_quote_unavailable` (no usable answer; the one a retry can clear) or
|
|
306
|
+
`workflow_quote_unpriced` (an answer without a price). The submit of the same body is reserved
|
|
307
|
+
at the ceiling above — unless it contains a training step (refused without a quote on both, as
|
|
308
|
+
on the single-step arm) or a `repeat` step at any depth (also refused on both, before any
|
|
309
|
+
reservation, as `workflow_repeat_unbounded`; its `error` states the cause). An older host
|
|
310
|
+
returns the ceiling as the estimate's `cost.total` instead of failing.
|
|
311
|
+
- **One author fee per workflow**, on the quoted base, itemised as `cost.authorFee` on the
|
|
312
|
+
estimate. If the workflow bills more, the fee charged is held to the fee shown; a workflow that
|
|
313
|
+
does not succeed has its whole fee reversed, even if earlier steps delivered output.
|
|
314
|
+
- **`repeat` over `arguments` only, at most 16 iterations** (`BLOCK_WORKFLOW_REPEAT_MAX_ITERATIONS`,
|
|
315
|
+
nested repeats multiplied): `for.$ref` must be `'$arguments'` and `path` must name an array
|
|
316
|
+
there. A `merge` step's `fields` entries each need a string `$ref` (an earlier step or
|
|
317
|
+
`$arguments`) and a `reduce`. Repeat children appear in `snapshot.steps` as `<name>.<n>`. The
|
|
318
|
+
velocity limit counts one unit per step, and a `repeat` one per iteration.
|
|
319
|
+
- `snapshot.steps` reports each step's `status`, `imageUrls`, `output` and `error`. A `failed`
|
|
320
|
+
workflow can still carry `cost.total > 0` and usable `imageUrls`: steps that succeeded before
|
|
321
|
+
the failing one stay charged.
|
|
322
|
+
- A refused body carries `snapshot.errorCode`: `workflow_step_denied` (a platform-internal
|
|
323
|
+
`$type`), `workflow_ref_invalid` (a reference to the step itself, a later step, or nothing, or a
|
|
324
|
+
step name that breaks the naming rules, or a malformed `repeat`/`merge`),
|
|
325
|
+
`workflow_repeat_unbounded` (a `repeat` not over an array in `arguments`, or over 16 iterations,
|
|
326
|
+
or a `repeat` with no price quote) or `workflow_too_many_steps`. The single-step pass-through arm refuses `repeat` outright.
|
|
327
|
+
- Requires a host that knows the kind; an older host refuses the body.
|
|
328
|
+
|
|
224
329
|
### `defineBlock` validator rules
|
|
225
330
|
|
|
226
331
|
**There is no rule list here, and that is the point.** `defineBlock` does not
|
package/dist/blocks/index.d.ts
CHANGED
|
@@ -109,7 +109,14 @@ export { isModelSlotContext, isPageSlotContext } from './types.js';
|
|
|
109
109
|
* in `types.ts` for which of the two it uses and why.
|
|
110
110
|
*/
|
|
111
111
|
export { isSignedIn } from './types.js';
|
|
112
|
-
export type { BlockContext, KnownSlotId, ModelSlotId, PageSlotContext, PageSlotId, UnknownSlotContext, BlockAnalyticsDeclaration, BlockAnalyticsEventDeclaration, BlockAnalyticsPropertyDeclaration, BlockManifest, BlockManifestGood, BlockManifestV1, BlockSettings, BlockToken, ContentRating, ManifestBooleanField, ManifestIframe, ManifestNumberField, ManifestPage, ManifestPreview, ManifestSettingField, ManifestSettings, ManifestStringField, ManifestTarget, ModelSlotContext, SettingScope, SettingWidget, Theme, ViewerInfo, BlockCheckpointInfo, BlockResourceInfo, BlockResourcePickerType, BlockSourceImage, BlockUploadedImageInfo, BlockGenerationSourceImageInfo, BlockPendingImageInfo, BlockImageScanResult, BlockUploadPurpose, BlockNavigateScope, BlockTextToImageParams, BlockWorkflowSnapshot, BlockEstimateBatchAggregate, BlockModelSubstitution, ModelSubstitutionReason, KnownBlockWorkflowErrorCode, BlockStepToolCall, BlockTrainedEpoch, BlockPublishedModel, BuzzAccountType, ShowcaseImage, WorkflowBody, WorkflowBodyTextToImage, WorkflowBodyCustomComfy, WorkflowBodyCustomComfyRecipe, WorkflowBodyCustomComfyInline, InlineComfyNode, WorkflowBodyStep, WorkflowBodyPassThroughStep, WorkflowStatus, BlockBuzzTransaction, BlockBuzzAccount, BlockDailyCompensationResource, BlockViewer, BlockWildcardPack, BlockWildcardPackErrorCode, AppWorkflow, AppWorkflowImage, BlockGatedImage, BlockCollectionFollowErrorCode, BlockCollectionFollowResult, BlockPostSource, BlockCreatePostRequest, BlockCreatePostResult, BlockCreatePostHostError, WorkflowBodyTraining, AiToolkitTrainingParams, AiToolkitTrainingParamsBase, AiToolkitPlainEcosystem, AiToolkitLrScheduler, AiToolkitOptimizerType, BlockTrainingQuote, BlockTrainingDatasetItem, BlockTrainingDatasetResult, BlockTrainingRejectionReason, BlockPrepareTrainingDatasetHostError, BlockRunTrainingHostError, } from './types.js';
|
|
112
|
+
export type { BlockContext, KnownSlotId, ModelSlotId, PageSlotContext, PageSlotId, UnknownSlotContext, BlockAnalyticsDeclaration, BlockAnalyticsEventDeclaration, BlockAnalyticsPropertyDeclaration, BlockManifest, BlockManifestGood, BlockManifestV1, BlockSettings, BlockToken, ContentRating, ManifestBooleanField, ManifestIframe, ManifestNumberField, ManifestPage, ManifestPreview, ManifestSettingField, ManifestSettings, ManifestStringField, ManifestTarget, ModelSlotContext, SettingScope, SettingWidget, Theme, ViewerInfo, BlockCheckpointInfo, BlockResourceInfo, BlockResourcePickerType, BlockSourceImage, BlockUploadedImageInfo, BlockGenerationSourceImageInfo, BlockPendingImageInfo, BlockImageScanResult, BlockUploadPurpose, BlockNavigateScope, BlockTextToImageParams, BlockWorkflowSnapshot, BlockEstimateBatchAggregate, BlockModelSubstitution, ModelSubstitutionReason, KnownBlockWorkflowErrorCode, BlockStepToolCall, BlockTrainedEpoch, BlockPublishedModel, BuzzAccountType, ShowcaseImage, WorkflowBody, WorkflowBodyTextToImage, WorkflowBodyCustomComfy, WorkflowBodyCustomComfyRecipe, WorkflowBodyCustomComfyInline, InlineComfyNode, WorkflowBodyStep, WorkflowBodyPassThroughStep, WorkflowBodyWorkflow, WorkflowBodyWorkflowStep, WorkflowStepRef, WithWorkflowStepRefs, BlockWorkflowStepSnapshot, WorkflowStatus, BlockBuzzTransaction, BlockBuzzAccount, BlockDailyCompensationResource, BlockViewer, BlockWildcardPack, BlockWildcardPackErrorCode, AppWorkflow, AppWorkflowImage, BlockGatedImage, BlockCollectionFollowErrorCode, BlockCollectionFollowResult, BlockPostSource, BlockCreatePostRequest, BlockCreatePostResult, BlockCreatePostHostError, WorkflowBodyTraining, AiToolkitTrainingParams, AiToolkitTrainingParamsBase, AiToolkitPlainEcosystem, AiToolkitLrScheduler, AiToolkitOptimizerType, BlockTrainingQuote, BlockTrainingDatasetItem, BlockTrainingDatasetResult, BlockTrainingRejectionReason, BlockPrepareTrainingDatasetHostError, BlockRunTrainingHostError, BlockStepQuote, BlockModel3dOutput, BlockRunConfirmedStepHostError, } from './types.js';
|
|
113
|
+
/** Host bound for the App Blocks `kind: 'workflow'` body — see `WorkflowBodyWorkflow`. */
|
|
114
|
+
export { BLOCK_WORKFLOW_MAX_STEPS, BLOCK_WORKFLOW_REPEAT_MAX_ITERATIONS } from './types.js';
|
|
115
|
+
/**
|
|
116
|
+
* Host bounds for a viewer-confirmed pass-through step, mirrored from
|
|
117
|
+
* civitai/civitai — see `BlockWorkflowSnapshot.stepQuote`.
|
|
118
|
+
*/
|
|
119
|
+
export { BLOCK_CONFIRMED_STEP_MAX_BUZZ_PER_JOB, BLOCK_STEP_QUOTE_ID_REGEX } from './types.js';
|
|
113
120
|
/**
|
|
114
121
|
* Host bounds for the App Blocks `kind: 'training'` flow, mirrored from
|
|
115
122
|
* civitai/civitai's zod — see `WorkflowBodyTraining`.
|
package/dist/blocks/index.js
CHANGED
|
@@ -108,6 +108,13 @@ export { isModelSlotContext, isPageSlotContext } from './types.js';
|
|
|
108
108
|
* in `types.ts` for which of the two it uses and why.
|
|
109
109
|
*/
|
|
110
110
|
export { isSignedIn } from './types.js';
|
|
111
|
+
/** Host bound for the App Blocks `kind: 'workflow'` body — see `WorkflowBodyWorkflow`. */
|
|
112
|
+
export { BLOCK_WORKFLOW_MAX_STEPS, BLOCK_WORKFLOW_REPEAT_MAX_ITERATIONS } from './types.js';
|
|
113
|
+
/**
|
|
114
|
+
* Host bounds for a viewer-confirmed pass-through step, mirrored from
|
|
115
|
+
* civitai/civitai — see `BlockWorkflowSnapshot.stepQuote`.
|
|
116
|
+
*/
|
|
117
|
+
export { BLOCK_CONFIRMED_STEP_MAX_BUZZ_PER_JOB, BLOCK_STEP_QUOTE_ID_REGEX } from './types.js';
|
|
111
118
|
/**
|
|
112
119
|
* Host bounds for the App Blocks `kind: 'training'` flow, mirrored from
|
|
113
120
|
* civitai/civitai's zod — see `WorkflowBodyTraining`.
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Wire format: `window.postMessage({ type, payload }, targetOrigin)`.
|
|
9
9
|
*/
|
|
10
10
|
import type { ColorDomain } from './browsingLevel.js';
|
|
11
|
-
import type { BlockCheckpointInfo, BlockResourceInfo, BlockResourcePickerType, BlockUploadedImageInfo, BlockGenerationSourceImageInfo, BlockPendingImageInfo, BlockImageScanResult, BlockUploadPurpose, BlockNavigateScope, BlockContext, BlockSettings, Theme, ViewerInfo, WorkflowBody, BlockWorkflowSnapshot, BlockEstimateBatchAggregate, BlockBuzzTransaction, BlockBuzzAccount, BlockDailyCompensationResource, BlockViewer, BlockWildcardPack, BlockWildcardPackErrorCode, AppWorkflow, BlockGatedImage, BlockCollectionFollowErrorCode, BlockCollectionFollowResult, BlockPostSource, BlockCreatePostResult, BlockTrainingDatasetItem, BlockTrainingDatasetResult, WorkflowBodyTraining } from './types.js';
|
|
11
|
+
import type { BlockCheckpointInfo, BlockResourceInfo, BlockResourcePickerType, BlockUploadedImageInfo, BlockGenerationSourceImageInfo, BlockPendingImageInfo, BlockImageScanResult, BlockUploadPurpose, BlockNavigateScope, BlockContext, BlockSettings, Theme, ViewerInfo, WorkflowBody, BlockWorkflowSnapshot, BlockEstimateBatchAggregate, BlockBuzzTransaction, BlockBuzzAccount, BlockDailyCompensationResource, BlockViewer, BlockWildcardPack, BlockWildcardPackErrorCode, AppWorkflow, BlockGatedImage, BlockCollectionFollowErrorCode, BlockCollectionFollowResult, BlockPostSource, BlockCreatePostResult, BlockTrainingDatasetItem, BlockTrainingDatasetResult, WorkflowBodyTraining, WorkflowBodyPassThroughStep } from './types.js';
|
|
12
12
|
/**
|
|
13
13
|
* Filter params for `GET_BUZZ_TRANSACTIONS`. All optional; the host validates
|
|
14
14
|
* them server-side (they are NEVER trusted for auth — the account is self-bound
|
|
@@ -508,6 +508,13 @@ export type ParentToBlockMessage = {
|
|
|
508
508
|
snapshot?: BlockWorkflowSnapshot;
|
|
509
509
|
error?: string;
|
|
510
510
|
};
|
|
511
|
+
} | {
|
|
512
|
+
type: 'CONFIRMED_STEP_RESULT';
|
|
513
|
+
payload: {
|
|
514
|
+
requestId: string;
|
|
515
|
+
snapshot?: BlockWorkflowSnapshot;
|
|
516
|
+
error?: string;
|
|
517
|
+
};
|
|
511
518
|
} | {
|
|
512
519
|
type: 'IMAGES_RESULT';
|
|
513
520
|
payload: {
|
|
@@ -846,6 +853,12 @@ export type BlockToParentMessage = {
|
|
|
846
853
|
requestId: string;
|
|
847
854
|
body: WorkflowBodyTraining;
|
|
848
855
|
};
|
|
856
|
+
} | {
|
|
857
|
+
type: 'RUN_CONFIRMED_STEP';
|
|
858
|
+
payload: {
|
|
859
|
+
requestId: string;
|
|
860
|
+
body: WorkflowBodyPassThroughStep;
|
|
861
|
+
};
|
|
849
862
|
} | {
|
|
850
863
|
type: 'GET_IMAGES_BY_IDS';
|
|
851
864
|
payload: {
|
|
@@ -1093,7 +1106,7 @@ export type BlockToParentMessageType = BlockToParentMessage['type'];
|
|
|
1093
1106
|
* it is a measurement, not an invariant, and civitai's own compile-time gate
|
|
1094
1107
|
* (published SDK union ⊆ `keyof INVENTORY`) is what holds one direction of it.
|
|
1095
1108
|
*/
|
|
1096
|
-
export declare const BLOCK_TO_PARENT_MESSAGE_TYPES: readonly ["BLOCK_HELLO", "BLOCK_READY", "BLOCK_ERROR", "BLOCK_MESSAGE_REJECTED", "REQUEST_TOKEN", "RESIZE_IFRAME", "SUBMIT_WORKFLOW", "ESTIMATE_WORKFLOW", "ESTIMATE_WORKFLOW_BATCH", "POLL_WORKFLOW", "CANCEL_WORKFLOW", "OPEN_BUZZ_PURCHASE", "GET_BUZZ_BALANCE", "GET_VIEWER", "GET_BUZZ_TRANSACTIONS", "GET_BUZZ_ACCOUNTS", "GET_DAILY_COMPENSATION", "GET_WILDCARD_PACK", "QUERY_APP_WORKFLOWS", "PUBLISH_GENERATION_OUTPUTS", "CREATE_POST_FROM_APP", "PREPARE_TRAINING_DATASET", "RUN_TRAINING", "GET_IMAGES_BY_IDS", "CANCEL_APP_WORKFLOW", "OPEN_CHECKPOINT_PICKER", "OPEN_RESOURCE_PICKER", "OPEN_IMAGE_UPLOAD", "SET_USER_CHECKPOINT", "NAVIGATE", "REQUEST_SIGN_IN", "REQUEST_CONSENT", "TRACK_EVENT", "APP_STORAGE_GET", "APP_STORAGE_SET", "APP_STORAGE_DELETE", "APP_STORAGE_LIST", "APP_STORAGE_QUOTA", "SHARED_LIST", "SHARED_GET_COUNT", "SHARED_GET_COUNTS", "SHARED_APPEND", "SHARED_VOTE", "SHARED_UNVOTE", "SHARED_WITHDRAW", "SHARED_UPDATE", "SHARED_GET", "SHARED_REPORT", "SAVE_IMAGE", "SET_COLLECTION_FOLLOW"];
|
|
1109
|
+
export declare const BLOCK_TO_PARENT_MESSAGE_TYPES: readonly ["BLOCK_HELLO", "BLOCK_READY", "BLOCK_ERROR", "BLOCK_MESSAGE_REJECTED", "REQUEST_TOKEN", "RESIZE_IFRAME", "SUBMIT_WORKFLOW", "ESTIMATE_WORKFLOW", "ESTIMATE_WORKFLOW_BATCH", "POLL_WORKFLOW", "CANCEL_WORKFLOW", "OPEN_BUZZ_PURCHASE", "GET_BUZZ_BALANCE", "GET_VIEWER", "GET_BUZZ_TRANSACTIONS", "GET_BUZZ_ACCOUNTS", "GET_DAILY_COMPENSATION", "GET_WILDCARD_PACK", "QUERY_APP_WORKFLOWS", "PUBLISH_GENERATION_OUTPUTS", "CREATE_POST_FROM_APP", "PREPARE_TRAINING_DATASET", "RUN_TRAINING", "RUN_CONFIRMED_STEP", "GET_IMAGES_BY_IDS", "CANCEL_APP_WORKFLOW", "OPEN_CHECKPOINT_PICKER", "OPEN_RESOURCE_PICKER", "OPEN_IMAGE_UPLOAD", "SET_USER_CHECKPOINT", "NAVIGATE", "REQUEST_SIGN_IN", "REQUEST_CONSENT", "TRACK_EVENT", "APP_STORAGE_GET", "APP_STORAGE_SET", "APP_STORAGE_DELETE", "APP_STORAGE_LIST", "APP_STORAGE_QUOTA", "SHARED_LIST", "SHARED_GET_COUNT", "SHARED_GET_COUNTS", "SHARED_APPEND", "SHARED_VOTE", "SHARED_UNVOTE", "SHARED_WITHDRAW", "SHARED_UPDATE", "SHARED_GET", "SHARED_REPORT", "SAVE_IMAGE", "SET_COLLECTION_FOLLOW"];
|
|
1097
1110
|
/**
|
|
1098
1111
|
* The bucket a message type falls into when the protocol does not declare it.
|
|
1099
1112
|
*
|
package/dist/blocks/messages.js
CHANGED
package/dist/blocks/types.d.ts
CHANGED
|
@@ -1168,6 +1168,9 @@ export type WorkflowBodyStep = {
|
|
|
1168
1168
|
* checkpoint itself.
|
|
1169
1169
|
* - `$type` is bounded to **1…64 characters** and `input` to **262144 bytes**
|
|
1170
1170
|
* (256 KB) serialized. Both REJECT; neither truncates.
|
|
1171
|
+
* - **`repeat` is refused on this arm**, outright: a `repeat` may only
|
|
1172
|
+
* iterate an array in a body's own `arguments`, and this arm has none. Use
|
|
1173
|
+
* a `kind: 'workflow'` body ({@link WorkflowBodyWorkflow}) to repeat a step.
|
|
1171
1174
|
* - `maxBuzz` is the app's spend knob, and the host's quote can raise the
|
|
1172
1175
|
* reservation above it — see its own note below.
|
|
1173
1176
|
*
|
|
@@ -1248,6 +1251,237 @@ export type WorkflowBodyPassThroughStep = {
|
|
|
1248
1251
|
* viewer as a maximum.
|
|
1249
1252
|
*/
|
|
1250
1253
|
maxBuzz: number;
|
|
1254
|
+
/**
|
|
1255
|
+
* The viewer-confirmable quote this job is charged against —
|
|
1256
|
+
* {@link BlockStepQuote.quoteId} from this body's own estimate
|
|
1257
|
+
* (`sq_` + 32 lowercase hex characters, {@link BLOCK_STEP_QUOTE_ID_REGEX}).
|
|
1258
|
+
*
|
|
1259
|
+
* OMIT it everywhere except a CONFIRMED run: an estimate never carries it,
|
|
1260
|
+
* and neither does an ordinary submit. It is REQUIRED on
|
|
1261
|
+
* `RUN_CONFIRMED_STEP` (`useRunConfirmedStep()` in `@civitai/blocks-react`),
|
|
1262
|
+
* the only message that can run a job priced above the token's per-call
|
|
1263
|
+
* budget — see {@link BlockWorkflowSnapshot.stepQuote} for the flow.
|
|
1264
|
+
*
|
|
1265
|
+
* 🔴 A body carrying it is NOT runnable through `SUBMIT_WORKFLOW`. The server
|
|
1266
|
+
* charges a confirmed job only against a quote the viewer confirmed in
|
|
1267
|
+
* Civitai's own dialog from a signed-in session, so the same body sent as a
|
|
1268
|
+
* plain submit is refused. Change nothing else in the body between the
|
|
1269
|
+
* estimate and the run: the server checks it against the quoted one
|
|
1270
|
+
* (`quoteId` itself is excluded from that comparison).
|
|
1271
|
+
*/
|
|
1272
|
+
quoteId?: string;
|
|
1273
|
+
};
|
|
1274
|
+
/**
|
|
1275
|
+
* Ceiling on what ONE viewer-confirmed pass-through job may cost, in Buzz. Host
|
|
1276
|
+
* constant `BLOCK_CONFIRMED_STEP_MAX_BUZZ_PER_JOB`. A fixed price above it gets
|
|
1277
|
+
* no {@link BlockWorkflowSnapshot.stepQuote} and cannot be run from an app.
|
|
1278
|
+
*/
|
|
1279
|
+
export declare const BLOCK_CONFIRMED_STEP_MAX_BUZZ_PER_JOB = 5000;
|
|
1280
|
+
/**
|
|
1281
|
+
* The shape of a confirmed-step quote id ({@link BlockStepQuote.quoteId}): `sq_`
|
|
1282
|
+
* followed by 32 lowercase hex characters. Host constant
|
|
1283
|
+
* `BLOCK_STEP_QUOTE_ID_REGEX`. Disjoint from the training quote's `tq_` shape,
|
|
1284
|
+
* so neither kind's id can name the other's quote.
|
|
1285
|
+
*/
|
|
1286
|
+
export declare const BLOCK_STEP_QUOTE_ID_REGEX: RegExp;
|
|
1287
|
+
/**
|
|
1288
|
+
* The most steps one `kind: 'workflow'` body may carry. The host refuses a
|
|
1289
|
+
* longer list with `errorCode: 'workflow_too_many_steps'`; an empty list is
|
|
1290
|
+
* refused too.
|
|
1291
|
+
*/
|
|
1292
|
+
export declare const BLOCK_WORKFLOW_MAX_STEPS = 8;
|
|
1293
|
+
/**
|
|
1294
|
+
* The most times one top-level `repeat` step of a `kind: 'workflow'` body may
|
|
1295
|
+
* run its template, NESTED REPEATS MULTIPLIED (a 4-item repeat inside a 4-item
|
|
1296
|
+
* repeat is 16). The host refuses more with
|
|
1297
|
+
* `errorCode: 'workflow_repeat_unbounded'`.
|
|
1298
|
+
*/
|
|
1299
|
+
export declare const BLOCK_WORKFLOW_REPEAT_MAX_ITERATIONS = 16;
|
|
1300
|
+
/**
|
|
1301
|
+
* A REFERENCE inside a `kind: 'workflow'` step's `input` — the orchestrator's
|
|
1302
|
+
* own mechanism for feeding one step's result into a later step. Put it
|
|
1303
|
+
* anywhere a value would go, at any depth.
|
|
1304
|
+
*
|
|
1305
|
+
* `$ref` names where the value comes from:
|
|
1306
|
+
* - `'$arguments'` — the body's own {@link WorkflowBodyWorkflow.arguments};
|
|
1307
|
+
* - the `name` of an EARLIER step in the same body;
|
|
1308
|
+
* - `'$<index>'` — an EARLIER step you did NOT name, by its zero-based
|
|
1309
|
+
* position (`'$0'` is the first step). A step that has a `name` is
|
|
1310
|
+
* referenced by that name only.
|
|
1311
|
+
*
|
|
1312
|
+
* An object counts as a reference only when it has BOTH `$ref` and `path` and
|
|
1313
|
+
* no key other than `default` / `format`; anything else is ordinary input.
|
|
1314
|
+
*
|
|
1315
|
+
* `path` selects the value inside that source, e.g. `'output.images[0].url'`
|
|
1316
|
+
* for a step, or `'prompt'` for `$arguments`. The orchestrator resolves it; the
|
|
1317
|
+
* path is not checked by this package or by the host.
|
|
1318
|
+
*
|
|
1319
|
+
* 🔴 A reference may only point BACKWARDS. A step that names itself, a later
|
|
1320
|
+
* step, or a step that does not exist is refused by the host with
|
|
1321
|
+
* `errorCode: 'workflow_ref_invalid'` before anything is priced or reserved.
|
|
1322
|
+
* A body may hold at most 64 references, in inputs nested at most 32 levels.
|
|
1323
|
+
*
|
|
1324
|
+
* `default` is the value used when the path resolves to nothing; `format` is a
|
|
1325
|
+
* template applied to the resolved value. Both are passed to the orchestrator
|
|
1326
|
+
* unmodified.
|
|
1327
|
+
*/
|
|
1328
|
+
export type WorkflowStepRef = {
|
|
1329
|
+
$ref: '$arguments' | `$${number}` | (string & {});
|
|
1330
|
+
path: string;
|
|
1331
|
+
default?: unknown;
|
|
1332
|
+
format?: string;
|
|
1333
|
+
};
|
|
1334
|
+
/**
|
|
1335
|
+
* `T` with a {@link WorkflowStepRef} allowed in place of any value, at any
|
|
1336
|
+
* depth. Use it to keep a step input typed while still wiring references in:
|
|
1337
|
+
*
|
|
1338
|
+
* ```ts
|
|
1339
|
+
* type CutoutInput = { image: string; format?: 'png' | 'webp' };
|
|
1340
|
+
* const input: WithWorkflowStepRefs<CutoutInput> = {
|
|
1341
|
+
* image: { $ref: 'draw', path: 'output.images[0].url' },
|
|
1342
|
+
* format: 'png',
|
|
1343
|
+
* };
|
|
1344
|
+
* ```
|
|
1345
|
+
*/
|
|
1346
|
+
export type WithWorkflowStepRefs<T> = WorkflowStepRef | (T extends ReadonlyArray<infer U> ? Array<WithWorkflowStepRefs<U>> : T extends object ? {
|
|
1347
|
+
[K in keyof T]: WithWorkflowStepRefs<T[K]>;
|
|
1348
|
+
} : T);
|
|
1349
|
+
/** One step of a {@link WorkflowBodyWorkflow}. */
|
|
1350
|
+
export type WorkflowBodyWorkflowStep = {
|
|
1351
|
+
/**
|
|
1352
|
+
* What later steps call this one in a {@link WorkflowStepRef}, and the `name`
|
|
1353
|
+
* it reports under on {@link BlockWorkflowSnapshot.steps}. Optional: an
|
|
1354
|
+
* unnamed step is named by its position (`'$0'`, `'$1'`, …).
|
|
1355
|
+
*
|
|
1356
|
+
* A lowercase letter followed by up to 31 of `a-z`, `0-9`, `_` or `-`
|
|
1357
|
+
* (`/^[a-z][a-z0-9_-]{0,31}$/`), unique within the body, and not
|
|
1358
|
+
* `'block-step'`, which is reserved. A name that breaks a rule is refused
|
|
1359
|
+
* with `errorCode: 'workflow_ref_invalid'`.
|
|
1360
|
+
*/
|
|
1361
|
+
name?: string;
|
|
1362
|
+
/**
|
|
1363
|
+
* The ORCHESTRATOR step type to run, verbatim — e.g. `'imageGen'`. Not
|
|
1364
|
+
* resolved against any allowlist: it is refused only when it names a
|
|
1365
|
+
* platform-internal type (scanners, moderation classifiers, hashing, web
|
|
1366
|
+
* scrape/search, and the retired `textToImage` step type), with
|
|
1367
|
+
* `errorCode: 'workflow_step_denied'`. 1…64 characters.
|
|
1368
|
+
*
|
|
1369
|
+
* Two step types are read by shape, because they name their sources outside
|
|
1370
|
+
* a {@link WorkflowStepRef}:
|
|
1371
|
+
* - **`repeat` — over `arguments` only, at most
|
|
1372
|
+
* {@link BLOCK_WORKFLOW_REPEAT_MAX_ITERATIONS} iterations.** Its input must
|
|
1373
|
+
* be exactly `{ for: { $ref, path, as }, template: { $type, name?, input? } }`
|
|
1374
|
+
* with `for.$ref === '$arguments'` and `path` naming an ARRAY in the body's
|
|
1375
|
+
* `arguments`; its length is the iteration count, nested repeats
|
|
1376
|
+
* multiplied. A repeat over another step's output, a missing or non-array
|
|
1377
|
+
* path, or too many iterations is refused with
|
|
1378
|
+
* `errorCode: 'workflow_repeat_unbounded'`; a wrong shape, or repeats nested
|
|
1379
|
+
* more than 4 deep, with `workflow_ref_invalid`. Inside the template the
|
|
1380
|
+
* `as` name is a source a reference may name; it may not equal a step name.
|
|
1381
|
+
* The template's `$type` is held to the denylist too.
|
|
1382
|
+
* - **`merge`** — every entry of `input.fields` needs a string `$ref` and a
|
|
1383
|
+
* `reduce`, and each `$ref` must name `$arguments` or an EARLIER step,
|
|
1384
|
+
* never a repeat variable. Each counts toward the 64-reference cap.
|
|
1385
|
+
* Otherwise `workflow_ref_invalid`.
|
|
1386
|
+
*/
|
|
1387
|
+
$type: string;
|
|
1388
|
+
/**
|
|
1389
|
+
* The step's own input object. Any value in it, at any depth, may be a
|
|
1390
|
+
* {@link WorkflowStepRef}. The orchestrator's per-`$type` schema is the only
|
|
1391
|
+
* authority for what a given `$type` accepts. Every step's `input` plus the
|
|
1392
|
+
* body's `arguments` may total at most 262144 bytes (256 KB) serialized.
|
|
1393
|
+
*/
|
|
1394
|
+
input: Record<string, unknown>;
|
|
1395
|
+
/**
|
|
1396
|
+
* `true` marks an INTERMEDIATE step: its blobs are not surfaced, neither on
|
|
1397
|
+
* its own {@link BlockWorkflowStepSnapshot.imageUrls} nor in the top-level
|
|
1398
|
+
* {@link BlockWorkflowSnapshot.imageUrls}. The step still runs and is still
|
|
1399
|
+
* charged.
|
|
1400
|
+
*/
|
|
1401
|
+
suppressOutput?: boolean;
|
|
1402
|
+
};
|
|
1403
|
+
/**
|
|
1404
|
+
* The `workflow` member of {@link WorkflowBody} — SEVERAL orchestrator steps
|
|
1405
|
+
* submitted as ONE workflow, where a later step can consume an earlier step's
|
|
1406
|
+
* result through a {@link WorkflowStepRef}. It travels through the same
|
|
1407
|
+
* messages and hooks as every other kind (`estimate`, `submit`, `watch`,
|
|
1408
|
+
* `cancel`, a batch-estimate cell, `useWorkflowBatch`).
|
|
1409
|
+
*
|
|
1410
|
+
* Between 1 and {@link BLOCK_WORKFLOW_MAX_STEPS} steps. There is no `maxBuzz`:
|
|
1411
|
+
* the spend ceiling is the app's per-generation budget × the number of steps,
|
|
1412
|
+
* enforced by the host. The host's schema is strict: an unknown key on the
|
|
1413
|
+
* body or on a step is rejected, not dropped.
|
|
1414
|
+
*
|
|
1415
|
+
* 🔴 THREE THINGS ABOUT THE PRICE, all of them different from a single-step
|
|
1416
|
+
* body:
|
|
1417
|
+
* 1. **The estimate is NOT a maximum.** When a step's input references an
|
|
1418
|
+
* earlier step, the orchestrator re-prices that step once the referenced
|
|
1419
|
+
* values are known and charges the difference. Show the estimate as an
|
|
1420
|
+
* estimate; never as "you will pay at most".
|
|
1421
|
+
* 2. **A workflow the host cannot price has no estimate, but its submit still
|
|
1422
|
+
* proceeds.** `estimate()` (and that body's cell in a batch estimate) FAILS
|
|
1423
|
+
* with no `cost` and `errorCode` `'workflow_quote_rejected'`,
|
|
1424
|
+
* `'workflow_quote_unavailable'` or `'workflow_quote_unpriced'` — see
|
|
1425
|
+
* {@link BlockWorkflowSnapshot.errorCode} for which of them a retry can
|
|
1426
|
+
* clear. `submit()` of the same body is NOT refused: it is reserved at the
|
|
1427
|
+
* ceiling above instead of at a quote. So a failed estimate does not predict
|
|
1428
|
+
* a refused submit. Two exceptions are refused on BOTH, before any
|
|
1429
|
+
* reservation: a workflow containing a training step, exactly as on the
|
|
1430
|
+
* single-step arm (a `training-quote-*` `errorCode`), and one with a
|
|
1431
|
+
* `repeat` step at any depth (`errorCode: 'workflow_repeat_unbounded'`).
|
|
1432
|
+
* Their `error` states the cause; only "none could be obtained; try again"
|
|
1433
|
+
* is one a retry of the same body can clear.
|
|
1434
|
+
* (An OLDER host returns the ceiling as the estimate's `cost.total` instead
|
|
1435
|
+
* of failing, so there a total equal to the ceiling may be unpriced.)
|
|
1436
|
+
* 3. **One author fee per workflow**, not one per step, computed on the
|
|
1437
|
+
* QUOTED base. The estimate's `cost.authorFee` is that single fee, already
|
|
1438
|
+
* inside `cost.total`. If the workflow bills more than the quote, the fee
|
|
1439
|
+
* charged is held to the fee shown. A workflow that does not succeed has
|
|
1440
|
+
* its WHOLE fee reversed, even when earlier steps delivered output.
|
|
1441
|
+
*
|
|
1442
|
+
* The app's velocity limit counts one unit per step, and a `repeat` step one
|
|
1443
|
+
* per iteration (nested repeats multiplied) instead of one.
|
|
1444
|
+
*
|
|
1445
|
+
* 🔴 A FAILED WORKFLOW CAN STILL HAVE COST AND IMAGES. Steps that succeeded
|
|
1446
|
+
* before the failing one stay charged, so a `failed` snapshot can carry
|
|
1447
|
+
* `cost.total > 0` and usable `imageUrls`. See {@link BlockWorkflowSnapshot.steps}.
|
|
1448
|
+
*
|
|
1449
|
+
* 🔴 REQUIRES A HOST THAT KNOWS THIS KIND. An older host refuses the body.
|
|
1450
|
+
*
|
|
1451
|
+
* @example An image step whose output a second step consumes.
|
|
1452
|
+
* ```ts
|
|
1453
|
+
* const body: WorkflowBody = {
|
|
1454
|
+
* kind: 'workflow',
|
|
1455
|
+
* arguments: { prompt: 'a lighthouse at dusk' },
|
|
1456
|
+
* steps: [
|
|
1457
|
+
* {
|
|
1458
|
+
* name: 'draw',
|
|
1459
|
+
* $type: 'imageGen',
|
|
1460
|
+
* input: {
|
|
1461
|
+
* engine: 'google',
|
|
1462
|
+
* model: 'nano-banana-2',
|
|
1463
|
+
* prompt: { $ref: '$arguments', path: 'prompt' },
|
|
1464
|
+
* },
|
|
1465
|
+
* suppressOutput: true,
|
|
1466
|
+
* },
|
|
1467
|
+
* {
|
|
1468
|
+
* name: 'cutout',
|
|
1469
|
+
* $type: 'imageBackgroundRemoval',
|
|
1470
|
+
* input: { image: { $ref: 'draw', path: 'output.images[0].url' } },
|
|
1471
|
+
* },
|
|
1472
|
+
* ],
|
|
1473
|
+
* };
|
|
1474
|
+
* ```
|
|
1475
|
+
*/
|
|
1476
|
+
export type WorkflowBodyWorkflow = {
|
|
1477
|
+
kind: 'workflow';
|
|
1478
|
+
/** The steps, in order. 1…{@link BLOCK_WORKFLOW_MAX_STEPS}. */
|
|
1479
|
+
steps: WorkflowBodyWorkflowStep[];
|
|
1480
|
+
/**
|
|
1481
|
+
* Values the steps can read through `{ $ref: '$arguments', path }` — one
|
|
1482
|
+
* place to put a prompt or a seed that several steps share.
|
|
1483
|
+
*/
|
|
1484
|
+
arguments?: Record<string, unknown>;
|
|
1251
1485
|
};
|
|
1252
1486
|
/** Ceiling on what ONE confirmed `kind: 'training'` run may cost, in Buzz. Host constant `BLOCK_TRAINING_MAX_BUZZ_PER_RUN`. */
|
|
1253
1487
|
export declare const BLOCK_TRAINING_MAX_BUZZ_PER_RUN = 5000;
|
|
@@ -1431,6 +1665,10 @@ export interface WorkflowBodyTraining {
|
|
|
1431
1665
|
* on a server-prepared dataset of the viewer's own images. ESTIMATE ONLY
|
|
1432
1666
|
* through `useBuzzWorkflow`; it runs through `useRunTraining()`, whose
|
|
1433
1667
|
* host-chrome consent dialog is the only way to confirm its quote.
|
|
1668
|
+
* - {@link WorkflowBodyWorkflow} (`kind: 'workflow'`) — up to
|
|
1669
|
+
* {@link BLOCK_WORKFLOW_MAX_STEPS} orchestrator steps submitted as one
|
|
1670
|
+
* workflow, a later step consuming an earlier one's result through a
|
|
1671
|
+
* {@link WorkflowStepRef}. Its estimate is not a maximum — read its doc.
|
|
1434
1672
|
*
|
|
1435
1673
|
* `kind: 'step'` is therefore itself a union, discriminated on the PRESENCE of
|
|
1436
1674
|
* `step` — the same nesting {@link WorkflowBodyCustomComfy} has on `mode`.
|
|
@@ -1447,7 +1685,7 @@ export interface WorkflowBodyTraining {
|
|
|
1447
1685
|
* over `kind`. Host code that must handle every member gets a compile error
|
|
1448
1686
|
* pointing at the new one, which is the intended behaviour.
|
|
1449
1687
|
*/
|
|
1450
|
-
export type WorkflowBody = WorkflowBodyTextToImage | WorkflowBodyCustomComfy | WorkflowBodyStep | WorkflowBodyPassThroughStep | WorkflowBodyTraining;
|
|
1688
|
+
export type WorkflowBody = WorkflowBodyTextToImage | WorkflowBodyCustomComfy | WorkflowBodyStep | WorkflowBodyPassThroughStep | WorkflowBodyTraining | WorkflowBodyWorkflow;
|
|
1451
1689
|
/**
|
|
1452
1690
|
* The host-mediated view of an orchestrator workflow that an iframe block
|
|
1453
1691
|
* receives over `postMessage`.
|
|
@@ -1487,6 +1725,9 @@ export interface BlockWorkflowSnapshot {
|
|
|
1487
1725
|
* orchestrator price quote, which refuses before any fee is looked up; and
|
|
1488
1726
|
* the kinds that price no fee (`customComfy`, pass-through `step`,
|
|
1489
1727
|
* `training`). **Do not read absent as `0`** — show `total` on its own.
|
|
1728
|
+
*
|
|
1729
|
+
* A `kind: 'workflow'` estimate itemises it too, and it is ONE fee for the
|
|
1730
|
+
* whole workflow however many steps it has.
|
|
1490
1731
|
*/
|
|
1491
1732
|
authorFee?: number;
|
|
1492
1733
|
};
|
|
@@ -1500,13 +1741,21 @@ export interface BlockWorkflowSnapshot {
|
|
|
1500
1741
|
*
|
|
1501
1742
|
* WHERE IT APPEARS today: the refusal for a pass-through `step` body
|
|
1502
1743
|
* ({@link WorkflowBodyPassThroughStep}) whose `$type` is a training type
|
|
1503
|
-
* (`'training'` or `'imageResourceTraining'
|
|
1744
|
+
* (`'training'` or `'imageResourceTraining'`, in any casing — the host
|
|
1745
|
+
* compares `$type` case-insensitively) when the host could not get a
|
|
1504
1746
|
* price quote for it. That refusal is `{ workflowId: 'failed', status:
|
|
1505
1747
|
* 'failed', error, errorCode }` with no `cost`, and it is the reply to
|
|
1506
1748
|
* `estimate()` (which rejects with `WorkflowEstimateError`), to `submit()`
|
|
1507
1749
|
* (which rejects with `WorkflowSubmitError`, before anything is reserved or
|
|
1508
1750
|
* charged), and to that body's cell in a batch estimate. Read it from the
|
|
1509
|
-
* error's `.snapshot.errorCode`.
|
|
1751
|
+
* error's `.snapshot.errorCode`. A `kind: 'training'` ESTIMATE does not set
|
|
1752
|
+
* it. The confirmed SUBMIT of a training run or a confirmed step can — see
|
|
1753
|
+
* `'daily-limit-exceeded'` below.
|
|
1754
|
+
* A refused `kind: 'workflow'` body ({@link WorkflowBodyWorkflow}) sets it in
|
|
1755
|
+
* the same shape, on the same three replies — except the three
|
|
1756
|
+
* `workflow_quote_*` codes, which are ESTIMATE-ONLY (`estimate()` and a
|
|
1757
|
+
* batch-estimate cell): `submit()` of the same body defines no such refusal
|
|
1758
|
+
* and proceeds, reserved at the ceiling.
|
|
1510
1759
|
*
|
|
1511
1760
|
* The values the host sends today ({@link KnownBlockWorkflowErrorCode}):
|
|
1512
1761
|
* - `'training-quote-rejected'` — the orchestrator refused the request
|
|
@@ -1515,6 +1764,50 @@ export interface BlockWorkflowSnapshot {
|
|
|
1515
1764
|
* - `'training-quote-unavailable'` — no usable answer (an outage, a timeout,
|
|
1516
1765
|
* a rate limit, insufficient funds, …). Retrying later may succeed.
|
|
1517
1766
|
* - `'training-quote-unpriced'` — the orchestrator answered without a price.
|
|
1767
|
+
* - `'daily-limit-exceeded'` — a viewer-confirmed job (a `kind: 'training'`
|
|
1768
|
+
* run or a confirmed step) would exceed what remains today of the daily
|
|
1769
|
+
* Buzz limit THE VIEWER set for this app. Nothing was charged and no job
|
|
1770
|
+
* was started; the confirm cannot override it, and only the viewer can
|
|
1771
|
+
* raise the limit. This one arrives on the failed snapshot a confirmed
|
|
1772
|
+
* SUBMIT resolves (`{ workflowId: 'failed', status: 'failed', cost, error,
|
|
1773
|
+
* errorCode }`), not on an estimate. On a confirmed step the host also
|
|
1774
|
+
* reports it as the `error` code of `CONFIRMED_STEP_RESULT` — see
|
|
1775
|
+
* {@link BlockRunConfirmedStepHostError}.
|
|
1776
|
+
* - `'workflow_step_denied'` — a step of a `kind: 'workflow'` body names a
|
|
1777
|
+
* platform-internal `$type`. Remove or replace that step.
|
|
1778
|
+
* - `'workflow_ref_invalid'` — a {@link WorkflowStepRef} in a step's `input`
|
|
1779
|
+
* points at the step itself, a later step, or nothing; or a step `name`
|
|
1780
|
+
* breaks the naming rules (see {@link WorkflowBodyWorkflowStep.name}).
|
|
1781
|
+
* `error` names the step by its position.
|
|
1782
|
+
* - `'workflow_too_many_steps'` — more than
|
|
1783
|
+
* {@link BLOCK_WORKFLOW_MAX_STEPS} steps.
|
|
1784
|
+
* - `'workflow_repeat_unbounded'` — a `repeat` step iterates something other
|
|
1785
|
+
* than an array in the body's `arguments`, or more than
|
|
1786
|
+
* {@link BLOCK_WORKFLOW_REPEAT_MAX_ITERATIONS} times, nested repeats
|
|
1787
|
+
* multiplied; or the workflow has a `repeat` and the host has no price
|
|
1788
|
+
* quote for it. `error` then reads `workflow step N: a workflow with a
|
|
1789
|
+
* repeat needs a price quote and <cause>`, where `<cause>` is one of the
|
|
1790
|
+
* three in the `workflow_quote_*` messages below. A retry of the same body
|
|
1791
|
+
* can succeed only when the cause is `none could be obtained; try again`;
|
|
1792
|
+
* otherwise the body is what has to change.
|
|
1793
|
+
* - `'workflow_quote_rejected'` — ESTIMATE only. The orchestrator refused
|
|
1794
|
+
* the body, so there is no price to show; resending the same body will not
|
|
1795
|
+
* help. `error` reads `No price quote for this workflow: the orchestrator
|
|
1796
|
+
* rejected the request: <reason>` when the reason is safe to show, else
|
|
1797
|
+
* `No price quote for this workflow: the orchestrator rejected the request;
|
|
1798
|
+
* check the step inputs and references (retrying the same body will not
|
|
1799
|
+
* help)`.
|
|
1800
|
+
* - `'workflow_quote_unavailable'` — ESTIMATE only. No usable answer (an
|
|
1801
|
+
* outage, a timeout, a rate limit, …). The one `workflow_quote_*` code a
|
|
1802
|
+
* retry of the same body can clear. `error` reads `No price quote for this
|
|
1803
|
+
* workflow: none could be obtained; try again`.
|
|
1804
|
+
* - `'workflow_quote_unpriced'` — ESTIMATE only. The orchestrator answered
|
|
1805
|
+
* without a price. `error` reads `No price quote for this workflow: the
|
|
1806
|
+
* orchestrator answered without one`.
|
|
1807
|
+
*
|
|
1808
|
+
* Each `workflow_quote_*` reply is `{ workflowId: 'failed', status: 'failed',
|
|
1809
|
+
* error, errorCode }` with NO `cost`. A host that predates these codes
|
|
1810
|
+
* resolves the estimate instead, with the spend ceiling as `cost.total`.
|
|
1518
1811
|
*
|
|
1519
1812
|
* 🔴 AN UNKNOWN VALUE IS POSSIBLE: the host may add codes, and the SDK's
|
|
1520
1813
|
* inbound validator accepts any string here. Handle an unrecognised code as a
|
|
@@ -1722,6 +2015,126 @@ export interface BlockWorkflowSnapshot {
|
|
|
1722
2015
|
* that predate civitai/civitai#5434.
|
|
1723
2016
|
*/
|
|
1724
2017
|
trainingQuote?: BlockTrainingQuote;
|
|
2018
|
+
/**
|
|
2019
|
+
* The viewer-confirmable quote a pass-through `step` ESTIMATE
|
|
2020
|
+
* ({@link WorkflowBodyPassThroughStep}) produced, when the job costs more than
|
|
2021
|
+
* the app may spend without asking. Its presence means: this job cannot run
|
|
2022
|
+
* through `submit()`, and CAN run through `useRunConfirmedStep()` once the
|
|
2023
|
+
* viewer confirms `stepQuote.total` in Civitai's own dialog.
|
|
2024
|
+
*
|
|
2025
|
+
* THE FLOW, mirroring a training run's:
|
|
2026
|
+
* 1. `useBuzzWorkflow().estimate(body)` — the reply carries `stepQuote`.
|
|
2027
|
+
* 2. `useRunConfirmedStep().runConfirmedStep({ ...body, quoteId:
|
|
2028
|
+
* stepQuote.quoteId })` — Civitai shows the viewer the price (read back
|
|
2029
|
+
* from the server, never from the body) and submits on their confirm.
|
|
2030
|
+
* 3. `useBuzzWorkflow().watch(snapshot.workflowId)`.
|
|
2031
|
+
*
|
|
2032
|
+
* WHEN THE HOST SENDS IT — all of these, decided server-side:
|
|
2033
|
+
* - the orchestrator quoted a **FIXED** price for exactly this step:
|
|
2034
|
+
* positive, and not a variable or metered one. The viewer confirms what
|
|
2035
|
+
* they are charged, so a price that may move is never confirmable;
|
|
2036
|
+
* - that price is ABOVE the token's per-call budget and at most
|
|
2037
|
+
* {@link BLOCK_CONFIRMED_STEP_MAX_BUZZ_PER_JOB} (5,000 Buzz);
|
|
2038
|
+
* - the block runs in a page app for a signed-in viewer on an ordinary
|
|
2039
|
+
* token. Development, dev-tunnel and review sessions never get one, and
|
|
2040
|
+
* neither does the model slot.
|
|
2041
|
+
* Everywhere else the field is ABSENT and the estimate is exactly what it was.
|
|
2042
|
+
* Absent is therefore not an error — it is also what every host that
|
|
2043
|
+
* predates civitai/civitai#5786 sends.
|
|
2044
|
+
*
|
|
2045
|
+
* 🔴 ONLY A SINGLE ESTIMATE CARRIES IT. A batch estimate
|
|
2046
|
+
* (`ESTIMATE_WORKFLOW_BATCH`, `useBatchEstimate()`) stores nothing, so its
|
|
2047
|
+
* cells never have a `stepQuote`, whatever they cost. Price a grid in a batch,
|
|
2048
|
+
* then estimate the one body you want to run on its own.
|
|
2049
|
+
*
|
|
2050
|
+
* 🔴 TWO BODIES MAKE THAT ESTIMATE FAIL INSTEAD OF RETURNING A PRICE — only
|
|
2051
|
+
* where a quote would otherwise have been granted (so not below the budget,
|
|
2052
|
+
* and not in a batch). The reply is the failure snapshot `{ workflowId:
|
|
2053
|
+
* 'failed', status: 'failed', error }`, which `estimate()` rejects with; the
|
|
2054
|
+
* same text arrives as `CONFIRMED_STEP_RESULT`'s `error` if such a body is
|
|
2055
|
+
* run. Neither has an {@link BlockWorkflowSnapshot.errorCode}; they are
|
|
2056
|
+
* server messages, so match on the text and keep a generic branch:
|
|
2057
|
+
* - `a training step type cannot run as a confirmed step — use
|
|
2058
|
+
* kind:'training'` — `$type` is `training` or `imageResourceTraining`, in
|
|
2059
|
+
* any casing.
|
|
2060
|
+
* Training has its own kind ({@link WorkflowBodyTraining}).
|
|
2061
|
+
* - `a confirmed step needs plain JSON input (objects, arrays, strings,
|
|
2062
|
+
* finite numbers, booleans, null) — <path> is <what>` — `input` holds a
|
|
2063
|
+
* `Date`, `Map`, `Set`, class instance, `BigInt`, `NaN`/`Infinity`, an
|
|
2064
|
+
* `undefined` array element or an empty slot in a sparse array
|
|
2065
|
+
* (`… — body.input.list[1] is an empty array slot`). The quote is bound to the exact body, so the
|
|
2066
|
+
* body must be exactly representable. The part after the dash names the
|
|
2067
|
+
* offending path (`body.input.when is a Date`) and varies: match on the
|
|
2068
|
+
* text BEFORE the dash.
|
|
2069
|
+
*
|
|
2070
|
+
* `total` is the price the viewer confirms and is charged. 🔴 It can differ
|
|
2071
|
+
* from `cost.total` on the same snapshot, which stays what an UNCONFIRMED
|
|
2072
|
+
* submit would reserve (`max(maxBuzz, quote)`); show `stepQuote.total` on a
|
|
2073
|
+
* confirm button. `expiresAt` is an ISO-8601 timestamp 15 minutes out; after
|
|
2074
|
+
* it the run is refused and you estimate again. A quote is single-use.
|
|
2075
|
+
*/
|
|
2076
|
+
stepQuote?: BlockStepQuote;
|
|
2077
|
+
/**
|
|
2078
|
+
* What each 3D model in {@link BlockWorkflowSnapshot.imageUrls} IS — one label
|
|
2079
|
+
* per model a pass-through step produced (e.g. `polyGen`).
|
|
2080
|
+
*
|
|
2081
|
+
* Every model url is still listed in `imageUrls`, unchanged and in the same
|
|
2082
|
+
* order as before the field existed; this only says which entry is which.
|
|
2083
|
+
* Match on `url`:
|
|
2084
|
+
*
|
|
2085
|
+
* ```ts
|
|
2086
|
+
* const glb = snapshot.model3dOutputs?.find(
|
|
2087
|
+
* (m) => m.format === 'glb' && m.variant === 'model',
|
|
2088
|
+
* );
|
|
2089
|
+
* if (glb) viewer.load(glb.url);
|
|
2090
|
+
* ```
|
|
2091
|
+
*
|
|
2092
|
+
* OMITTED when the workflow produced no 3D model, and on hosts that predate
|
|
2093
|
+
* civitai/civitai#5786 — in which case `imageUrls` is all there is.
|
|
2094
|
+
*/
|
|
2095
|
+
model3dOutputs?: BlockModel3dOutput[];
|
|
2096
|
+
/**
|
|
2097
|
+
* The steps of a `kind: 'workflow'` run ({@link WorkflowBodyWorkflow}), in
|
|
2098
|
+
* the orchestrator's order, each with its own status and results. The steps a
|
|
2099
|
+
* `repeat` step generates follow it, named `<repeat name>.<n>`, so the list
|
|
2100
|
+
* can be longer than the body's.
|
|
2101
|
+
*
|
|
2102
|
+
* The top-level fields keep their meaning: `status` is the workflow's,
|
|
2103
|
+
* `imageUrls` is the union of every step that did NOT set `suppressOutput`,
|
|
2104
|
+
* and `cost` is the whole workflow's.
|
|
2105
|
+
*
|
|
2106
|
+
* 🔴 A `failed` WORKFLOW IS NOT AN EMPTY ONE. Steps that succeeded before the
|
|
2107
|
+
* failing step stay charged and keep their results, so a snapshot with
|
|
2108
|
+
* `status: 'failed'` can carry `cost.total > 0` and usable `imageUrls`. Read
|
|
2109
|
+
* `steps` to see which step failed (`status: 'failed'`, with its `error`)
|
|
2110
|
+
* and which finished.
|
|
2111
|
+
*
|
|
2112
|
+
* Read it from the poll and cancel replies of a `kind: 'workflow'` run; do
|
|
2113
|
+
* not rely on it being on the submit reply. ABSENT for every other kind, on
|
|
2114
|
+
* an estimate (which creates no workflow) and on a host that predates it.
|
|
2115
|
+
*/
|
|
2116
|
+
steps?: BlockWorkflowStepSnapshot[];
|
|
2117
|
+
}
|
|
2118
|
+
/** One entry of {@link BlockWorkflowSnapshot.steps}. */
|
|
2119
|
+
export interface BlockWorkflowStepSnapshot {
|
|
2120
|
+
/** The step's `name` from the body, or the name the host gave an unnamed step. */
|
|
2121
|
+
name: string;
|
|
2122
|
+
/** The orchestrator step type that ran. */
|
|
2123
|
+
$type: string;
|
|
2124
|
+
status: 'pending' | 'processing' | 'succeeded' | 'failed' | 'expired' | 'canceled';
|
|
2125
|
+
/**
|
|
2126
|
+
* This step's own image urls. Omitted when it has none, and always omitted
|
|
2127
|
+
* for a step submitted with `suppressOutput: true`.
|
|
2128
|
+
*/
|
|
2129
|
+
imageUrls?: string[];
|
|
2130
|
+
/**
|
|
2131
|
+
* The step's raw orchestrator output, minus its blobs — the same treatment
|
|
2132
|
+
* and the same caveats as {@link BlockWorkflowSnapshot.stepOutputs}: its shape
|
|
2133
|
+
* is whatever the orchestrator returns for that `$type`, and it is UNSCANNED.
|
|
2134
|
+
*/
|
|
2135
|
+
output?: unknown;
|
|
2136
|
+
/** Why this step failed. Diagnostic text; do not render it verbatim. */
|
|
2137
|
+
error?: string;
|
|
1725
2138
|
}
|
|
1726
2139
|
/**
|
|
1727
2140
|
* The run total a BATCH estimate reports beside its per-cell snapshots
|
|
@@ -1755,6 +2168,42 @@ export interface BlockTrainingQuote {
|
|
|
1755
2168
|
/** ISO-8601. The quote cannot be run after this. */
|
|
1756
2169
|
expiresAt: string;
|
|
1757
2170
|
}
|
|
2171
|
+
/** {@link BlockWorkflowSnapshot.stepQuote}. */
|
|
2172
|
+
export interface BlockStepQuote {
|
|
2173
|
+
/**
|
|
2174
|
+
* `sq_` + 32 lowercase hex characters ({@link BLOCK_STEP_QUOTE_ID_REGEX}).
|
|
2175
|
+
* Opaque — pass it back verbatim as the body's `quoteId`.
|
|
2176
|
+
*/
|
|
2177
|
+
quoteId: string;
|
|
2178
|
+
/** The exact price the viewer confirms and is charged, in Buzz. */
|
|
2179
|
+
total: number;
|
|
2180
|
+
/** The orchestrator `$type` that was priced — the body's own `$type`. */
|
|
2181
|
+
stepType: string;
|
|
2182
|
+
/** ISO-8601. The quote cannot be run after this. */
|
|
2183
|
+
expiresAt: string;
|
|
2184
|
+
}
|
|
2185
|
+
/**
|
|
2186
|
+
* One entry of {@link BlockWorkflowSnapshot.model3dOutputs} /
|
|
2187
|
+
* {@link AppWorkflow.model3dOutputs} — the label for one 3D model url.
|
|
2188
|
+
*/
|
|
2189
|
+
export interface BlockModel3dOutput {
|
|
2190
|
+
/** The model's url. Also present in the snapshot's `imageUrls` (an `AppWorkflow`'s `images`). */
|
|
2191
|
+
url: string;
|
|
2192
|
+
/**
|
|
2193
|
+
* The model's own file format as the orchestrator reports it — `'glb'`,
|
|
2194
|
+
* `'fbx'`, …. An open set: compare against the formats your viewer loads and
|
|
2195
|
+
* ignore the rest.
|
|
2196
|
+
*/
|
|
2197
|
+
format: string;
|
|
2198
|
+
/**
|
|
2199
|
+
* Which output of the step this model is: the output field it came from,
|
|
2200
|
+
* dot-joined when nested — `'model'`, `'riggedFbxModel'`,
|
|
2201
|
+
* `'basicAnimations.walkingModel'`, …. An array index is a segment
|
|
2202
|
+
* (`'models.0'`), and it is `''` when the step's whole output is the model.
|
|
2203
|
+
* The names are the orchestrator's, per `$type`; nothing here lists them.
|
|
2204
|
+
*/
|
|
2205
|
+
variant: string;
|
|
2206
|
+
}
|
|
1758
2207
|
/**
|
|
1759
2208
|
* Why the host substituted a checkpoint version — see
|
|
1760
2209
|
* {@link BlockWorkflowSnapshot.modelSubstitutions}.
|
|
@@ -1781,7 +2230,7 @@ export type ModelSubstitutionReason = 'wrong-workflow' | 'unrecognized' | 'gated
|
|
|
1781
2230
|
* and the SDK's inbound validator accepts any string. Handle an unrecognised
|
|
1782
2231
|
* code as a generic failure.
|
|
1783
2232
|
*/
|
|
1784
|
-
export type KnownBlockWorkflowErrorCode = 'training-quote-rejected' | 'training-quote-unavailable' | 'training-quote-unpriced';
|
|
2233
|
+
export type KnownBlockWorkflowErrorCode = 'training-quote-rejected' | 'training-quote-unavailable' | 'training-quote-unpriced' | 'daily-limit-exceeded' | 'workflow_step_denied' | 'workflow_ref_invalid' | 'workflow_too_many_steps' | 'workflow_repeat_unbounded' | 'workflow_quote_rejected' | 'workflow_quote_unavailable' | 'workflow_quote_unpriced';
|
|
1785
2234
|
/** One entry of {@link BlockWorkflowSnapshot.modelSubstitutions}. */
|
|
1786
2235
|
export interface BlockModelSubstitution {
|
|
1787
2236
|
/** The checkpoint version id the block asked for. */
|
|
@@ -2437,6 +2886,13 @@ export interface AppWorkflow {
|
|
|
2437
2886
|
* absence as "unknown", not as "no checkpoint".
|
|
2438
2887
|
*/
|
|
2439
2888
|
trainedEpochs?: BlockTrainedEpoch[];
|
|
2889
|
+
/**
|
|
2890
|
+
* Labels for the 3D models among this workflow's {@link AppWorkflow.images} —
|
|
2891
|
+
* same shape and rule as {@link BlockWorkflowSnapshot.model3dOutputs}: every
|
|
2892
|
+
* labelled `url` is also an entry of `images`, and the field is OMITTED when
|
|
2893
|
+
* there are none (and on hosts that predate it).
|
|
2894
|
+
*/
|
|
2895
|
+
model3dOutputs?: BlockModel3dOutput[];
|
|
2440
2896
|
}
|
|
2441
2897
|
/**
|
|
2442
2898
|
* Per-viewer gated projection of ONE image returned by `GET_IMAGES_BY_IDS`
|
|
@@ -2754,5 +3210,37 @@ export type BlockPrepareTrainingDatasetHostError = 'review-mode' | 'block is not
|
|
|
2754
3210
|
* run is a SECOND, separately charged run.
|
|
2755
3211
|
*/
|
|
2756
3212
|
export type BlockRunTrainingHostError = 'review-mode' | 'block is not ready' | 'sign in to train' | 'invalid training request' | 'no block token' | 'declined' | 'submission-unconfirmed';
|
|
3213
|
+
/**
|
|
3214
|
+
* The HOST'S OWN refusal codes on a `CONFIRMED_STEP_RESULT`'s `error`. Mirrors
|
|
3215
|
+
* civitai/civitai's `RUN_CONFIRMED_STEP_HOST_ERRORS`
|
|
3216
|
+
* (`src/components/AppBlocks/runConfirmedStepGate.ts`, civitai/civitai#5786).
|
|
3217
|
+
*
|
|
3218
|
+
* 🔴 THE SET A BLOCK MAY RELY ON, NOT THE SET IT MAY RECEIVE: server messages
|
|
3219
|
+
* (an expired or already-used quote, a body that differs from the quoted one, a
|
|
3220
|
+
* price that changed, `confirmed steps from apps are not enabled`) arrive
|
|
3221
|
+
* verbatim in the same field.
|
|
3222
|
+
*
|
|
3223
|
+
* - `review-mode` — a mod-review sandbox with "run for real" off.
|
|
3224
|
+
* - `block is not ready` — the host handshake has not completed.
|
|
3225
|
+
* - `sign in to run` — anonymous viewer; there is no account to charge.
|
|
3226
|
+
* - `invalid confirmed step request` — the body is not a pass-through
|
|
3227
|
+
* `kind: 'step'` body naming an `sq_`-shaped `quoteId`.
|
|
3228
|
+
* - `no block token` — the host holds no block token yet.
|
|
3229
|
+
* - `declined` — the viewer dismissed the confirm. 🔴 GUARANTEED to mean NO JOB
|
|
3230
|
+
* WAS SUBMITTED. The quote is untouched and can still be run before it
|
|
3231
|
+
* expires.
|
|
3232
|
+
* - `daily-limit-exceeded` — the job would exceed what remains today of the
|
|
3233
|
+
* daily Buzz limit the VIEWER set for this app. NO job was submitted and
|
|
3234
|
+
* nothing was charged. The host has already told the viewer, in its own
|
|
3235
|
+
* chrome, and pointed them at where to raise the limit; there is no confirm
|
|
3236
|
+
* to click and nothing the app can do about it. Do not retry.
|
|
3237
|
+
* - `submission-unconfirmed` — the submit was SENT but its outcome is unknown.
|
|
3238
|
+
* 🔴 The job MAY BE RUNNING AND CHARGED. Every confirmation is its own job,
|
|
3239
|
+
* so a retry (which needs a new estimate and a new confirmation) starts a
|
|
3240
|
+
* SECOND, separately charged job if the first one did start. Check the
|
|
3241
|
+
* viewer's generations (`useAppWorkflows()`) before offering one, and never
|
|
3242
|
+
* retry automatically.
|
|
3243
|
+
*/
|
|
3244
|
+
export type BlockRunConfirmedStepHostError = 'review-mode' | 'block is not ready' | 'sign in to run' | 'invalid confirmed step request' | 'no block token' | 'declined' | 'daily-limit-exceeded' | 'submission-unconfirmed';
|
|
2757
3245
|
export {};
|
|
2758
3246
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/blocks/types.js
CHANGED
|
@@ -115,6 +115,38 @@ export function isSignedIn(viewer) {
|
|
|
115
115
|
return viewer !== null && viewer !== undefined;
|
|
116
116
|
}
|
|
117
117
|
// ============================================================
|
|
118
|
+
// Confirmed steps (a pass-through job above the per-call budget)
|
|
119
|
+
// ============================================================
|
|
120
|
+
/**
|
|
121
|
+
* Ceiling on what ONE viewer-confirmed pass-through job may cost, in Buzz. Host
|
|
122
|
+
* constant `BLOCK_CONFIRMED_STEP_MAX_BUZZ_PER_JOB`. A fixed price above it gets
|
|
123
|
+
* no {@link BlockWorkflowSnapshot.stepQuote} and cannot be run from an app.
|
|
124
|
+
*/
|
|
125
|
+
export const BLOCK_CONFIRMED_STEP_MAX_BUZZ_PER_JOB = 5000;
|
|
126
|
+
/**
|
|
127
|
+
* The shape of a confirmed-step quote id ({@link BlockStepQuote.quoteId}): `sq_`
|
|
128
|
+
* followed by 32 lowercase hex characters. Host constant
|
|
129
|
+
* `BLOCK_STEP_QUOTE_ID_REGEX`. Disjoint from the training quote's `tq_` shape,
|
|
130
|
+
* so neither kind's id can name the other's quote.
|
|
131
|
+
*/
|
|
132
|
+
export const BLOCK_STEP_QUOTE_ID_REGEX = /^sq_[a-f0-9]{32}$/;
|
|
133
|
+
// ============================================================
|
|
134
|
+
// App Blocks MULTI-STEP kind (`kind: 'workflow'`)
|
|
135
|
+
// ============================================================
|
|
136
|
+
/**
|
|
137
|
+
* The most steps one `kind: 'workflow'` body may carry. The host refuses a
|
|
138
|
+
* longer list with `errorCode: 'workflow_too_many_steps'`; an empty list is
|
|
139
|
+
* refused too.
|
|
140
|
+
*/
|
|
141
|
+
export const BLOCK_WORKFLOW_MAX_STEPS = 8;
|
|
142
|
+
/**
|
|
143
|
+
* The most times one top-level `repeat` step of a `kind: 'workflow'` body may
|
|
144
|
+
* run its template, NESTED REPEATS MULTIPLIED (a 4-item repeat inside a 4-item
|
|
145
|
+
* repeat is 16). The host refuses more with
|
|
146
|
+
* `errorCode: 'workflow_repeat_unbounded'`.
|
|
147
|
+
*/
|
|
148
|
+
export const BLOCK_WORKFLOW_REPEAT_MAX_ITERATIONS = 16;
|
|
149
|
+
// ============================================================
|
|
118
150
|
// App Blocks TRAINING kind (`kind: 'training'`)
|
|
119
151
|
// ============================================================
|
|
120
152
|
//
|
package/dist/index.d.ts
CHANGED
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
*
|
|
26
26
|
* - **`./blocks`** — importing it RUNS `./safe-storage` for its side effect
|
|
27
27
|
* (repairing `localStorage`/`sessionStorage` at an opaque origin). Folding
|
|
28
|
-
*
|
|
28
|
+
* 172 symbols and that side effect into the root would make every OAuth app
|
|
29
29
|
* that writes `import { exchangeCode } from '@civitai/app-sdk'` pay for the
|
|
30
30
|
* Civitai-Apps contract it does not use. Blocks and OAuth apps are disjoint
|
|
31
31
|
* audiences; see this package's README.
|
|
32
|
-
* 🔴 That
|
|
32
|
+
* 🔴 That 172 is ASSERTED, not merely quoted — by
|
|
33
33
|
* `packages/civitai-app-sdk/test/export-surface.test.ts`, which pins
|
|
34
34
|
* `surface.get('./blocks').size`. It said 119 here against a real 125 until
|
|
35
35
|
* 2026-10-04, because the existing checks pin the root as an exact union and
|
package/dist/index.js
CHANGED
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
*
|
|
26
26
|
* - **`./blocks`** — importing it RUNS `./safe-storage` for its side effect
|
|
27
27
|
* (repairing `localStorage`/`sessionStorage` at an opaque origin). Folding
|
|
28
|
-
*
|
|
28
|
+
* 172 symbols and that side effect into the root would make every OAuth app
|
|
29
29
|
* that writes `import { exchangeCode } from '@civitai/app-sdk'` pay for the
|
|
30
30
|
* Civitai-Apps contract it does not use. Blocks and OAuth apps are disjoint
|
|
31
31
|
* audiences; see this package's README.
|
|
32
|
-
* 🔴 That
|
|
32
|
+
* 🔴 That 172 is ASSERTED, not merely quoted — by
|
|
33
33
|
* `packages/civitai-app-sdk/test/export-surface.test.ts`, which pins
|
|
34
34
|
* `surface.get('./blocks').size`. It said 119 here against a real 125 until
|
|
35
35
|
* 2026-10-04, because the existing checks pin the root as an exact union and
|
package/package.json
CHANGED