@xuda.io/ai_module 1.1.4866 → 1.1.4868
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/index.mjs +191 -188
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -5470,6 +5470,194 @@ export const get_profile_avatar = async function (profile_picture, uid, prompt,
|
|
|
5470
5470
|
}
|
|
5471
5471
|
};
|
|
5472
5472
|
|
|
5473
|
+
export const get_profile_picture = async function (uid, account_type = 'business', name, metadata = {}, account_profile_info, job_id, headers = {}) {
|
|
5474
|
+
const tempDir = os.tmpdir();
|
|
5475
|
+
const uniqueId = Date.now() + '_' + Math.random().toString(36).substring(7);
|
|
5476
|
+
const tempOutputPath = path.join(tempDir, `output_${uniqueId}.png`);
|
|
5477
|
+
|
|
5478
|
+
const { email, create_avatar } = metadata;
|
|
5479
|
+
|
|
5480
|
+
let prompt,
|
|
5481
|
+
url,
|
|
5482
|
+
factual_prompt,
|
|
5483
|
+
originalname,
|
|
5484
|
+
factual_image_mode,
|
|
5485
|
+
imageBase64,
|
|
5486
|
+
image_blob_ret,
|
|
5487
|
+
file,
|
|
5488
|
+
profile_picture_source,
|
|
5489
|
+
drive_ret = { code: 1, data: {} },
|
|
5490
|
+
resize = {};
|
|
5491
|
+
|
|
5492
|
+
switch (account_type) {
|
|
5493
|
+
case 'personal': {
|
|
5494
|
+
prompt = `find "${name}" person profile image base on the following facts: "${JSON.stringify(metadata)}", Return only png,jpg image url single result e.g: "https://fb.com/person_image.png", nothing else`;
|
|
5495
|
+
factual_prompt = `analyze the the person info base on the name and the facts: {"name": "${name || ''}", facts: "${JSON.stringify(
|
|
5496
|
+
metadata,
|
|
5497
|
+
)}" and create realistic fictional profile picture transparent background ,person in the center of the picture add top margin the person should cover the whole picture`;
|
|
5498
|
+
originalname = normalizeFilename(name) + '_xu_profile.png';
|
|
5499
|
+
resize = {
|
|
5500
|
+
fit: 'inside', // Scale up/down to fit inside 1024×1024 while preserving aspect ratio
|
|
5501
|
+
withoutEnlargement: false, // Allow enlargement if original is smaller
|
|
5502
|
+
background: { r: 0, g: 0, b: 0, alpha: 0 },
|
|
5503
|
+
};
|
|
5504
|
+
break;
|
|
5505
|
+
}
|
|
5506
|
+
|
|
5507
|
+
case 'business': {
|
|
5508
|
+
prompt = `Search for a large, high-quality "${name}" logo or icon in PNG or JPG format. Output **exclusively** a single valid image URL, like this: "https://example.com/large-logo.png". Do not include any other text, descriptions, or additional information.`;
|
|
5509
|
+
factual_prompt = `create logo for the company named: "${name}" the logo should only be initials of the name or geometric shape`;
|
|
5510
|
+
originalname = normalizeFilename(name) + '_xu_logo.png';
|
|
5511
|
+
resize = {
|
|
5512
|
+
fit: 'cover', // Fill the 1024×1024 area (may crop edges)
|
|
5513
|
+
position: 'centre', // Center the crop
|
|
5514
|
+
background: { r: 0, g: 0, b: 0, alpha: 0 },
|
|
5515
|
+
};
|
|
5516
|
+
break;
|
|
5517
|
+
}
|
|
5518
|
+
|
|
5519
|
+
default:
|
|
5520
|
+
throw new Error('account_type not supported');
|
|
5521
|
+
break;
|
|
5522
|
+
}
|
|
5523
|
+
|
|
5524
|
+
const getUserPhotoByEmail = async function (email) {
|
|
5525
|
+
try {
|
|
5526
|
+
const auth = admin.auth();
|
|
5527
|
+
const userRecord = await auth.getUserByEmail(email);
|
|
5528
|
+
|
|
5529
|
+
// photoURL is the profile picture URL (or null if not set)
|
|
5530
|
+
const photoURL = userRecord.photoURL;
|
|
5531
|
+
// console.log(`User found: ${JSON.stringify(userRecord)}`);
|
|
5532
|
+
|
|
5533
|
+
// console.log(`User found: ${userRecord.uid}`);
|
|
5534
|
+
// console.log(`Display name: ${userRecord.displayName || 'None'}`);
|
|
5535
|
+
// console.log(`Email verified: ${userRecord.emailVerified}`);
|
|
5536
|
+
// console.log(`Profile picture URL: ${photoURL || 'No photo set'}`);
|
|
5537
|
+
|
|
5538
|
+
return photoURL;
|
|
5539
|
+
} catch (error) {
|
|
5540
|
+
if (error.code === 'auth/user-not-found') {
|
|
5541
|
+
console.log('getUserPhotoByEmail', `No user found with email: ${email}`);
|
|
5542
|
+
return null;
|
|
5543
|
+
}
|
|
5544
|
+
|
|
5545
|
+
console.error('Error fetching user:', error);
|
|
5546
|
+
// throw error;
|
|
5547
|
+
}
|
|
5548
|
+
};
|
|
5549
|
+
|
|
5550
|
+
const get_url = async function () {
|
|
5551
|
+
const ret = await submit_chat_gpt_prompt({
|
|
5552
|
+
uid,
|
|
5553
|
+
prompt,
|
|
5554
|
+
model: 'gpt-5-nano',
|
|
5555
|
+
metadata: { func: 'get_profile_picture' },
|
|
5556
|
+
account_profile_info,
|
|
5557
|
+
tools: [{ type: 'web_search_preview' }],
|
|
5558
|
+
});
|
|
5559
|
+
|
|
5560
|
+
return ret.data;
|
|
5561
|
+
};
|
|
5562
|
+
|
|
5563
|
+
// debugger;
|
|
5564
|
+
try {
|
|
5565
|
+
url = await getUserPhotoByEmail(email);
|
|
5566
|
+
if (url) {
|
|
5567
|
+
try {
|
|
5568
|
+
image_blob_ret = await get_image_blob_from_downloaded_image(url);
|
|
5569
|
+
profile_picture_source = 'google';
|
|
5570
|
+
drive_ret.data = { file_url: url };
|
|
5571
|
+
} catch (err) {
|
|
5572
|
+
if (!err.message.includes('Failed to fetch image URL')) {
|
|
5573
|
+
console.error(err);
|
|
5574
|
+
return '';
|
|
5575
|
+
}
|
|
5576
|
+
url = '';
|
|
5577
|
+
}
|
|
5578
|
+
}
|
|
5579
|
+
|
|
5580
|
+
if (!url && create_avatar) {
|
|
5581
|
+
// first attempt
|
|
5582
|
+
if (account_type === 'business') {
|
|
5583
|
+
url = await get_url();
|
|
5584
|
+
|
|
5585
|
+
if (url.substr(0, 8) !== 'https://') {
|
|
5586
|
+
profile_picture_source = 'factual';
|
|
5587
|
+
// second attempt
|
|
5588
|
+
url = await get_url();
|
|
5589
|
+
if (url.substr(0, 8) !== 'https://') {
|
|
5590
|
+
factual_image_mode = true;
|
|
5591
|
+
profile_picture_source = 'factual';
|
|
5592
|
+
}
|
|
5593
|
+
} else {
|
|
5594
|
+
// success
|
|
5595
|
+
profile_picture_source = 'internet search';
|
|
5596
|
+
try {
|
|
5597
|
+
image_blob_ret = await get_image_blob_from_downloaded_image(url);
|
|
5598
|
+
} catch (err) {
|
|
5599
|
+
if (!err.message.includes('Failed to fetch image URL')) {
|
|
5600
|
+
console.error(err);
|
|
5601
|
+
return '';
|
|
5602
|
+
}
|
|
5603
|
+
profile_picture_source = 'factual';
|
|
5604
|
+
factual_image_mode = true;
|
|
5605
|
+
}
|
|
5606
|
+
}
|
|
5607
|
+
} else {
|
|
5608
|
+
factual_image_mode = true;
|
|
5609
|
+
profile_picture_source = 'factual';
|
|
5610
|
+
}
|
|
5611
|
+
|
|
5612
|
+
if (factual_image_mode) {
|
|
5613
|
+
imageBase64 = await create_image(uid, factual_prompt, undefined, undefined, 1, undefined, undefined, {}, account_profile_info);
|
|
5614
|
+
} else {
|
|
5615
|
+
const model = 'gpt-image-1-mini'; // 'chatgpt-image-latest';
|
|
5616
|
+
const prompt = `
|
|
5617
|
+
extract the logo from the image
|
|
5618
|
+
`;
|
|
5619
|
+
let image_response;
|
|
5620
|
+
try {
|
|
5621
|
+
image_response = await client.images.edit({
|
|
5622
|
+
model,
|
|
5623
|
+
image: image_blob_ret.image_blob,
|
|
5624
|
+
prompt,
|
|
5625
|
+
background: 'transparent',
|
|
5626
|
+
});
|
|
5627
|
+
report_ai_status(model);
|
|
5628
|
+
} catch (err) {
|
|
5629
|
+
report_ai_status(model, err);
|
|
5630
|
+
throw err;
|
|
5631
|
+
}
|
|
5632
|
+
|
|
5633
|
+
imageBase64 = await normalizeBase64To1024(image_response.data[0].b64_json, resize);
|
|
5634
|
+
account_module.record_ai_usage(uid, image_response.usage.input_tokens, image_response.usage.output_tokens, 'profile image', prompt, model, { url }, account_profile_info);
|
|
5635
|
+
}
|
|
5636
|
+
|
|
5637
|
+
const outputBuffer = Buffer.from(imageBase64, 'base64');
|
|
5638
|
+
const outputPath = tempOutputPath;
|
|
5639
|
+
await fs.promises.writeFile(outputPath, outputBuffer);
|
|
5640
|
+
|
|
5641
|
+
console.log('Success! Saved →', outputPath);
|
|
5642
|
+
|
|
5643
|
+
console.log(file);
|
|
5644
|
+
|
|
5645
|
+
const file_obj = {
|
|
5646
|
+
originalname,
|
|
5647
|
+
path: outputPath,
|
|
5648
|
+
mimetype: `image/png`,
|
|
5649
|
+
};
|
|
5650
|
+
|
|
5651
|
+
drive_ret = await drive_module.upload_drive_file_user({ uid, path: '/Profile Images' }, job_id, headers, file_obj);
|
|
5652
|
+
drive_ret.profile_picture_source = profile_picture_source;
|
|
5653
|
+
}
|
|
5654
|
+
return drive_ret;
|
|
5655
|
+
} catch (err) {
|
|
5656
|
+
console.error(err);
|
|
5657
|
+
return;
|
|
5658
|
+
}
|
|
5659
|
+
};
|
|
5660
|
+
|
|
5473
5661
|
export const conversation_actions = async function (req, job_id, headers) {
|
|
5474
5662
|
const { conversation_id, item_id, action, uid, account_profile_info } = req;
|
|
5475
5663
|
try {
|
|
@@ -6005,6 +6193,9 @@ const attachment_handler = async function (uid, app_id, conversation_id, attachm
|
|
|
6005
6193
|
// file_names.push(file.filename);
|
|
6006
6194
|
let transcript;
|
|
6007
6195
|
try {
|
|
6196
|
+
if (conversation_doc.reference_type === 'contacts' && conversation_doc.conversation_type === 'email') {
|
|
6197
|
+
}
|
|
6198
|
+
|
|
6008
6199
|
transcript = await get_transcript(file.filename);
|
|
6009
6200
|
} catch (error) {
|
|
6010
6201
|
process_stat = 'partial';
|
|
@@ -6154,194 +6345,6 @@ function normalizeFilename(name) {
|
|
|
6154
6345
|
.replace(/^_+|_+$/g, ''); // trim leading/trailing underscores
|
|
6155
6346
|
}
|
|
6156
6347
|
|
|
6157
|
-
export const get_profile_picture = async function (uid, account_type = 'business', name, metadata = {}, account_profile_info, job_id, headers = {}) {
|
|
6158
|
-
const tempDir = os.tmpdir();
|
|
6159
|
-
const uniqueId = Date.now() + '_' + Math.random().toString(36).substring(7);
|
|
6160
|
-
const tempOutputPath = path.join(tempDir, `output_${uniqueId}.png`);
|
|
6161
|
-
|
|
6162
|
-
const { email, create_avatar } = metadata;
|
|
6163
|
-
|
|
6164
|
-
let prompt,
|
|
6165
|
-
url,
|
|
6166
|
-
factual_prompt,
|
|
6167
|
-
originalname,
|
|
6168
|
-
factual_image_mode,
|
|
6169
|
-
imageBase64,
|
|
6170
|
-
image_blob_ret,
|
|
6171
|
-
file,
|
|
6172
|
-
profile_picture_source,
|
|
6173
|
-
drive_ret = { code: 1, data: {} },
|
|
6174
|
-
resize = {};
|
|
6175
|
-
|
|
6176
|
-
switch (account_type) {
|
|
6177
|
-
case 'personal': {
|
|
6178
|
-
prompt = `find "${name}" person profile image base on the following facts: "${JSON.stringify(metadata)}", Return only png,jpg image url single result e.g: "https://fb.com/person_image.png", nothing else`;
|
|
6179
|
-
factual_prompt = `analyze the the person info base on the name and the facts: {"name": "${name || ''}", facts: "${JSON.stringify(
|
|
6180
|
-
metadata,
|
|
6181
|
-
)}" and create realistic fictional profile picture transparent background ,person in the center of the picture add top margin the person should cover the whole picture`;
|
|
6182
|
-
originalname = normalizeFilename(name) + '_xu_profile.png';
|
|
6183
|
-
resize = {
|
|
6184
|
-
fit: 'inside', // Scale up/down to fit inside 1024×1024 while preserving aspect ratio
|
|
6185
|
-
withoutEnlargement: false, // Allow enlargement if original is smaller
|
|
6186
|
-
background: { r: 0, g: 0, b: 0, alpha: 0 },
|
|
6187
|
-
};
|
|
6188
|
-
break;
|
|
6189
|
-
}
|
|
6190
|
-
|
|
6191
|
-
case 'business': {
|
|
6192
|
-
prompt = `Search for a large, high-quality "${name}" logo or icon in PNG or JPG format. Output **exclusively** a single valid image URL, like this: "https://example.com/large-logo.png". Do not include any other text, descriptions, or additional information.`;
|
|
6193
|
-
factual_prompt = `create logo for the company named: "${name}" the logo should only be initials of the name or geometric shape`;
|
|
6194
|
-
originalname = normalizeFilename(name) + '_xu_logo.png';
|
|
6195
|
-
resize = {
|
|
6196
|
-
fit: 'cover', // Fill the 1024×1024 area (may crop edges)
|
|
6197
|
-
position: 'centre', // Center the crop
|
|
6198
|
-
background: { r: 0, g: 0, b: 0, alpha: 0 },
|
|
6199
|
-
};
|
|
6200
|
-
break;
|
|
6201
|
-
}
|
|
6202
|
-
|
|
6203
|
-
default:
|
|
6204
|
-
throw new Error('account_type not supported');
|
|
6205
|
-
break;
|
|
6206
|
-
}
|
|
6207
|
-
|
|
6208
|
-
const getUserPhotoByEmail = async function (email) {
|
|
6209
|
-
try {
|
|
6210
|
-
const auth = admin.auth();
|
|
6211
|
-
const userRecord = await auth.getUserByEmail(email);
|
|
6212
|
-
|
|
6213
|
-
// photoURL is the profile picture URL (or null if not set)
|
|
6214
|
-
const photoURL = userRecord.photoURL;
|
|
6215
|
-
// console.log(`User found: ${JSON.stringify(userRecord)}`);
|
|
6216
|
-
|
|
6217
|
-
// console.log(`User found: ${userRecord.uid}`);
|
|
6218
|
-
// console.log(`Display name: ${userRecord.displayName || 'None'}`);
|
|
6219
|
-
// console.log(`Email verified: ${userRecord.emailVerified}`);
|
|
6220
|
-
// console.log(`Profile picture URL: ${photoURL || 'No photo set'}`);
|
|
6221
|
-
|
|
6222
|
-
return photoURL;
|
|
6223
|
-
} catch (error) {
|
|
6224
|
-
if (error.code === 'auth/user-not-found') {
|
|
6225
|
-
console.log('getUserPhotoByEmail', `No user found with email: ${email}`);
|
|
6226
|
-
return null;
|
|
6227
|
-
}
|
|
6228
|
-
|
|
6229
|
-
console.error('Error fetching user:', error);
|
|
6230
|
-
// throw error;
|
|
6231
|
-
}
|
|
6232
|
-
};
|
|
6233
|
-
|
|
6234
|
-
const get_url = async function () {
|
|
6235
|
-
const ret = await submit_chat_gpt_prompt({
|
|
6236
|
-
uid,
|
|
6237
|
-
prompt,
|
|
6238
|
-
model: 'gpt-5-nano',
|
|
6239
|
-
metadata: { func: 'get_profile_picture' },
|
|
6240
|
-
account_profile_info,
|
|
6241
|
-
tools: [{ type: 'web_search_preview' }],
|
|
6242
|
-
});
|
|
6243
|
-
|
|
6244
|
-
return ret.data;
|
|
6245
|
-
};
|
|
6246
|
-
|
|
6247
|
-
// debugger;
|
|
6248
|
-
try {
|
|
6249
|
-
url = await getUserPhotoByEmail(email);
|
|
6250
|
-
if (url) {
|
|
6251
|
-
try {
|
|
6252
|
-
image_blob_ret = await get_image_blob_from_downloaded_image(url);
|
|
6253
|
-
profile_picture_source = 'google';
|
|
6254
|
-
drive_ret.data = { file_url: url };
|
|
6255
|
-
} catch (err) {
|
|
6256
|
-
if (!err.message.includes('Failed to fetch image URL')) {
|
|
6257
|
-
console.error(err);
|
|
6258
|
-
return '';
|
|
6259
|
-
}
|
|
6260
|
-
url = '';
|
|
6261
|
-
}
|
|
6262
|
-
}
|
|
6263
|
-
|
|
6264
|
-
if (!url && create_avatar) {
|
|
6265
|
-
// first attempt
|
|
6266
|
-
if (account_type === 'business') {
|
|
6267
|
-
url = await get_url();
|
|
6268
|
-
|
|
6269
|
-
if (url.substr(0, 8) !== 'https://') {
|
|
6270
|
-
profile_picture_source = 'factual';
|
|
6271
|
-
// second attempt
|
|
6272
|
-
url = await get_url();
|
|
6273
|
-
if (url.substr(0, 8) !== 'https://') {
|
|
6274
|
-
factual_image_mode = true;
|
|
6275
|
-
profile_picture_source = 'factual';
|
|
6276
|
-
}
|
|
6277
|
-
} else {
|
|
6278
|
-
// success
|
|
6279
|
-
profile_picture_source = 'internet search';
|
|
6280
|
-
try {
|
|
6281
|
-
image_blob_ret = await get_image_blob_from_downloaded_image(url);
|
|
6282
|
-
} catch (err) {
|
|
6283
|
-
if (!err.message.includes('Failed to fetch image URL')) {
|
|
6284
|
-
console.error(err);
|
|
6285
|
-
return '';
|
|
6286
|
-
}
|
|
6287
|
-
profile_picture_source = 'factual';
|
|
6288
|
-
factual_image_mode = true;
|
|
6289
|
-
}
|
|
6290
|
-
}
|
|
6291
|
-
} else {
|
|
6292
|
-
factual_image_mode = true;
|
|
6293
|
-
profile_picture_source = 'factual';
|
|
6294
|
-
}
|
|
6295
|
-
|
|
6296
|
-
if (factual_image_mode) {
|
|
6297
|
-
imageBase64 = await create_image(uid, factual_prompt, undefined, undefined, 1, undefined, undefined, {}, account_profile_info);
|
|
6298
|
-
} else {
|
|
6299
|
-
const model = 'gpt-image-1-mini'; // 'chatgpt-image-latest';
|
|
6300
|
-
const prompt = `
|
|
6301
|
-
extract the logo from the image
|
|
6302
|
-
`;
|
|
6303
|
-
let image_response;
|
|
6304
|
-
try {
|
|
6305
|
-
image_response = await client.images.edit({
|
|
6306
|
-
model,
|
|
6307
|
-
image: image_blob_ret.image_blob,
|
|
6308
|
-
prompt,
|
|
6309
|
-
background: 'transparent',
|
|
6310
|
-
});
|
|
6311
|
-
report_ai_status(model);
|
|
6312
|
-
} catch (err) {
|
|
6313
|
-
report_ai_status(model, err);
|
|
6314
|
-
throw err;
|
|
6315
|
-
}
|
|
6316
|
-
|
|
6317
|
-
imageBase64 = await normalizeBase64To1024(image_response.data[0].b64_json, resize);
|
|
6318
|
-
account_module.record_ai_usage(uid, image_response.usage.input_tokens, image_response.usage.output_tokens, 'profile image', prompt, model, { url }, account_profile_info);
|
|
6319
|
-
}
|
|
6320
|
-
|
|
6321
|
-
const outputBuffer = Buffer.from(imageBase64, 'base64');
|
|
6322
|
-
const outputPath = tempOutputPath;
|
|
6323
|
-
await fs.promises.writeFile(outputPath, outputBuffer);
|
|
6324
|
-
|
|
6325
|
-
console.log('Success! Saved →', outputPath);
|
|
6326
|
-
|
|
6327
|
-
console.log(file);
|
|
6328
|
-
|
|
6329
|
-
const file_obj = {
|
|
6330
|
-
originalname,
|
|
6331
|
-
path: outputPath,
|
|
6332
|
-
mimetype: `image/png`,
|
|
6333
|
-
};
|
|
6334
|
-
|
|
6335
|
-
drive_ret = await drive_module.upload_drive_file_user({ uid, path: '/Profile Images' }, job_id, headers, file_obj);
|
|
6336
|
-
drive_ret.profile_picture_source = profile_picture_source;
|
|
6337
|
-
}
|
|
6338
|
-
return drive_ret;
|
|
6339
|
-
} catch (err) {
|
|
6340
|
-
console.error(err);
|
|
6341
|
-
return;
|
|
6342
|
-
}
|
|
6343
|
-
};
|
|
6344
|
-
|
|
6345
6348
|
async function normalizeBase64To1024(
|
|
6346
6349
|
base64Image,
|
|
6347
6350
|
resize = {
|