@framers/agentos 0.1.163 → 0.1.165

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 (52) hide show
  1. package/dist/api/generateImage.d.ts +6 -0
  2. package/dist/api/generateImage.d.ts.map +1 -1
  3. package/dist/api/generateImage.js +18 -0
  4. package/dist/api/generateImage.js.map +1 -1
  5. package/dist/api/index.d.ts +4 -1
  6. package/dist/api/index.d.ts.map +1 -1
  7. package/dist/api/index.js +4 -0
  8. package/dist/api/index.js.map +1 -1
  9. package/dist/api/types.d.ts +71 -0
  10. package/dist/api/types.d.ts.map +1 -1
  11. package/dist/api/types.js.map +1 -1
  12. package/dist/core/index.d.ts +1 -0
  13. package/dist/core/index.d.ts.map +1 -1
  14. package/dist/core/index.js +2 -1
  15. package/dist/core/index.js.map +1 -1
  16. package/dist/core/llm/routing/index.d.ts +10 -0
  17. package/dist/core/llm/routing/index.d.ts.map +1 -0
  18. package/dist/core/llm/routing/index.js +9 -0
  19. package/dist/core/llm/routing/index.js.map +1 -0
  20. package/dist/media/avatar/AvatarPipeline.d.ts +56 -0
  21. package/dist/media/avatar/AvatarPipeline.d.ts.map +1 -0
  22. package/dist/media/avatar/AvatarPipeline.js +308 -0
  23. package/dist/media/avatar/AvatarPipeline.js.map +1 -0
  24. package/dist/media/avatar/index.d.ts +8 -0
  25. package/dist/media/avatar/index.d.ts.map +1 -0
  26. package/dist/media/avatar/index.js +7 -0
  27. package/dist/media/avatar/index.js.map +1 -0
  28. package/dist/media/avatar/prompts.d.ts +48 -0
  29. package/dist/media/avatar/prompts.d.ts.map +1 -0
  30. package/dist/media/avatar/prompts.js +88 -0
  31. package/dist/media/avatar/prompts.js.map +1 -0
  32. package/dist/media/avatar/types.d.ts +101 -0
  33. package/dist/media/avatar/types.d.ts.map +1 -0
  34. package/dist/media/avatar/types.js +8 -0
  35. package/dist/media/avatar/types.js.map +1 -0
  36. package/dist/media/images/face/IFaceEmbeddingService.d.ts +69 -0
  37. package/dist/media/images/face/IFaceEmbeddingService.d.ts.map +1 -0
  38. package/dist/media/images/face/IFaceEmbeddingService.js +40 -0
  39. package/dist/media/images/face/IFaceEmbeddingService.js.map +1 -0
  40. package/dist/media/images/face/ReplicateFaceEmbeddingService.d.ts +57 -0
  41. package/dist/media/images/face/ReplicateFaceEmbeddingService.d.ts.map +1 -0
  42. package/dist/media/images/face/ReplicateFaceEmbeddingService.js +151 -0
  43. package/dist/media/images/face/ReplicateFaceEmbeddingService.js.map +1 -0
  44. package/dist/media/images/face/index.d.ts +7 -0
  45. package/dist/media/images/face/index.d.ts.map +1 -0
  46. package/dist/media/images/face/index.js +7 -0
  47. package/dist/media/images/face/index.js.map +1 -0
  48. package/dist/media/images/index.d.ts +2 -0
  49. package/dist/media/images/index.d.ts.map +1 -1
  50. package/dist/media/images/index.js +2 -0
  51. package/dist/media/images/index.js.map +1 -1
  52. package/package.json +1 -1
@@ -0,0 +1,308 @@
1
+ /**
2
+ * @file AvatarPipeline.ts
3
+ * Core orchestrator for staged avatar image generation.
4
+ *
5
+ * Executes the avatar pipeline stages in order — neutral portrait, face
6
+ * embedding extraction, expression sheet, animated emotes, full body —
7
+ * with cosine-similarity drift checking against the anchor face embedding.
8
+ * Images that drift too far from the anchor are regenerated up to a
9
+ * configurable maximum number of attempts.
10
+ */
11
+ import { randomUUID } from 'crypto';
12
+ import { AVATAR_EMOTIONS, buildPortraitPrompt, buildExpressionPrompt, buildEmotePrompt } from './prompts.js';
13
+ // ---------------------------------------------------------------------------
14
+ // Default thresholds
15
+ // ---------------------------------------------------------------------------
16
+ const DEFAULT_DRIFT_SIMILARITY = 0.6;
17
+ const DEFAULT_REJECT_BELOW_THRESHOLD = true;
18
+ const DEFAULT_MAX_REGEN_ATTEMPTS = 3;
19
+ const ALL_STAGES = [
20
+ 'neutral_portrait',
21
+ 'face_embedding',
22
+ 'expression_sheet',
23
+ 'animated_emotes',
24
+ 'full_body',
25
+ ];
26
+ // ---------------------------------------------------------------------------
27
+ // Pipeline
28
+ // ---------------------------------------------------------------------------
29
+ /**
30
+ * Orchestrates multi-stage avatar image generation with drift detection.
31
+ *
32
+ * Stages run in dependency order. The expression sheet and animated emote
33
+ * stages drift-check each generated image against the anchor face embedding
34
+ * and regenerate on low similarity.
35
+ */
36
+ export class AvatarPipeline {
37
+ /**
38
+ * @param faceService - Face embedding extraction and comparison service.
39
+ * @param generateImage - Image generation function (prompt → URL).
40
+ */
41
+ constructor(faceService, generateImage) {
42
+ this.faceService = faceService;
43
+ this.generateImage = generateImage;
44
+ }
45
+ /**
46
+ * Execute the avatar generation pipeline.
47
+ *
48
+ * @param request - Generation request with identity, stages, and config.
49
+ * @returns Result containing the identity package, job records, and drift report.
50
+ */
51
+ async generate(request) {
52
+ const startTime = Date.now();
53
+ const stages = request.stages ?? ALL_STAGES;
54
+ const jobs = [];
55
+ const driftConfig = {
56
+ faceSimilarity: request.driftGuard?.faceSimilarity ?? DEFAULT_DRIFT_SIMILARITY,
57
+ rejectBelowThreshold: request.driftGuard?.rejectBelowThreshold ?? DEFAULT_REJECT_BELOW_THRESHOLD,
58
+ maxRegenerationAttempts: request.driftGuard?.maxRegenerationAttempts ?? DEFAULT_MAX_REGEN_ATTEMPTS,
59
+ };
60
+ // Mutable state accumulated across stages
61
+ let neutralPortraitUrl = request.existingAnchors?.neutralPortrait ?? '';
62
+ let faceEmbedding = request.existingAnchors?.faceEmbedding;
63
+ const expressionSheet = {};
64
+ const animatedEmotes = {};
65
+ let fullBodyUrl;
66
+ const driftScores = {};
67
+ const driftRejected = [];
68
+ const driftRegenerated = [];
69
+ // -----------------------------------------------------------------------
70
+ // Stage: neutral_portrait
71
+ // -----------------------------------------------------------------------
72
+ if (stages.includes('neutral_portrait') && !neutralPortraitUrl) {
73
+ const job = this.createJob('neutral_portrait', 'neutral_portrait');
74
+ const jobStart = Date.now();
75
+ try {
76
+ job.status = 'running';
77
+ const prompt = buildPortraitPrompt(request.identity);
78
+ neutralPortraitUrl = await this.generateImage(prompt, {
79
+ seed: request.generationConfig.seed,
80
+ negativePrompt: request.generationConfig.negativePrompt,
81
+ stylePreset: request.generationConfig.stylePreset,
82
+ policyTier: request.policyTier,
83
+ });
84
+ job.imageUrl = neutralPortraitUrl;
85
+ job.status = 'completed';
86
+ job.attempts = 1;
87
+ }
88
+ catch (err) {
89
+ job.status = 'failed';
90
+ job.error = err instanceof Error ? err.message : String(err);
91
+ }
92
+ job.durationMs = Date.now() - jobStart;
93
+ jobs.push(job);
94
+ }
95
+ // -----------------------------------------------------------------------
96
+ // Stage: face_embedding
97
+ // -----------------------------------------------------------------------
98
+ if (stages.includes('face_embedding') && !faceEmbedding && neutralPortraitUrl) {
99
+ const job = this.createJob('face_embedding', 'face_embedding');
100
+ const jobStart = Date.now();
101
+ try {
102
+ job.status = 'running';
103
+ const result = await this.faceService.extractEmbedding(neutralPortraitUrl);
104
+ faceEmbedding = result.vector;
105
+ job.status = 'completed';
106
+ job.attempts = 1;
107
+ }
108
+ catch (err) {
109
+ job.status = 'failed';
110
+ job.error = err instanceof Error ? err.message : String(err);
111
+ }
112
+ job.durationMs = Date.now() - jobStart;
113
+ jobs.push(job);
114
+ }
115
+ // -----------------------------------------------------------------------
116
+ // Stage: expression_sheet
117
+ // -----------------------------------------------------------------------
118
+ if (stages.includes('expression_sheet')) {
119
+ for (const emotion of AVATAR_EMOTIONS) {
120
+ // Neutral portrait is already the anchor; skip re-generating it
121
+ if (emotion === 'neutral') {
122
+ if (neutralPortraitUrl) {
123
+ expressionSheet.neutral = neutralPortraitUrl;
124
+ }
125
+ continue;
126
+ }
127
+ const label = `expression:${emotion}`;
128
+ const job = this.createJob('expression_sheet', label);
129
+ const jobStart = Date.now();
130
+ try {
131
+ job.status = 'running';
132
+ const prompt = buildExpressionPrompt(request.identity, emotion);
133
+ let imageUrl;
134
+ let bestScore = -1;
135
+ let attempts = 0;
136
+ while (attempts < driftConfig.maxRegenerationAttempts) {
137
+ attempts++;
138
+ const url = await this.generateImage(prompt, {
139
+ seed: request.generationConfig.seed,
140
+ negativePrompt: request.generationConfig.negativePrompt,
141
+ stylePreset: request.generationConfig.stylePreset,
142
+ policyTier: request.policyTier,
143
+ referenceImageUrl: neutralPortraitUrl || undefined,
144
+ });
145
+ // Drift check against anchor embedding
146
+ if (faceEmbedding) {
147
+ try {
148
+ const generated = await this.faceService.extractEmbedding(url);
149
+ const comparison = this.faceService.compareFaces(faceEmbedding, generated.vector, driftConfig.faceSimilarity);
150
+ if (comparison.similarity > bestScore) {
151
+ bestScore = comparison.similarity;
152
+ imageUrl = url;
153
+ }
154
+ if (comparison.match) {
155
+ break; // Acceptable drift
156
+ }
157
+ if (attempts > 1) {
158
+ driftRegenerated.push(label);
159
+ }
160
+ }
161
+ catch {
162
+ // If face extraction fails on the generated image, accept it
163
+ imageUrl = url;
164
+ break;
165
+ }
166
+ }
167
+ else {
168
+ // No anchor embedding available — accept the first result
169
+ imageUrl = url;
170
+ break;
171
+ }
172
+ }
173
+ if (imageUrl) {
174
+ expressionSheet[emotion] = imageUrl;
175
+ job.imageUrl = imageUrl;
176
+ job.driftScore = bestScore >= 0 ? bestScore : undefined;
177
+ job.status = 'completed';
178
+ if (bestScore >= 0) {
179
+ driftScores[label] = bestScore;
180
+ if (bestScore < driftConfig.faceSimilarity && driftConfig.rejectBelowThreshold) {
181
+ driftRejected.push(label);
182
+ }
183
+ }
184
+ }
185
+ else {
186
+ job.status = 'failed';
187
+ job.error = 'All regeneration attempts failed drift check.';
188
+ }
189
+ job.attempts = attempts;
190
+ }
191
+ catch (err) {
192
+ job.status = 'failed';
193
+ job.error = err instanceof Error ? err.message : String(err);
194
+ }
195
+ job.durationMs = Date.now() - jobStart;
196
+ jobs.push(job);
197
+ }
198
+ }
199
+ // -----------------------------------------------------------------------
200
+ // Stage: animated_emotes
201
+ // -----------------------------------------------------------------------
202
+ if (stages.includes('animated_emotes')) {
203
+ for (const emotion of AVATAR_EMOTIONS) {
204
+ const label = `emote:${emotion}`;
205
+ const job = this.createJob('animated_emotes', label);
206
+ const jobStart = Date.now();
207
+ try {
208
+ job.status = 'running';
209
+ const prompt = buildEmotePrompt(emotion);
210
+ const url = await this.generateImage(prompt, {
211
+ seed: request.generationConfig.seed,
212
+ negativePrompt: request.generationConfig.negativePrompt,
213
+ policyTier: request.policyTier,
214
+ });
215
+ animatedEmotes[emotion] = url;
216
+ job.imageUrl = url;
217
+ job.status = 'completed';
218
+ job.attempts = 1;
219
+ }
220
+ catch (err) {
221
+ job.status = 'failed';
222
+ job.error = err instanceof Error ? err.message : String(err);
223
+ }
224
+ job.durationMs = Date.now() - jobStart;
225
+ jobs.push(job);
226
+ }
227
+ }
228
+ // -----------------------------------------------------------------------
229
+ // Stage: full_body
230
+ // -----------------------------------------------------------------------
231
+ if (stages.includes('full_body')) {
232
+ const job = this.createJob('full_body', 'full_body');
233
+ const jobStart = Date.now();
234
+ try {
235
+ job.status = 'running';
236
+ const basePrompt = buildPortraitPrompt(request.identity);
237
+ const prompt = basePrompt.replace(/^portrait of/, 'full body shot of');
238
+ fullBodyUrl = await this.generateImage(prompt, {
239
+ seed: request.generationConfig.seed,
240
+ negativePrompt: request.generationConfig.negativePrompt,
241
+ stylePreset: request.generationConfig.stylePreset,
242
+ policyTier: request.policyTier,
243
+ referenceImageUrl: neutralPortraitUrl || undefined,
244
+ });
245
+ job.imageUrl = fullBodyUrl;
246
+ job.status = 'completed';
247
+ job.attempts = 1;
248
+ }
249
+ catch (err) {
250
+ job.status = 'failed';
251
+ job.error = err instanceof Error ? err.message : String(err);
252
+ }
253
+ job.durationMs = Date.now() - jobStart;
254
+ jobs.push(job);
255
+ }
256
+ // -----------------------------------------------------------------------
257
+ // Assemble identity package
258
+ // -----------------------------------------------------------------------
259
+ const now = new Date().toISOString();
260
+ const identityPackage = {
261
+ id: randomUUID(),
262
+ characterId: request.characterId,
263
+ identity: request.identity,
264
+ anchors: {
265
+ neutralPortrait: neutralPortraitUrl,
266
+ expressionSheet: Object.keys(expressionSheet).length > 0 ? expressionSheet : undefined,
267
+ animatedEmotes: Object.keys(animatedEmotes).length > 0 ? animatedEmotes : undefined,
268
+ fullBody: fullBodyUrl,
269
+ },
270
+ faceEmbedding,
271
+ driftGuard: driftConfig,
272
+ generationConfig: request.generationConfig,
273
+ createdAt: now,
274
+ updatedAt: now,
275
+ };
276
+ // -----------------------------------------------------------------------
277
+ // Drift report
278
+ // -----------------------------------------------------------------------
279
+ let driftReport;
280
+ if (faceEmbedding) {
281
+ driftReport = {
282
+ anchorEmbeddingDim: faceEmbedding.length,
283
+ scores: driftScores,
284
+ rejected: driftRejected,
285
+ regenerated: [...new Set(driftRegenerated)],
286
+ passed: driftRejected.length === 0,
287
+ };
288
+ }
289
+ return {
290
+ identityPackage,
291
+ jobs,
292
+ driftReport,
293
+ totalDurationMs: Date.now() - startTime,
294
+ };
295
+ }
296
+ // -------------------------------------------------------------------------
297
+ // Helpers
298
+ // -------------------------------------------------------------------------
299
+ createJob(stage, label) {
300
+ return {
301
+ stage,
302
+ label,
303
+ status: 'pending',
304
+ attempts: 0,
305
+ };
306
+ }
307
+ }
308
+ //# sourceMappingURL=AvatarPipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AvatarPipeline.js","sourceRoot":"","sources":["../../../src/media/avatar/AvatarPipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @file index.ts
3
+ * Barrel export for the avatar generation pipeline.
4
+ */
5
+ export { AvatarPipeline, type ImageGeneratorFn } from './AvatarPipeline.js';
6
+ export type { AvatarGenerationStage, AvatarGenerationRequest, AvatarGenerationJob, DriftAuditReport, AvatarGenerationResult, } from './types.js';
7
+ export { AVATAR_EMOTIONS, type AvatarEmotion, buildPortraitPrompt, buildExpressionPrompt, buildEmotePrompt, } from './prompts.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/media/avatar/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5E,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,eAAe,EACf,KAAK,aAAa,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @file index.ts
3
+ * Barrel export for the avatar generation pipeline.
4
+ */
5
+ export { AvatarPipeline } from './AvatarPipeline.js';
6
+ export { AVATAR_EMOTIONS, buildPortraitPrompt, buildExpressionPrompt, buildEmotePrompt, } from './prompts.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/media/avatar/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAyB,MAAM,qBAAqB,CAAC;AAU5E,OAAO,EACL,eAAe,EAEf,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @file prompts.ts
3
+ * Prompt construction utilities for avatar image generation.
4
+ *
5
+ * Builds deterministic text prompts from {@link AvatarIdentityDescriptor}
6
+ * fields, producing consistent character depictions across emotion variants,
7
+ * emote animations, and full-body shots.
8
+ */
9
+ import type { AvatarIdentityDescriptor } from '../../api/types.js';
10
+ /**
11
+ * Canonical set of emotions for expression sheets and animated emotes.
12
+ * The first entry is always "neutral" — it doubles as the anchor portrait.
13
+ */
14
+ export declare const AVATAR_EMOTIONS: readonly ["neutral", "happy", "sad", "angry", "surprised", "flirty", "fearful"];
15
+ /** Union type of supported avatar emotions. */
16
+ export type AvatarEmotion = (typeof AVATAR_EMOTIONS)[number];
17
+ /**
18
+ * Concatenate all identity descriptor fields into a portrait prompt.
19
+ *
20
+ * Produces a detailed, comma-separated description suitable for
21
+ * text-to-image models. Omits undefined optional fields.
22
+ *
23
+ * @param identity - Character identity descriptors.
24
+ * @returns Prompt string for a neutral portrait.
25
+ */
26
+ export declare function buildPortraitPrompt(identity: AvatarIdentityDescriptor): string;
27
+ /**
28
+ * Build a prompt for a specific emotion expression of the character.
29
+ *
30
+ * Appends the emotion keyword to the base portrait prompt so the model
31
+ * generates the same face with the requested expression.
32
+ *
33
+ * @param identity - Character identity descriptors.
34
+ * @param emotion - Target emotion expression.
35
+ * @returns Prompt string for an emotion-specific portrait.
36
+ */
37
+ export declare function buildExpressionPrompt(identity: AvatarIdentityDescriptor, emotion: AvatarEmotion | string): string;
38
+ /**
39
+ * Build a prompt for an animated emote loop of a given emotion.
40
+ *
41
+ * Produces a concise prompt targeting short animation generation models
42
+ * (e.g. Stable Video Diffusion, AnimateDiff).
43
+ *
44
+ * @param emotion - The emotion to animate.
45
+ * @returns Prompt string for an animated emote.
46
+ */
47
+ export declare function buildEmotePrompt(emotion: AvatarEmotion | string): string;
48
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/media/avatar/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAMnE;;;GAGG;AACH,eAAO,MAAM,eAAe,iFAQlB,CAAC;AAEX,+CAA+C;AAC/C,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAM7D;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,MAAM,CA6B9E;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,wBAAwB,EAClC,OAAO,EAAE,aAAa,GAAG,MAAM,GAC9B,MAAM,CAMR;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,GAAG,MAAM,CAExE"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @file prompts.ts
3
+ * Prompt construction utilities for avatar image generation.
4
+ *
5
+ * Builds deterministic text prompts from {@link AvatarIdentityDescriptor}
6
+ * fields, producing consistent character depictions across emotion variants,
7
+ * emote animations, and full-body shots.
8
+ */
9
+ // ---------------------------------------------------------------------------
10
+ // Emotion catalogue
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Canonical set of emotions for expression sheets and animated emotes.
14
+ * The first entry is always "neutral" — it doubles as the anchor portrait.
15
+ */
16
+ export const AVATAR_EMOTIONS = [
17
+ 'neutral',
18
+ 'happy',
19
+ 'sad',
20
+ 'angry',
21
+ 'surprised',
22
+ 'flirty',
23
+ 'fearful',
24
+ ];
25
+ // ---------------------------------------------------------------------------
26
+ // Prompt builders
27
+ // ---------------------------------------------------------------------------
28
+ /**
29
+ * Concatenate all identity descriptor fields into a portrait prompt.
30
+ *
31
+ * Produces a detailed, comma-separated description suitable for
32
+ * text-to-image models. Omits undefined optional fields.
33
+ *
34
+ * @param identity - Character identity descriptors.
35
+ * @returns Prompt string for a neutral portrait.
36
+ */
37
+ export function buildPortraitPrompt(identity) {
38
+ const parts = [];
39
+ parts.push(`portrait of ${identity.displayName}`);
40
+ parts.push(`${identity.ageBand.replace(/_/g, ' ')} age`);
41
+ if (identity.bodyType) {
42
+ parts.push(`${identity.bodyType} build`);
43
+ }
44
+ parts.push(identity.faceDescriptor);
45
+ if (identity.hairDescriptor) {
46
+ parts.push(identity.hairDescriptor);
47
+ }
48
+ if (identity.skinDescriptor) {
49
+ parts.push(identity.skinDescriptor);
50
+ }
51
+ if (identity.distinguishingFeatures) {
52
+ parts.push(identity.distinguishingFeatures);
53
+ }
54
+ if (identity.styleNotes) {
55
+ parts.push(identity.styleNotes);
56
+ }
57
+ return parts.join(', ');
58
+ }
59
+ /**
60
+ * Build a prompt for a specific emotion expression of the character.
61
+ *
62
+ * Appends the emotion keyword to the base portrait prompt so the model
63
+ * generates the same face with the requested expression.
64
+ *
65
+ * @param identity - Character identity descriptors.
66
+ * @param emotion - Target emotion expression.
67
+ * @returns Prompt string for an emotion-specific portrait.
68
+ */
69
+ export function buildExpressionPrompt(identity, emotion) {
70
+ const base = buildPortraitPrompt(identity);
71
+ if (emotion === 'neutral') {
72
+ return base;
73
+ }
74
+ return `${base}, ${emotion} expression`;
75
+ }
76
+ /**
77
+ * Build a prompt for an animated emote loop of a given emotion.
78
+ *
79
+ * Produces a concise prompt targeting short animation generation models
80
+ * (e.g. Stable Video Diffusion, AnimateDiff).
81
+ *
82
+ * @param emotion - The emotion to animate.
83
+ * @returns Prompt string for an animated emote.
84
+ */
85
+ export function buildEmotePrompt(emotion) {
86
+ return `animated emote loop, ${emotion} expression, character portrait, seamless loop`;
87
+ }
88
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/media/avatar/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,SAAS;IACT,OAAO;IACP,KAAK;IACL,OAAO;IACP,WAAW;IACX,QAAQ;IACR,SAAS;CACD,CAAC;AAKX,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAkC;IACpE,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,eAAe,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IAClD,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAEzD,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,QAAQ,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IAEpC,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,QAAQ,CAAC,sBAAsB,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAkC,EAClC,OAA+B;IAE/B,MAAM,IAAI,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,GAAG,IAAI,KAAK,OAAO,aAAa,CAAC;AAC1C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAA+B;IAC9D,OAAO,wBAAwB,OAAO,gDAAgD,CAAC;AACzF,CAAC"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @file types.ts
3
+ * Type definitions for the avatar generation pipeline.
4
+ *
5
+ * Covers the full lifecycle: request → staged jobs → drift audit → result.
6
+ */
7
+ import type { AvatarIdentityDescriptor, AvatarIdentityPackage } from '../../api/types.js';
8
+ import type { PolicyTier } from '../../core/llm/routing/UncensoredModelCatalog.js';
9
+ /**
10
+ * Discrete stages of the avatar generation pipeline, executed in order.
11
+ *
12
+ * - `neutral_portrait` — Generate the canonical neutral-expression portrait.
13
+ * - `face_embedding` — Extract a 512-dim face vector from the neutral portrait.
14
+ * - `expression_sheet` — Generate emotion variants and drift-check each one.
15
+ * - `animated_emotes` — Generate animated emote loops per emotion.
16
+ * - `full_body` — Generate a full-body reference image.
17
+ * - `additional_angles` — Generate extra viewpoint references (3/4, profile).
18
+ */
19
+ export type AvatarGenerationStage = 'neutral_portrait' | 'face_embedding' | 'expression_sheet' | 'animated_emotes' | 'full_body' | 'additional_angles';
20
+ /** Input to the avatar generation pipeline. */
21
+ export interface AvatarGenerationRequest {
22
+ /** Character identifier for the generated identity package. */
23
+ characterId: string;
24
+ /** Identity descriptors driving image generation prompts. */
25
+ identity: AvatarIdentityDescriptor;
26
+ /** Which stages to execute (defaults to all). */
27
+ stages?: AvatarGenerationStage[];
28
+ /** Content policy tier forwarded to the image generator. */
29
+ policyTier?: PolicyTier;
30
+ /** Image generation parameters. */
31
+ generationConfig: {
32
+ /** Model identifier (e.g. "black-forest-labs/flux-schnell"). */
33
+ baseModel: string;
34
+ /** Provider identifier (e.g. "replicate"). */
35
+ provider: string;
36
+ /** Random seed for reproducible output. */
37
+ seed?: number;
38
+ /** Negative prompt to avoid unwanted artefacts. */
39
+ negativePrompt?: string;
40
+ /** Named style preset (provider-specific). */
41
+ stylePreset?: string;
42
+ };
43
+ /** Drift-guard thresholds. */
44
+ driftGuard?: {
45
+ /** Minimum cosine similarity to the anchor face embedding. */
46
+ faceSimilarity?: number;
47
+ /** Reject images below the similarity threshold. */
48
+ rejectBelowThreshold?: boolean;
49
+ /** Maximum retries when generated face drifts. */
50
+ maxRegenerationAttempts?: number;
51
+ };
52
+ /** Pre-existing anchors to reuse instead of regenerating. */
53
+ existingAnchors?: {
54
+ neutralPortrait?: string;
55
+ faceEmbedding?: number[];
56
+ };
57
+ }
58
+ /** Tracking record for a single pipeline job. */
59
+ export interface AvatarGenerationJob {
60
+ /** Which stage this job belongs to. */
61
+ stage: AvatarGenerationStage;
62
+ /** Human-readable label (e.g. "neutral_portrait", "expression:happy"). */
63
+ label: string;
64
+ /** Job status. */
65
+ status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
66
+ /** Generated image URL on success. */
67
+ imageUrl?: string;
68
+ /** Drift similarity score (for expression/emote stages). */
69
+ driftScore?: number;
70
+ /** Number of regeneration attempts for this job. */
71
+ attempts: number;
72
+ /** Error message on failure. */
73
+ error?: string;
74
+ /** Wall-clock duration in milliseconds. */
75
+ durationMs?: number;
76
+ }
77
+ /** Aggregate drift audit across all generated assets. */
78
+ export interface DriftAuditReport {
79
+ /** Anchor face embedding used as the reference. */
80
+ anchorEmbeddingDim: number;
81
+ /** Per-image drift scores keyed by label. */
82
+ scores: Record<string, number>;
83
+ /** Labels of images that were rejected for excessive drift. */
84
+ rejected: string[];
85
+ /** Labels of images that were regenerated (at least once). */
86
+ regenerated: string[];
87
+ /** Overall pass/fail for the entire batch. */
88
+ passed: boolean;
89
+ }
90
+ /** Output of a complete avatar generation pipeline run. */
91
+ export interface AvatarGenerationResult {
92
+ /** The assembled identity package. */
93
+ identityPackage: AvatarIdentityPackage;
94
+ /** Per-stage job records for observability. */
95
+ jobs: AvatarGenerationJob[];
96
+ /** Drift audit report (present when face_embedding stage ran). */
97
+ driftReport?: DriftAuditReport;
98
+ /** Total wall-clock time in milliseconds. */
99
+ totalDurationMs: number;
100
+ }
101
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/media/avatar/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC1F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kDAAkD,CAAC;AAMnF;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,GAC7B,kBAAkB,GAClB,gBAAgB,GAChB,kBAAkB,GAClB,iBAAiB,GACjB,WAAW,GACX,mBAAmB,CAAC;AAMxB,+CAA+C;AAC/C,MAAM,WAAW,uBAAuB;IACtC,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,QAAQ,EAAE,wBAAwB,CAAC;IACnC,iDAAiD;IACjD,MAAM,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACjC,4DAA4D;IAC5D,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,mCAAmC;IACnC,gBAAgB,EAAE;QAChB,gEAAgE;QAChE,SAAS,EAAE,MAAM,CAAC;QAClB,8CAA8C;QAC9C,QAAQ,EAAE,MAAM,CAAC;QACjB,2CAA2C;QAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,mDAAmD;QACnD,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,8CAA8C;QAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,8BAA8B;IAC9B,UAAU,CAAC,EAAE;QACX,8DAA8D;QAC9D,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,oDAAoD;QACpD,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAC/B,kDAAkD;QAClD,uBAAuB,CAAC,EAAE,MAAM,CAAC;KAClC,CAAC;IACF,6DAA6D;IAC7D,eAAe,CAAC,EAAE;QAChB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;CACH;AAED,iDAAiD;AACjD,MAAM,WAAW,mBAAmB;IAClC,uCAAuC;IACvC,KAAK,EAAE,qBAAqB,CAAC;IAC7B,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IACnE,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,yDAAyD;AACzD,MAAM,WAAW,gBAAgB;IAC/B,mDAAmD;IACnD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,8CAA8C;IAC9C,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,2DAA2D;AAC3D,MAAM,WAAW,sBAAsB;IACrC,sCAAsC;IACtC,eAAe,EAAE,qBAAqB,CAAC;IACvC,+CAA+C;IAC/C,IAAI,EAAE,mBAAmB,EAAE,CAAC;IAC5B,kEAAkE;IAClE,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,6CAA6C;IAC7C,eAAe,EAAE,MAAM,CAAC;CACzB"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @file types.ts
3
+ * Type definitions for the avatar generation pipeline.
4
+ *
5
+ * Covers the full lifecycle: request → staged jobs → drift audit → result.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/media/avatar/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}