@zodic/shared 0.0.314 → 0.0.316
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/app/api/index.ts +114 -16
- package/app/services/ArchetypeService.ts +738 -1244
- package/app/services/LeonardoService.ts +187 -288
- package/app/workflow/ArchetypeWorkflow.ts +175 -141
- package/db/migrations/0014_green_marvel_apes.sql +10 -0
- package/db/migrations/meta/0014_snapshot.json +2723 -0
- package/db/migrations/meta/_journal.json +7 -0
- package/db/schema.ts +17 -0
- package/package.json +1 -1
- package/utils/buildMessages.ts +273 -59
|
@@ -1,382 +1,281 @@
|
|
|
1
|
+
import { eq } from 'drizzle-orm';
|
|
1
2
|
import { inject, injectable } from 'inversify';
|
|
2
3
|
import 'reflect-metadata';
|
|
3
4
|
import { schema } from '../..';
|
|
4
|
-
import { Gender
|
|
5
|
-
import {
|
|
6
|
-
KVArchetype,
|
|
7
|
-
LeonardoGenerateImageResponse,
|
|
8
|
-
sizes,
|
|
9
|
-
} from '../../types/scopes/legacy';
|
|
10
|
-
import { buildCosmicMirrorArchetypeKVKey } from '../../utils/KVKeysBuilders';
|
|
5
|
+
import { Gender } from '../../types';
|
|
11
6
|
import { AppContext } from '../base/AppContext';
|
|
12
7
|
|
|
8
|
+
interface QueueMessage {
|
|
9
|
+
archetypeDataId: string;
|
|
10
|
+
combination: string;
|
|
11
|
+
gender: Gender;
|
|
12
|
+
language: string;
|
|
13
|
+
archetypeIndex: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
13
16
|
@injectable()
|
|
14
17
|
export class LeonardoService {
|
|
15
18
|
constructor(@inject(AppContext) private context: AppContext) {}
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
kvKey: string;
|
|
25
|
-
name: string;
|
|
26
|
-
visualDescription: string;
|
|
27
|
-
}> = [];
|
|
28
|
-
|
|
29
|
-
for (const gender of VALID_GENDERS_ARRAY) {
|
|
30
|
-
for (let index = 1; index <= 3; index++) {
|
|
31
|
-
const kvKey = buildCosmicMirrorArchetypeKVKey(
|
|
32
|
-
'en-us',
|
|
33
|
-
crown,
|
|
34
|
-
gender,
|
|
35
|
-
index
|
|
36
|
-
);
|
|
37
|
-
console.log(`Fetching archetype from KV: ${kvKey}`);
|
|
38
|
-
|
|
39
|
-
const kvData = await this.context
|
|
40
|
-
.kvCosmicMirrorArchetypesStore()
|
|
41
|
-
.get<KVArchetype>(kvKey, 'json');
|
|
42
|
-
if (kvData && !kvData.leonardoPrompt) {
|
|
43
|
-
promptsToGenerate.push({
|
|
44
|
-
kvKey,
|
|
45
|
-
name: kvData.name,
|
|
46
|
-
visualDescription: kvData.visualDescription,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (promptsToGenerate.length === 0) {
|
|
53
|
-
console.log('No archetype prompts need to be generated.');
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
console.log('Archetypes requiring prompt generation:', promptsToGenerate);
|
|
58
|
-
|
|
59
|
-
const archetypes = promptsToGenerate.map(({ name, visualDescription }) => ({
|
|
60
|
-
name,
|
|
61
|
-
visualDescription,
|
|
62
|
-
}));
|
|
63
|
-
const leonardoPrompts =
|
|
64
|
-
await this.generateCosmicMirrorArchetypesLeonardoPrompts(archetypes);
|
|
65
|
-
|
|
66
|
-
if (leonardoPrompts.length !== archetypes.length) {
|
|
67
|
-
throw new Error('Mismatch between archetypes and generated prompts.');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
for (const [index, promptSet] of leonardoPrompts.entries()) {
|
|
71
|
-
const { kvKey } = promptsToGenerate[index];
|
|
72
|
-
console.log(`Updating KV with prompts for archetype: ${kvKey}`);
|
|
20
|
+
private async log(
|
|
21
|
+
level: 'info' | 'debug' | 'warn' | 'error',
|
|
22
|
+
message: string,
|
|
23
|
+
context: Record<string, any> = {}
|
|
24
|
+
) {
|
|
25
|
+
const logId = `leonardo-service:${Date.now()}`;
|
|
26
|
+
const logMessage = `[${level.toUpperCase()}] ${message}`;
|
|
73
27
|
|
|
74
|
-
|
|
75
|
-
.kvCosmicMirrorArchetypesStore()
|
|
76
|
-
.get<KVArchetype>(kvKey, 'json');
|
|
77
|
-
if (!kvData) {
|
|
78
|
-
console.warn(`KV data not found for key: ${kvKey}. Skipping update.`);
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
28
|
+
console[level](logMessage, context);
|
|
81
29
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
.
|
|
30
|
+
const db = this.context.drizzle();
|
|
31
|
+
try {
|
|
32
|
+
await db
|
|
33
|
+
.insert(schema.logs)
|
|
34
|
+
.values({
|
|
35
|
+
id: logId,
|
|
36
|
+
level,
|
|
37
|
+
message,
|
|
38
|
+
context: JSON.stringify(context),
|
|
39
|
+
createdAt: new Date().getTime(),
|
|
40
|
+
})
|
|
41
|
+
.execute();
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error('[ERROR] Failed to persist log to database:', {
|
|
44
|
+
error,
|
|
45
|
+
logId,
|
|
46
|
+
message,
|
|
47
|
+
context,
|
|
48
|
+
});
|
|
86
49
|
}
|
|
87
|
-
|
|
88
|
-
console.log(`Completed prompt processing for crown: ${crown}`);
|
|
89
50
|
}
|
|
90
51
|
|
|
91
52
|
/**
|
|
92
|
-
*
|
|
53
|
+
* Processes a message from ARCHETYPE_POPULATION_QUEUE to ensure the archetype has three images.
|
|
93
54
|
*/
|
|
94
|
-
async
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
index
|
|
105
|
-
);
|
|
106
|
-
console.info(`Fetching KV for archetype: ${kvKey}`);
|
|
107
|
-
|
|
108
|
-
const kvData = await this.context
|
|
109
|
-
.kvCosmicMirrorArchetypesStore()
|
|
110
|
-
.get<KVArchetype>(kvKey, 'json');
|
|
111
|
-
if (!kvData || kvData.images.length >= 3) {
|
|
112
|
-
console.info(
|
|
113
|
-
`Skipping image generation for index ${index}, images already exist.`
|
|
114
|
-
);
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
console.info(`No images found. Queuing generation for index ${index}...`);
|
|
119
|
-
|
|
120
|
-
const generationResponse = await this.queueImageGeneration(
|
|
121
|
-
kvData.leonardoPrompt
|
|
122
|
-
);
|
|
123
|
-
const generationId = generationResponse.sdGenerationJob.generationId;
|
|
55
|
+
async processArchetypePopulation(message: QueueMessage): Promise<void> {
|
|
56
|
+
const { archetypeDataId, combination, gender, language, archetypeIndex } =
|
|
57
|
+
message;
|
|
58
|
+
await this.log('info', 'Processing archetype population', {
|
|
59
|
+
archetypeDataId,
|
|
60
|
+
combination,
|
|
61
|
+
gender,
|
|
62
|
+
language,
|
|
63
|
+
archetypeIndex,
|
|
64
|
+
});
|
|
124
65
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
66
|
+
const db = this.context.drizzle();
|
|
67
|
+
const archetype = await db
|
|
68
|
+
.select()
|
|
69
|
+
.from(schema.archetypesData)
|
|
70
|
+
.where(eq(schema.archetypesData.id, archetypeDataId))
|
|
71
|
+
.limit(1)
|
|
72
|
+
.execute();
|
|
73
|
+
|
|
74
|
+
if (!archetype[0]) {
|
|
75
|
+
await this.log('error', 'Archetype not found', { archetypeDataId });
|
|
76
|
+
throw new Error(`Archetype not found: ${archetypeDataId}`);
|
|
77
|
+
}
|
|
128
78
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
status: 'pending',
|
|
135
|
-
createdAt: new Date(),
|
|
79
|
+
const images = JSON.parse(archetype[0].images || '[]');
|
|
80
|
+
if (images.length >= 3) {
|
|
81
|
+
await this.log('info', 'Archetype already has sufficient images', {
|
|
82
|
+
archetypeDataId,
|
|
83
|
+
imageCount: images.length,
|
|
136
84
|
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
137
87
|
|
|
138
|
-
|
|
139
|
-
|
|
88
|
+
if (!archetype[0].leonardoPrompt) {
|
|
89
|
+
await this.log('error', 'Missing Leonardo prompt for archetype', {
|
|
90
|
+
archetypeDataId,
|
|
91
|
+
});
|
|
92
|
+
throw new Error(
|
|
93
|
+
`Missing Leonardo prompt for archetype: ${archetypeDataId}`
|
|
140
94
|
);
|
|
141
95
|
}
|
|
142
|
-
}
|
|
143
96
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
archetypes: Array<{ name: string; visualDescription: string }>
|
|
149
|
-
): Promise<string[]> {
|
|
150
|
-
console.log(`Generating Leonardo prompts for archetypes`);
|
|
97
|
+
await this.log('debug', 'Generating images for archetype', {
|
|
98
|
+
archetypeDataId,
|
|
99
|
+
prompt: archetype[0].leonardoPrompt,
|
|
100
|
+
});
|
|
151
101
|
|
|
152
|
-
const
|
|
153
|
-
.
|
|
154
|
-
.
|
|
155
|
-
|
|
102
|
+
const generationResponse = await this.context
|
|
103
|
+
.api()
|
|
104
|
+
.callLeonardo.generateImage({
|
|
105
|
+
prompt: archetype[0].leonardoPrompt,
|
|
106
|
+
width: 512,
|
|
107
|
+
height: 640,
|
|
108
|
+
quantity: 3 - images.length,
|
|
109
|
+
});
|
|
156
110
|
|
|
157
|
-
|
|
158
|
-
|
|
111
|
+
const generationId = generationResponse.sdGenerationJob.generationId;
|
|
112
|
+
if (!generationId) {
|
|
113
|
+
await this.log(
|
|
114
|
+
'error',
|
|
115
|
+
'Leonardo generation failed to return a valid ID',
|
|
116
|
+
{ archetypeDataId }
|
|
117
|
+
);
|
|
118
|
+
throw new Error('Leonardo generation failed to return a valid ID');
|
|
159
119
|
}
|
|
160
120
|
|
|
161
|
-
|
|
121
|
+
await db.insert(schema.generations).values({
|
|
122
|
+
id: generationId,
|
|
123
|
+
archetypeIndex: parseInt(archetypeIndex),
|
|
124
|
+
archetypeDataId,
|
|
125
|
+
type: 'archetype_image',
|
|
126
|
+
status: 'pending',
|
|
127
|
+
gender,
|
|
128
|
+
createdAt: new Date(),
|
|
129
|
+
});
|
|
162
130
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
.
|
|
131
|
+
await this.log('info', 'Queued image generation', {
|
|
132
|
+
generationId,
|
|
133
|
+
archetypeDataId,
|
|
134
|
+
imagesToGenerate: 3 - images.length,
|
|
135
|
+
});
|
|
167
136
|
}
|
|
168
137
|
|
|
169
138
|
/**
|
|
170
|
-
*
|
|
139
|
+
* Uploads a user-provided image to Leonardo.ai.
|
|
171
140
|
*/
|
|
172
|
-
private async queueImageGeneration(
|
|
173
|
-
prompt: string
|
|
174
|
-
): Promise<LeonardoGenerateImageResponse> {
|
|
175
|
-
console.log(`Queuing Leonardo image generation...`);
|
|
176
|
-
|
|
177
|
-
const { width, height } = sizes['alchemy']['post4:5'];
|
|
178
|
-
|
|
179
|
-
try {
|
|
180
|
-
const response = await this.context
|
|
181
|
-
.api()
|
|
182
|
-
.callLeonardo.generateImage({ width, height, prompt });
|
|
183
|
-
if (!response) {
|
|
184
|
-
throw new Error('Leonardo image generation failed');
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
console.log('Leonardo Image Generation Response:', response);
|
|
188
|
-
return response;
|
|
189
|
-
} catch (error) {
|
|
190
|
-
console.error('Error queuing Leonardo image generation:', error);
|
|
191
|
-
throw error;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
141
|
async uploadImage(
|
|
196
142
|
file: File
|
|
197
143
|
): Promise<{ uploadedImageId: string; uploadedImageUrl: string }> {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
144
|
+
await this.log('info', 'Starting image upload', {
|
|
145
|
+
fileName: file.name,
|
|
146
|
+
fileSize: file.size,
|
|
147
|
+
});
|
|
201
148
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
149
|
+
const fileExtension = file.name.split('.').pop()?.toLowerCase();
|
|
150
|
+
const mimeType = file.type || `image/${fileExtension}`;
|
|
205
151
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
152
|
+
if (!fileExtension || !mimeType.startsWith('image/')) {
|
|
153
|
+
await this.log('error', 'Invalid file extension or type', {
|
|
154
|
+
fileName: file.name,
|
|
155
|
+
});
|
|
156
|
+
throw new Error('Invalid file extension or type');
|
|
157
|
+
}
|
|
211
158
|
|
|
212
159
|
try {
|
|
213
|
-
console.log('Requesting presigned URL...');
|
|
214
160
|
const presignedUrlData = await this.context
|
|
215
161
|
.api()
|
|
216
|
-
.callLeonardo.generatePresignedUrl(
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
!presignedUrlData.url ||
|
|
222
|
-
!presignedUrlData.fields ||
|
|
223
|
-
!presignedUrlData.id
|
|
224
|
-
) {
|
|
225
|
-
throw new Error('Invalid presigned URL response from API');
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
console.log('Uploading file...');
|
|
229
|
-
await this.uploadToPresignedUrl(
|
|
230
|
-
presignedUrlData.url,
|
|
231
|
-
presignedUrlData.fields,
|
|
232
|
-
file
|
|
233
|
-
);
|
|
162
|
+
.callLeonardo.generatePresignedUrl();
|
|
163
|
+
await this.context.api().callLeonardo.uploadImageToPresignedUrl(file, {
|
|
164
|
+
fields: presignedUrlData.fields,
|
|
165
|
+
url: presignedUrlData.url,
|
|
166
|
+
});
|
|
234
167
|
|
|
235
168
|
const uploadedImageId = presignedUrlData.id;
|
|
169
|
+
// TODO: Replace hardcoded user ID with dynamic value from env or context
|
|
236
170
|
const uploadedImageUrl = `https://cdn.leonardo.ai/users/b117a933-e5c9-45b2-96aa-4b619c2d74ba/initImages/${uploadedImageId}.${fileExtension}`;
|
|
237
171
|
|
|
238
|
-
|
|
172
|
+
await this.log('info', 'Image uploaded successfully', {
|
|
239
173
|
uploadedImageId,
|
|
240
174
|
uploadedImageUrl,
|
|
241
175
|
});
|
|
242
|
-
|
|
243
176
|
return { uploadedImageId, uploadedImageUrl };
|
|
244
177
|
} catch (error: any) {
|
|
245
|
-
|
|
178
|
+
await this.log('error', 'Error during image upload', {
|
|
179
|
+
message: error.message,
|
|
180
|
+
});
|
|
246
181
|
throw new Error('Failed to upload image');
|
|
247
182
|
}
|
|
248
183
|
}
|
|
249
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Uploads an image from a URL to Leonardo.ai.
|
|
187
|
+
*/
|
|
250
188
|
async uploadImageByUrl(
|
|
251
189
|
imageUrl: string
|
|
252
190
|
): Promise<{ uploadedImageId: string; uploadedImageUrl: string }> {
|
|
253
|
-
|
|
191
|
+
await this.log('info', 'Starting image upload by URL', { imageUrl });
|
|
254
192
|
|
|
255
193
|
try {
|
|
256
|
-
console.log('Fetching image from URL...');
|
|
257
194
|
const response = await fetch(imageUrl);
|
|
258
|
-
|
|
259
195
|
if (!response.ok) {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
196
|
+
await this.log('error', 'Failed to fetch image from URL', {
|
|
197
|
+
status: response.status,
|
|
198
|
+
statusText: response.statusText,
|
|
199
|
+
});
|
|
200
|
+
throw new Error(`Failed to fetch image: ${response.statusText}`);
|
|
263
201
|
}
|
|
264
202
|
|
|
265
203
|
const blob = await response.blob();
|
|
266
204
|
const fileExtension = imageUrl.split('.').pop()?.toLowerCase() || 'jpg';
|
|
267
205
|
const mimeType = blob.type || `image/${fileExtension}`;
|
|
268
206
|
|
|
269
|
-
if (!
|
|
270
|
-
|
|
207
|
+
if (!mimeType.startsWith('image/')) {
|
|
208
|
+
await this.log('error', 'Invalid image type', { imageUrl, mimeType });
|
|
209
|
+
throw new Error('Invalid image type');
|
|
271
210
|
}
|
|
272
211
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
mimeType,
|
|
212
|
+
// Explicitly use global File constructor to ensure Web API File
|
|
213
|
+
const file = new File([blob], `upload.${fileExtension}`, {
|
|
214
|
+
type: mimeType,
|
|
276
215
|
});
|
|
277
216
|
|
|
278
|
-
console.log('Requesting presigned URL...');
|
|
279
217
|
const presignedUrlData = await this.context
|
|
280
218
|
.api()
|
|
281
|
-
.callLeonardo.generatePresignedUrl(
|
|
282
|
-
|
|
219
|
+
.callLeonardo.generatePresignedUrl();
|
|
220
|
+
await this.context
|
|
221
|
+
.api()
|
|
222
|
+
.callLeonardo.uploadImageToPresignedUrl(file as File, {
|
|
223
|
+
fields: presignedUrlData.fields,
|
|
224
|
+
url: presignedUrlData.url,
|
|
283
225
|
});
|
|
284
226
|
|
|
285
|
-
if (
|
|
286
|
-
!presignedUrlData.url ||
|
|
287
|
-
!presignedUrlData.fields ||
|
|
288
|
-
!presignedUrlData.id
|
|
289
|
-
) {
|
|
290
|
-
throw new Error('Invalid presigned URL response from API');
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
console.log('Presigned URL obtained:', presignedUrlData);
|
|
294
|
-
|
|
295
|
-
const file = new File([blob], `upload.${fileExtension}`, {
|
|
296
|
-
type: mimeType,
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
console.log('Uploading file to presigned URL...');
|
|
300
|
-
await this.uploadToPresignedUrl(
|
|
301
|
-
presignedUrlData.url,
|
|
302
|
-
presignedUrlData.fields,
|
|
303
|
-
file as any
|
|
304
|
-
);
|
|
305
|
-
|
|
306
227
|
const uploadedImageId = presignedUrlData.id;
|
|
228
|
+
// TODO: Replace hardcoded user ID with dynamic value from env or context
|
|
307
229
|
const uploadedImageUrl = `https://cdn.leonardo.ai/users/b117a933-e5c9-45b2-96aa-4b619c2d74ba/initImages/${uploadedImageId}.${fileExtension}`;
|
|
308
230
|
|
|
309
|
-
|
|
231
|
+
await this.log('info', 'Image uploaded successfully', {
|
|
310
232
|
uploadedImageId,
|
|
311
233
|
uploadedImageUrl,
|
|
312
234
|
});
|
|
313
|
-
|
|
314
235
|
return { uploadedImageId, uploadedImageUrl };
|
|
315
236
|
} catch (error: any) {
|
|
316
|
-
|
|
237
|
+
await this.log('error', 'Error during uploadImageByUrl', {
|
|
238
|
+
message: error.message,
|
|
239
|
+
});
|
|
317
240
|
throw new Error('Failed to upload image by URL');
|
|
318
241
|
}
|
|
319
242
|
}
|
|
320
243
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
formData.append('file', file);
|
|
333
|
-
|
|
334
|
-
console.log('Uploading with FormData:', Array.from(formData.entries()));
|
|
335
|
-
|
|
336
|
-
const response = await fetch(presignedUrl, {
|
|
337
|
-
method: 'POST',
|
|
338
|
-
body: formData,
|
|
244
|
+
/**
|
|
245
|
+
* Personalizes a Leonardo prompt based on user-specific traits.
|
|
246
|
+
*/
|
|
247
|
+
async personalizeCosmicMirrorLeonardoPrompt(params: {
|
|
248
|
+
leonardoPrompt: string;
|
|
249
|
+
traits: string;
|
|
250
|
+
}): Promise<string> {
|
|
251
|
+
const { leonardoPrompt, traits } = params;
|
|
252
|
+
await this.log('info', 'Personalizing Leonardo prompt', {
|
|
253
|
+
leonardoPrompt,
|
|
254
|
+
traits,
|
|
339
255
|
});
|
|
340
256
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
throw new Error(`Image upload failed: ${response.status}`);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
console.log('Upload to presigned URL successful');
|
|
348
|
-
}
|
|
257
|
+
const messages = this.context
|
|
258
|
+
.buildLLMMessages()
|
|
259
|
+
.personalizeCosmicMirrorLeonardoPrompt({ leonardoPrompt, traits });
|
|
349
260
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}): Promise<string> {
|
|
359
|
-
const { leonardoPrompt, traits } = params;
|
|
360
|
-
|
|
361
|
-
const messages = this.context
|
|
362
|
-
.buildLLMMessages()
|
|
363
|
-
.personalizeCosmicMirrorLeonardoPrompt({ leonardoPrompt, traits });
|
|
364
|
-
|
|
365
|
-
try {
|
|
366
|
-
const personalizedPrompt = await this.context
|
|
367
|
-
.api()
|
|
368
|
-
.callChatGPT.single(messages, {});
|
|
261
|
+
try {
|
|
262
|
+
const personalizedPrompt = await this.context
|
|
263
|
+
.api()
|
|
264
|
+
.callChatGPT.single(messages, {});
|
|
265
|
+
if (!personalizedPrompt) {
|
|
266
|
+
await this.log('error', 'Failed to generate personalized prompt');
|
|
267
|
+
throw new Error('Failed to generate personalized prompt');
|
|
268
|
+
}
|
|
369
269
|
|
|
370
|
-
|
|
371
|
-
|
|
270
|
+
await this.log('info', 'Successfully personalized prompt', {
|
|
271
|
+
personalizedPrompt,
|
|
272
|
+
});
|
|
273
|
+
return personalizedPrompt.trim();
|
|
274
|
+
} catch (error: any) {
|
|
275
|
+
await this.log('error', 'Error personalizing Leonardo prompt', {
|
|
276
|
+
message: error.message,
|
|
277
|
+
});
|
|
278
|
+
throw error;
|
|
372
279
|
}
|
|
373
|
-
|
|
374
|
-
console.log('Personalized Leonardo Prompt:', personalizedPrompt);
|
|
375
|
-
|
|
376
|
-
return personalizedPrompt.trim();
|
|
377
|
-
} catch (error) {
|
|
378
|
-
console.error('Error personalizing Leonardo prompt:', error);
|
|
379
|
-
throw error;
|
|
380
280
|
}
|
|
381
281
|
}
|
|
382
|
-
}
|