@civitai/app-sdk 0.73.0 → 0.75.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/dist/blocks/index.d.ts +8 -1
- package/dist/blocks/index.js +6 -0
- package/dist/blocks/messages.d.ts +61 -2
- package/dist/blocks/messages.js +3 -0
- package/dist/blocks/reactions.d.ts +126 -0
- package/dist/blocks/reactions.js +85 -0
- package/dist/blocks/scopes.js +4 -3
- package/dist/blocks/types.d.ts +53 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/orchestrator/index.d.ts +4 -1
- package/dist/orchestrator/index.js +4 -1
- package/package.json +1 -1
package/dist/blocks/index.d.ts
CHANGED
|
@@ -28,6 +28,13 @@ export type { BlockScope, BlockScopeKey, BlockCategory } from './scopes.js';
|
|
|
28
28
|
export { BrowsingLevel, SFW_LEVELS, NSFW_LEVELS, isSfwCeiling, isLevelAllowed, effectiveBrowsingCeiling, } from './browsingLevel.js';
|
|
29
29
|
export type { BrowsingLevelKey, BrowsingLevelBit, ColorDomain } from './browsingLevel.js';
|
|
30
30
|
export { APP_STORAGE_MAX_VALUE_BYTES, APP_STORAGE_MAX_BYTES, APP_STORAGE_MAX_ROWS, } from './appStorageLimits.js';
|
|
31
|
+
/**
|
|
32
|
+
* App reactions (`SET_ENTITY_REACTION` / `GET_ENTITY_REACTIONS`, scope
|
|
33
|
+
* `social:react:self`). The vocabulary mirrors civitai's
|
|
34
|
+
* `block-reaction.constants.ts`; see `reactions.ts`.
|
|
35
|
+
*/
|
|
36
|
+
export { APP_REACTIONS, STORED_REACTIONS, REACTION_ENTITY_TYPES, REACTION_READ_MAX_IDS, REACT_TICKET_MAX_LENGTH, ENTITY_REACTION_ERROR_CODES, isEntityReactionErrorCode, isAppReaction, } from './reactions.js';
|
|
37
|
+
export type { BlockAppReaction, BlockStoredReaction, BlockReactionEntityType, BlockEntityReactionErrorCode, BlockReactionCounts, BlockEntityReactionState, BlockEntityReactionResult, BlockEntityReactionsResult, } from './reactions.js';
|
|
31
38
|
export { BLOCK_IDEMPOTENCY_KEY_REGEX, BLOCK_IDEMPOTENCY_KEY_MAX_LENGTH, isValidBlockIdempotencyKey, blockIdempotencyKeyRejection, } from './idempotency.js';
|
|
32
39
|
/**
|
|
33
40
|
* The `srcdoc` escape hatch for embedding one of your own bundled documents
|
|
@@ -109,7 +116,7 @@ export { isModelSlotContext, isPageSlotContext } from './types.js';
|
|
|
109
116
|
* in `types.ts` for which of the two it uses and why.
|
|
110
117
|
*/
|
|
111
118
|
export { isSignedIn } from './types.js';
|
|
112
|
-
export type { BlockContext, KnownSlotId, ModelSlotId, PageSlotContext, PageSlotId, UnknownSlotContext, BlockAnalyticsDeclaration, BlockAnalyticsEventDeclaration, BlockAnalyticsPropertyDeclaration, BlockManifest, BlockManifestGood, BlockManifestV1, BlockSettings, BlockStorageCollectionDeclaration, BlockStorageDeclaration, BlockStorageIndexes, BlockStorageIndexType, BlockStoragePrivateCollectionDeclaration, BlockStorageSharedCollectionDeclaration, BlockToken, ContentRating, ManifestBooleanField, ManifestIframe, ManifestNumberField, ManifestPage, ManifestPreview, ManifestSettingField, ManifestSettings, ManifestStringField, ManifestTarget, ModelSlotContext, SettingScope, SettingWidget, Theme, ViewerInfo, BlockCheckpointInfo, BlockResourceInfo, BlockResourcePickerType, BlockSourceImage, BlockUploadedImageInfo, BlockGenerationSourceImageInfo, BlockImagePickerSource, BlockPickedImageInfo, 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';
|
|
119
|
+
export type { BlockContext, KnownSlotId, ModelSlotId, PageSlotContext, PageSlotId, UnknownSlotContext, BlockAnalyticsDeclaration, BlockAnalyticsEventDeclaration, BlockAnalyticsPropertyDeclaration, BlockManifest, BlockManifestGood, BlockManifestV1, BlockSettings, BlockStorageCollectionDeclaration, BlockStorageDeclaration, BlockStorageIndexes, BlockStorageIndexType, BlockStoragePrivateCollectionDeclaration, BlockStorageSharedCollectionDeclaration, BlockToken, ContentRating, ManifestBooleanField, ManifestIframe, ManifestNumberField, ManifestPage, ManifestPreview, ManifestSettingField, ManifestSettings, ManifestStringField, ManifestTarget, ModelSlotContext, SettingScope, SettingWidget, Theme, ViewerInfo, BlockCheckpointInfo, BlockResourceInfo, BlockResourcePickerType, BlockSourceImage, BlockUploadedImageInfo, BlockGenerationSourceImageInfo, BlockImagePickerSource, BlockPickedImageInfo, BlockMediaKind, BlockMediaUploadInfo, 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
120
|
/** Host bound for the App Blocks `kind: 'workflow'` body — see `WorkflowBodyWorkflow`. */
|
|
114
121
|
export { BLOCK_WORKFLOW_MAX_STEPS, BLOCK_WORKFLOW_REPEAT_MAX_ITERATIONS } from './types.js';
|
|
115
122
|
/**
|
package/dist/blocks/index.js
CHANGED
|
@@ -31,6 +31,12 @@ export { BlockManifestError } from './manifestError.js';
|
|
|
31
31
|
export { BLOCK_SCOPES, BLOCK_SCOPE_PATTERN, BLOCK_CATEGORIES, BLOCK_TAGLINE_MAX_LENGTH, } from './scopes.js';
|
|
32
32
|
export { BrowsingLevel, SFW_LEVELS, NSFW_LEVELS, isSfwCeiling, isLevelAllowed, effectiveBrowsingCeiling, } from './browsingLevel.js';
|
|
33
33
|
export { APP_STORAGE_MAX_VALUE_BYTES, APP_STORAGE_MAX_BYTES, APP_STORAGE_MAX_ROWS, } from './appStorageLimits.js';
|
|
34
|
+
/**
|
|
35
|
+
* App reactions (`SET_ENTITY_REACTION` / `GET_ENTITY_REACTIONS`, scope
|
|
36
|
+
* `social:react:self`). The vocabulary mirrors civitai's
|
|
37
|
+
* `block-reaction.constants.ts`; see `reactions.ts`.
|
|
38
|
+
*/
|
|
39
|
+
export { APP_REACTIONS, STORED_REACTIONS, REACTION_ENTITY_TYPES, REACTION_READ_MAX_IDS, REACT_TICKET_MAX_LENGTH, ENTITY_REACTION_ERROR_CODES, isEntityReactionErrorCode, isAppReaction, } from './reactions.js';
|
|
34
40
|
export { BLOCK_IDEMPOTENCY_KEY_REGEX, BLOCK_IDEMPOTENCY_KEY_MAX_LENGTH, isValidBlockIdempotencyKey, blockIdempotencyKeyRejection, } from './idempotency.js';
|
|
35
41
|
/**
|
|
36
42
|
* The `srcdoc` escape hatch for embedding one of your own bundled documents
|
|
@@ -8,7 +8,8 @@
|
|
|
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, BlockImagePickerSource, BlockPickedImageInfo, 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';
|
|
11
|
+
import type { BlockCheckpointInfo, BlockResourceInfo, BlockResourcePickerType, BlockUploadedImageInfo, BlockGenerationSourceImageInfo, BlockImagePickerSource, BlockPickedImageInfo, BlockMediaKind, BlockMediaUploadInfo, 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
|
+
import type { BlockAppReaction, BlockEntityReactionErrorCode, BlockEntityReactionResult, BlockEntityReactionsResult, BlockReactionEntityType } from './reactions.js';
|
|
12
13
|
/**
|
|
13
14
|
* Filter params for `GET_BUZZ_TRANSACTIONS`. All optional; the host validates
|
|
14
15
|
* them server-side (they are NEVER trusted for auth — the account is self-bound
|
|
@@ -531,6 +532,20 @@ export type ParentToBlockMessage = {
|
|
|
531
532
|
result?: BlockCollectionFollowResult;
|
|
532
533
|
error?: BlockCollectionFollowErrorCode | string;
|
|
533
534
|
};
|
|
535
|
+
} | {
|
|
536
|
+
type: 'ENTITY_REACTION_RESULT';
|
|
537
|
+
payload: {
|
|
538
|
+
requestId: string;
|
|
539
|
+
result?: BlockEntityReactionResult;
|
|
540
|
+
error?: BlockEntityReactionErrorCode | string;
|
|
541
|
+
};
|
|
542
|
+
} | {
|
|
543
|
+
type: 'ENTITY_REACTIONS_RESULT';
|
|
544
|
+
payload: {
|
|
545
|
+
requestId: string;
|
|
546
|
+
result?: BlockEntityReactionsResult;
|
|
547
|
+
error?: BlockEntityReactionErrorCode | string;
|
|
548
|
+
};
|
|
534
549
|
} | {
|
|
535
550
|
type: 'CANCEL_APP_WORKFLOW_RESULT';
|
|
536
551
|
payload: {
|
|
@@ -577,6 +592,13 @@ export type ParentToBlockMessage = {
|
|
|
577
592
|
selectedImages?: BlockPickedImageInfo[];
|
|
578
593
|
error?: string;
|
|
579
594
|
};
|
|
595
|
+
} | {
|
|
596
|
+
type: 'MEDIA_UPLOAD_RESULT';
|
|
597
|
+
payload: {
|
|
598
|
+
requestId: string;
|
|
599
|
+
selected?: BlockMediaUploadInfo;
|
|
600
|
+
error?: string;
|
|
601
|
+
};
|
|
580
602
|
} | {
|
|
581
603
|
type: 'USER_CHECKPOINT_SET';
|
|
582
604
|
payload: {
|
|
@@ -958,6 +980,19 @@ export type BlockToParentMessage = {
|
|
|
958
980
|
*/
|
|
959
981
|
publicOnly?: boolean;
|
|
960
982
|
};
|
|
983
|
+
} | {
|
|
984
|
+
type: 'OPEN_MEDIA_UPLOAD';
|
|
985
|
+
payload: {
|
|
986
|
+
requestId: string;
|
|
987
|
+
/** What kind of media to upload. The host refuses any other value. */
|
|
988
|
+
kind: BlockMediaKind;
|
|
989
|
+
/** Required. The only accepted value today. */
|
|
990
|
+
purpose: 'generationSource';
|
|
991
|
+
/** In-tab bytes: present = bytes mode (no picker), absent = picker mode. */
|
|
992
|
+
bytes?: ArrayBuffer;
|
|
993
|
+
/** Bytes mode only: the type the app believes it is sending; must match the content. */
|
|
994
|
+
mimeType?: string;
|
|
995
|
+
};
|
|
961
996
|
} | {
|
|
962
997
|
type: 'SET_USER_CHECKPOINT';
|
|
963
998
|
payload: {
|
|
@@ -1112,6 +1147,30 @@ export type BlockToParentMessage = {
|
|
|
1112
1147
|
/** `true` ⇒ follow, `false` ⇒ unfollow. */
|
|
1113
1148
|
follow: boolean;
|
|
1114
1149
|
};
|
|
1150
|
+
} | {
|
|
1151
|
+
type: 'SET_ENTITY_REACTION';
|
|
1152
|
+
payload: {
|
|
1153
|
+
requestId: string;
|
|
1154
|
+
entityType: BlockReactionEntityType;
|
|
1155
|
+
/** Positive integer. A numeric STRING is refused, never coerced. */
|
|
1156
|
+
entityId: number;
|
|
1157
|
+
/** One of `APP_REACTIONS`. `Dislike` is refused as `invalid-request`. */
|
|
1158
|
+
reaction: BlockAppReaction;
|
|
1159
|
+
/** `true` ⇒ the reaction exists afterwards; `false` ⇒ it does not. */
|
|
1160
|
+
reacted: boolean;
|
|
1161
|
+
/** 1 to `REACT_TICKET_MAX_LENGTH` characters. */
|
|
1162
|
+
ticket?: string;
|
|
1163
|
+
};
|
|
1164
|
+
} | {
|
|
1165
|
+
type: 'GET_ENTITY_REACTIONS';
|
|
1166
|
+
payload: {
|
|
1167
|
+
requestId: string;
|
|
1168
|
+
entityType: BlockReactionEntityType;
|
|
1169
|
+
/** 1 to `REACTION_READ_MAX_IDS` positive integers. Duplicates are collapsed. */
|
|
1170
|
+
ids: number[];
|
|
1171
|
+
/** A ticket per id, keyed by the id as a string. */
|
|
1172
|
+
tickets?: Record<string, string>;
|
|
1173
|
+
};
|
|
1115
1174
|
};
|
|
1116
1175
|
export type BlockToParentMessageType = BlockToParentMessage['type'];
|
|
1117
1176
|
/**
|
|
@@ -1155,7 +1214,7 @@ export type BlockToParentMessageType = BlockToParentMessage['type'];
|
|
|
1155
1214
|
* it is a measurement, not an invariant, and civitai's own compile-time gate
|
|
1156
1215
|
* (published SDK union ⊆ `keyof INVENTORY`) is what holds one direction of it.
|
|
1157
1216
|
*/
|
|
1158
|
-
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", "OPEN_IMAGE_PICKER", "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"];
|
|
1217
|
+
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", "OPEN_IMAGE_PICKER", "OPEN_MEDIA_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", "SET_ENTITY_REACTION", "GET_ENTITY_REACTIONS"];
|
|
1159
1218
|
/**
|
|
1160
1219
|
* The bucket a message type falls into when the protocol does not declare it.
|
|
1161
1220
|
*
|
package/dist/blocks/messages.js
CHANGED
|
@@ -79,6 +79,7 @@ export const BLOCK_TO_PARENT_MESSAGE_TYPES = [
|
|
|
79
79
|
'OPEN_RESOURCE_PICKER',
|
|
80
80
|
'OPEN_IMAGE_UPLOAD',
|
|
81
81
|
'OPEN_IMAGE_PICKER',
|
|
82
|
+
'OPEN_MEDIA_UPLOAD',
|
|
82
83
|
'SET_USER_CHECKPOINT',
|
|
83
84
|
'NAVIGATE',
|
|
84
85
|
'REQUEST_SIGN_IN',
|
|
@@ -101,6 +102,8 @@ export const BLOCK_TO_PARENT_MESSAGE_TYPES = [
|
|
|
101
102
|
'SHARED_REPORT',
|
|
102
103
|
'SAVE_IMAGE',
|
|
103
104
|
'SET_COLLECTION_FOLLOW',
|
|
105
|
+
'SET_ENTITY_REACTION',
|
|
106
|
+
'GET_ENTITY_REACTIONS',
|
|
104
107
|
];
|
|
105
108
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
106
109
|
const _messageTypesGate = true;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App reactions — the block side of `SET_ENTITY_REACTION` / `GET_ENTITY_REACTIONS`
|
|
3
|
+
* (scope `social:react:self`, civitai/civitai#6144).
|
|
4
|
+
*
|
|
5
|
+
* A block may set, or read, the VIEWER'S reaction on an image a block endpoint
|
|
6
|
+
* served it. The host calls `blocks.setReactionFromApp` /
|
|
7
|
+
* `blocks.getReactionsForApp`, which run the SAME handler as the site's own
|
|
8
|
+
* reaction button: rewards, metrics and notifications are the site's. What the
|
|
9
|
+
* app path adds is an audit row per change, a provenance ticket per image and a
|
|
10
|
+
* fail-closed kill switch.
|
|
11
|
+
*
|
|
12
|
+
* Every constant here MIRRORS civitai/civitai's
|
|
13
|
+
* `src/shared/constants/block-reaction.constants.ts`. The host's copy is the
|
|
14
|
+
* definition and this is the copy; `test/blocks/reactions.test.ts` pins each
|
|
15
|
+
* value literally, so a change on either side is a visible diff here.
|
|
16
|
+
*
|
|
17
|
+
* The scope is `BLOCK_SCOPES.SOCIAL_REACT_SELF`: consent-gated (a token carries
|
|
18
|
+
* it only after the viewer granted it) and sensitive (the manifest must justify
|
|
19
|
+
* it in `scopeJustifications`).
|
|
20
|
+
*
|
|
21
|
+
* Zero dependencies, like the rest of `./blocks`.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* The reactions an app may SET on an image.
|
|
25
|
+
*
|
|
26
|
+
* 🔴 `Dislike` IS DELIBERATELY ABSENT, and the host and the server both refuse
|
|
27
|
+
* it. Image stats hardcode the dislike count to 0, so a Dislike is invisible on
|
|
28
|
+
* the site, yet it is stored and still pays the reactor's encouragement reward.
|
|
29
|
+
*/
|
|
30
|
+
export declare const APP_REACTIONS: readonly ["Like", "Heart", "Laugh", "Cry"];
|
|
31
|
+
export type BlockAppReaction = (typeof APP_REACTIONS)[number];
|
|
32
|
+
/**
|
|
33
|
+
* Every reaction the site STORES. A viewer's existing reactions are reported in
|
|
34
|
+
* this wider set: a viewer who disliked an image on the site still holds that
|
|
35
|
+
* Dislike, and the read says so, even though an app may not set one.
|
|
36
|
+
*/
|
|
37
|
+
export declare const STORED_REACTIONS: readonly ["Like", "Dislike", "Laugh", "Cry", "Heart"];
|
|
38
|
+
export type BlockStoredReaction = (typeof STORED_REACTIONS)[number];
|
|
39
|
+
/** Entity types the host accepts. Image only in v1: nothing else is ticketed yet. */
|
|
40
|
+
export declare const REACTION_ENTITY_TYPES: readonly ["image"];
|
|
41
|
+
export type BlockReactionEntityType = (typeof REACTION_ENTITY_TYPES)[number];
|
|
42
|
+
/** Most ids one `GET_ENTITY_REACTIONS` may carry. More is refused as `invalid-request`. */
|
|
43
|
+
export declare const REACTION_READ_MAX_IDS = 100;
|
|
44
|
+
/** Longest ticket the host accepts. A real one is about 60 characters. */
|
|
45
|
+
export declare const REACT_TICKET_MAX_LENGTH = 256;
|
|
46
|
+
/**
|
|
47
|
+
* The CLOSED set of errors `ENTITY_REACTION_RESULT` and `ENTITY_REACTIONS_RESULT`
|
|
48
|
+
* carry. Unlike the follow and post bridges, the host maps EVERY failure,
|
|
49
|
+
* its own refusals and every server error alike, onto one of these
|
|
50
|
+
* (`classifyEntityReactionError` in civitai's `reactionGate.ts`), so a block can
|
|
51
|
+
* branch on the code.
|
|
52
|
+
*
|
|
53
|
+
* - `invalid-request`: a malformed payload, or a reaction apps may not set
|
|
54
|
+
* (`Dislike`). A block bug, not a viewer outcome.
|
|
55
|
+
* - `sign-in-required`: no session. Route it into `useRequestSignIn()`.
|
|
56
|
+
* - `review-mode`: the app is running in a moderator's review sandbox, where
|
|
57
|
+
* the scope is never granted.
|
|
58
|
+
* - `not-ready`: the host has not finished the handshake, or holds no token yet.
|
|
59
|
+
* Retry after `ready`.
|
|
60
|
+
* - `needs-consent`: the viewer has not granted `social:react:self`. Ask with
|
|
61
|
+
* `useRequestConsent()`.
|
|
62
|
+
* - `entity-unavailable`: everything else. A missing, expired or foreign
|
|
63
|
+
* ticket, an image the viewer may not react to, an owner who blocked the
|
|
64
|
+
* viewer, the kill switch, or a network failure. Deliberately one code: the
|
|
65
|
+
* block can retry or give up, and there is no truthful finer answer.
|
|
66
|
+
* - `rate-limited`: the viewer's reaction quota is spent. It is the SAME quota
|
|
67
|
+
* the site's own reaction button draws on.
|
|
68
|
+
*/
|
|
69
|
+
export declare const ENTITY_REACTION_ERROR_CODES: readonly ["invalid-request", "sign-in-required", "review-mode", "not-ready", "needs-consent", "entity-unavailable", "rate-limited"];
|
|
70
|
+
export type BlockEntityReactionErrorCode = (typeof ENTITY_REACTION_ERROR_CODES)[number];
|
|
71
|
+
/** `true` when `value` is one of the closed {@link ENTITY_REACTION_ERROR_CODES}. */
|
|
72
|
+
export declare function isEntityReactionErrorCode(value: unknown): value is BlockEntityReactionErrorCode;
|
|
73
|
+
/** `true` when `value` is a reaction an app may set ({@link APP_REACTIONS}). */
|
|
74
|
+
export declare function isAppReaction(value: unknown): value is BlockAppReaction;
|
|
75
|
+
/** Reaction counts for one image, as the site's own feeds show them. */
|
|
76
|
+
export type BlockReactionCounts = Record<BlockAppReaction, number>;
|
|
77
|
+
/** One image's reaction state, as the read reports it. */
|
|
78
|
+
export interface BlockEntityReactionState {
|
|
79
|
+
counts: BlockReactionCounts;
|
|
80
|
+
/** Every reaction the viewer holds on the image. A viewer may hold several. */
|
|
81
|
+
viewerReactions: BlockStoredReaction[];
|
|
82
|
+
/**
|
|
83
|
+
* `true` when the metric store could not answer for this image. `counts` are
|
|
84
|
+
* then zeros, and must not be shown as "nobody reacted".
|
|
85
|
+
*/
|
|
86
|
+
statsUnknown: boolean;
|
|
87
|
+
}
|
|
88
|
+
/** The success payload of `ENTITY_REACTION_RESULT`. */
|
|
89
|
+
export interface BlockEntityReactionResult extends BlockEntityReactionState {
|
|
90
|
+
entityType: BlockReactionEntityType;
|
|
91
|
+
entityId: number;
|
|
92
|
+
reaction: BlockAppReaction;
|
|
93
|
+
/**
|
|
94
|
+
* Whether the viewer holds `reaction` NOW, read on the primary after the
|
|
95
|
+
* write. 🔴 When this differs from the `reacted` the block asked for, a
|
|
96
|
+
* concurrent change (a double tap, the viewer's own click elsewhere) won and
|
|
97
|
+
* this request did not apply.
|
|
98
|
+
*/
|
|
99
|
+
reacted: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Did THIS request write a change? `false` when the viewer was already in the
|
|
102
|
+
* requested state: nothing was toggled, so nothing was paid and no metric
|
|
103
|
+
* moved.
|
|
104
|
+
*/
|
|
105
|
+
changed: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* 🔴 `counts` CAN LAG `reacted`. They come from the metric store, which
|
|
108
|
+
* updates asynchronously, so right after a change they may not include it yet.
|
|
109
|
+
* `reacted` and `viewerReactions` are the truth.
|
|
110
|
+
*/
|
|
111
|
+
counts: BlockReactionCounts;
|
|
112
|
+
}
|
|
113
|
+
/** The success payload of `ENTITY_REACTIONS_RESULT`. */
|
|
114
|
+
export interface BlockEntityReactionsResult {
|
|
115
|
+
entityType: BlockReactionEntityType;
|
|
116
|
+
/** One entry per ticketed id, keyed by the id as a string (it crossed JSON). */
|
|
117
|
+
byId: Record<string, BlockEntityReactionState>;
|
|
118
|
+
/**
|
|
119
|
+
* Ids the host did not answer, because their ticket was missing, expired, or
|
|
120
|
+
* issued to another app or viewer. 🔴 Not "the viewer has not reacted": an
|
|
121
|
+
* unanswered id has NO known state, and a block must not offer a fresh
|
|
122
|
+
* reaction on the assumption that there is none.
|
|
123
|
+
*/
|
|
124
|
+
unavailable: number[];
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=reactions.d.ts.map
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App reactions — the block side of `SET_ENTITY_REACTION` / `GET_ENTITY_REACTIONS`
|
|
3
|
+
* (scope `social:react:self`, civitai/civitai#6144).
|
|
4
|
+
*
|
|
5
|
+
* A block may set, or read, the VIEWER'S reaction on an image a block endpoint
|
|
6
|
+
* served it. The host calls `blocks.setReactionFromApp` /
|
|
7
|
+
* `blocks.getReactionsForApp`, which run the SAME handler as the site's own
|
|
8
|
+
* reaction button: rewards, metrics and notifications are the site's. What the
|
|
9
|
+
* app path adds is an audit row per change, a provenance ticket per image and a
|
|
10
|
+
* fail-closed kill switch.
|
|
11
|
+
*
|
|
12
|
+
* Every constant here MIRRORS civitai/civitai's
|
|
13
|
+
* `src/shared/constants/block-reaction.constants.ts`. The host's copy is the
|
|
14
|
+
* definition and this is the copy; `test/blocks/reactions.test.ts` pins each
|
|
15
|
+
* value literally, so a change on either side is a visible diff here.
|
|
16
|
+
*
|
|
17
|
+
* The scope is `BLOCK_SCOPES.SOCIAL_REACT_SELF`: consent-gated (a token carries
|
|
18
|
+
* it only after the viewer granted it) and sensitive (the manifest must justify
|
|
19
|
+
* it in `scopeJustifications`).
|
|
20
|
+
*
|
|
21
|
+
* Zero dependencies, like the rest of `./blocks`.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* The reactions an app may SET on an image.
|
|
25
|
+
*
|
|
26
|
+
* 🔴 `Dislike` IS DELIBERATELY ABSENT, and the host and the server both refuse
|
|
27
|
+
* it. Image stats hardcode the dislike count to 0, so a Dislike is invisible on
|
|
28
|
+
* the site, yet it is stored and still pays the reactor's encouragement reward.
|
|
29
|
+
*/
|
|
30
|
+
export const APP_REACTIONS = ['Like', 'Heart', 'Laugh', 'Cry'];
|
|
31
|
+
/**
|
|
32
|
+
* Every reaction the site STORES. A viewer's existing reactions are reported in
|
|
33
|
+
* this wider set: a viewer who disliked an image on the site still holds that
|
|
34
|
+
* Dislike, and the read says so, even though an app may not set one.
|
|
35
|
+
*/
|
|
36
|
+
export const STORED_REACTIONS = ['Like', 'Dislike', 'Laugh', 'Cry', 'Heart'];
|
|
37
|
+
/** Entity types the host accepts. Image only in v1: nothing else is ticketed yet. */
|
|
38
|
+
export const REACTION_ENTITY_TYPES = ['image'];
|
|
39
|
+
/** Most ids one `GET_ENTITY_REACTIONS` may carry. More is refused as `invalid-request`. */
|
|
40
|
+
export const REACTION_READ_MAX_IDS = 100;
|
|
41
|
+
/** Longest ticket the host accepts. A real one is about 60 characters. */
|
|
42
|
+
export const REACT_TICKET_MAX_LENGTH = 256;
|
|
43
|
+
/**
|
|
44
|
+
* The CLOSED set of errors `ENTITY_REACTION_RESULT` and `ENTITY_REACTIONS_RESULT`
|
|
45
|
+
* carry. Unlike the follow and post bridges, the host maps EVERY failure,
|
|
46
|
+
* its own refusals and every server error alike, onto one of these
|
|
47
|
+
* (`classifyEntityReactionError` in civitai's `reactionGate.ts`), so a block can
|
|
48
|
+
* branch on the code.
|
|
49
|
+
*
|
|
50
|
+
* - `invalid-request`: a malformed payload, or a reaction apps may not set
|
|
51
|
+
* (`Dislike`). A block bug, not a viewer outcome.
|
|
52
|
+
* - `sign-in-required`: no session. Route it into `useRequestSignIn()`.
|
|
53
|
+
* - `review-mode`: the app is running in a moderator's review sandbox, where
|
|
54
|
+
* the scope is never granted.
|
|
55
|
+
* - `not-ready`: the host has not finished the handshake, or holds no token yet.
|
|
56
|
+
* Retry after `ready`.
|
|
57
|
+
* - `needs-consent`: the viewer has not granted `social:react:self`. Ask with
|
|
58
|
+
* `useRequestConsent()`.
|
|
59
|
+
* - `entity-unavailable`: everything else. A missing, expired or foreign
|
|
60
|
+
* ticket, an image the viewer may not react to, an owner who blocked the
|
|
61
|
+
* viewer, the kill switch, or a network failure. Deliberately one code: the
|
|
62
|
+
* block can retry or give up, and there is no truthful finer answer.
|
|
63
|
+
* - `rate-limited`: the viewer's reaction quota is spent. It is the SAME quota
|
|
64
|
+
* the site's own reaction button draws on.
|
|
65
|
+
*/
|
|
66
|
+
export const ENTITY_REACTION_ERROR_CODES = [
|
|
67
|
+
'invalid-request',
|
|
68
|
+
'sign-in-required',
|
|
69
|
+
'review-mode',
|
|
70
|
+
'not-ready',
|
|
71
|
+
'needs-consent',
|
|
72
|
+
'entity-unavailable',
|
|
73
|
+
'rate-limited',
|
|
74
|
+
];
|
|
75
|
+
const ERROR_CODE_SET = new Set(ENTITY_REACTION_ERROR_CODES);
|
|
76
|
+
const APP_REACTION_SET = new Set(APP_REACTIONS);
|
|
77
|
+
/** `true` when `value` is one of the closed {@link ENTITY_REACTION_ERROR_CODES}. */
|
|
78
|
+
export function isEntityReactionErrorCode(value) {
|
|
79
|
+
return typeof value === 'string' && ERROR_CODE_SET.has(value);
|
|
80
|
+
}
|
|
81
|
+
/** `true` when `value` is a reaction an app may set ({@link APP_REACTIONS}). */
|
|
82
|
+
export function isAppReaction(value) {
|
|
83
|
+
return typeof value === 'string' && APP_REACTION_SET.has(value);
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=reactions.js.map
|
package/dist/blocks/scopes.js
CHANGED
|
@@ -93,9 +93,10 @@ export const BLOCK_SCOPES = {
|
|
|
93
93
|
// social:react:self — set the VIEWER'S reaction on an image a block endpoint
|
|
94
94
|
// served the app (civitai/civitai#6144). SENSITIVE (a public, reward-paying
|
|
95
95
|
// reaction under the viewer's name, so a declaring manifest MUST carry a
|
|
96
|
-
// `scopeJustifications` entry) and CONSENT-GATED.
|
|
97
|
-
//
|
|
98
|
-
//
|
|
96
|
+
// `scopeJustifications` entry) and CONSENT-GATED. The bridge is
|
|
97
|
+
// SET_ENTITY_REACTION / GET_ENTITY_REACTIONS (see `reactions.ts`), and
|
|
98
|
+
// `useReactions` in `@civitai/blocks-react` drives it. The server gates it
|
|
99
|
+
// behind a fail-closed flag as well as the grant.
|
|
99
100
|
SOCIAL_REACT_SELF: 'social:react:self',
|
|
100
101
|
};
|
|
101
102
|
/**
|
package/dist/blocks/types.d.ts
CHANGED
|
@@ -372,6 +372,51 @@ export interface BlockPickedImageInfo {
|
|
|
372
372
|
*/
|
|
373
373
|
imageId?: number;
|
|
374
374
|
}
|
|
375
|
+
/**
|
|
376
|
+
* What kind of media `OPEN_MEDIA_UPLOAD` (via `useMediaUpload`) uploads. The
|
|
377
|
+
* host decides the file's real type from its MAGIC BYTES, never from a declared
|
|
378
|
+
* MIME type, and accepts per kind:
|
|
379
|
+
* - `'image'`: PNG, JPEG or WebP;
|
|
380
|
+
* - `'video'`: MP4 or WebM;
|
|
381
|
+
* - `'audio'`: MP3, WAV or WebM.
|
|
382
|
+
*/
|
|
383
|
+
export type BlockMediaKind = 'image' | 'video' | 'audio';
|
|
384
|
+
/**
|
|
385
|
+
* One media file the host uploaded for the block as a GENERATION INPUT
|
|
386
|
+
* (`MEDIA_UPLOAD_RESULT.selected`, via `useMediaUpload`).
|
|
387
|
+
*
|
|
388
|
+
* `url` is a PRIVATE generation-input URL: pass it into a workflow step input
|
|
389
|
+
* (an image, video or audio input). It is not a public Civitai image and has no
|
|
390
|
+
* `imageId`. The host refuses data URIs and inline
|
|
391
|
+
* base64 in step inputs, so this is how a block gets media it holds (a picked
|
|
392
|
+
* file, a canvas, a recording) into a step.
|
|
393
|
+
*
|
|
394
|
+
* Per kind:
|
|
395
|
+
* - `'image'`: the host RESIZES the picture so both sides are within 64–2048
|
|
396
|
+
* pixels and RE-ENCODES it as JPEG. `mimeType` is always `'image/jpeg'`,
|
|
397
|
+
* and `sizeBytes`, `width` and `height` describe that JPEG.
|
|
398
|
+
* - `'video'`: uploaded as sent. `width` / `height` are always set (the host
|
|
399
|
+
* refuses a file with no video track); `durationMs` is set when the browser
|
|
400
|
+
* reports a finite duration.
|
|
401
|
+
* - `'audio'`: uploaded as sent. No `width` / `height`; `durationMs` as for
|
|
402
|
+
* video. A `MediaRecorder` WebM can report no duration, so do not rely on it.
|
|
403
|
+
*/
|
|
404
|
+
export interface BlockMediaUploadInfo {
|
|
405
|
+
/** The private generation-input URL. Pass it into a step input. */
|
|
406
|
+
url: string;
|
|
407
|
+
/** The kind that was requested. */
|
|
408
|
+
kind: BlockMediaKind;
|
|
409
|
+
/** The type actually uploaded. Always `'image/jpeg'` for `'image'`. */
|
|
410
|
+
mimeType: string;
|
|
411
|
+
/** Bytes actually uploaded (for `'image'`, the re-encoded JPEG's size). */
|
|
412
|
+
sizeBytes: number;
|
|
413
|
+
/** Pixel width. Always set for `'image'` and `'video'`; absent for `'audio'`. */
|
|
414
|
+
width?: number;
|
|
415
|
+
/** Pixel height. Always set for `'image'` and `'video'`; absent for `'audio'`. */
|
|
416
|
+
height?: number;
|
|
417
|
+
/** Duration in milliseconds, for `'video'` / `'audio'` when known. Never set for `'image'`. */
|
|
418
|
+
durationMs?: number;
|
|
419
|
+
}
|
|
375
420
|
/**
|
|
376
421
|
* One of the model version's curated preview images, with the standard
|
|
377
422
|
* gen params extracted from its source meta. Block UIs use these to let
|
|
@@ -1295,8 +1340,14 @@ export type WorkflowBodyPassThroughStep = {
|
|
|
1295
1340
|
*
|
|
1296
1341
|
* Consequently the orchestrator's per-`$type` schema is the ONLY authority for
|
|
1297
1342
|
* what a given `$type` accepts; nothing in this package or on the host mirrors
|
|
1298
|
-
* it.
|
|
1299
|
-
* is a payload-DoS bound and not a shape gate.
|
|
1343
|
+
* it. Its shape is not checked; its size is: at most **262144 bytes** (256 KB)
|
|
1344
|
+
* serialized, which is a payload-DoS bound and not a shape gate.
|
|
1345
|
+
*
|
|
1346
|
+
* 🔴 **No inline media.** The host refuses a `data:image|video|audio` URI or a
|
|
1347
|
+
* long raw base64 string anywhere in here: upload the image, video or audio
|
|
1348
|
+
* with `useMediaUpload()` (an image also works with
|
|
1349
|
+
* `useImageUpload({ purpose: 'generationSource' })` or `useImagePicker()`)
|
|
1350
|
+
* and pass the returned `url`.
|
|
1300
1351
|
*/
|
|
1301
1352
|
input: Record<string, unknown>;
|
|
1302
1353
|
/**
|
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
|
+
* 198 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 198 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
|
+
* 198 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 198 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
|
|
@@ -430,11 +430,14 @@ export interface BuildImageGenBodyOptions {
|
|
|
430
430
|
*
|
|
431
431
|
* @example Nano Banana 2 with a reference image
|
|
432
432
|
* ```ts
|
|
433
|
+
* // Pass a hosted image URL, not a data URI or raw base64. In an App Block, the
|
|
434
|
+
* // `url` from `useImageUpload({ purpose: 'generationSource' })` or `useImagePicker()`;
|
|
435
|
+
* // the block host refuses inline media in a step input.
|
|
433
436
|
* const body = buildImageGenBody({
|
|
434
437
|
* engine: 'google',
|
|
435
438
|
* model: 'nano-banana-2',
|
|
436
439
|
* prompt: 'turn this into a cartoon sticker',
|
|
437
|
-
* images: [
|
|
440
|
+
* images: [source.url],
|
|
438
441
|
* aspectRatio: '1:1',
|
|
439
442
|
* numImages: 1,
|
|
440
443
|
* resolution: '1K',
|
|
@@ -393,11 +393,14 @@ export function buildTextToImageBody(input, opts = {}) {
|
|
|
393
393
|
*
|
|
394
394
|
* @example Nano Banana 2 with a reference image
|
|
395
395
|
* ```ts
|
|
396
|
+
* // Pass a hosted image URL, not a data URI or raw base64. In an App Block, the
|
|
397
|
+
* // `url` from `useImageUpload({ purpose: 'generationSource' })` or `useImagePicker()`;
|
|
398
|
+
* // the block host refuses inline media in a step input.
|
|
396
399
|
* const body = buildImageGenBody({
|
|
397
400
|
* engine: 'google',
|
|
398
401
|
* model: 'nano-banana-2',
|
|
399
402
|
* prompt: 'turn this into a cartoon sticker',
|
|
400
|
-
* images: [
|
|
403
|
+
* images: [source.url],
|
|
401
404
|
* aspectRatio: '1:1',
|
|
402
405
|
* numImages: 1,
|
|
403
406
|
* resolution: '1K',
|
package/package.json
CHANGED