@purpleschool/gptbot 0.14.27 → 0.14.29

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.
Files changed (71) hide show
  1. package/api/controllers/http/avatar-studio.ts +23 -12
  2. package/api/routes.ts +68 -19
  3. package/build/api/controllers/http/avatar-studio.js +22 -12
  4. package/build/api/routes.js +41 -10
  5. package/build/commands/avatar-studio/generation-job/generate-avatar-studio-frame.command.js +2 -1
  6. package/build/commands/avatar-studio/generation-job/generate-avatar-studio-image.command.js +23 -0
  7. package/build/commands/avatar-studio/generation-job/generate-avatar-studio-scene-voice.command.js +4 -1
  8. package/build/commands/avatar-studio/generation-job/index.js +1 -3
  9. package/build/commands/avatar-studio/media/create-avatar-studio-media-from-file.command.js +6 -9
  10. package/build/commands/avatar-studio/media/find-avatar-studio-media.query.js +7 -5
  11. package/build/commands/avatar-studio/media/update-avatar-studio-media.command.js +1 -4
  12. package/build/commands/avatar-studio/scene/apply-avatar-studio-voice-sample-to-all-scenes.command.js +15 -0
  13. package/build/commands/avatar-studio/scene/index.js +2 -0
  14. package/build/commands/avatar-studio/scene/set-avatar-studio-scene-slot.command.js +21 -0
  15. package/build/commands/avatar-studio/scriptwriter/calculate-avatar-studio-scriptwriter-price.command.js +13 -6
  16. package/build/commands/avatar-studio/scriptwriter/create-avatar-studio-scriptwriter-message.command.js +23 -1
  17. package/build/commands/avatar-studio/shared/avatar-studio-common.schema.js +2 -1
  18. package/build/commands/avatar-studio/shared/get-avatar-studio-config.query.js +28 -18
  19. package/build/commands/avatar-studio/voice/design-avatar-studio-voice.command.js +5 -7
  20. package/build/commands/avatar-studio/voice/index.js +0 -3
  21. package/build/commands/photo-studio/execute-photo-studio-action.command.js +7 -2
  22. package/build/commands/photo-studio/find-photo-studio-job-by-id.query.js +2 -1
  23. package/build/constants/avatar-studio/enums/avatar-studio-job-type.enum.js +0 -3
  24. package/build/constants/avatar-studio/enums/avatar-studio-slot.enum.js +10 -7
  25. package/build/constants/avatar-studio/enums/avatar-studio-unavailable-reason.enum.js +16 -0
  26. package/build/constants/avatar-studio/enums/index.js +1 -5
  27. package/build/models/avatar-studio/avatar-studio.schema.js +60 -68
  28. package/commands/avatar-studio/generation-job/generate-avatar-studio-frame.command.ts +2 -1
  29. package/commands/avatar-studio/generation-job/{generate-avatar-studio-media-image.command.ts → generate-avatar-studio-image.command.ts} +5 -1
  30. package/commands/avatar-studio/generation-job/generate-avatar-studio-scene-voice.command.ts +4 -1
  31. package/commands/avatar-studio/generation-job/index.ts +1 -3
  32. package/commands/avatar-studio/media/create-avatar-studio-media-from-file.command.ts +7 -16
  33. package/commands/avatar-studio/media/find-avatar-studio-media.query.ts +9 -7
  34. package/commands/avatar-studio/media/update-avatar-studio-media.command.ts +1 -4
  35. package/commands/avatar-studio/scene/apply-avatar-studio-voice-sample-to-all-scenes.command.ts +20 -0
  36. package/commands/avatar-studio/scene/index.ts +2 -0
  37. package/commands/avatar-studio/{generation-job/generate-avatar-studio-voice-timings.command.ts → scene/set-avatar-studio-scene-slot.command.ts} +8 -5
  38. package/commands/avatar-studio/scriptwriter/calculate-avatar-studio-scriptwriter-price.command.ts +14 -7
  39. package/commands/avatar-studio/scriptwriter/create-avatar-studio-scriptwriter-message.command.ts +26 -1
  40. package/commands/avatar-studio/shared/avatar-studio-common.schema.ts +2 -1
  41. package/commands/avatar-studio/shared/get-avatar-studio-config.query.ts +31 -19
  42. package/commands/avatar-studio/voice/design-avatar-studio-voice.command.ts +6 -14
  43. package/commands/avatar-studio/voice/index.ts +0 -3
  44. package/commands/photo-studio/execute-photo-studio-action.command.ts +8 -2
  45. package/commands/photo-studio/find-photo-studio-job-by-id.query.ts +2 -1
  46. package/constants/avatar-studio/enums/avatar-studio-job-type.enum.ts +0 -3
  47. package/constants/avatar-studio/enums/avatar-studio-slot.enum.ts +10 -7
  48. package/constants/avatar-studio/enums/avatar-studio-unavailable-reason.enum.ts +12 -0
  49. package/constants/avatar-studio/enums/index.ts +1 -5
  50. package/models/avatar-studio/avatar-studio.schema.ts +59 -75
  51. package/package.json +1 -1
  52. package/build/commands/avatar-studio/generation-job/generate-avatar-studio-library-image.command.js +0 -20
  53. package/build/commands/avatar-studio/generation-job/generate-avatar-studio-media-image.command.js +0 -19
  54. package/build/commands/avatar-studio/generation-job/generate-avatar-studio-voice-timings.command.js +0 -18
  55. package/build/commands/avatar-studio/voice/find-avatar-studio-clip-voices.query.js +0 -14
  56. package/build/commands/avatar-studio/voice/find-avatar-studio-voices.query.js +0 -19
  57. package/build/commands/avatar-studio/voice/update-avatar-studio-clip-voice.command.js +0 -19
  58. package/build/constants/avatar-studio/enums/avatar-studio-job-phase.enum.js +0 -12
  59. package/build/constants/avatar-studio/enums/avatar-studio-media-role.enum.js +0 -14
  60. package/build/constants/avatar-studio/enums/avatar-studio-media-source.enum.js +0 -13
  61. package/build/constants/avatar-studio/enums/avatar-studio-scene-kind.enum.js +0 -7
  62. package/build/constants/avatar-studio/enums/avatar-studio-voice-source.enum.js +0 -10
  63. package/commands/avatar-studio/generation-job/generate-avatar-studio-library-image.command.ts +0 -25
  64. package/commands/avatar-studio/voice/find-avatar-studio-clip-voices.query.ts +0 -21
  65. package/commands/avatar-studio/voice/find-avatar-studio-voices.query.ts +0 -24
  66. package/commands/avatar-studio/voice/update-avatar-studio-clip-voice.command.ts +0 -21
  67. package/constants/avatar-studio/enums/avatar-studio-job-phase.enum.ts +0 -8
  68. package/constants/avatar-studio/enums/avatar-studio-media-role.enum.ts +0 -10
  69. package/constants/avatar-studio/enums/avatar-studio-media-source.enum.ts +0 -9
  70. package/constants/avatar-studio/enums/avatar-studio-scene-kind.enum.ts +0 -3
  71. package/constants/avatar-studio/enums/avatar-studio-voice-source.enum.ts +0 -6
@@ -1,18 +1,15 @@
1
1
  import { z } from 'zod';
2
- import { AVATAR_STUDIO_MEDIA_ROLE } from '../../../constants';
3
2
  import { AvatarStudioMediaSchema } from '../../../models';
4
3
  import { AvatarStudioMediaIdParamsSchema } from '../shared/avatar-studio-common.schema';
5
4
 
5
+ /** Только метаданные: прикрепление медиа в сцену — операция сцены, а не медиа. */
6
6
  export namespace UpdateAvatarStudioMediaCommand {
7
7
  export const ParamsSchema = AvatarStudioMediaIdParamsSchema;
8
8
  export type Params = z.infer<typeof ParamsSchema>;
9
9
 
10
10
  export const RequestSchema = z
11
11
  .object({
12
- sceneId: z.string().uuid().nullable().optional(),
13
- role: z.nativeEnum(AVATAR_STUDIO_MEDIA_ROLE).optional(),
14
12
  title: z.string().trim().min(1).max(255).nullable().optional(),
15
- prompt: z.string().nullable().optional(),
16
13
  })
17
14
  .strict();
18
15
  export type Request = z.infer<typeof RequestSchema>;
@@ -0,0 +1,20 @@
1
+ import { z } from 'zod';
2
+ import { AvatarStudioClipSchema } from '../../../models';
3
+ import {
4
+ AvatarStudioClipIdParamsSchema,
5
+ AvatarStudioMediaIdParamsSchema,
6
+ } from '../shared/avatar-studio-common.schema';
7
+
8
+ export namespace ApplyAvatarStudioVoiceSampleToAllScenesCommand {
9
+ export const ParamsSchema = AvatarStudioClipIdParamsSchema.merge(
10
+ AvatarStudioMediaIdParamsSchema,
11
+ );
12
+ export type Params = z.infer<typeof ParamsSchema>;
13
+
14
+ // Ответ — клип со сценами, а не список сцен: фронт перерисовывает клип целиком
15
+ // и не ходит следом за GET /clips/:clipId.
16
+ export const ResponseSchema = z.object({
17
+ data: AvatarStudioClipSchema,
18
+ });
19
+ export type Response = z.infer<typeof ResponseSchema>;
20
+ }
@@ -1,4 +1,6 @@
1
+ export * from './apply-avatar-studio-voice-sample-to-all-scenes.command';
1
2
  export * from './create-avatar-studio-scene.command';
2
3
  export * from './delete-avatar-studio-scene.command';
3
4
  export * from './reorder-avatar-studio-scenes.command';
5
+ export * from './set-avatar-studio-scene-slot.command';
4
6
  export * from './update-avatar-studio-scene.command';
@@ -1,20 +1,23 @@
1
1
  import { z } from 'zod';
2
- import { AvatarStudioGenerationJobSchema } from '../../../models';
2
+ import { AVATAR_STUDIO_SLOT } from '../../../constants';
3
+ import { AvatarStudioSceneSchema } from '../../../models';
3
4
  import { AvatarStudioSceneIdParamsSchema } from '../shared/avatar-studio-common.schema';
4
5
 
5
- export namespace GenerateAvatarStudioVoiceTimingsCommand {
6
- export const ParamsSchema = AvatarStudioSceneIdParamsSchema;
6
+ export namespace SetAvatarStudioSceneSlotCommand {
7
+ export const ParamsSchema = AvatarStudioSceneIdParamsSchema.extend({
8
+ slot: z.nativeEnum(AVATAR_STUDIO_SLOT),
9
+ });
7
10
  export type Params = z.infer<typeof ParamsSchema>;
8
11
 
9
12
  export const RequestSchema = z
10
13
  .object({
11
- mediaId: z.string().uuid().optional(),
14
+ mediaId: z.string().uuid(),
12
15
  })
13
16
  .strict();
14
17
  export type Request = z.infer<typeof RequestSchema>;
15
18
 
16
19
  export const ResponseSchema = z.object({
17
- data: AvatarStudioGenerationJobSchema,
20
+ data: AvatarStudioSceneSchema,
18
21
  });
19
22
  export type Response = z.infer<typeof ResponseSchema>;
20
23
  }
@@ -1,21 +1,28 @@
1
1
  import { z } from 'zod';
2
- import { AvatarStudioClipIdParamsSchema } from '../shared/avatar-studio-common.schema';
3
2
 
4
- export namespace CalculateAvatarStudioScriptwriterPriceCommand {
5
- export const ParamsSchema = AvatarStudioClipIdParamsSchema;
6
- export type Params = z.infer<typeof ParamsSchema>;
3
+ /** Сама цена, без транспортной обёртки: её считает и сервис сценариста. */
4
+ export const AvatarStudioScriptwriterPriceSchema = z.object({
5
+ price: z.number(),
6
+ charsUntilNextPriceIncrease: z.number().int().nonnegative().nullable(),
7
+ charsUntilNextPriceDecrease: z.number().int().nonnegative().nullable(),
8
+ });
9
+ export type AvatarStudioScriptwriterPrice = z.infer<typeof AvatarStudioScriptwriterPriceSchema>;
7
10
 
11
+ export namespace CalculateAvatarStudioScriptwriterPriceCommand {
12
+ /**
13
+ * Клип опционален: цену спрашивают ещё до его создания. Без клипа считаем по одной длине
14
+ * ввода, без контекста прошлого диалога — история в цену и не входит, если её нет.
15
+ */
8
16
  export const RequestSchema = z
9
17
  .object({
10
18
  inputLength: z.number().int().nonnegative(),
19
+ clipId: z.string().uuid().optional(),
11
20
  })
12
21
  .strict();
13
22
  export type Request = z.infer<typeof RequestSchema>;
14
23
 
15
24
  export const ResponseSchema = z.object({
16
- price: z.number(),
17
- charsUntilNextPriceIncrease: z.number().int().nonnegative().nullable(),
18
- charsUntilNextPriceDecrease: z.number().int().nonnegative().nullable(),
25
+ data: AvatarStudioScriptwriterPriceSchema,
19
26
  });
20
27
  export type Response = z.infer<typeof ResponseSchema>;
21
28
  }
@@ -50,10 +50,35 @@ export namespace CreateAvatarStudioScriptwriterMessageCommand {
50
50
 
51
51
  export type ScenePlan = z.infer<typeof ScenePlanSchema>;
52
52
 
53
+ export const ModelOutputScenePlanSchema = z
54
+ .object({
55
+ voiceConfig: z.object({
56
+ text: z.string().trim().min(1),
57
+ trimStart: z.number().nonnegative().nullable(),
58
+ trimEnd: z.number().nonnegative().nullable(),
59
+ }),
60
+ imageConfig: z.object({
61
+ prompt: z.string().trim().min(1),
62
+ style: z.nativeEnum(AVATAR_STUDIO_IMAGE_STYLE),
63
+ }),
64
+ videoConfig: z.object({
65
+ prompt: z.string().trim().min(1),
66
+ durationSeconds: z.number().positive(),
67
+ videoMode: z.nativeEnum(AVATAR_STUDIO_VIDEO_MODE),
68
+ quality: z.nativeEnum(AVATAR_STUDIO_VIDEO_QUALITY),
69
+ sound: z.boolean(),
70
+ trimStart: z.number().nonnegative().nullable(),
71
+ trimEnd: z.number().nonnegative().nullable(),
72
+ }),
73
+ })
74
+ .strict();
75
+
76
+ export type ModelOutputScenePlan = z.infer<typeof ModelOutputScenePlanSchema>;
77
+
53
78
  export const ModelOutputSchema = z
54
79
  .object({
55
80
  message: z.string().trim().min(1),
56
- scenes: z.array(ScenePlanSchema).min(1).max(20),
81
+ scenes: z.array(ModelOutputScenePlanSchema).min(1).max(20),
57
82
  })
58
83
  .strict();
59
84
  export type ModelOutput = z.infer<typeof ModelOutputSchema>;
@@ -15,7 +15,8 @@ export const AvatarStudioSceneIdParamsSchema = AvatarStudioClipIdParamsSchema.ex
15
15
  sceneId: z.string().uuid(),
16
16
  });
17
17
 
18
- export const AvatarStudioMediaIdParamsSchema = AvatarStudioClipIdParamsSchema.extend({
18
+ // Медиа принадлежит пользователю, а не клипу, поэтому clipId в его параметрах нет.
19
+ export const AvatarStudioMediaIdParamsSchema = z.object({
19
20
  mediaId: z.string().uuid(),
20
21
  });
21
22
 
@@ -2,7 +2,7 @@ import { z } from 'zod';
2
2
  import {
3
3
  AVATAR_STUDIO_IMAGE_STYLE,
4
4
  AVATAR_STUDIO_MEDIA_KIND,
5
- AVATAR_STUDIO_MEDIA_ROLE,
5
+ AVATAR_STUDIO_UNAVAILABLE_REASON,
6
6
  AVATAR_STUDIO_VIDEO_MODE,
7
7
  AVATAR_STUDIO_VIDEO_QUALITY,
8
8
  } from '../../../constants';
@@ -21,13 +21,32 @@ const AvatarStudioGenerationPriceSchema = z
21
21
  })
22
22
  .strict();
23
23
 
24
+ /**
25
+ * Картинки генерирует одна модель, с референсами и без. Наценка за референсы плоская:
26
+ * её берёт сам инструмент за факт вложения, количество картинок значения не имеет.
27
+ */
28
+ const AvatarStudioImagePricingSchema = z
29
+ .object({
30
+ base: AvatarStudioGenerationPriceSchema.nullable(),
31
+ referenceSurcharge: z.number().nonnegative(),
32
+ })
33
+ .strict();
34
+
24
35
  const AvatarStudioConfigSectionBaseSchema = z
25
36
  .object({
26
37
  available: z.boolean(),
27
- unavailableReason: z.string().optional(),
38
+ /** Присутствует только когда available = false. */
39
+ unavailableReason: z.nativeEnum(AVATAR_STUDIO_UNAVAILABLE_REASON).optional(),
28
40
  })
29
41
  .strict();
30
42
 
43
+ /**
44
+ * Сценарист доступен не всем: у анрега нет доступа к его модели. Цены здесь нет: она зависит
45
+ * от длины ввода и считается на лету — POST scriptwriter/price. Конфиг отвечает только на
46
+ * вопрос «можно ли пользоваться».
47
+ */
48
+ const AvatarStudioScriptwriterConfigSectionSchema = AvatarStudioConfigSectionBaseSchema;
49
+
31
50
  const AvatarStudioTextFieldSchema = z
32
51
  .object({
33
52
  kind: z.literal('text'),
@@ -50,7 +69,6 @@ const AvatarStudioMediaFieldSchema = z
50
69
  kind: z.literal('media'),
51
70
  required: z.boolean(),
52
71
  mediaKind: z.nativeEnum(AVATAR_STUDIO_MEDIA_KIND),
53
- mediaRole: z.nativeEnum(AVATAR_STUDIO_MEDIA_ROLE),
54
72
  })
55
73
  .strict();
56
74
 
@@ -59,6 +77,8 @@ const AvatarStudioMediaArrayFieldSchema = z
59
77
  kind: z.literal('media-array'),
60
78
  required: z.boolean(),
61
79
  supported: z.boolean(),
80
+ /** Предел задаёт модель (maxAttachedImages), поэтому он приезжает сюда, а не зашит в контракт. */
81
+ maxCount: z.number().int().nonnegative(),
62
82
  })
63
83
  .strict();
64
84
 
@@ -93,10 +113,11 @@ const AvatarStudioAudioConfigSectionSchema = AvatarStudioConfigSectionBaseSchema
93
113
  text: AvatarStudioTextFieldSchema.extend({
94
114
  required: z.boolean(),
95
115
  }),
96
- mediaId: AvatarStudioMediaFieldSchema.extend({
116
+ // Образец голоса — вход генерации наравне с текстом, поэтому живёт
117
+ // в voiceConfig и ставится через PATCH .../scenes/:sceneId.
118
+ voiceSampleMediaId: AvatarStudioMediaFieldSchema.extend({
97
119
  required: z.boolean(),
98
120
  mediaKind: z.literal(AVATAR_STUDIO_MEDIA_KIND.AUDIO),
99
- mediaRole: z.literal(AVATAR_STUDIO_MEDIA_ROLE.VOICE_SAMPLE),
100
121
  }),
101
122
  })
102
123
  .strict(),
@@ -116,7 +137,7 @@ const AvatarStudioFrameConfigSectionSchema = AvatarStudioConfigSectionBaseSchema
116
137
  style: AvatarStudioSelectFieldSchema(z.nativeEnum(AVATAR_STUDIO_IMAGE_STYLE)).extend({
117
138
  required: z.boolean(),
118
139
  }),
119
- referenceMediaIds: AvatarStudioMediaArrayFieldSchema.extend({
140
+ references: AvatarStudioMediaArrayFieldSchema.extend({
120
141
  required: z.boolean(),
121
142
  }),
122
143
  aspectRatio: AvatarStudioFixedFieldSchema(z.literal('9:16')),
@@ -125,12 +146,7 @@ const AvatarStudioFrameConfigSectionSchema = AvatarStudioConfigSectionBaseSchema
125
146
  defaults: AvatarStudioSceneImageConfigSchema.extend({
126
147
  aspectRatio: z.literal('9:16'),
127
148
  }),
128
- pricing: z
129
- .object({
130
- withoutReference: AvatarStudioGenerationPriceSchema.nullable(),
131
- withReference: AvatarStudioGenerationPriceSchema.nullable(),
132
- })
133
- .strict(),
149
+ pricing: AvatarStudioImagePricingSchema,
134
150
  });
135
151
 
136
152
  const AvatarStudioVideoConfigSectionSchema = AvatarStudioConfigSectionBaseSchema.extend({
@@ -183,7 +199,7 @@ const AvatarStudioLibraryImageConfigSectionSchema = AvatarStudioConfigSectionBas
183
199
  fields: z
184
200
  .object({
185
201
  prompt: AvatarStudioTextFieldSchema.extend({ required: z.boolean() }),
186
- referenceMediaIds: AvatarStudioMediaArrayFieldSchema.extend({
202
+ references: AvatarStudioMediaArrayFieldSchema.extend({
187
203
  required: z.boolean(),
188
204
  }),
189
205
  aspectRatio: AvatarStudioSelectFieldSchema(AvatarStudioAspectRatioSchema).extend({
@@ -197,12 +213,7 @@ const AvatarStudioLibraryImageConfigSectionSchema = AvatarStudioConfigSectionBas
197
213
  aspectRatio: AvatarStudioAspectRatioSchema,
198
214
  })
199
215
  .strict(),
200
- pricing: z
201
- .object({
202
- withoutReference: AvatarStudioGenerationPriceSchema.nullable(),
203
- withReference: AvatarStudioGenerationPriceSchema.nullable(),
204
- })
205
- .strict(),
216
+ pricing: AvatarStudioImagePricingSchema,
206
217
  });
207
218
 
208
219
  export namespace GetAvatarStudioConfigQuery {
@@ -213,6 +224,7 @@ export namespace GetAvatarStudioConfigQuery {
213
224
  frame: AvatarStudioFrameConfigSectionSchema,
214
225
  video: AvatarStudioVideoConfigSectionSchema,
215
226
  libraryImage: AvatarStudioLibraryImageConfigSectionSchema,
227
+ scriptwriter: AvatarStudioScriptwriterConfigSectionSchema,
216
228
  })
217
229
  .strict(),
218
230
  });
@@ -1,15 +1,7 @@
1
1
  import { z } from 'zod';
2
- import {
3
- AvatarStudioGenerationJobSchema,
4
- AvatarStudioMediaSchema,
5
- AvatarStudioVoiceSchema,
6
- } from '../../../models';
7
- import { AvatarStudioClipIdParamsSchema } from '../shared/avatar-studio-common.schema';
2
+ import { AvatarStudioGenerationJobSchema } from '../../../models';
8
3
 
9
4
  export namespace DesignAvatarStudioVoiceCommand {
10
- export const ParamsSchema = AvatarStudioClipIdParamsSchema;
11
- export type Params = z.infer<typeof ParamsSchema>;
12
-
13
5
  export const RequestSchema = z
14
6
  .object({
15
7
  title: z.string().trim().min(1).optional(),
@@ -19,12 +11,12 @@ export namespace DesignAvatarStudioVoiceCommand {
19
11
  .strict();
20
12
  export type Request = z.infer<typeof RequestSchema>;
21
13
 
14
+ /**
15
+ * Отдаём job, как и все остальные генерации: созданный голос лежит в job.resultMedia.
16
+ * Отдельного поля media нет — форма ответа одинакова у всех роутов генерации.
17
+ */
22
18
  export const ResponseSchema = z.object({
23
- data: z.object({
24
- job: AvatarStudioGenerationJobSchema,
25
- voice: AvatarStudioVoiceSchema,
26
- media: AvatarStudioMediaSchema,
27
- }),
19
+ data: AvatarStudioGenerationJobSchema,
28
20
  });
29
21
  export type Response = z.infer<typeof ResponseSchema>;
30
22
  }
@@ -1,4 +1 @@
1
1
  export * from './design-avatar-studio-voice.command';
2
- export * from './find-avatar-studio-clip-voices.query';
3
- export * from './find-avatar-studio-voices.query';
4
- export * from './update-avatar-studio-clip-voice.command';
@@ -6,6 +6,7 @@ import {
6
6
  PHOTO_STUDIO_PLACEMENT_ALIAS,
7
7
  PHOTO_STUDIO_UPSCALE_SIZE,
8
8
  PHOTO_STUDIO_VARIATION_STRENGTH_ALIAS,
9
+ IMAGE_GENERATION_RESOLUTION,
9
10
  } from '../../constants';
10
11
  import { CanvasNodePositionSchema, ToolJobSchema } from '../../models';
11
12
 
@@ -14,6 +15,7 @@ export namespace ExecutePhotoStudioActionCommand {
14
15
  .object({
15
16
  enhancePrompt: z.boolean().optional(),
16
17
  aspectRatio: z.string().optional(),
18
+ resolution: z.nativeEnum(IMAGE_GENERATION_RESOLUTION).optional(),
17
19
  })
18
20
  .strict();
19
21
  const OneImageParamsSchema = z
@@ -41,6 +43,7 @@ export namespace ExecutePhotoStudioActionCommand {
41
43
  variationsCount: z.union([z.literal(2), z.literal(3), z.literal(4)]),
42
44
  variationStrength: z.nativeEnum(PHOTO_STUDIO_VARIATION_STRENGTH_ALIAS).optional(),
43
45
  enhancePrompt: z.boolean().optional(),
46
+ aspectRatio: z.string().optional(),
44
47
  positions: z.array(CanvasNodePositionSchema).min(2).max(4).optional(),
45
48
  })
46
49
  .strict();
@@ -69,18 +72,20 @@ export namespace ExecutePhotoStudioActionCommand {
69
72
  .object({
70
73
  imageUrls: z.array(z.string().uuid()).min(2).max(5),
71
74
  enhancePrompt: z.boolean().optional(),
75
+ aspectRatio: z.string().optional(),
72
76
  })
73
77
  .strict();
74
78
  const StyleParamsSchema = z
75
79
  .object({
76
80
  imageUrls: z.array(z.string().uuid()).length(2),
81
+ aspectRatio: z.string().optional(),
77
82
  })
78
83
  .strict();
79
84
 
80
85
  const BaseRequestSchema = z.object({
81
86
  actionAlias: z.nativeEnum(PHOTO_STUDIO_ACTION_ALIAS),
82
87
  position: CanvasNodePositionSchema,
83
- baseCheckpointSequence: z.number().int().optional(),
88
+ baseCheckpointSequence: z.number().int().min(0).optional(),
84
89
  });
85
90
 
86
91
  const GenerationActionRequestSchema = BaseRequestSchema.extend({
@@ -184,7 +189,8 @@ export namespace ExecutePhotoStudioActionCommand {
184
189
 
185
190
  export const PhotoStudioExecuteJobSchema = ToolJobSchema.extend({
186
191
  actionType: z.nativeEnum(PHOTO_STUDIO_ACTION_ALIAS),
187
- checkpointSequence: z.number().int().positive(),
192
+ baseCheckpointSequence: z.number().int().min(0).nullable(),
193
+ targetCheckpointSequence: z.number().int().positive().nullable(),
188
194
  position: CanvasNodePositionSchema,
189
195
  params: PhotoStudioJobParamsSchema,
190
196
  });
@@ -28,7 +28,8 @@ export namespace FindPhotoStudioJobByIdQuery {
28
28
  jobId: z.string().uuid(),
29
29
  actionType: z.nativeEnum(PHOTO_STUDIO_ACTION_ALIAS),
30
30
  status: z.nativeEnum(TOOL_JOB_STATUS),
31
- checkpointSequence: z.number().int().positive(),
31
+ baseCheckpointSequence: z.number().int().min(0).nullable(),
32
+ targetCheckpointSequence: z.number().int().positive().nullable(),
32
33
  position: CanvasNodePositionSchema,
33
34
  params: PhotoStudioJobParamsSchema,
34
35
  images: z.array(PhotoStudioJobImageSchema),
@@ -2,11 +2,8 @@ export enum AVATAR_STUDIO_JOB_TYPE {
2
2
  FRAME_IMAGE = 'frame_image',
3
3
  LIBRARY_IMAGE = 'library_image',
4
4
  SCENE_VIDEO = 'scene_video',
5
- SCENE_VOICE = 'scene_voice',
6
5
  VOICE_TTS = 'voice_tts',
7
6
  VOICE_STT = 'voice_stt',
8
- VOICE_TIMINGS = 'voice_timings',
9
7
  TALKING_AVATAR = 'talking_avatar',
10
8
  VOICE_DESIGN = 'voice_design',
11
- SCRIPTWRITER = 'scriptwriter',
12
9
  }
@@ -1,11 +1,14 @@
1
+ /**
2
+ * Слоты-результаты сцены: в каждом ровно одно медиа за раз.
3
+ *
4
+ * Здесь только то, что действительно является слотом сцены:
5
+ * - аватар и b-roll — два способа получить VIDEO, а не два слота (режим в videoConfig.videoMode);
6
+ * - образец голоса — вход сцены (scene.voiceSampleMediaId), а не её результат;
7
+ * - референсы — несколько упорядоченных медиа, у них своя join-таблица;
8
+ * - «медиатека» слотом никогда не была: у таких job'ов targetSlot = null.
9
+ */
1
10
  export enum AVATAR_STUDIO_SLOT {
11
+ VOICE = 'voice',
2
12
  FRAME = 'frame',
3
13
  VIDEO = 'video',
4
- VOICE = 'voice',
5
- AVATAR = 'avatar',
6
- LIBRARY = 'library',
7
- VOICE_TIMINGS = 'voice_timings',
8
- VOICE_SAMPLE = 'voice_sample',
9
- SCRIPTWRITER = 'scriptwriter',
10
- EXPORT = 'export',
11
14
  }
@@ -0,0 +1,12 @@
1
+ export enum AVATAR_STUDIO_UNAVAILABLE_REASON {
2
+ /**
3
+ * Функция есть, но этому пользователю не положена: анрег либо нет подходящей подписки.
4
+ * Фронт вправе звать зарегистрироваться или улучшить тариф.
5
+ */
6
+ NO_ACCESS = 'no_access',
7
+ /**
8
+ * Модель выключена, не найдена или проверка доступа не удалась. Пользователь ни при чём,
9
+ * звать его никуда не нужно — это наша проблема.
10
+ */
11
+ MODEL_UNAVAILABLE = 'model_unavailable',
12
+ }
@@ -1,16 +1,12 @@
1
1
  export * from './avatar-studio-export-status.enum';
2
2
  export * from './avatar-studio-image-style.enum';
3
- export * from './avatar-studio-job-phase.enum';
4
3
  export * from './avatar-studio-job-status.enum';
5
4
  export * from './avatar-studio-job-type.enum';
6
5
  export * from './avatar-studio-media-kind.enum';
7
- export * from './avatar-studio-media-role.enum';
8
- export * from './avatar-studio-media-source.enum';
9
- export * from './avatar-studio-scene-kind.enum';
10
6
  export * from './avatar-studio-scriptwriter-role.enum';
11
7
  export * from './avatar-studio-slot.enum';
12
8
  export * from './avatar-studio-subtitle-font.enum';
9
+ export * from './avatar-studio-unavailable-reason.enum';
13
10
  export * from './avatar-studio-subtitle-mode.enum';
14
11
  export * from './avatar-studio-video-mode.enum';
15
12
  export * from './avatar-studio-video-quality.enum';
16
- export * from './avatar-studio-voice-source.enum';