feat: 完善图像工作区与创作工具体验
Some checks failed
Electron E2E / Electron E2E (macos-latest) (push) Has been cancelled
Electron E2E / Electron E2E (ubuntu-latest) (push) Has been cancelled
Electron E2E / Electron E2E (windows-latest) (push) Has been cancelled

This commit is contained in:
inman
2026-08-16 14:08:02 +08:00
parent bfcb88cfef
commit 26b52d76e3
92 changed files with 16678 additions and 2975 deletions

View File

@@ -10,6 +10,9 @@ import type {
DesignConfirmGenerationInput,
DesignCreateConversationInput,
DesignCreateWorkspaceInput,
DesignDeleteWorkspaceResult,
DesignGenerationOption,
DesignGenerationQuoteUpdateInput,
DesignGenerationQuote,
DesignGenerationTask,
DesignGenerationTaskUpdatedEvent,
@@ -48,6 +51,25 @@ type ServerQuote = {
medium: DesignGenerationQuote['medium'];
brief_version: number;
brief_summary: string;
final_prompt: string;
prompt_mode: string;
generation_parameters: {
model: string;
resolution: string;
aspect_ratio: string;
duration_seconds: number | null;
};
generation_options: {
models: Array<DesignGenerationOption<string>>;
resolutions: Array<DesignGenerationOption<string>>;
durations: Array<DesignGenerationOption<number>>;
aspect_ratios: Array<DesignGenerationOption<string>>;
};
pricing: {
schema: string;
amount: number;
rounding: string;
};
quoted_design_points: number;
expires_at: string;
};
@@ -176,6 +198,13 @@ type AgentDesignTurnSubmission = {
action: null | {
type: 'confirm_generation';
quote_id: string;
final_prompt?: string;
aspect_ratio?: string;
generation_parameters?: {
model: string;
resolution: string;
duration_seconds: number | null;
};
};
};
@@ -260,6 +289,25 @@ function mapQuote(quote: ServerQuote | null): DesignGenerationQuote | null {
medium: quote.medium,
briefVersion: quote.brief_version,
briefSummary: quote.brief_summary,
finalPrompt: quote.final_prompt,
promptMode: quote.prompt_mode,
generationParameters: {
model: quote.generation_parameters.model,
resolution: quote.generation_parameters.resolution,
aspectRatio: quote.generation_parameters.aspect_ratio,
durationSeconds: quote.generation_parameters.duration_seconds,
},
generationOptions: {
models: quote.generation_options.models,
resolutions: quote.generation_options.resolutions,
durations: quote.generation_options.durations,
aspectRatios: quote.generation_options.aspect_ratios,
},
pricing: {
schema: quote.pricing.schema,
amount: quote.pricing.amount,
rounding: quote.pricing.rounding,
},
quotedDesignPoints: quote.quoted_design_points,
expiresAt: quote.expires_at,
};
@@ -810,6 +858,15 @@ export class WorksSquareDesignWorkspace implements DesignWorkspaceModule {
return this.getWorkspace(workspace.workspace_id);
}
async deleteWorkspace(workspaceId: string): Promise<DesignDeleteWorkspaceResult> {
await this.requestJson<unknown>(
`/api/design/workspaces/${encodeURIComponent(workspaceId)}`,
{ method: 'DELETE' },
);
this.forgetWorkspace(workspaceId);
return { workspaceId, deleted: true };
}
async renameWorkspace(input: DesignRenameWorkspaceInput): Promise<DesignWorkspace> {
const workspace = await this.requestJson<ServerWorkspace>(
`/api/design/workspaces/${encodeURIComponent(input.workspaceId)}`,
@@ -873,8 +930,43 @@ export class WorksSquareDesignWorkspace implements DesignWorkspaceModule {
});
}
async updateGenerationQuote(
input: DesignGenerationQuoteUpdateInput,
): Promise<DesignGenerationQuote> {
const quote = await this.requestJson<ServerQuote>(
`/api/design/workspaces/${encodeURIComponent(input.workspaceId)}/generation-quotes/${encodeURIComponent(input.quoteId)}`,
{
method: 'PATCH',
body: JSON.stringify({
final_prompt: input.finalPrompt,
model: input.generationParameters.model,
resolution: input.generationParameters.resolution,
aspect_ratio: input.generationParameters.aspectRatio,
duration_seconds: input.generationParameters.durationSeconds,
}),
},
);
return mapQuote(quote)!;
}
async confirmGeneration(input: DesignConfirmGenerationInput): Promise<DesignConversation> {
const agentSessionId = await this.getAgentSessionId(input.workspaceId, input.conversationId);
const action = input.finalPrompt === undefined || input.generationParameters === undefined
? {
type: 'confirm_generation' as const,
quote_id: input.quoteId,
}
: {
type: 'confirm_generation' as const,
quote_id: input.quoteId,
final_prompt: input.finalPrompt,
aspect_ratio: input.generationParameters.aspectRatio,
generation_parameters: {
model: input.generationParameters.model,
resolution: input.generationParameters.resolution,
duration_seconds: input.generationParameters.durationSeconds,
},
};
return this.executeAgentTurn({
workspaceId: input.workspaceId,
conversationId: input.conversationId,
@@ -883,10 +975,7 @@ export class WorksSquareDesignWorkspace implements DesignWorkspaceModule {
expectedTurnRevision: input.expectedTurnRevision,
message: '确认生成',
attachmentAssetIds: [],
action: {
type: 'confirm_generation',
quote_id: input.quoteId,
},
action,
});
}
@@ -1438,6 +1527,30 @@ export class WorksSquareDesignWorkspace implements DesignWorkspaceModule {
this.conversationSessionIds.delete(this.conversationKey(workspaceId, conversationId));
}
private forgetWorkspace(workspaceId: string): void {
const keyPrefix = `${workspaceId}:`;
const sessionIds = new Set<string>();
for (const [key, sessionId] of this.conversationSessionIds) {
if (!key.startsWith(keyPrefix)) continue;
sessionIds.add(sessionId);
this.conversationSessionIds.delete(key);
}
const activeSubscriptions: Array<() => void> = [];
for (const [key, closers] of this.eventSubscriptionClosers) {
if (!key.startsWith(keyPrefix)) continue;
activeSubscriptions.push(...closers);
this.eventSubscriptionClosers.delete(key);
}
for (const close of activeSubscriptions) close();
for (const key of this.terminalAgentRuns.keys()) {
if ([...sessionIds].some((sessionId) => key.startsWith(`${sessionId}:`))) {
this.terminalAgentRuns.delete(key);
}
}
}
private async getAgentSessionId(
workspaceId: string,
conversationId: string,