@civitai/blocks-react 0.76.1 → 0.78.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 +125 -52
- package/dist/hooks/useImageUpload.d.ts +40 -6
- package/dist/hooks/useImageUpload.js +19 -3
- package/dist/hooks/useResourceFile.d.ts +71 -0
- package/dist/hooks/useResourceFile.js +113 -0
- package/dist/hooks/useRunTraining.d.ts +31 -10
- package/dist/hooks/useRunTraining.js +32 -7
- package/dist/index.d.ts +5 -5
- package/dist/index.js +1 -1
- package/dist/internal/liveHost.d.ts +7 -8
- package/dist/internal/liveHost.js +43 -28
- package/dist/internal/mockHost.d.ts +53 -44
- package/dist/internal/mockHost.js +219 -84
- package/dist/transport/requestTimeouts.d.ts +32 -7
- package/dist/transport/requestTimeouts.js +36 -12
- package/dist/transport/validate.d.ts +18 -17
- package/dist/transport/validate.js +97 -47
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/package.json +2 -2
- package/dist/hooks/usePrepareTrainingDataset.d.ts +0 -99
- package/dist/hooks/usePrepareTrainingDataset.js +0 -159
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { BlockRunTrainingHostError, BlockTrainingQuote, BlockWorkflowSnapshot, WorkflowBodyTraining } from '@civitai/app-sdk/blocks';
|
|
2
|
-
export type { BlockRunTrainingHostError, BlockTrainingQuote, WorkflowBodyTraining };
|
|
1
|
+
import type { BlockRunTrainingHostError, BlockTrainingDatasetItem, BlockTrainingQuote, BlockWorkflowSnapshot, WorkflowBodyTraining } from '@civitai/app-sdk/blocks';
|
|
2
|
+
export type { BlockRunTrainingHostError, BlockTrainingDatasetItem, BlockTrainingQuote, WorkflowBodyTraining, };
|
|
3
3
|
/**
|
|
4
4
|
* A training body ready to RUN: {@link WorkflowBodyTraining} with the `quoteId`
|
|
5
5
|
* its estimate returned. Required here so a body without one is a compile error
|
|
@@ -16,7 +16,7 @@ export type QuotedTrainingBody = WorkflowBodyTraining & {
|
|
|
16
16
|
* a body that differs from the quoted one) arrive in the same field — see
|
|
17
17
|
* {@link isRunTrainingErrorCode}.
|
|
18
18
|
*/
|
|
19
|
-
export declare const RUN_TRAINING_ERROR_CODES: readonly ["review-mode", "block is not ready", "sign in to train", "invalid training request", "no block token", "declined", "submission-unconfirmed"];
|
|
19
|
+
export declare const RUN_TRAINING_ERROR_CODES: readonly ["review-mode", "block is not ready", "sign in to train", "invalid training request", "no block token", "training data not uploaded here", "declined", "submission-unconfirmed"];
|
|
20
20
|
/**
|
|
21
21
|
* The `code` a {@link RunTrainingError} can carry: one of the host's closed
|
|
22
22
|
* refusal codes, or `'refused'` — assigned by THIS SDK, never sent by the host,
|
|
@@ -49,9 +49,15 @@ export declare function isRunTrainingErrorCode(error: string): error is BlockRun
|
|
|
49
49
|
* `.snapshot` the refusal it arrived in. Retrying needs a new estimate and
|
|
50
50
|
* usually a later time; buying Buzz does not lift these caps.
|
|
51
51
|
* - `.signInRequired` — no session. Route into `useRequestSignIn()`.
|
|
52
|
+
* - `.trainingDataNotUploaded` (`code: 'training data not uploaded here'`) —
|
|
53
|
+
* the quote names an image THIS host did not upload for this block. The host
|
|
54
|
+
* remembers only the blobs its own `useImageUpload({ purpose: 'trainingData' })`
|
|
55
|
+
* uploaded, and forgets them on a page reload. Refused before any dialog:
|
|
56
|
+
* NO RUN, nothing charged. Ask the viewer to upload the images again, then
|
|
57
|
+
* estimate and run the new quote.
|
|
52
58
|
* - anything else — a refusal before any submit (an expired or used quote, a
|
|
53
|
-
* body that no longer matches its quote
|
|
54
|
-
*
|
|
59
|
+
* body that no longer matches its quote). Estimate again before retrying;
|
|
60
|
+
* `.message` is the host's or server's text.
|
|
55
61
|
*/
|
|
56
62
|
export declare class RunTrainingError extends Error {
|
|
57
63
|
/**
|
|
@@ -78,6 +84,12 @@ export declare class RunTrainingError extends Error {
|
|
|
78
84
|
readonly timedOut: boolean;
|
|
79
85
|
/** There is no session (`sign in to train`, or a bare `UNAUTHORIZED`). */
|
|
80
86
|
readonly signInRequired: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* The quote names an image this host did not upload for this block
|
|
89
|
+
* (`training data not uploaded here`). No run, nothing charged: upload the
|
|
90
|
+
* images again, estimate again, and run that quote.
|
|
91
|
+
*/
|
|
92
|
+
readonly trainingDataNotUploaded: boolean;
|
|
81
93
|
constructor(error: string, opts?: {
|
|
82
94
|
timedOut?: boolean;
|
|
83
95
|
refusedSnapshot?: BlockWorkflowSnapshot;
|
|
@@ -112,15 +124,19 @@ export interface UseRunTraining {
|
|
|
112
124
|
* viewer. Refused from `dev:live` and from review sessions — build the flow
|
|
113
125
|
* against the mock host. See `WorkflowBodyTraining` in `@civitai/app-sdk`.
|
|
114
126
|
*
|
|
115
|
-
* The flow: `
|
|
116
|
-
*
|
|
117
|
-
* `useBuzzWorkflow().
|
|
118
|
-
*
|
|
127
|
+
* The flow: `useImageUpload({ purpose: 'trainingData' }).open()` (the viewer
|
|
128
|
+
* uploads the images; you caption them into `items: [{ air, caption }]`) →
|
|
129
|
+
* `useBuzzWorkflow().estimate(body)` (its `trainingQuote.quoteId`) →
|
|
130
|
+
* `runTraining({ ...body, quoteId })` → `useBuzzWorkflow().watch(workflowId)`.
|
|
131
|
+
* Change nothing in the body between the estimate and the run: the server checks
|
|
132
|
+
* it against the quoted one. Upload and run in the same page session: the host
|
|
133
|
+
* refuses a quote naming an image it did not upload for this block.
|
|
119
134
|
*
|
|
120
135
|
* 🔴 THE CONSENT DIALOG IS CIVITAI'S, AND IT IS THE CHARGE. Every number on it is
|
|
121
136
|
* read back from the server's stored quote — never from your body. A run may cost
|
|
122
137
|
* more than the token's per-call budget (the viewer confirms the exact price), up
|
|
123
|
-
* to `BLOCK_TRAINING_MAX_BUZZ_PER_RUN` (5,000 Buzz). Images are the
|
|
138
|
+
* to `BLOCK_TRAINING_MAX_BUZZ_PER_RUN` (5,000 Buzz). Images are the ones the
|
|
139
|
+
* viewer uploaded through the host.
|
|
124
140
|
*
|
|
125
141
|
* 🔴 NO AUTOMATIC CONSENT RETRY, unlike the other consent-gated hooks — on
|
|
126
142
|
* purpose. `RUN_TRAINING` carries no idempotency key and has an outcome
|
|
@@ -132,8 +148,12 @@ export interface UseRunTraining {
|
|
|
132
148
|
* the viewer clicks or dismisses its dialog.
|
|
133
149
|
*
|
|
134
150
|
* @example
|
|
151
|
+
* const { open } = useImageUpload({ purpose: 'trainingData' });
|
|
135
152
|
* const { estimate, watch } = useBuzzWorkflow();
|
|
136
153
|
* const { runTraining } = useRunTraining();
|
|
154
|
+
* const images = await open();
|
|
155
|
+
* if (!images) return; // cancelled
|
|
156
|
+
* const body = { ...settings, items: images.map((i) => ({ air: i.air, caption: captionFor(i) })) };
|
|
137
157
|
* const quote = (await estimate(body)).trainingQuote!;
|
|
138
158
|
* try {
|
|
139
159
|
* const started = await runTraining({ ...body, quoteId: quote.quoteId });
|
|
@@ -142,6 +162,7 @@ export interface UseRunTraining {
|
|
|
142
162
|
* if (!(e instanceof RunTrainingError)) throw e;
|
|
143
163
|
* if (e.declined) return; // no run — say nothing
|
|
144
164
|
* if (e.signInRequired) return requestSignIn();
|
|
165
|
+
* if (e.trainingDataNotUploaded) return askToUploadAgain(); // no run — re-upload, re-estimate
|
|
145
166
|
* if (e.unconfirmed) return showCheckYourTrainings(); // may be running — never auto-retry
|
|
146
167
|
* if (e.refused) return showError(e.message); // a cap / availability refusal; no run, nothing charged
|
|
147
168
|
* showError('Could not start training. Get a new price and try again.');
|
|
@@ -17,9 +17,12 @@ export const RUN_TRAINING_ERROR_CODES = [
|
|
|
17
17
|
'sign in to train',
|
|
18
18
|
'invalid training request',
|
|
19
19
|
'no block token',
|
|
20
|
+
'training data not uploaded here',
|
|
20
21
|
'declined',
|
|
21
22
|
'submission-unconfirmed',
|
|
22
23
|
];
|
|
24
|
+
/** The host code for a quote naming an image this host did not upload — see {@link RunTrainingError.trainingDataNotUploaded}. */
|
|
25
|
+
const NOT_UPLOADED_HERE = 'training data not uploaded here';
|
|
23
26
|
const CODE_SET = new Set(RUN_TRAINING_ERROR_CODES);
|
|
24
27
|
/**
|
|
25
28
|
* The `workflowId` the host's training submit stamps on a snapshot that is NOT a
|
|
@@ -55,9 +58,15 @@ export function isRunTrainingErrorCode(error) {
|
|
|
55
58
|
* `.snapshot` the refusal it arrived in. Retrying needs a new estimate and
|
|
56
59
|
* usually a later time; buying Buzz does not lift these caps.
|
|
57
60
|
* - `.signInRequired` — no session. Route into `useRequestSignIn()`.
|
|
61
|
+
* - `.trainingDataNotUploaded` (`code: 'training data not uploaded here'`) —
|
|
62
|
+
* the quote names an image THIS host did not upload for this block. The host
|
|
63
|
+
* remembers only the blobs its own `useImageUpload({ purpose: 'trainingData' })`
|
|
64
|
+
* uploaded, and forgets them on a page reload. Refused before any dialog:
|
|
65
|
+
* NO RUN, nothing charged. Ask the viewer to upload the images again, then
|
|
66
|
+
* estimate and run the new quote.
|
|
58
67
|
* - anything else — a refusal before any submit (an expired or used quote, a
|
|
59
|
-
* body that no longer matches its quote
|
|
60
|
-
*
|
|
68
|
+
* body that no longer matches its quote). Estimate again before retrying;
|
|
69
|
+
* `.message` is the host's or server's text.
|
|
61
70
|
*/
|
|
62
71
|
export class RunTrainingError extends Error {
|
|
63
72
|
/**
|
|
@@ -84,6 +93,12 @@ export class RunTrainingError extends Error {
|
|
|
84
93
|
timedOut;
|
|
85
94
|
/** There is no session (`sign in to train`, or a bare `UNAUTHORIZED`). */
|
|
86
95
|
signInRequired;
|
|
96
|
+
/**
|
|
97
|
+
* The quote names an image this host did not upload for this block
|
|
98
|
+
* (`training data not uploaded here`). No run, nothing charged: upload the
|
|
99
|
+
* images again, estimate again, and run that quote.
|
|
100
|
+
*/
|
|
101
|
+
trainingDataNotUploaded;
|
|
87
102
|
constructor(error, opts) {
|
|
88
103
|
super(error);
|
|
89
104
|
this.name = 'RunTrainingError';
|
|
@@ -99,6 +114,7 @@ export class RunTrainingError extends Error {
|
|
|
99
114
|
this.declined = error === 'declined';
|
|
100
115
|
this.unconfirmed = this.timedOut || error === 'submission-unconfirmed';
|
|
101
116
|
this.signInRequired = error === 'sign in to train' || error === 'UNAUTHORIZED';
|
|
117
|
+
this.trainingDataNotUploaded = error === NOT_UPLOADED_HERE;
|
|
102
118
|
}
|
|
103
119
|
}
|
|
104
120
|
/**
|
|
@@ -110,15 +126,19 @@ export class RunTrainingError extends Error {
|
|
|
110
126
|
* viewer. Refused from `dev:live` and from review sessions — build the flow
|
|
111
127
|
* against the mock host. See `WorkflowBodyTraining` in `@civitai/app-sdk`.
|
|
112
128
|
*
|
|
113
|
-
* The flow: `
|
|
114
|
-
*
|
|
115
|
-
* `useBuzzWorkflow().
|
|
116
|
-
*
|
|
129
|
+
* The flow: `useImageUpload({ purpose: 'trainingData' }).open()` (the viewer
|
|
130
|
+
* uploads the images; you caption them into `items: [{ air, caption }]`) →
|
|
131
|
+
* `useBuzzWorkflow().estimate(body)` (its `trainingQuote.quoteId`) →
|
|
132
|
+
* `runTraining({ ...body, quoteId })` → `useBuzzWorkflow().watch(workflowId)`.
|
|
133
|
+
* Change nothing in the body between the estimate and the run: the server checks
|
|
134
|
+
* it against the quoted one. Upload and run in the same page session: the host
|
|
135
|
+
* refuses a quote naming an image it did not upload for this block.
|
|
117
136
|
*
|
|
118
137
|
* 🔴 THE CONSENT DIALOG IS CIVITAI'S, AND IT IS THE CHARGE. Every number on it is
|
|
119
138
|
* read back from the server's stored quote — never from your body. A run may cost
|
|
120
139
|
* more than the token's per-call budget (the viewer confirms the exact price), up
|
|
121
|
-
* to `BLOCK_TRAINING_MAX_BUZZ_PER_RUN` (5,000 Buzz). Images are the
|
|
140
|
+
* to `BLOCK_TRAINING_MAX_BUZZ_PER_RUN` (5,000 Buzz). Images are the ones the
|
|
141
|
+
* viewer uploaded through the host.
|
|
122
142
|
*
|
|
123
143
|
* 🔴 NO AUTOMATIC CONSENT RETRY, unlike the other consent-gated hooks — on
|
|
124
144
|
* purpose. `RUN_TRAINING` carries no idempotency key and has an outcome
|
|
@@ -130,8 +150,12 @@ export class RunTrainingError extends Error {
|
|
|
130
150
|
* the viewer clicks or dismisses its dialog.
|
|
131
151
|
*
|
|
132
152
|
* @example
|
|
153
|
+
* const { open } = useImageUpload({ purpose: 'trainingData' });
|
|
133
154
|
* const { estimate, watch } = useBuzzWorkflow();
|
|
134
155
|
* const { runTraining } = useRunTraining();
|
|
156
|
+
* const images = await open();
|
|
157
|
+
* if (!images) return; // cancelled
|
|
158
|
+
* const body = { ...settings, items: images.map((i) => ({ air: i.air, caption: captionFor(i) })) };
|
|
135
159
|
* const quote = (await estimate(body)).trainingQuote!;
|
|
136
160
|
* try {
|
|
137
161
|
* const started = await runTraining({ ...body, quoteId: quote.quoteId });
|
|
@@ -140,6 +164,7 @@ export class RunTrainingError extends Error {
|
|
|
140
164
|
* if (!(e instanceof RunTrainingError)) throw e;
|
|
141
165
|
* if (e.declined) return; // no run — say nothing
|
|
142
166
|
* if (e.signInRequired) return requestSignIn();
|
|
167
|
+
* if (e.trainingDataNotUploaded) return askToUploadAgain(); // no run — re-upload, re-estimate
|
|
143
168
|
* if (e.unconfirmed) return showCheckYourTrainings(); // may be running — never auto-retry
|
|
144
169
|
* if (e.refused) return showError(e.message); // a cap / availability refusal; no run, nothing charged
|
|
145
170
|
* showError('Could not start training. Get a new price and try again.');
|
package/dist/index.d.ts
CHANGED
|
@@ -57,6 +57,8 @@ export { useDailyCompensation } from './hooks/useDailyCompensation.js';
|
|
|
57
57
|
export type { UseDailyCompensation } from './hooks/useDailyCompensation.js';
|
|
58
58
|
export { useWildcardPack, WildcardPackError } from './hooks/useWildcardPack.js';
|
|
59
59
|
export type { UseWildcardPack } from './hooks/useWildcardPack.js';
|
|
60
|
+
export { useResourceFile, ResourceFileError } from './hooks/useResourceFile.js';
|
|
61
|
+
export type { UseResourceFile } from './hooks/useResourceFile.js';
|
|
60
62
|
export { useAppWorkflows } from './hooks/useAppWorkflows.js';
|
|
61
63
|
export type { UseAppWorkflows } from './hooks/useAppWorkflows.js';
|
|
62
64
|
export { usePublishGenerationOutputs } from './hooks/usePublishGenerationOutputs.js';
|
|
@@ -73,19 +75,17 @@ export { useReactions, ReactionError, REACTIONS, REACTION_ERROR_CODES, isReactio
|
|
|
73
75
|
export type { UseReactions, UseReactionsOptions } from './hooks/useReactions.js';
|
|
74
76
|
export { useCreatePostFromApp, CreatePostError, CREATE_POST_ERROR_CODES, isCreatePostErrorCode, } from './hooks/useCreatePostFromApp.js';
|
|
75
77
|
export type { UseCreatePostFromApp, BlockPostSource, BlockCreatePostRequest, BlockCreatePostResult, BlockCreatePostHostError, } from './hooks/useCreatePostFromApp.js';
|
|
76
|
-
export { usePrepareTrainingDataset, PrepareTrainingDatasetError, PREPARE_TRAINING_DATASET_ERROR_CODES, isPrepareTrainingDatasetErrorCode, } from './hooks/usePrepareTrainingDataset.js';
|
|
77
|
-
export type { UsePrepareTrainingDataset, BlockPrepareTrainingDatasetHostError, BlockTrainingDatasetItem, BlockTrainingDatasetResult, BlockTrainingRejectionReason, } from './hooks/usePrepareTrainingDataset.js';
|
|
78
78
|
export { useRunTraining, RunTrainingError, RUN_TRAINING_ERROR_CODES, isRunTrainingErrorCode, } from './hooks/useRunTraining.js';
|
|
79
|
-
export type { UseRunTraining, QuotedTrainingBody, RunTrainingErrorCode, BlockRunTrainingHostError, BlockTrainingQuote, WorkflowBodyTraining, } from './hooks/useRunTraining.js';
|
|
79
|
+
export type { UseRunTraining, QuotedTrainingBody, RunTrainingErrorCode, BlockRunTrainingHostError, BlockTrainingQuote, BlockTrainingDatasetItem, WorkflowBodyTraining, } from './hooks/useRunTraining.js';
|
|
80
80
|
export { useRunConfirmedStep, RunConfirmedStepError, RUN_CONFIRMED_STEP_ERROR_CODES, isRunConfirmedStepErrorCode, isStepQuoteId, } from './hooks/useRunConfirmedStep.js';
|
|
81
81
|
export type { UseRunConfirmedStep, QuotedStepBody, RunConfirmedStepErrorCode, BlockRunConfirmedStepHostError, BlockStepQuote, WorkflowBodyPassThroughStep, } from './hooks/useRunConfirmedStep.js';
|
|
82
|
-
export type { BlockBuzzTransaction, BlockBuzzAccount, BlockDailyCompensationResource, BlockWildcardPack, BlockWildcardPackErrorCode, AppWorkflow, AppWorkflowImage, AppWorkflowsParams, BlockGatedImage, BlockCollectionFollowErrorCode, BlockCollectionFollowResult, BlockAppReaction, BlockStoredReaction, BlockReactionEntityType, BlockEntityReactionErrorCode, BlockReactionCounts, BlockEntityReactionState, BlockEntityReactionResult, BlockEntityReactionsResult, } from '@civitai/app-sdk/blocks';
|
|
82
|
+
export type { BlockBuzzTransaction, BlockBuzzAccount, BlockDailyCompensationResource, BlockWildcardPack, BlockWildcardPackErrorCode, BlockResourceFile, BlockResourceFileEntry, BlockResourceFileEntryFormat, BlockResourceFileErrorCode, BlockResourceFileMeta, AppWorkflow, AppWorkflowImage, AppWorkflowsParams, BlockGatedImage, BlockCollectionFollowErrorCode, BlockCollectionFollowResult, BlockAppReaction, BlockStoredReaction, BlockReactionEntityType, BlockEntityReactionErrorCode, BlockReactionCounts, BlockEntityReactionState, BlockEntityReactionResult, BlockEntityReactionsResult, } from '@civitai/app-sdk/blocks';
|
|
83
83
|
export { useCheckpointPicker } from './hooks/useCheckpointPicker.js';
|
|
84
84
|
export type { UseCheckpointPicker } from './hooks/useCheckpointPicker.js';
|
|
85
85
|
export { useResourcePicker, RESOURCE_PICKER_MULTIPLE_MAX } from './hooks/useResourcePicker.js';
|
|
86
86
|
export type { UseResourcePicker, ResourcePickerOpenOptions, ResourcePickerMultiple, } from './hooks/useResourcePicker.js';
|
|
87
87
|
export { useImageUpload } from './hooks/useImageUpload.js';
|
|
88
|
-
export type { UseImageUpload, UseImageUploadAsyncScan, UseImageUploadGenerationSource, UseImageUploadOptions, } from './hooks/useImageUpload.js';
|
|
88
|
+
export type { UseImageUpload, UseImageUploadAsyncScan, UseImageUploadGenerationSource, UseImageUploadTrainingData, UseImageUploadOptions, BlockTrainingDataImage, } from './hooks/useImageUpload.js';
|
|
89
89
|
export { useUploadImageBytes } from './hooks/useUploadImageBytes.js';
|
|
90
90
|
export type { UploadImageBytesOptions, UseUploadImageBytes, } from './hooks/useUploadImageBytes.js';
|
|
91
91
|
export { useMediaUpload } from './hooks/useMediaUpload.js';
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,7 @@ export { useBuzzTransactions } from './hooks/useBuzzTransactions.js';
|
|
|
46
46
|
export { useBuzzAccounts } from './hooks/useBuzzAccounts.js';
|
|
47
47
|
export { useDailyCompensation } from './hooks/useDailyCompensation.js';
|
|
48
48
|
export { useWildcardPack, WildcardPackError } from './hooks/useWildcardPack.js';
|
|
49
|
+
export { useResourceFile, ResourceFileError } from './hooks/useResourceFile.js';
|
|
49
50
|
export { useAppWorkflows } from './hooks/useAppWorkflows.js';
|
|
50
51
|
export { usePublishGenerationOutputs } from './hooks/usePublishGenerationOutputs.js';
|
|
51
52
|
export { useGatedImages } from './hooks/useGatedImages.js';
|
|
@@ -62,7 +63,6 @@ export { InvalidIdempotencyKeyError } from './transport/transport.js';
|
|
|
62
63
|
export { useCollectionFollow, CollectionFollowError, COLLECTION_FOLLOW_ERROR_CODES, isCollectionFollowErrorCode, } from './hooks/useCollectionFollow.js';
|
|
63
64
|
export { useReactions, ReactionError, REACTIONS, REACTION_ERROR_CODES, isReactionErrorCode, } from './hooks/useReactions.js';
|
|
64
65
|
export { useCreatePostFromApp, CreatePostError, CREATE_POST_ERROR_CODES, isCreatePostErrorCode, } from './hooks/useCreatePostFromApp.js';
|
|
65
|
-
export { usePrepareTrainingDataset, PrepareTrainingDatasetError, PREPARE_TRAINING_DATASET_ERROR_CODES, isPrepareTrainingDatasetErrorCode, } from './hooks/usePrepareTrainingDataset.js';
|
|
66
66
|
export { useRunTraining, RunTrainingError, RUN_TRAINING_ERROR_CODES, isRunTrainingErrorCode, } from './hooks/useRunTraining.js';
|
|
67
67
|
export { useRunConfirmedStep, RunConfirmedStepError, RUN_CONFIRMED_STEP_ERROR_CODES, isRunConfirmedStepErrorCode, isStepQuoteId, } from './hooks/useRunConfirmedStep.js';
|
|
68
68
|
export { useCheckpointPicker } from './hooks/useCheckpointPicker.js';
|
|
@@ -113,12 +113,9 @@
|
|
|
113
113
|
* `entity-unavailable`.
|
|
114
114
|
* • CREATE_POST_FROM_APP — needs the server-resolved preview plus host-chrome
|
|
115
115
|
* confirm before a PUBLIC post is written. Replies with a refusal.
|
|
116
|
-
* •
|
|
117
|
-
*
|
|
118
|
-
* refusal.
|
|
119
|
-
* • RUN_TRAINING — the same dev-token refusal, plus the host-chrome consent
|
|
120
|
-
* dialog a run is confirmed in, which this harness does not have. Replies
|
|
121
|
-
* with a refusal.
|
|
116
|
+
* • RUN_TRAINING — the server refuses every `kind: 'training'` request from a
|
|
117
|
+
* dev token, and a run is confirmed in a host-chrome consent dialog this
|
|
118
|
+
* harness does not have. Replies with a refusal.
|
|
122
119
|
* • RUN_CONFIRMED_STEP — the server refuses a confirmed step from a dev token
|
|
123
120
|
* and the estimate never returns a `stepQuote` for one, and the price is
|
|
124
121
|
* confirmed in host chrome this harness does not have. Replies with a
|
|
@@ -130,6 +127,9 @@
|
|
|
130
127
|
* `publishError` options. Replies with a refusal.
|
|
131
128
|
* • GET_WILDCARD_PACK — needs the session-authed resolve plus the in-tab
|
|
132
129
|
* zip/yaml parse that lives in civitai, not this SDK. Replies `parse-failed`.
|
|
130
|
+
* • GET_RESOURCE_FILE — the same session-authed resolve plus in-tab
|
|
131
|
+
* fetch/unzip/parse, and only full-page app hosts answer it. Replies
|
|
132
|
+
* `parse-failed`.
|
|
133
133
|
* • OPEN_IMAGE_UPLOAD — needs the host's native modal + session-authed byte
|
|
134
134
|
* pipeline. Replies DISMISSED (the hook resolves `null`).
|
|
135
135
|
* • OPEN_IMAGE_PICKER — needs the host's picker over the viewer's own posted
|
|
@@ -239,8 +239,7 @@ export interface LiveHostOptions {
|
|
|
239
239
|
manifest?: unknown;
|
|
240
240
|
}
|
|
241
241
|
/**
|
|
242
|
-
* The reply
|
|
243
|
-
* string so the two cannot drift.
|
|
242
|
+
* The reply `RUN_TRAINING` gets in dev:live — see its handler.
|
|
244
243
|
*/
|
|
245
244
|
export declare const TRAINING_UNSUPPORTED_ERROR = "training is not supported in dev:live \u2014 use dev:mock";
|
|
246
245
|
/**
|
|
@@ -113,12 +113,9 @@
|
|
|
113
113
|
* `entity-unavailable`.
|
|
114
114
|
* • CREATE_POST_FROM_APP — needs the server-resolved preview plus host-chrome
|
|
115
115
|
* confirm before a PUBLIC post is written. Replies with a refusal.
|
|
116
|
-
* •
|
|
117
|
-
*
|
|
118
|
-
* refusal.
|
|
119
|
-
* • RUN_TRAINING — the same dev-token refusal, plus the host-chrome consent
|
|
120
|
-
* dialog a run is confirmed in, which this harness does not have. Replies
|
|
121
|
-
* with a refusal.
|
|
116
|
+
* • RUN_TRAINING — the server refuses every `kind: 'training'` request from a
|
|
117
|
+
* dev token, and a run is confirmed in a host-chrome consent dialog this
|
|
118
|
+
* harness does not have. Replies with a refusal.
|
|
122
119
|
* • RUN_CONFIRMED_STEP — the server refuses a confirmed step from a dev token
|
|
123
120
|
* and the estimate never returns a `stepQuote` for one, and the price is
|
|
124
121
|
* confirmed in host chrome this harness does not have. Replies with a
|
|
@@ -130,6 +127,9 @@
|
|
|
130
127
|
* `publishError` options. Replies with a refusal.
|
|
131
128
|
* • GET_WILDCARD_PACK — needs the session-authed resolve plus the in-tab
|
|
132
129
|
* zip/yaml parse that lives in civitai, not this SDK. Replies `parse-failed`.
|
|
130
|
+
* • GET_RESOURCE_FILE — the same session-authed resolve plus in-tab
|
|
131
|
+
* fetch/unzip/parse, and only full-page app hosts answer it. Replies
|
|
132
|
+
* `parse-failed`.
|
|
133
133
|
* • OPEN_IMAGE_UPLOAD — needs the host's native modal + session-authed byte
|
|
134
134
|
* pipeline. Replies DISMISSED (the hook resolves `null`).
|
|
135
135
|
* • OPEN_IMAGE_PICKER — needs the host's picker over the viewer's own posted
|
|
@@ -174,8 +174,7 @@ const DEFAULT_BACKEND_BASE_URL = 'https://civitai.com';
|
|
|
174
174
|
/** The budgeted-spend scope the workflow procedures require. */
|
|
175
175
|
const BUDGETED_SCOPE = 'ai:write:budgeted';
|
|
176
176
|
/**
|
|
177
|
-
* The reply
|
|
178
|
-
* string so the two cannot drift.
|
|
177
|
+
* The reply `RUN_TRAINING` gets in dev:live — see its handler.
|
|
179
178
|
*/
|
|
180
179
|
export const TRAINING_UNSUPPORTED_ERROR = 'training is not supported in dev:live — use dev:mock';
|
|
181
180
|
/** The once-per-session console line for a refused training bridge. */
|
|
@@ -1139,35 +1138,25 @@ export function createLiveHost(options) {
|
|
|
1139
1138
|
});
|
|
1140
1139
|
return;
|
|
1141
1140
|
}
|
|
1142
|
-
case '
|
|
1141
|
+
case 'RUN_TRAINING': {
|
|
1143
1142
|
// UNSUPPORTED in live, and here the SERVER decides it, not this
|
|
1144
1143
|
// harness: every `kind: 'training'` procedure refuses a dev token
|
|
1145
1144
|
// ("training is not available from a development or review session"
|
|
1146
1145
|
// — `assertTrainingRequestAllowed` in civitai/civitai), because there
|
|
1147
1146
|
// is no host page whose chrome can show the viewer a price. A
|
|
1148
1147
|
// training ESTIMATE is still forwarded (ESTIMATE_WORKFLOW above) and
|
|
1149
|
-
// comes back carrying that same server refusal.
|
|
1148
|
+
// comes back carrying that same server refusal. A run is also
|
|
1149
|
+
// CHARGED and confirmed in host chrome this harness does not have, so
|
|
1150
|
+
// faking either half would let dev prove out a flow production does
|
|
1151
|
+
// not have. The upload half (`OPEN_IMAGE_UPLOAD { purpose:
|
|
1152
|
+
// 'trainingData' }`) is answered as a dismissal (`null`), like every
|
|
1153
|
+
// other upload mode — see OPEN_IMAGE_UPLOAD below.
|
|
1150
1154
|
//
|
|
1151
1155
|
// FREE TEXT on the message's own reply channel; no host code is
|
|
1152
1156
|
// honest about "this harness cannot do it". Use dev:mock — its
|
|
1153
|
-
// `
|
|
1154
|
-
//
|
|
1155
|
-
|
|
1156
|
-
return;
|
|
1157
|
-
logOnce('training-dataset', trainingUnsupportedLog('PREPARE_TRAINING_DATASET'));
|
|
1158
|
-
dispatchToBlock({
|
|
1159
|
-
type: 'TRAINING_DATASET_RESULT',
|
|
1160
|
-
payload: { requestId, error: TRAINING_UNSUPPORTED_ERROR },
|
|
1161
|
-
});
|
|
1162
|
-
return;
|
|
1163
|
-
}
|
|
1164
|
-
case 'RUN_TRAINING': {
|
|
1165
|
-
// UNSUPPORTED in live for the same server-side reason as
|
|
1166
|
-
// PREPARE_TRAINING_DATASET directly above — and doubly so: a run is
|
|
1167
|
-
// CHARGED and confirmed in host chrome this harness does not have, so
|
|
1168
|
-
// faking either half would let dev prove out a flow production does
|
|
1169
|
-
// not have. Use dev:mock — its `runTrainingError` knob covers
|
|
1170
|
-
// `declined`, `submission-unconfirmed` and the rest.
|
|
1157
|
+
// `cannedTrainingDataUpload`, `trainingDataNotUploadedHere` and
|
|
1158
|
+
// `runTrainingError` knobs cover the upload, the not-uploaded-here
|
|
1159
|
+
// refusal, `declined`, `submission-unconfirmed` and the rest.
|
|
1171
1160
|
if (!isRoutableRequestId(requestId))
|
|
1172
1161
|
return;
|
|
1173
1162
|
logOnce('training-run', trainingUnsupportedLog('RUN_TRAINING'));
|
|
@@ -1221,6 +1210,26 @@ export function createLiveHost(options) {
|
|
|
1221
1210
|
});
|
|
1222
1211
|
return;
|
|
1223
1212
|
}
|
|
1213
|
+
case 'GET_RESOURCE_FILE': {
|
|
1214
|
+
// UNSUPPORTED in live v1, for the same reason as GET_WILDCARD_PACK
|
|
1215
|
+
// directly above: the real host resolves the file through a
|
|
1216
|
+
// SESSION-authed procedure and fetches + unzips + parses it in the
|
|
1217
|
+
// viewer's page tab. A liveHost holds a BLOCK token, not a session,
|
|
1218
|
+
// so it cannot resolve the file. Reply with an honest `parse-failed`
|
|
1219
|
+
// (never a fabricated file) so the hook surfaces a typed error rather
|
|
1220
|
+
// than hanging. The closed error set has no "unsupported" code, and
|
|
1221
|
+
// `parse-failed` is the one the wildcard refusal already uses.
|
|
1222
|
+
if (!isRoutableRequestId(requestId))
|
|
1223
|
+
return;
|
|
1224
|
+
logOnce('resource-file', 'GET_RESOURCE_FILE is not supported in dev:live (it needs the session-authed ' +
|
|
1225
|
+
'resolve + in-tab fetch and unzip, on a full-page app host). Replying ' +
|
|
1226
|
+
'`parse-failed`. Use dev:mock to exercise the resource-file path.');
|
|
1227
|
+
dispatchToBlock({
|
|
1228
|
+
type: 'RESOURCE_FILE_RESULT',
|
|
1229
|
+
payload: { requestId, error: 'parse-failed' },
|
|
1230
|
+
});
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1224
1233
|
case 'QUERY_APP_WORKFLOWS': {
|
|
1225
1234
|
// App generator SUBQUEUE read via the token-bound
|
|
1226
1235
|
// `blocks.queryAppWorkflows` MUTATION (POST). params (cursor/limit) are
|
|
@@ -1391,6 +1400,12 @@ export function createLiveHost(options) {
|
|
|
1391
1400
|
'Test the bytes upload against the real site, or use ' +
|
|
1392
1401
|
'createMockHost({ uploadImageBytesResult }) in dev:mock.');
|
|
1393
1402
|
}
|
|
1403
|
+
else if (typed.payload?.purpose === 'trainingData') {
|
|
1404
|
+
logOnce('open-image-upload-training-data', "OPEN_IMAGE_UPLOAD { purpose: 'trainingData' } received but live dev mode " +
|
|
1405
|
+
'cannot serve the training-data upload modal — resolving the upload as cancelled (null). ' +
|
|
1406
|
+
'Test the training flow against the real site, or use ' +
|
|
1407
|
+
'createMockHost({ cannedTrainingDataUpload }) in dev:mock.');
|
|
1408
|
+
}
|
|
1394
1409
|
else {
|
|
1395
1410
|
logOnce('open-image-upload', 'OPEN_IMAGE_UPLOAD received but live dev mode cannot serve the native upload ' +
|
|
1396
1411
|
'modal — resolving the upload as dismissed (null). Test the image-upload flow ' +
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
* called). Only the postMessage bridge round-trips are exercised. Never import
|
|
38
38
|
* this from production code.
|
|
39
39
|
*/
|
|
40
|
-
import { type BlockContext, type BlockResourceInfo, type BlockResourcePickerType, type BlockUploadedImageInfo, type BlockGenerationSourceImageInfo, type BuzzAccountType, type BlockBuzzTransaction, type BlockBuzzAccount, type BlockDailyCompensationResource, type BlockViewer, type BlockWildcardPack, type BlockWildcardPackErrorCode, type AppWorkflow, type BlockModel3dOutput, type BlockPublishedModel, type BlockRunConfirmedStepHostError, type BlockGatedImage, type BlockPickedImageInfo, type BlockCollectionFollowErrorCode, type BlockEntityReactionErrorCode, type BlockCreatePostHostError, type BlockCreatePostResult, type
|
|
40
|
+
import { type BlockContext, type BlockResourceInfo, type BlockResourcePickerType, type BlockUploadedImageInfo, type BlockGenerationSourceImageInfo, type BuzzAccountType, type BlockBuzzTransaction, type BlockBuzzAccount, type BlockDailyCompensationResource, type BlockViewer, type BlockWildcardPack, type BlockWildcardPackErrorCode, type BlockResourceFile, type BlockResourceFileErrorCode, type AppWorkflow, type BlockModel3dOutput, type BlockPublishedModel, type BlockRunConfirmedStepHostError, type BlockGatedImage, type BlockPickedImageInfo, type BlockCollectionFollowErrorCode, type BlockEntityReactionErrorCode, type BlockCreatePostHostError, type BlockCreatePostResult, type BlockRunTrainingHostError, type BlockTrainingDataImage, type ColorDomain, type SharedStorageValue, type Theme, type ViewerInfo, type WorkflowBody } from '@civitai/app-sdk/blocks';
|
|
41
41
|
import { type MockMediaUploads } from './mediaUploadBytes.js';
|
|
42
42
|
import { type MockWorkflowQuoteFailure } from './mockWorkflowGraph.js';
|
|
43
43
|
import { type MockReactionSeed } from './mockHostReactions.js';
|
|
@@ -412,7 +412,7 @@ export interface MockGenerationScenario {
|
|
|
412
412
|
*/
|
|
413
413
|
export declare const MOCK_TRAINING_BOUNDS: {
|
|
414
414
|
readonly datasetMaxItems: 50;
|
|
415
|
-
readonly captionMaxChars:
|
|
415
|
+
readonly captionMaxChars: 8192;
|
|
416
416
|
readonly maxBuzzPerRun: 5000;
|
|
417
417
|
};
|
|
418
418
|
/**
|
|
@@ -425,16 +425,15 @@ export declare const MOCK_TRAINING_BOUNDS: {
|
|
|
425
425
|
export declare const MOCK_SPEND_SCOPE_ERROR = "block lacks ai:write:budgeted scope";
|
|
426
426
|
/** The real server's refusal for an unknown, expired or spent quote on `RUN_TRAINING`. */
|
|
427
427
|
export declare const MOCK_TRAINING_QUOTE_GONE_ERROR = "training quote not found, expired or already used \u2014 estimate again";
|
|
428
|
-
/** The real server's refusal for a training estimate naming a dataset it does not hold. */
|
|
429
|
-
export declare const MOCK_TRAINING_DATASET_GONE_ERROR = "training dataset not found or expired";
|
|
430
428
|
/**
|
|
431
|
-
* The
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
*
|
|
429
|
+
* The estimate's refusals for `items` outside the server's schema. The first two
|
|
430
|
+
* are the server's own custom messages (`blockTrainingDatasetItemsSchema`); the
|
|
431
|
+
* third stands for every other zod issue (count, caption length, missing or extra
|
|
432
|
+
* keys), whose real text is zod's formatting and not a contract.
|
|
435
433
|
*/
|
|
436
|
-
export declare const
|
|
437
|
-
export declare const
|
|
434
|
+
export declare const MOCK_TRAINING_AIR_ERROR = "air must be a consumer blob key or its Civitai-hosted blob url";
|
|
435
|
+
export declare const MOCK_TRAINING_DUPLICATE_ERROR = "a training dataset names each image once";
|
|
436
|
+
export declare const MOCK_TRAINING_ITEMS_ERROR = "training items must be 1 to 50 { air, caption } entries with captions of at most 8192 characters";
|
|
438
437
|
/**
|
|
439
438
|
* The per-job ceiling of a confirmed step — a COPY of `@civitai/app-sdk/blocks`'s
|
|
440
439
|
* `BLOCK_CONFIRMED_STEP_MAX_BUZZ_PER_JOB`, not value-imported for the reason
|
|
@@ -932,6 +931,21 @@ export interface MockHostOptions {
|
|
|
932
931
|
* returned. Live-tunable via {@link MockHost.setScenario}.
|
|
933
932
|
*/
|
|
934
933
|
wildcardPackError?: BlockWildcardPackErrorCode;
|
|
934
|
+
/**
|
|
935
|
+
* The parsed file returned from `GET_RESOURCE_FILE` (what `useResourceFile`
|
|
936
|
+
* reads). Absent → {@link DEFAULT_RESOURCE_FILE}, one UI-format graph. Ignored
|
|
937
|
+
* when {@link resourceFileError} is set. The mock returns it whatever
|
|
938
|
+
* `modelVersionId` / `fileId` the block asks for.
|
|
939
|
+
*/
|
|
940
|
+
resourceFile?: BlockResourceFile;
|
|
941
|
+
/**
|
|
942
|
+
* Force `GET_RESOURCE_FILE` to reply with this code from the CLOSED set
|
|
943
|
+
* (`not-found` | `forbidden` | `unauthorized` | `too-large` | `parse-failed` |
|
|
944
|
+
* `busy` | `rate-limited`) instead of a file — exercises `useResourceFile`'s
|
|
945
|
+
* error UI. Absent → a file is returned. Live-tunable via
|
|
946
|
+
* {@link MockHost.setScenario}, where passing the key as `undefined` clears it.
|
|
947
|
+
*/
|
|
948
|
+
resourceFileError?: BlockResourceFileErrorCode;
|
|
935
949
|
/**
|
|
936
950
|
* Force `SET_COLLECTION_FOLLOW` to reply with an `error` instead of writing —
|
|
937
951
|
* exercises `useCollectionFollow`'s refusal handling. Pass a
|
|
@@ -1014,41 +1028,34 @@ export interface MockHostOptions {
|
|
|
1014
1028
|
*/
|
|
1015
1029
|
createPostError?: BlockCreatePostHostError | string;
|
|
1016
1030
|
/**
|
|
1017
|
-
*
|
|
1018
|
-
* `
|
|
1019
|
-
*
|
|
1020
|
-
*
|
|
1031
|
+
* The images an `OPEN_IMAGE_UPLOAD { purpose: 'trainingData' }` returns — what
|
|
1032
|
+
* `useImageUpload({ purpose: 'trainingData' }).open()` resolves with. Absent →
|
|
1033
|
+
* {@link DEFAULT_TRAINING_DATA_UPLOAD_COUNT} images with FRESH keys on every
|
|
1034
|
+
* upload, so two uploads never collide. `null` (or `[]`) → the viewer cancelled.
|
|
1021
1035
|
* Live-tunable via {@link MockHost.setScenario}.
|
|
1022
1036
|
*
|
|
1023
|
-
*
|
|
1024
|
-
*
|
|
1025
|
-
*
|
|
1026
|
-
*
|
|
1027
|
-
* `
|
|
1028
|
-
*
|
|
1029
|
-
* KIND-FAITHFUL, like the rest of the training path: the
|
|
1030
|
-
*
|
|
1031
|
-
*
|
|
1032
|
-
* `ai:write:budgeted` on the token
|
|
1033
|
-
* a signed-in viewer. What it
|
|
1034
|
-
*
|
|
1035
|
-
*
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
*
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
reason: BlockTrainingRejectionReason;
|
|
1044
|
-
}>;
|
|
1045
|
-
/**
|
|
1046
|
-
* Force `PREPARE_TRAINING_DATASET` to reply with an `error` — a
|
|
1047
|
-
* {@link BlockPrepareTrainingDatasetHostError} for a host refusal, or any other
|
|
1048
|
-
* string for the free-text server-message variant. Absent → it prepares.
|
|
1049
|
-
* Live-tunable via {@link MockHost.setScenario}.
|
|
1037
|
+
* The mock REMEMBERS every key it hands out, per install, as the real host
|
|
1038
|
+
* does per block instance: `RUN_TRAINING` refuses a quote naming any other key
|
|
1039
|
+
* with `training data not uploaded here`, before any other check, and keeps the
|
|
1040
|
+
* quote. Keys compare case-insensitively; an item may name its blob by the
|
|
1041
|
+
* `url` too.
|
|
1042
|
+
*
|
|
1043
|
+
* KIND-FAITHFUL, like the rest of the training path: the estimate refuses items
|
|
1044
|
+
* outside the server's schema, a quote is run at most once and is checked
|
|
1045
|
+
* against the whole body it was quoted for (minus `quoteId`), and every
|
|
1046
|
+
* training call needs `ai:write:budgeted` on the token
|
|
1047
|
+
* ({@link MockHostOptions.consentGranted}) and a signed-in viewer. What it
|
|
1048
|
+
* cannot model: blob storage, the Civitai-hosted-url rule on `air`, the flag,
|
|
1049
|
+
* and the page-only / dev-token refusals.
|
|
1050
|
+
*/
|
|
1051
|
+
cannedTrainingDataUpload?: BlockTrainingDataImage[] | null;
|
|
1052
|
+
/**
|
|
1053
|
+
* Make `RUN_TRAINING` refuse EVERY quote with `training data not uploaded
|
|
1054
|
+
* here`, as the real host does after a page reload forgot the uploads. Settles
|
|
1055
|
+
* before the server claims the quote, so the quote survives. Live-tunable via
|
|
1056
|
+
* {@link MockHost.setScenario}; `undefined` clears it.
|
|
1050
1057
|
*/
|
|
1051
|
-
|
|
1058
|
+
trainingDataNotUploadedHere?: boolean;
|
|
1052
1059
|
/**
|
|
1053
1060
|
* The Buzz total a `kind: 'training'` estimate quotes. Default `500`. Above
|
|
1054
1061
|
* `BLOCK_TRAINING_MAX_BUZZ_PER_RUN` (5,000) the estimate fails exactly as the
|
|
@@ -1064,7 +1071,8 @@ export interface MockHostOptions {
|
|
|
1064
1071
|
*
|
|
1065
1072
|
* Whether the QUOTE survives follows the real flow: the host's own gate and
|
|
1066
1073
|
* dialog codes (`declined`, `review-mode`, `block is not ready`, `sign in to
|
|
1067
|
-
* train`, `invalid training request`, `no block token`
|
|
1074
|
+
* train`, `invalid training request`, `no block token`, `training data not
|
|
1075
|
+
* uploaded here`) settle before the
|
|
1068
1076
|
* server claims the quote, so it stays runnable; `submission-unconfirmed` and
|
|
1069
1077
|
* any server message settle after the claim, so it is used up — re-running it
|
|
1070
1078
|
* gets the quote-gone error. Live-tunable via {@link MockHost.setScenario};
|
|
@@ -1431,7 +1439,7 @@ export interface MockHostOptions {
|
|
|
1431
1439
|
* {@link MockHost.setTheme}, which pushes a real `THEME_CHANGE` — the mock of
|
|
1432
1440
|
* the viewer toggling dark mode with the block already mounted.)
|
|
1433
1441
|
*/
|
|
1434
|
-
export type MockHostScenarioPatch = Pick<MockHostOptions, 'consentGrantable' | 'failMode' | 'cost' | 'pollsUntilDone' | 'cannedPicks' | 'cannedMultiPicks' | 'cannedImagePicks' | 'cannedImageUpload' | 'cannedGenerationSourceUpload' | 'cannedImageScan' | 'generation' | 'buzz' | 'storage' | 'shared' | 'buzzBalanceError' | 'viewerResult' | 'viewerError' | 'buzzTransactions' | 'buzzAccounts' | 'dailyCompensation' | 'buzzReadError' | 'wildcardPack' | 'wildcardPackError' | 'collectionFollowError' | 'reactionStates' | 'reactionError' | 'createPostResult' | 'createPostError' | '
|
|
1442
|
+
export type MockHostScenarioPatch = Pick<MockHostOptions, 'consentGrantable' | 'failMode' | 'cost' | 'pollsUntilDone' | 'cannedPicks' | 'cannedMultiPicks' | 'cannedImagePicks' | 'cannedImageUpload' | 'cannedGenerationSourceUpload' | 'cannedImageScan' | 'generation' | 'buzz' | 'storage' | 'shared' | 'buzzBalanceError' | 'viewerResult' | 'viewerError' | 'buzzTransactions' | 'buzzAccounts' | 'dailyCompensation' | 'buzzReadError' | 'wildcardPack' | 'wildcardPackError' | 'resourceFile' | 'resourceFileError' | 'collectionFollowError' | 'reactionStates' | 'reactionError' | 'createPostResult' | 'createPostError' | 'cannedTrainingDataUpload' | 'trainingDataNotUploadedHere' | 'trainingQuoteTotal' | 'runTrainingError' | 'runTrainingCapRefusal' | 'runConfirmedStepError' | 'runConfirmedStepCapRefusal' | 'appWorkflows' | 'appWorkflowsError' | 'publishImageIds' | 'publishError' | 'gatedImages' | 'gatedImagesError' | 'disallowedAccountTypes' | 'saveImageError' | 'uploadImageBytesResult' | 'uploadImageBytesError' | 'cannedMediaUploads' | 'mediaUploadError'>;
|
|
1435
1443
|
/** Runtime Buzz-balance handle exposed on {@link MockHost.buzz}. */
|
|
1436
1444
|
export interface MockBuzzHandle {
|
|
1437
1445
|
/** Current simulated balance, or `undefined` when balance isn't simulated. */
|
|
@@ -1447,6 +1455,7 @@ export interface MockBuzzHandle {
|
|
|
1447
1455
|
*
|
|
1448
1456
|
* After install, a harness UI can drive scenarios live:
|
|
1449
1457
|
* - `setScenario(patch)` — merge new generation/buzz/storage/failMode controls.
|
|
1458
|
+
* `setScenario({ resourceFileError: undefined })` clears a forced resource-file error.
|
|
1450
1459
|
* - `setTheme('light' | 'dark')` — flip the site theme and push `THEME_CHANGE`.
|
|
1451
1460
|
* - `buzz.setBalance(n)` / `buzz.getBalance()` — flip the simulated wallet.
|
|
1452
1461
|
*
|