merge: integrate marketplace and design v2 client
This commit is contained in:
@@ -3,9 +3,17 @@ export const IMAGE_WORKSPACE_UNAVAILABLE_MESSAGE = 'AI 设计暂不可用';
|
||||
export const IMAGE_WORKSPACE_API_PATH = '/api/works/image-workspace';
|
||||
|
||||
export type DesignMedium = 'image' | 'video';
|
||||
export type DesignWorkspacePhase = 'shaping' | 'awaiting_confirmation' | 'blocked';
|
||||
export type DesignTaskStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled';
|
||||
export type DesignQuoteStatus = 'active' | 'consumed' | 'expired' | 'superseded';
|
||||
export type DesignResolution = 'open' | 'proposed' | 'resolved' | 'delegated' | 'not_applicable';
|
||||
export type DesignProvenance =
|
||||
| 'user'
|
||||
| 'extracted_user'
|
||||
| 'agent_proposal'
|
||||
| 'delegated_agent'
|
||||
| 'deterministic'
|
||||
| 'inherited'
|
||||
| 'reference_observation'
|
||||
| 'restored'
|
||||
| 'legacy_import';
|
||||
|
||||
export type DesignCapabilities = {
|
||||
conversation: boolean;
|
||||
@@ -14,181 +22,309 @@ export type DesignCapabilities = {
|
||||
video: boolean;
|
||||
};
|
||||
|
||||
export type DesignBrief = {
|
||||
version: number;
|
||||
status: 'draft' | 'ready' | 'confirmed';
|
||||
medium: DesignMedium | null;
|
||||
summary: string;
|
||||
ready: boolean;
|
||||
missingDecision: string | null;
|
||||
export type DesignFieldDecision = {
|
||||
resolution: DesignResolution;
|
||||
provenance: DesignProvenance;
|
||||
locked: boolean;
|
||||
changed_by: string;
|
||||
origin_turn_id: string | null;
|
||||
};
|
||||
|
||||
export type DesignGenerationOption<TValue extends string | number> = {
|
||||
value: TValue;
|
||||
export type DesignSpecificationValues = {
|
||||
intent: {
|
||||
media: DesignMedium | null;
|
||||
creation_intent: 'create' | 'edit' | 'vary' | 'composite' | 'animate' | 'extend' | null;
|
||||
purpose: string | null;
|
||||
channel: string | null;
|
||||
audience: string | null;
|
||||
intended_response: string | null;
|
||||
communication_goal: string | null;
|
||||
success_definition: string | null;
|
||||
related_direction_id: string | null;
|
||||
related_asset_id: string | null;
|
||||
};
|
||||
content: {
|
||||
concept: string | null;
|
||||
narrative: string | null;
|
||||
subjects: Array<{
|
||||
id: string;
|
||||
description: string;
|
||||
attributes: string[];
|
||||
action: string | null;
|
||||
spatial_relationship: string | null;
|
||||
}>;
|
||||
action: string | null;
|
||||
environment: string | null;
|
||||
emotional_tone: string | null;
|
||||
exact_content: Array<{
|
||||
id: string;
|
||||
text: string;
|
||||
role: string | null;
|
||||
language: string | null;
|
||||
hierarchy: string | null;
|
||||
exact: boolean;
|
||||
}>;
|
||||
};
|
||||
visual: {
|
||||
art_direction: string | null;
|
||||
cultural_cues: string | null;
|
||||
composition: string | null;
|
||||
viewpoint: string | null;
|
||||
lighting: string | null;
|
||||
palette: string | null;
|
||||
materials: string | null;
|
||||
finish: string | null;
|
||||
};
|
||||
layout: {
|
||||
regions: Array<{ id: string; role: string; placement: string; priority: number }>;
|
||||
subject_placement: string | null;
|
||||
text_placement: string | null;
|
||||
logo_placement: string | null;
|
||||
safe_areas: string | null;
|
||||
crop_behavior: string | null;
|
||||
typography: string | null;
|
||||
exact_rendering: string | null;
|
||||
};
|
||||
references: Array<{
|
||||
id: string;
|
||||
asset_id: string;
|
||||
asset_revision: number | null;
|
||||
role: string;
|
||||
preserve: string[];
|
||||
adapt: string[];
|
||||
do_not_copy: string[];
|
||||
reviewed_observations: string[];
|
||||
}>;
|
||||
image: {
|
||||
operation_intent: string | null;
|
||||
source_asset_id: string | null;
|
||||
mask_asset_id: string | null;
|
||||
preserve_instructions: string[];
|
||||
change_instructions: string[];
|
||||
background_behavior: string | null;
|
||||
transparency_required: boolean | null;
|
||||
edge_crop_behavior: string | null;
|
||||
variant_relationship: string | null;
|
||||
};
|
||||
video: {
|
||||
total_duration_seconds: number | null;
|
||||
pacing: string | null;
|
||||
first_frame_asset_id: string | null;
|
||||
last_frame_asset_id: string | null;
|
||||
shots: Array<{
|
||||
id: string;
|
||||
start_milliseconds: number | null;
|
||||
end_milliseconds: number | null;
|
||||
story_beat: string;
|
||||
framing: string | null;
|
||||
camera: string | null;
|
||||
subject_motion: string | null;
|
||||
environment_motion: string | null;
|
||||
focus_behavior: string | null;
|
||||
transition: string | null;
|
||||
}>;
|
||||
rhythm: string | null;
|
||||
speed_behavior: string | null;
|
||||
stillness: string | null;
|
||||
loop_behavior: string | null;
|
||||
end_state: string | null;
|
||||
continuity: string | null;
|
||||
audio_intent: string | null;
|
||||
};
|
||||
output: {
|
||||
aspect_ratio: string | null;
|
||||
orientation: string | null;
|
||||
quality_intent: string | null;
|
||||
delivery_format: string | null;
|
||||
variant_count: number | null;
|
||||
variant_purposes: string[];
|
||||
crop_requirements: string | null;
|
||||
export_requirements: string | null;
|
||||
safe_areas: string | null;
|
||||
};
|
||||
constraints: {
|
||||
must_include: string[];
|
||||
must_preserve: string[];
|
||||
must_avoid: string[];
|
||||
brand_constraints: string[];
|
||||
flexible_preferences: string[];
|
||||
acceptance_criteria: Array<{ id: string; description: string; required: boolean }>;
|
||||
};
|
||||
};
|
||||
|
||||
export type DesignSpecification = {
|
||||
schema_version: 1;
|
||||
values: DesignSpecificationValues;
|
||||
field_decisions: Record<string, DesignFieldDecision>;
|
||||
};
|
||||
|
||||
export type DesignFieldChange = {
|
||||
path: string;
|
||||
kind: 'set' | 'update' | 'clear' | 'decision' | 'lock' | 'unlock';
|
||||
before_value?: unknown;
|
||||
after_value?: unknown;
|
||||
before_decision?: DesignFieldDecision | null;
|
||||
after_decision?: DesignFieldDecision | null;
|
||||
};
|
||||
|
||||
export type DesignChangeSet = {
|
||||
interaction_id: string;
|
||||
changes: DesignFieldChange[];
|
||||
};
|
||||
|
||||
export type DesignDecisionOption = {
|
||||
id: string;
|
||||
label: string;
|
||||
default: boolean;
|
||||
disabled: boolean;
|
||||
multiplier: number;
|
||||
description: string | null;
|
||||
};
|
||||
|
||||
export type DesignGenerationParameters = {
|
||||
model: string;
|
||||
resolution: string;
|
||||
export type DesignDecisionPrompt = {
|
||||
id: string;
|
||||
kind: 'suggestion' | 'question';
|
||||
basedOnSpecificationRevisionId: string;
|
||||
targetPaths: string[];
|
||||
title: string;
|
||||
body: string;
|
||||
options: DesignDecisionOption[];
|
||||
};
|
||||
|
||||
export type DesignQuoteOutputSummary = {
|
||||
medium: DesignMedium;
|
||||
strategy: 'direct' | 'multi_step';
|
||||
aspectRatio: string;
|
||||
outputCount: number;
|
||||
deliveryFormat: string | null;
|
||||
durationSeconds: number | null;
|
||||
};
|
||||
|
||||
export type DesignGenerationOptions = {
|
||||
models: DesignGenerationOption<string>[];
|
||||
resolutions: DesignGenerationOption<string>[];
|
||||
durations: DesignGenerationOption<number>[];
|
||||
aspectRatios: DesignGenerationOption<string>[];
|
||||
};
|
||||
|
||||
export type DesignGenerationPricing = {
|
||||
schema: string;
|
||||
amount: number;
|
||||
rounding: string;
|
||||
requiredOutputRoles: string[];
|
||||
};
|
||||
|
||||
export type DesignGenerationQuote = {
|
||||
quoteId: string;
|
||||
status: DesignQuoteStatus;
|
||||
status: 'offered' | 'consumed' | 'expired' | 'superseded';
|
||||
specificationRevision: number;
|
||||
specificationRevisionId: string;
|
||||
specificationDigest: string;
|
||||
medium: DesignMedium;
|
||||
briefVersion: number;
|
||||
briefSummary: string;
|
||||
finalPrompt: string;
|
||||
promptMode: string;
|
||||
generationParameters: DesignGenerationParameters;
|
||||
generationOptions: DesignGenerationOptions;
|
||||
pricing: DesignGenerationPricing;
|
||||
compilerVersion: string;
|
||||
outputSummary: DesignQuoteOutputSummary;
|
||||
warnings: DesignCompilationIssue[];
|
||||
quotedDesignPoints: number;
|
||||
maximumCustomerChargeAtoms: number;
|
||||
expiresAt: string;
|
||||
};
|
||||
|
||||
export type DesignMessage = {
|
||||
id: string;
|
||||
role: 'user' | 'assistant';
|
||||
kind: 'user' | 'reply' | 'choice' | 'confirmation' | 'safety_redirect' | 'failure';
|
||||
text: string;
|
||||
quickReplies: string[];
|
||||
generationQuote: DesignGenerationQuote | null;
|
||||
turnRevision: number;
|
||||
createdAt: string;
|
||||
export type DesignForm = {
|
||||
schemaVersion: 1;
|
||||
workspaceId: string;
|
||||
directionId: string;
|
||||
directionRevision: number;
|
||||
rawTurnSequence: number;
|
||||
specificationRevision: number;
|
||||
workspaceViewRevision: number;
|
||||
specificationRevisionId: string;
|
||||
specificationDigest: string;
|
||||
specification: DesignSpecification;
|
||||
decisionPrompts: DesignDecisionPrompt[];
|
||||
activeQuotes: DesignGenerationQuote[];
|
||||
recentChangeSet: DesignChangeSet;
|
||||
};
|
||||
|
||||
export type DesignTurn = {
|
||||
turnId: string;
|
||||
rawTurnSequence: number;
|
||||
userMessage: string;
|
||||
assistantMessage: string;
|
||||
};
|
||||
|
||||
export type DesignWorkspaceSummary = {
|
||||
workspaceId: string;
|
||||
clientWorkspaceId: string;
|
||||
title: string;
|
||||
viewRevision: number;
|
||||
conversationCount: number;
|
||||
phase: DesignWorkspacePhase;
|
||||
directionId: string;
|
||||
sessionId: string;
|
||||
directionRevision: number;
|
||||
specificationRevision: number;
|
||||
workspaceViewRevision: number;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type DesignWorkspace = DesignWorkspaceSummary & {
|
||||
conversations: DesignConversationSummary[];
|
||||
};
|
||||
|
||||
export type DesignConversationSummary = {
|
||||
conversationId: string;
|
||||
workspaceId: string;
|
||||
title: string;
|
||||
/** A compact preview for history navigation; full messages are loaded on selection. */
|
||||
latestMessagePreview?: string | null;
|
||||
turnRevision: number;
|
||||
phase: DesignWorkspacePhase;
|
||||
brief: DesignBrief;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type DesignConversation = DesignConversationSummary & {
|
||||
messages: DesignMessage[];
|
||||
/** Cursor for the next older message page; absent only for legacy adapters. */
|
||||
messagePage?: DesignConversationMessagePage;
|
||||
};
|
||||
|
||||
export type DesignConversationMessagePage = {
|
||||
hasOlder: boolean;
|
||||
nextBefore: string | null;
|
||||
};
|
||||
|
||||
export type DesignAsset = {
|
||||
assetId: string;
|
||||
workspaceId: string;
|
||||
role: 'uploaded' | 'generated';
|
||||
mediaType: DesignMedium;
|
||||
mimeType: string;
|
||||
width: number;
|
||||
height: number;
|
||||
durationMilliseconds: number | null;
|
||||
generationTaskId: string | null;
|
||||
createdAt: string;
|
||||
contentPath: string;
|
||||
};
|
||||
|
||||
export type DesignAssetSaveResult = {
|
||||
status: 'saved' | 'cancelled';
|
||||
};
|
||||
|
||||
export type DesignImageUploadMimeType = 'image/jpeg' | 'image/png' | 'image/webp';
|
||||
|
||||
export type DesignAssetUploadInput = {
|
||||
workspaceId: string;
|
||||
fileName: string;
|
||||
mimeType: DesignImageUploadMimeType;
|
||||
bytes: Uint8Array;
|
||||
export type DesignTaskProgress = {
|
||||
stage:
|
||||
| 'queued'
|
||||
| 'preparing'
|
||||
| 'submitting'
|
||||
| 'generating'
|
||||
| 'composing'
|
||||
| 'validating'
|
||||
| 'finalizing'
|
||||
| 'completed'
|
||||
| 'failed'
|
||||
| 'cancelled';
|
||||
completedRequiredSteps: number;
|
||||
totalRequiredSteps: number;
|
||||
};
|
||||
|
||||
export type DesignGenerationTask = {
|
||||
taskId: string;
|
||||
workspaceId: string;
|
||||
conversationId: string | null;
|
||||
quoteId: string;
|
||||
status: 'queued' | 'running' | 'succeeded' | 'failed' | 'cancelled';
|
||||
taskRevision: number;
|
||||
specificationRevision: number;
|
||||
specificationRevisionId: string;
|
||||
specificationDigest: string;
|
||||
medium: DesignMedium;
|
||||
status: DesignTaskStatus;
|
||||
briefVersion: number;
|
||||
briefSummary: string;
|
||||
quoteId: string | null;
|
||||
quotedDesignPoints: number | null;
|
||||
failureCode: string | null;
|
||||
resultAssets: DesignAsset[];
|
||||
compilerVersion: string;
|
||||
outputSummary: DesignQuoteOutputSummary;
|
||||
maximumCustomerChargeAtoms: number;
|
||||
customerBilling: {
|
||||
quotedAtoms: number;
|
||||
heldAtoms: number;
|
||||
chargedAtoms: number;
|
||||
refundedAtoms: number;
|
||||
pendingResolutionAtoms: number;
|
||||
};
|
||||
customerHoldExpiresAt: string;
|
||||
resolutionDeadlineAt: string | null;
|
||||
progress: DesignTaskProgress;
|
||||
executionHealth: 'normal' | 'recovering' | 'operator_required';
|
||||
cancellation: {
|
||||
state: 'available' | 'requested' | 'resolved' | 'unavailable';
|
||||
outcome: 'stopped_before_submit' | null;
|
||||
};
|
||||
issues: Array<{
|
||||
code: string;
|
||||
message: string;
|
||||
recoveryOwner: 'platform' | 'operator';
|
||||
}>;
|
||||
resultAssetIds: string[];
|
||||
nextActions: Array<
|
||||
'cancel' | 'view_result' | 'revise_design' | 'generate_again' | 'wait_for_resolution'
|
||||
>;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type DesignGenerationTaskUpdatedEvent = {
|
||||
id: string;
|
||||
type: 'design.generation_task.updated';
|
||||
workspaceId: string;
|
||||
workspaceViewRevision: number;
|
||||
generationTask: DesignGenerationTask;
|
||||
export type DesignWorkspace = {
|
||||
workspace: DesignWorkspaceSummary;
|
||||
form: DesignForm;
|
||||
turns: DesignTurn[];
|
||||
tasks: DesignGenerationTask[];
|
||||
assets: DesignAsset[];
|
||||
};
|
||||
|
||||
export type DesignConversationSnapshotEvent = {
|
||||
id: string;
|
||||
type: 'design.conversation.snapshot';
|
||||
workspaceId: string;
|
||||
conversationId: string;
|
||||
workspaceViewRevision: number;
|
||||
conversation: DesignConversation;
|
||||
generationTasks: DesignGenerationTask[];
|
||||
};
|
||||
|
||||
export type DesignAssistantDeltaEvent = {
|
||||
id: string;
|
||||
type: 'design.assistant.delta';
|
||||
workspaceId: string;
|
||||
conversationId: string;
|
||||
clientTurnId: string;
|
||||
turnRevision: number;
|
||||
chunkIndex: number;
|
||||
delta: string;
|
||||
};
|
||||
|
||||
export type DesignWorkspaceEvent =
|
||||
| DesignGenerationTaskUpdatedEvent
|
||||
| DesignConversationSnapshotEvent
|
||||
| DesignAssistantDeltaEvent;
|
||||
|
||||
export type DesignWorkspaceBootstrap = {
|
||||
capabilities: DesignCapabilities;
|
||||
workspaces: DesignWorkspaceSummary[];
|
||||
@@ -199,46 +335,173 @@ export type DesignCreateWorkspaceInput = {
|
||||
title: string;
|
||||
};
|
||||
|
||||
export type DesignDeleteWorkspaceResult = {
|
||||
workspaceId: string;
|
||||
deleted: true;
|
||||
};
|
||||
|
||||
export type DesignCreateConversationInput = {
|
||||
workspaceId: string;
|
||||
clientConversationId: string;
|
||||
title: string;
|
||||
};
|
||||
|
||||
export type DesignRenameWorkspaceInput = {
|
||||
workspaceId: string;
|
||||
title: string;
|
||||
};
|
||||
|
||||
export type DesignSubmitMessageInput = {
|
||||
export type DesignDeleteWorkspaceResult = {
|
||||
workspaceId: string;
|
||||
conversationId: string;
|
||||
clientTurnId: string;
|
||||
expectedTurnRevision: number;
|
||||
deleted: true;
|
||||
};
|
||||
|
||||
export type DesignUserFieldOperation =
|
||||
| { kind: 'set'; path: string; value: unknown }
|
||||
| { kind: 'clear'; path: string; resolution?: 'open' | 'not_applicable' }
|
||||
| { kind: 'set_lock'; path: string; locked: boolean };
|
||||
|
||||
export type DesignUserInput =
|
||||
| { kind: 'direct_edit'; operations: DesignUserFieldOperation[] }
|
||||
| { kind: 'chat'; message: string }
|
||||
| {
|
||||
kind: 'prompt_resolution';
|
||||
promptId: string;
|
||||
action: 'select' | 'reject';
|
||||
optionId?: string;
|
||||
}
|
||||
| { kind: 'restore'; specificationRevisionId: string };
|
||||
|
||||
export type DesignCommandInput =
|
||||
| {
|
||||
kind: 'apply_input';
|
||||
workspaceId: string;
|
||||
sessionId: string;
|
||||
expectedDirectionRevision: number;
|
||||
clientOperationId: string;
|
||||
input: DesignUserInput;
|
||||
}
|
||||
| {
|
||||
kind: 'request_quote';
|
||||
workspaceId: string;
|
||||
sessionId: string;
|
||||
expectedDirectionRevision: number;
|
||||
specificationRevision: number;
|
||||
clientOperationId: string;
|
||||
}
|
||||
| {
|
||||
kind: 'confirm_generation';
|
||||
workspaceId: string;
|
||||
sessionId: string;
|
||||
quoteId: string;
|
||||
expectedDirectionRevision: number;
|
||||
clientOperationId: string;
|
||||
};
|
||||
|
||||
export type DesignCommandResult = {
|
||||
clientOperationId: string;
|
||||
runId: string;
|
||||
workspace: DesignWorkspace;
|
||||
};
|
||||
|
||||
export type DesignCompilationIssue = {
|
||||
code: string;
|
||||
message: string;
|
||||
attachmentAssetIds?: string[];
|
||||
severity: 'blocker' | 'warning';
|
||||
path?: string | null;
|
||||
};
|
||||
|
||||
export type DesignGenerationQuoteUpdateInput = {
|
||||
workspaceId: string;
|
||||
quoteId: string;
|
||||
finalPrompt: string;
|
||||
generationParameters: DesignGenerationParameters;
|
||||
export type DesignInteractionOutcome = {
|
||||
operationKind:
|
||||
| 'bootstrap'
|
||||
| 'legacy_import'
|
||||
| 'direct_edit'
|
||||
| 'chat'
|
||||
| 'prompt_resolution'
|
||||
| 'restore'
|
||||
| 'quote_request'
|
||||
| 'generation_confirmation';
|
||||
interactionId: string;
|
||||
baseDirectionRevision: number;
|
||||
newDirectionRevision: number;
|
||||
rawTurnSequence: number;
|
||||
specificationRevision: number;
|
||||
specificationRevisionId: string;
|
||||
workspaceViewRevision: number;
|
||||
specificationRevisionCreated: boolean;
|
||||
meaningChanged: boolean;
|
||||
changeSet: DesignChangeSet;
|
||||
turnId: string | null;
|
||||
assistantMessage: string | null;
|
||||
createdDecisionPromptIds: string[];
|
||||
resolvedDecisionPromptId: string | null;
|
||||
supersededDecisionPromptIds: string[];
|
||||
supersededQuoteCount: number;
|
||||
quoteId: string | null;
|
||||
generationTaskId: string | null;
|
||||
};
|
||||
|
||||
export type DesignConfirmGenerationInput = {
|
||||
export type DesignSessionSnapshotEvent = {
|
||||
id: string;
|
||||
type: 'design.session.snapshot';
|
||||
form: DesignForm;
|
||||
};
|
||||
|
||||
export type DesignAssistantDeltaEvent = {
|
||||
id: string;
|
||||
type: 'design.assistant.delta';
|
||||
workspaceId: string;
|
||||
conversationId: string;
|
||||
clientTurnId: string;
|
||||
expectedTurnRevision: number;
|
||||
quoteId: string;
|
||||
finalPrompt: string;
|
||||
generationParameters: DesignGenerationParameters;
|
||||
directionId: string;
|
||||
clientOperationId: string;
|
||||
directionRevision: number;
|
||||
chunkIndex: number;
|
||||
delta: string;
|
||||
};
|
||||
|
||||
export type DesignDirectionUpdatedEvent = {
|
||||
id: string;
|
||||
type: 'design.direction.updated';
|
||||
replayed: boolean;
|
||||
operation: DesignInteractionOutcome;
|
||||
form: DesignForm;
|
||||
};
|
||||
|
||||
export type DesignQuoteBlockedEvent = {
|
||||
id: string;
|
||||
type: 'design.quote.blocked';
|
||||
clientOperationId: string;
|
||||
blockers: DesignCompilationIssue[];
|
||||
warnings: DesignCompilationIssue[];
|
||||
form: DesignForm;
|
||||
};
|
||||
|
||||
export type DesignWorkspaceUpdatedEvent = {
|
||||
id: string;
|
||||
type: 'design.workspace.updated';
|
||||
workspaceId: string;
|
||||
workspaceViewRevision: number;
|
||||
changedDirection: {
|
||||
directionId: string;
|
||||
directionRevision: number;
|
||||
specificationRevision: number;
|
||||
} | null;
|
||||
changedTask: DesignGenerationTask | null;
|
||||
};
|
||||
|
||||
export type DesignWorkspaceEvent =
|
||||
| DesignSessionSnapshotEvent
|
||||
| DesignAssistantDeltaEvent
|
||||
| DesignDirectionUpdatedEvent
|
||||
| DesignQuoteBlockedEvent
|
||||
| DesignWorkspaceUpdatedEvent;
|
||||
|
||||
export type DesignWorkspaceEventSubscription = {
|
||||
events: AsyncIterable<DesignWorkspaceEvent>;
|
||||
close(): void;
|
||||
};
|
||||
|
||||
export type DesignWorkspaceEventSubscriptionInput = {
|
||||
workspaceId: string;
|
||||
sessionId: string;
|
||||
afterEventId?: string;
|
||||
};
|
||||
|
||||
export type DesignAssetSaveResult = { status: 'saved' | 'cancelled' };
|
||||
export type DesignImageUploadMimeType = 'image/jpeg' | 'image/png' | 'image/webp';
|
||||
export type DesignAssetUploadInput = {
|
||||
workspaceId: string;
|
||||
fileName: string;
|
||||
mimeType: DesignImageUploadMimeType;
|
||||
bytes: Uint8Array;
|
||||
};
|
||||
|
||||
export function designAssetContentPath(workspaceId: string, assetId: string): string {
|
||||
|
||||
Reference in New Issue
Block a user