@xuda.io/ai_module 1.1.4382 → 1.1.4384

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 (2) hide show
  1. package/index.mjs +5 -272
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -5661,13 +5661,14 @@ const create_and_upload_image_to_drive = async function (drive_type, file_path,
5661
5661
  };
5662
5662
 
5663
5663
  export const create_account_profile_avatar = async function (req, job_id, headers) {
5664
- const { uid } = req;
5664
+ const { uid, url } = req;
5665
5665
  try {
5666
+ const account_profile_info = await get_active_account_profile_info(uid);
5666
5667
  req.account_profile_info = await account_module.get_active_account_profile_info(uid);
5667
- req.is_profile_avatar = true;
5668
+ // req.is_profile_avatar = true;
5668
5669
  req.account_obj = await db_module.get_couch_doc_native('xuda_accounts', uid);
5669
5670
 
5670
- return await get_profile_avatar(req, job_id, headers);
5671
+ return await get_profile_avatar(url, uid, null, account_profile_info, 'business', 'account_profile', job_id, headers);
5671
5672
  } catch (err) {
5672
5673
  return {
5673
5674
  code: -25,
@@ -5681,75 +5682,6 @@ export const get_profile_avatar = async function (profile_picture, uid, prompt,
5681
5682
  const uniqueId = Date.now() + '_' + Math.random().toString(36).substring(7);
5682
5683
  const tempOutputPath = path.join(tempDir, `output_${uniqueId}.png`);
5683
5684
 
5684
- // const { url, uid, prompt, account_profile_info, account_type, docType = 'account', _id, metadata = {}, profile_picture, business_size = 'unknown', name, email } = req;
5685
-
5686
- // async function normalizeBase64To1024(base64Image) {
5687
- // const inputBuffer = Buffer.from(base64Image, 'base64');
5688
-
5689
- // const normalizedBuffer = await sharp(inputBuffer)
5690
- // .resize(1024, 1024, {
5691
- // fit: 'contain', // Preserve aspect ratio, fit within 211x211
5692
- // background: { r: 0, g: 0, b: 0, alpha: 0 }, // Transparent background for padding
5693
- // })
5694
- // .png({
5695
- // quality: 100,
5696
- // compressionLevel: 9,
5697
- // force: true,
5698
- // })
5699
- // .toBuffer();
5700
-
5701
- // return normalizedBuffer.toString('base64'); // Return normalized base64 string
5702
- // }
5703
-
5704
- // async function hasTransparentBackground(filePath) {
5705
- // const image = sharp(filePath);
5706
- // const metadata = await image.metadata();
5707
-
5708
- // // If the image doesn't have an alpha channel at all → no transparency possible
5709
- // if (!metadata.hasAlpha) {
5710
- // return false;
5711
- // }
5712
-
5713
- // // For images with alpha channel, check if any pixel actually has alpha < 255
5714
- // const { data, info } = await image.raw().toBuffer({ resolveWithObject: true });
5715
-
5716
- // // Determine position of alpha channel based on number of channels
5717
- // const channels = info.channels; // 2 (grayscale+alpha), 4 (RGBA), etc.
5718
- // const alphaOffset = channels === 2 ? 1 : channels === 4 ? 3 : -1;
5719
-
5720
- // if (alphaOffset === -1) {
5721
- // // Unusual channel count – be conservative and assume it might have transparency
5722
- // return true;
5723
- // }
5724
-
5725
- // for (let i = alphaOffset; i < data.length; i += channels) {
5726
- // if (data[i] < 255) {
5727
- // return true; // Found at least one transparent/semi-transparent pixel
5728
- // }
5729
- // }
5730
-
5731
- // return false; // Has alpha channel but all pixels are fully opaque
5732
- // }
5733
-
5734
- // async function imageToPngBlob(filePath) {
5735
- // const ext = path.extname(filePath).toLowerCase();
5736
-
5737
- // let buffer;
5738
-
5739
- // let is_transparent = false;
5740
- // if (ext === '.png') {
5741
- // buffer = await fs.promises.readFile(filePath);
5742
- // is_transparent = await hasTransparentBackground(filePath);
5743
- // } else {
5744
- // console.log(`Converting ${path.basename(filePath)} to PNG...`);
5745
- // buffer = await sharp(filePath).png({ quality: 100, compressionLevel: 9, force: true }).toBuffer();
5746
- // }
5747
-
5748
- // // Create a Blob with correct MIME type
5749
-
5750
- // return { is_transparent, image_blob: new Blob([buffer], { type: 'image/png' }) };
5751
- // }
5752
-
5753
5685
  const detect_real_person_in_image = async function (base64) {
5754
5686
  const ret = await submit_chat_gpt_prompt({
5755
5687
  uid,
@@ -5780,60 +5712,14 @@ export const get_profile_avatar = async function (profile_picture, uid, prompt,
5780
5712
  return res?.is_real_person_in_picture;
5781
5713
  };
5782
5714
 
5783
- // const drive_module = await import(`${module_path}/drive_module/index.mjs`);
5784
-
5785
- // if (!is_profile_avatar) {
5786
- // await update_profile_avatar_status(account_obj._id, 2);
5787
- // }
5788
5715
  try {
5789
- // if (!url) {
5790
- // throw new Error('No URL provided in request');
5791
- // }
5792
-
5793
- // 3. Download the image to a Buffer
5794
- // const res = await fetch(url);
5795
- // if (!res.ok) {
5796
- // throw new Error(`Failed to fetch image URL: ${res.status} ${res.statusText}`);
5797
- // }
5798
-
5799
- // const arrayBuffer = await res.arrayBuffer();
5800
- // const imageBuffer = Buffer.from(arrayBuffer);
5801
-
5802
- // const tempDir = os.tmpdir();
5803
- // const uniqueId = Date.now() + '_' + Math.random().toString(36).substring(7);
5804
-
5805
- // const inputExt = path.extname(url) || '.jpg';
5806
- // const tempInputPath = path.join(tempDir, `input_${uniqueId}${inputExt}`);
5807
- // const tempOutputPath = path.join(tempDir, `output_${uniqueId}.png`); // Output is always PNG (transparent)
5808
-
5809
- // 5. Write the downloaded image to disk
5810
- // fs.writeFileSync(tempInputPath, imageBuffer);
5811
- /////////////////////////////////
5812
-
5813
- // const imageFiles = [tempInputPath];
5814
-
5815
- // const images = await Promise.all(
5816
- // imageFiles.map(async (filePath) => {
5817
- // const img_ret = await imageToPngBlob(filePath);
5818
- // const blob = img_ret.image_blob;
5819
-
5820
- // // OpenAI expects a filename for logging/debugging
5821
- // const filename = path.basename(filePath, path.extname(filePath)) + '.png';
5822
- // blob.name = filename; // Optional but helpful
5823
- // // @ts-ignore – name is allowed in Node 20+
5824
- // blob.lastModified = Date.now();
5825
-
5826
- // return { is_transparent: img_ret.is_transparent, image_blob: blob };
5827
- // }),
5828
- // );
5829
-
5830
5716
  let imageBase64;
5831
5717
  const image_blob_ret = await get_image_blob_from_downloaded_image(profile_picture);
5832
5718
  let avatar_source = '';
5833
5719
  if (prompt) {
5834
5720
  const model = 'chatgpt-image-latest';
5835
5721
  const ai_avatar_response = await client.images.edit({
5836
- model, // 'gpt-image-1',
5722
+ model,
5837
5723
  image: image_blob_ret.image_blob, //base photo
5838
5724
  prompt,
5839
5725
  background: 'transparent',
@@ -5841,30 +5727,10 @@ export const get_profile_avatar = async function (profile_picture, uid, prompt,
5841
5727
  imageBase64 = ai_avatar_response.data[0].b64_json;
5842
5728
  record_chat_usage(uid, ai_avatar_response.usage.input_tokens, ai_avatar_response.usage.output_tokens, 'profile avatar', prompt, model, { profile_picture }, account_profile_info);
5843
5729
  } else {
5844
- //////////////////
5845
5730
  imageBase64 = Buffer.from(await image_blob_ret.image_blob.arrayBuffer()).toString('base64');
5846
5731
  if (account_type === 'business') {
5847
5732
  // create avatar from logo - BUSINESS
5848
5733
  const { bio, country, mainCategory, subCategory } = metadata;
5849
- // const ai_avatar_response = await client.images.edit({
5850
- // model: 'chatgpt-image-latest',
5851
- // image: image_blob_ret.image_blob, // only one image allowed
5852
- // prompt: `Generate a realistic fictional portrait wearing a hat. The portrait should be centered, head-and-shoulders only, on a transparent background. Place the provided logo on the hat, and ensure the subject is large enough to fill most of the frame. Use the supplied name, country, and context to guide the character’s appearance.
5853
- // Context: ${JSON.stringify({ bio, business_name, country, mainCategory, subCategory })}`,
5854
- // background: 'transparent',
5855
- // });
5856
- ///////////////////
5857
- // const ai_avatar_response = await client.images.edit({
5858
- // model: 'chatgpt-image-latest',
5859
- // image: image_blob_ret.image_blob, //base photo
5860
- // prompt: `Create a transparent PNG profile image for a business account featuring building branded as ${business_name}.
5861
- // Display the attached logo clearly as prominent exterior signage.
5862
- // The building’s architecture and overall atmosphere should reflect the nature of the business, aligning with ${mainCategory} and ${subCategory}.
5863
- // Use the provided bio (${bio}) to understand the company’s focus and personality, and adapt the architectural style to match the ${country} country’s local design language. Select an appropriate building type for the specific business category, and present a contemporary,
5864
- // creative office environment with a strong, recognizable brand identity. The background should be fully removed, remove trees,clouds,sky or any landscape objects`,
5865
- // background: 'transparent',
5866
- // });
5867
- /////////////////
5868
5734
 
5869
5735
  // const obj = {
5870
5736
  // free: {
@@ -7008,139 +6874,6 @@ const get_image_blob_from_downloaded_image = async function (url) {
7008
6874
  return images[0];
7009
6875
  };
7010
6876
 
7011
- // export const get_business_info = async function (uid, name, email, account_profile_info) {
7012
- // // 1. Prepare the valid values from your categories list
7013
- // const categories = [
7014
- // {
7015
- // id: 'ind_technology',
7016
- // name: 'Technology',
7017
- // sub: ['Software Development', 'AI & Machine Learning', 'Cybersecurity', 'Cloud Computing', 'IT Services', 'SaaS & Platforms', 'Hardware & Electronics'],
7018
- // },
7019
- // {
7020
- // id: 'ind_marketing',
7021
- // name: 'Marketing & Advertising',
7022
- // sub: ['Digital Marketing', 'PPC & SEO', 'Content Creation', 'Branding', 'Social Media Management', 'Email Marketing', 'Market Research'],
7023
- // },
7024
- // {
7025
- // id: 'ind_sales',
7026
- // name: 'Sales',
7027
- // sub: ['B2B Sales', 'B2C Sales', 'Real Estate Sales', 'Account Management', 'Lead Generation', 'Inside Sales', 'Field Sales'],
7028
- // },
7029
- // {
7030
- // id: 'ind_finance',
7031
- // name: 'Finance & Accounting',
7032
- // sub: ['Banking', 'Investment', 'Financial Planning', 'Accounting', 'Bookkeeping', 'Insurance', 'FinTech'],
7033
- // },
7034
- // {
7035
- // id: 'ind_healthcare',
7036
- // name: 'Healthcare',
7037
- // sub: ['Medical Clinics', 'Hospitals', 'Pharma', 'Mental Health', 'Healthcare IT', 'Home Care', 'Medical Research'],
7038
- // },
7039
- // {
7040
- // id: 'ind_realestate',
7041
- // name: 'Real Estate',
7042
- // sub: ['Residential Real Estate', 'Commercial Real Estate', 'Property Management', 'Investment & BRRRR', 'Construction', 'Architecture', 'Interior Design'],
7043
- // },
7044
- // {
7045
- // id: 'ind_ecommerce',
7046
- // name: 'E-commerce',
7047
- // sub: ['Online Store', 'Dropshipping', 'Amazon FBA', 'Marketplace Selling', 'Retail', 'Inventory Management', 'Fulfillment & Logistics'],
7048
- // },
7049
- // {
7050
- // id: 'ind_education',
7051
- // name: 'Education',
7052
- // sub: ['Schools', 'Universities', 'Private Tutoring', 'Online Courses', 'EdTech', 'Training & Development'],
7053
- // },
7054
- // {
7055
- // id: 'ind_hospitality',
7056
- // name: 'Hospitality & Travel',
7057
- // sub: ['Hotels', 'Restaurants', 'Cafes & Bars', 'Travel Agencies', 'Tourism', 'Events & Catering', 'Transportation'],
7058
- // },
7059
- // {
7060
- // id: 'ind_professional',
7061
- // name: 'Professional Services',
7062
- // sub: ['Legal', 'Consulting', 'HR & Recruiting', 'Accounting Firms', 'Business Services', 'Management Consulting'],
7063
- // },
7064
- // {
7065
- // id: 'ind_manufacturing',
7066
- // name: 'Manufacturing',
7067
- // sub: ['Automotive', 'Industrial', 'Textile', 'Electronics', 'Food Production', 'Machinery', 'Chemicals'],
7068
- // },
7069
- // {
7070
- // id: 'ind_nonprofit',
7071
- // name: 'Nonprofit & Government',
7072
- // sub: ['NGOs', 'Municipality', 'Government Services', 'Public Health', 'Community Organizations', 'Education Programs'],
7073
- // },
7074
- // {
7075
- // id: 'ind_media',
7076
- // name: 'Media & Entertainment',
7077
- // sub: ['Film & Video', 'Music', 'Publishing', 'Gaming', 'News & Journalism', 'Influencers', 'Production Studios'],
7078
- // },
7079
- // {
7080
- // id: 'ind_logistics',
7081
- // name: 'Logistics & Transportation',
7082
- // sub: ['Shipping', 'Trucking', 'Last-Mile Delivery', 'Warehousing', 'Freight Forwarding', 'Route Optimization'],
7083
- // },
7084
- // {
7085
- // id: 'ind_energy',
7086
- // name: 'Energy & Utilities',
7087
- // sub: ['Solar', 'Oil & Gas', 'Electricity Providers', 'Water Utilities', 'Environmental Services', 'Renewable Energy'],
7088
- // },
7089
- // {
7090
- // id: 'ind_construction',
7091
- // name: 'Construction & Trades',
7092
- // sub: ['General Contracting', 'Roofing', 'Plumbing', 'HVAC', 'Electrical', 'Renovation', 'Engineering'],
7093
- // },
7094
- // {
7095
- // id: 'ind_food',
7096
- // name: 'Food & Beverage',
7097
- // sub: ['Restaurants', 'Catering', 'Food Manufacturing', 'Bakeries', 'Bars & Nightlife', 'Food Delivery'],
7098
- // },
7099
- // {
7100
- // id: 'ind_retail',
7101
- // name: 'Retail',
7102
- // sub: ['Physical Stores', 'Boutiques', 'Supermarkets', 'Consumer Goods', 'Fashion Retail', 'Home Goods'],
7103
- // },
7104
- // ];
7105
- // // Prepare enums for the model
7106
- // const categoryNames = categories.map((c) => c.name);
7107
- // const allSubCategories = categories.flatMap((c) => c.sub);
7108
-
7109
- // const business_info_ret = await submit_chat_gpt_prompt({
7110
- // uid,
7111
- // prompt: `Research the company: "${name}" (${email}).
7112
- // Tasks:
7113
- // 1. Identify the company size.
7114
- // 2. Select the most accurate Industry Category and Sub-Category from the provided lists.
7115
- // 3. Identify the primary country and return its ISO 3166-1 alpha-2 code (e.g., 'US', 'GB', 'IL').`,
7116
- // model: 'gpt-5-nano',
7117
- // response_format: z.object({
7118
- // business_size: z.enum(['unknown', 'small', 'medium', 'large', 'enterprise']),
7119
- // business_category: z.enum(categoryNames),
7120
- // business_sub_category: z.enum(allSubCategories),
7121
- // business_country: z.string().length(2).describe("The 2-letter ISO country code, e.g., 'US'"),
7122
- // }),
7123
- // metadata: { func: 'get_business_info' },
7124
- // account_profile_info,
7125
- // tools: [{ type: 'web_search_preview' }],
7126
- // });
7127
-
7128
- // try {
7129
- // if (business_info_ret.code > -1) {
7130
- // const data = typeof business_info_ret.data === 'string' ? JSON.parse(business_info_ret.data) : business_info_ret.data;
7131
-
7132
- // // Ensure the country code is always uppercase
7133
- // if (data.business_country) {
7134
- // data.business_country = data.business_country.toUpperCase();
7135
- // }
7136
-
7137
- // return data;
7138
- // }
7139
- // } catch (error) {
7140
- // console.error('Error processing business info:', error);
7141
- // }
7142
- // };
7143
-
7144
6877
  export const get_business_info = async function (uid, name, email, account_profile_info) {
7145
6878
  // Extract lists from your JSON categories array
7146
6879
  const categories = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xuda.io/ai_module",
3
- "version": "1.1.4382",
3
+ "version": "1.1.4384",
4
4
  "description": "Xuda AI Module",
5
5
  "main": "index.mjs",
6
6
  "type": "module",