@xuda.io/ai_module 1.1.4673 → 1.1.4675
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 +1259 -131
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -7061,141 +7061,143 @@ const get_image_blob_from_downloaded_image = async function (url) {
|
|
|
7061
7061
|
return images[0];
|
|
7062
7062
|
};
|
|
7063
7063
|
|
|
7064
|
-
export const get_business_info = async function (uid, name, email, account_profile_info) {
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7064
|
+
// export const get_business_info = async function (uid, name, email, account_profile_info) {
|
|
7065
|
+
// // Extract lists from your JSON categories array
|
|
7066
|
+
// const categories = [
|
|
7067
|
+
// {
|
|
7068
|
+
// id: 'ind_technology',
|
|
7069
|
+
// name: 'Technology',
|
|
7070
|
+
// sub: ['Software Development', 'AI & Machine Learning', 'Cybersecurity', 'Cloud Computing', 'IT Services', 'SaaS & Platforms', 'Hardware & Electronics'],
|
|
7071
|
+
// },
|
|
7072
|
+
// {
|
|
7073
|
+
// id: 'ind_marketing',
|
|
7074
|
+
// name: 'Marketing & Advertising',
|
|
7075
|
+
// sub: ['Digital Marketing', 'PPC & SEO', 'Content Creation', 'Branding', 'Social Media Management', 'Email Marketing', 'Market Research'],
|
|
7076
|
+
// },
|
|
7077
|
+
// {
|
|
7078
|
+
// id: 'ind_sales',
|
|
7079
|
+
// name: 'Sales',
|
|
7080
|
+
// sub: ['B2B Sales', 'B2C Sales', 'Real Estate Sales', 'Account Management', 'Lead Generation', 'Inside Sales', 'Field Sales'],
|
|
7081
|
+
// },
|
|
7082
|
+
// {
|
|
7083
|
+
// id: 'ind_finance',
|
|
7084
|
+
// name: 'Finance & Accounting',
|
|
7085
|
+
// sub: ['Banking', 'Investment', 'Financial Planning', 'Accounting', 'Bookkeeping', 'Insurance', 'FinTech'],
|
|
7086
|
+
// },
|
|
7087
|
+
// {
|
|
7088
|
+
// id: 'ind_healthcare',
|
|
7089
|
+
// name: 'Healthcare',
|
|
7090
|
+
// sub: ['Medical Clinics', 'Hospitals', 'Pharma', 'Mental Health', 'Healthcare IT', 'Home Care', 'Medical Research'],
|
|
7091
|
+
// },
|
|
7092
|
+
// {
|
|
7093
|
+
// id: 'ind_realestate',
|
|
7094
|
+
// name: 'Real Estate',
|
|
7095
|
+
// sub: ['Residential Real Estate', 'Commercial Real Estate', 'Property Management', 'Investment & BRRRR', 'Construction', 'Architecture', 'Interior Design'],
|
|
7096
|
+
// },
|
|
7097
|
+
// {
|
|
7098
|
+
// id: 'ind_ecommerce',
|
|
7099
|
+
// name: 'E-commerce',
|
|
7100
|
+
// sub: ['Online Store', 'Dropshipping', 'Amazon FBA', 'Marketplace Selling', 'Retail', 'Inventory Management', 'Fulfillment & Logistics'],
|
|
7101
|
+
// },
|
|
7102
|
+
// {
|
|
7103
|
+
// id: 'ind_education',
|
|
7104
|
+
// name: 'Education',
|
|
7105
|
+
// sub: ['Schools', 'Universities', 'Private Tutoring', 'Online Courses', 'EdTech', 'Training & Development'],
|
|
7106
|
+
// },
|
|
7107
|
+
// {
|
|
7108
|
+
// id: 'ind_hospitality',
|
|
7109
|
+
// name: 'Hospitality & Travel',
|
|
7110
|
+
// sub: ['Hotels', 'Restaurants', 'Cafes & Bars', 'Travel Agencies', 'Tourism', 'Events & Catering', 'Transportation'],
|
|
7111
|
+
// },
|
|
7112
|
+
// {
|
|
7113
|
+
// id: 'ind_professional',
|
|
7114
|
+
// name: 'Professional Services',
|
|
7115
|
+
// sub: ['Legal', 'Consulting', 'HR & Recruiting', 'Accounting Firms', 'Business Services', 'Management Consulting'],
|
|
7116
|
+
// },
|
|
7117
|
+
// {
|
|
7118
|
+
// id: 'ind_manufacturing',
|
|
7119
|
+
// name: 'Manufacturing',
|
|
7120
|
+
// sub: ['Automotive', 'Industrial', 'Textile', 'Electronics', 'Food Production', 'Machinery', 'Chemicals'],
|
|
7121
|
+
// },
|
|
7122
|
+
// {
|
|
7123
|
+
// id: 'ind_nonprofit',
|
|
7124
|
+
// name: 'Nonprofit & Government',
|
|
7125
|
+
// sub: ['NGOs', 'Municipality', 'Government Services', 'Public Health', 'Community Organizations', 'Education Programs'],
|
|
7126
|
+
// },
|
|
7127
|
+
// {
|
|
7128
|
+
// id: 'ind_media',
|
|
7129
|
+
// name: 'Media & Entertainment',
|
|
7130
|
+
// sub: ['Film & Video', 'Music', 'Publishing', 'Gaming', 'News & Journalism', 'Influencers', 'Production Studios'],
|
|
7131
|
+
// },
|
|
7132
|
+
// {
|
|
7133
|
+
// id: 'ind_logistics',
|
|
7134
|
+
// name: 'Logistics & Transportation',
|
|
7135
|
+
// sub: ['Shipping', 'Trucking', 'Last-Mile Delivery', 'Warehousing', 'Freight Forwarding', 'Route Optimization'],
|
|
7136
|
+
// },
|
|
7137
|
+
// {
|
|
7138
|
+
// id: 'ind_energy',
|
|
7139
|
+
// name: 'Energy & Utilities',
|
|
7140
|
+
// sub: ['Solar', 'Oil & Gas', 'Electricity Providers', 'Water Utilities', 'Environmental Services', 'Renewable Energy'],
|
|
7141
|
+
// },
|
|
7142
|
+
// {
|
|
7143
|
+
// id: 'ind_construction',
|
|
7144
|
+
// name: 'Construction & Trades',
|
|
7145
|
+
// sub: ['General Contracting', 'Roofing', 'Plumbing', 'HVAC', 'Electrical', 'Renovation', 'Engineering'],
|
|
7146
|
+
// },
|
|
7147
|
+
// {
|
|
7148
|
+
// id: 'ind_food',
|
|
7149
|
+
// name: 'Food & Beverage',
|
|
7150
|
+
// sub: ['Restaurants', 'Catering', 'Food Manufacturing', 'Bakeries', 'Bars & Nightlife', 'Food Delivery'],
|
|
7151
|
+
// },
|
|
7152
|
+
// {
|
|
7153
|
+
// id: 'ind_retail',
|
|
7154
|
+
// name: 'Retail',
|
|
7155
|
+
// sub: ['Physical Stores', 'Boutiques', 'Supermarkets', 'Consumer Goods', 'Fashion Retail', 'Home Goods'],
|
|
7156
|
+
// },
|
|
7157
|
+
// ];
|
|
7158
|
+
// const categoryNames = categories.map((c) => c.name);
|
|
7159
|
+
// const allSubCategories = categories.flatMap((c) => c.sub);
|
|
7160
|
+
|
|
7161
|
+
// const business_info_ret = await submit_chat_gpt_prompt({
|
|
7162
|
+
// uid,
|
|
7163
|
+
// prompt: `Research the company: "${name}" (${email}).
|
|
7164
|
+
// 1. get the company name.
|
|
7165
|
+
// 2. get the domain name from the email.
|
|
7166
|
+
// 2. Provide a professional one-sentence biography of the company.
|
|
7167
|
+
// 3. Categorize them using the provided industry lists.
|
|
7168
|
+
// 4. Identify their primary country as a 2-letter ISO code (e.g., 'US').`,
|
|
7169
|
+
// model: 'gpt-5-nano',
|
|
7170
|
+
// response_format: z.object({
|
|
7171
|
+
// business_name: z.string().describe('the company name'),
|
|
7172
|
+
// business_domain: z.string().describe('the email domain name'),
|
|
7173
|
+
// business_bio: z.string().describe('A concise, professional one-sentence summary of what the business does'),
|
|
7174
|
+
// business_size: z.enum(['unknown', 'small', 'medium', 'large', 'enterprise']),
|
|
7175
|
+
// business_category: z.enum(categoryNames),
|
|
7176
|
+
// business_sub_category: z.enum(allSubCategories),
|
|
7177
|
+
// business_country: z.string().length(2).describe("2-letter ISO country code (e.g., 'US')"),
|
|
7178
|
+
// }),
|
|
7179
|
+
// metadata: { func: 'get_business_info' },
|
|
7180
|
+
// account_profile_info,
|
|
7181
|
+
// tools: [{ type: 'web_search_preview' }],
|
|
7182
|
+
// });
|
|
7160
7183
|
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
1. get the company name.
|
|
7165
|
-
2. Provide a professional one-sentence biography of the company.
|
|
7166
|
-
3. Categorize them using the provided industry lists.
|
|
7167
|
-
4. Identify their primary country as a 2-letter ISO code (e.g., 'US').`,
|
|
7168
|
-
model: 'gpt-5-nano',
|
|
7169
|
-
response_format: z.object({
|
|
7170
|
-
business_name: z.string().describe('the company name'),
|
|
7171
|
-
business_bio: z.string().describe('A concise, professional one-sentence summary of what the business does'),
|
|
7172
|
-
business_size: z.enum(['unknown', 'small', 'medium', 'large', 'enterprise']),
|
|
7173
|
-
business_category: z.enum(categoryNames),
|
|
7174
|
-
business_sub_category: z.enum(allSubCategories),
|
|
7175
|
-
business_country: z.string().length(2).describe("2-letter ISO country code (e.g., 'US')"),
|
|
7176
|
-
}),
|
|
7177
|
-
metadata: { func: 'get_business_info' },
|
|
7178
|
-
account_profile_info,
|
|
7179
|
-
tools: [{ type: 'web_search_preview' }],
|
|
7180
|
-
});
|
|
7181
|
-
|
|
7182
|
-
try {
|
|
7183
|
-
if (business_info_ret.code > -1) {
|
|
7184
|
-
const data = typeof business_info_ret.data === 'string' ? JSON.parse(business_info_ret.data) : business_info_ret.data;
|
|
7184
|
+
// try {
|
|
7185
|
+
// if (business_info_ret.code > -1) {
|
|
7186
|
+
// const data = typeof business_info_ret.data === 'string' ? JSON.parse(business_info_ret.data) : business_info_ret.data;
|
|
7185
7187
|
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
+
// // Standardize country to uppercase
|
|
7189
|
+
// if (data.business_country) data.business_country = data.business_country.toUpperCase();
|
|
7188
7190
|
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7191
|
+
// // Logic to attach the ID for your database
|
|
7192
|
+
// const matched = categories.find((c) => c.name === data.business_category);
|
|
7193
|
+
// data.business_category_id = matched ? matched.id : null;
|
|
7192
7194
|
|
|
7193
|
-
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7197
|
-
|
|
7198
|
-
};
|
|
7195
|
+
// return data;
|
|
7196
|
+
// }
|
|
7197
|
+
// } catch (error) {
|
|
7198
|
+
// console.error('Error in get_business_info:', error);
|
|
7199
|
+
// }
|
|
7200
|
+
// };
|
|
7199
7201
|
|
|
7200
7202
|
const get_chat_picture_cache = async function (uid, docType, key) {
|
|
7201
7203
|
if (!key || typeof key !== 'string') return null;
|
|
@@ -8598,3 +8600,1129 @@ Category:`;
|
|
|
8598
8600
|
};
|
|
8599
8601
|
}
|
|
8600
8602
|
};
|
|
8603
|
+
|
|
8604
|
+
export const get_business_info = async function (uid, name, email, account_profile_info) {
|
|
8605
|
+
// ========== HELPER FUNCTIONS ==========
|
|
8606
|
+
|
|
8607
|
+
function validatePhoneNumber(phone) {
|
|
8608
|
+
if (!phone || phone.toLowerCase() === 'not available' || phone.trim() === '') {
|
|
8609
|
+
return 'Not available';
|
|
8610
|
+
}
|
|
8611
|
+
|
|
8612
|
+
const cleaned = phone.replace(/[^\d\+\(\)\-\s]/g, '');
|
|
8613
|
+
const digitCount = (cleaned.match(/\d/g) || []).length;
|
|
8614
|
+
|
|
8615
|
+
// Require at least 7 digits for a valid phone number
|
|
8616
|
+
if (digitCount < 7) {
|
|
8617
|
+
return 'Not available';
|
|
8618
|
+
}
|
|
8619
|
+
|
|
8620
|
+
return cleaned.trim();
|
|
8621
|
+
}
|
|
8622
|
+
|
|
8623
|
+
function validateWebsite(website) {
|
|
8624
|
+
if (!website || website.toLowerCase() === 'not available' || website.trim() === '') {
|
|
8625
|
+
return 'Not available';
|
|
8626
|
+
}
|
|
8627
|
+
|
|
8628
|
+
const trimmed = website.trim();
|
|
8629
|
+
|
|
8630
|
+
// Ensure URL has proper protocol
|
|
8631
|
+
if (!trimmed.startsWith('http://') && !trimmed.startsWith('https://')) {
|
|
8632
|
+
// Check if it looks like a domain
|
|
8633
|
+
if (trimmed.includes('.') && !trimmed.includes(' ')) {
|
|
8634
|
+
return `https://${trimmed.replace(/^www\./, '')}`;
|
|
8635
|
+
}
|
|
8636
|
+
return 'Not available';
|
|
8637
|
+
}
|
|
8638
|
+
|
|
8639
|
+
return trimmed;
|
|
8640
|
+
}
|
|
8641
|
+
|
|
8642
|
+
function cleanStreetAddress(street) {
|
|
8643
|
+
if (!street || street.toLowerCase() === 'not available' || street.trim() === '') {
|
|
8644
|
+
return 'Not available';
|
|
8645
|
+
}
|
|
8646
|
+
|
|
8647
|
+
return street
|
|
8648
|
+
.replace(/\s+/g, ' ')
|
|
8649
|
+
.replace(/,\s*$/g, '') // Remove trailing commas
|
|
8650
|
+
.trim();
|
|
8651
|
+
}
|
|
8652
|
+
|
|
8653
|
+
function cleanText(text) {
|
|
8654
|
+
if (!text || text.toLowerCase() === 'not available' || text.trim() === '') {
|
|
8655
|
+
return 'Not available';
|
|
8656
|
+
}
|
|
8657
|
+
|
|
8658
|
+
return text.replace(/\s+/g, ' ').trim();
|
|
8659
|
+
}
|
|
8660
|
+
|
|
8661
|
+
function cleanZipCode(zip, country) {
|
|
8662
|
+
if (!zip || zip.toLowerCase() === 'not available' || zip.trim() === '') {
|
|
8663
|
+
return 'Not available';
|
|
8664
|
+
}
|
|
8665
|
+
|
|
8666
|
+
const cleaned = zip.trim();
|
|
8667
|
+
|
|
8668
|
+
// Country-specific formatting
|
|
8669
|
+
switch (country) {
|
|
8670
|
+
case 'US':
|
|
8671
|
+
// US ZIP: 5 digits or 5-4 format
|
|
8672
|
+
return cleaned.replace(/\D/g, '').replace(/^(\d{5})(\d{4})$/, '$1-$2');
|
|
8673
|
+
case 'CA':
|
|
8674
|
+
// Canada: A1A 1A1 format
|
|
8675
|
+
return cleaned.toUpperCase().replace(/\s+/g, '');
|
|
8676
|
+
case 'UK':
|
|
8677
|
+
// UK: various formats, preserve as is but uppercase
|
|
8678
|
+
return cleaned.toUpperCase();
|
|
8679
|
+
case 'AU':
|
|
8680
|
+
// Australia: 4 digits
|
|
8681
|
+
return cleaned.replace(/\D/g, '');
|
|
8682
|
+
default:
|
|
8683
|
+
return cleaned;
|
|
8684
|
+
}
|
|
8685
|
+
}
|
|
8686
|
+
|
|
8687
|
+
function cleanStateProvince(state, country) {
|
|
8688
|
+
if (!state || state.toLowerCase() === 'not available' || state.trim() === '') {
|
|
8689
|
+
return 'Not available';
|
|
8690
|
+
}
|
|
8691
|
+
|
|
8692
|
+
const cleaned = state.trim();
|
|
8693
|
+
|
|
8694
|
+
// Standardize US state abbreviations
|
|
8695
|
+
if (country === 'US') {
|
|
8696
|
+
const stateMap = {
|
|
8697
|
+
alabama: 'AL',
|
|
8698
|
+
alaska: 'AK',
|
|
8699
|
+
arizona: 'AZ',
|
|
8700
|
+
arkansas: 'AR',
|
|
8701
|
+
california: 'CA',
|
|
8702
|
+
colorado: 'CO',
|
|
8703
|
+
connecticut: 'CT',
|
|
8704
|
+
delaware: 'DE',
|
|
8705
|
+
florida: 'FL',
|
|
8706
|
+
georgia: 'GA',
|
|
8707
|
+
hawaii: 'HI',
|
|
8708
|
+
idaho: 'ID',
|
|
8709
|
+
illinois: 'IL',
|
|
8710
|
+
indiana: 'IN',
|
|
8711
|
+
iowa: 'IA',
|
|
8712
|
+
kansas: 'KS',
|
|
8713
|
+
kentucky: 'KY',
|
|
8714
|
+
louisiana: 'LA',
|
|
8715
|
+
maine: 'ME',
|
|
8716
|
+
maryland: 'MD',
|
|
8717
|
+
massachusetts: 'MA',
|
|
8718
|
+
michigan: 'MI',
|
|
8719
|
+
minnesota: 'MN',
|
|
8720
|
+
mississippi: 'MS',
|
|
8721
|
+
missouri: 'MO',
|
|
8722
|
+
montana: 'MT',
|
|
8723
|
+
nebraska: 'NE',
|
|
8724
|
+
nevada: 'NV',
|
|
8725
|
+
'new hampshire': 'NH',
|
|
8726
|
+
'new jersey': 'NJ',
|
|
8727
|
+
'new mexico': 'NM',
|
|
8728
|
+
'new york': 'NY',
|
|
8729
|
+
'north carolina': 'NC',
|
|
8730
|
+
'north dakota': 'ND',
|
|
8731
|
+
ohio: 'OH',
|
|
8732
|
+
oklahoma: 'OK',
|
|
8733
|
+
oregon: 'OR',
|
|
8734
|
+
pennsylvania: 'PA',
|
|
8735
|
+
'rhode island': 'RI',
|
|
8736
|
+
'south carolina': 'SC',
|
|
8737
|
+
'south dakota': 'SD',
|
|
8738
|
+
tennessee: 'TN',
|
|
8739
|
+
texas: 'TX',
|
|
8740
|
+
utah: 'UT',
|
|
8741
|
+
vermont: 'VT',
|
|
8742
|
+
virginia: 'VA',
|
|
8743
|
+
washington: 'WA',
|
|
8744
|
+
'west virginia': 'WV',
|
|
8745
|
+
wisconsin: 'WI',
|
|
8746
|
+
wyoming: 'WY',
|
|
8747
|
+
'district of columbia': 'DC',
|
|
8748
|
+
};
|
|
8749
|
+
|
|
8750
|
+
const lowerState = cleaned.toLowerCase();
|
|
8751
|
+
if (stateMap[lowerState]) {
|
|
8752
|
+
return stateMap[lowerState];
|
|
8753
|
+
}
|
|
8754
|
+
|
|
8755
|
+
// If already 2-letter code, uppercase it
|
|
8756
|
+
if (/^[A-Z]{2}$/i.test(cleaned)) {
|
|
8757
|
+
return cleaned.toUpperCase();
|
|
8758
|
+
}
|
|
8759
|
+
}
|
|
8760
|
+
|
|
8761
|
+
return cleaned;
|
|
8762
|
+
}
|
|
8763
|
+
|
|
8764
|
+
function cleanCountry(country) {
|
|
8765
|
+
if (!country || country.toLowerCase() === 'not available' || country.trim() === '') {
|
|
8766
|
+
return 'Not available';
|
|
8767
|
+
}
|
|
8768
|
+
|
|
8769
|
+
// Convert 2-letter codes to full country names for display
|
|
8770
|
+
const countryMap = {
|
|
8771
|
+
US: 'United States',
|
|
8772
|
+
CA: 'Canada',
|
|
8773
|
+
UK: 'United Kingdom',
|
|
8774
|
+
GB: 'United Kingdom',
|
|
8775
|
+
AU: 'Australia',
|
|
8776
|
+
DE: 'Germany',
|
|
8777
|
+
FR: 'France',
|
|
8778
|
+
JP: 'Japan',
|
|
8779
|
+
CN: 'China',
|
|
8780
|
+
IN: 'India',
|
|
8781
|
+
BR: 'Brazil',
|
|
8782
|
+
MX: 'Mexico',
|
|
8783
|
+
};
|
|
8784
|
+
|
|
8785
|
+
const upperCountry = country.toUpperCase();
|
|
8786
|
+
return countryMap[upperCountry] || upperCountry;
|
|
8787
|
+
}
|
|
8788
|
+
|
|
8789
|
+
function formatFullAddress(data) {
|
|
8790
|
+
const parts = [];
|
|
8791
|
+
|
|
8792
|
+
if (data.business_address_street && data.business_address_street !== 'Not available') {
|
|
8793
|
+
parts.push(data.business_address_street);
|
|
8794
|
+
}
|
|
8795
|
+
|
|
8796
|
+
const cityStateZip = [];
|
|
8797
|
+
if (data.business_address_city && data.business_address_city !== 'Not available') {
|
|
8798
|
+
cityStateZip.push(data.business_address_city);
|
|
8799
|
+
}
|
|
8800
|
+
|
|
8801
|
+
if (data.business_address_state && data.business_address_state !== 'Not available') {
|
|
8802
|
+
cityStateZip.push(data.business_address_state);
|
|
8803
|
+
}
|
|
8804
|
+
|
|
8805
|
+
if (data.business_address_zip && data.business_address_zip !== 'Not available') {
|
|
8806
|
+
cityStateZip.push(data.business_address_zip);
|
|
8807
|
+
}
|
|
8808
|
+
|
|
8809
|
+
if (cityStateZip.length > 0) {
|
|
8810
|
+
parts.push(cityStateZip.join(', '));
|
|
8811
|
+
}
|
|
8812
|
+
|
|
8813
|
+
if (data.business_address_country && data.business_address_country !== 'Not available') {
|
|
8814
|
+
parts.push(data.business_address_country);
|
|
8815
|
+
}
|
|
8816
|
+
|
|
8817
|
+
return parts.length > 0 ? parts.join(', ') : 'Not available';
|
|
8818
|
+
}
|
|
8819
|
+
|
|
8820
|
+
function getRegionFromState(state, country) {
|
|
8821
|
+
if (country !== 'US' || state === 'Not available') return null;
|
|
8822
|
+
|
|
8823
|
+
const regions = {
|
|
8824
|
+
Northeast: ['CT', 'ME', 'MA', 'NH', 'RI', 'VT', 'NJ', 'NY', 'PA'],
|
|
8825
|
+
Midwest: ['IL', 'IN', 'MI', 'OH', 'WI', 'IA', 'KS', 'MN', 'MO', 'NE', 'ND', 'SD'],
|
|
8826
|
+
South: ['DE', 'FL', 'GA', 'MD', 'NC', 'SC', 'VA', 'DC', 'WV', 'AL', 'KY', 'MS', 'TN', 'AR', 'LA', 'OK', 'TX'],
|
|
8827
|
+
West: ['AZ', 'CO', 'ID', 'MT', 'NV', 'NM', 'UT', 'WY', 'AK', 'CA', 'HI', 'OR', 'WA'],
|
|
8828
|
+
};
|
|
8829
|
+
|
|
8830
|
+
for (const [region, states] of Object.entries(regions)) {
|
|
8831
|
+
if (states.includes(state)) {
|
|
8832
|
+
return region;
|
|
8833
|
+
}
|
|
8834
|
+
}
|
|
8835
|
+
|
|
8836
|
+
return null;
|
|
8837
|
+
}
|
|
8838
|
+
|
|
8839
|
+
function getDefaultBusinessInfo(name, email, error = null) {
|
|
8840
|
+
const domain = email.includes('@') ? email.split('@')[1] : '';
|
|
8841
|
+
|
|
8842
|
+
return {
|
|
8843
|
+
business_name: name,
|
|
8844
|
+
business_domain: domain,
|
|
8845
|
+
business_bio: 'Information not available',
|
|
8846
|
+
business_size: 'unknown',
|
|
8847
|
+
business_category: 'Professional Services',
|
|
8848
|
+
business_sub_category: 'Business Services',
|
|
8849
|
+
business_country: 'US',
|
|
8850
|
+
business_phone: 'Not available',
|
|
8851
|
+
business_website: 'Not available',
|
|
8852
|
+
|
|
8853
|
+
// Address components
|
|
8854
|
+
business_address_street: 'Not available',
|
|
8855
|
+
business_address_city: 'Not available',
|
|
8856
|
+
business_address_state: 'Not available',
|
|
8857
|
+
business_address_zip: 'Not available',
|
|
8858
|
+
business_address_country: 'Not available',
|
|
8859
|
+
business_address_full: 'Not available',
|
|
8860
|
+
|
|
8861
|
+
// Structured objects
|
|
8862
|
+
business_category_id: null,
|
|
8863
|
+
business_address: {
|
|
8864
|
+
street: 'Not available',
|
|
8865
|
+
city: 'Not available',
|
|
8866
|
+
state: 'Not available',
|
|
8867
|
+
zip: 'Not available',
|
|
8868
|
+
country: 'Not available',
|
|
8869
|
+
full: 'Not available',
|
|
8870
|
+
coordinates: null,
|
|
8871
|
+
timezone: null,
|
|
8872
|
+
},
|
|
8873
|
+
business_location: {
|
|
8874
|
+
region: null,
|
|
8875
|
+
metro_area: null,
|
|
8876
|
+
is_headquarters: null,
|
|
8877
|
+
},
|
|
8878
|
+
error: error || 'API call failed',
|
|
8879
|
+
};
|
|
8880
|
+
}
|
|
8881
|
+
|
|
8882
|
+
// Extract lists from your JSON categories array
|
|
8883
|
+
const categories = [
|
|
8884
|
+
{
|
|
8885
|
+
id: 'ind_technology',
|
|
8886
|
+
name: 'Technology',
|
|
8887
|
+
sub: ['Software Development', 'AI & Machine Learning', 'Cybersecurity', 'Cloud Computing', 'IT Services', 'SaaS & Platforms', 'Hardware & Electronics'],
|
|
8888
|
+
},
|
|
8889
|
+
{
|
|
8890
|
+
id: 'ind_marketing',
|
|
8891
|
+
name: 'Marketing & Advertising',
|
|
8892
|
+
sub: ['Digital Marketing', 'PPC & SEO', 'Content Creation', 'Branding', 'Social Media Management', 'Email Marketing', 'Market Research'],
|
|
8893
|
+
},
|
|
8894
|
+
{
|
|
8895
|
+
id: 'ind_sales',
|
|
8896
|
+
name: 'Sales',
|
|
8897
|
+
sub: ['B2B Sales', 'B2C Sales', 'Real Estate Sales', 'Account Management', 'Lead Generation', 'Inside Sales', 'Field Sales'],
|
|
8898
|
+
},
|
|
8899
|
+
{
|
|
8900
|
+
id: 'ind_finance',
|
|
8901
|
+
name: 'Finance & Accounting',
|
|
8902
|
+
sub: ['Banking', 'Investment', 'Financial Planning', 'Accounting', 'Bookkeeping', 'Insurance', 'FinTech'],
|
|
8903
|
+
},
|
|
8904
|
+
{
|
|
8905
|
+
id: 'ind_healthcare',
|
|
8906
|
+
name: 'Healthcare',
|
|
8907
|
+
sub: ['Medical Clinics', 'Hospitals', 'Pharma', 'Mental Health', 'Healthcare IT', 'Home Care', 'Medical Research'],
|
|
8908
|
+
},
|
|
8909
|
+
{
|
|
8910
|
+
id: 'ind_realestate',
|
|
8911
|
+
name: 'Real Estate',
|
|
8912
|
+
sub: ['Residential Real Estate', 'Commercial Real Estate', 'Property Management', 'Investment & BRRRR', 'Construction', 'Architecture', 'Interior Design'],
|
|
8913
|
+
},
|
|
8914
|
+
{
|
|
8915
|
+
id: 'ind_ecommerce',
|
|
8916
|
+
name: 'E-commerce',
|
|
8917
|
+
sub: ['Online Store', 'Dropshipping', 'Amazon FBA', 'Marketplace Selling', 'Retail', 'Inventory Management', 'Fulfillment & Logistics'],
|
|
8918
|
+
},
|
|
8919
|
+
{
|
|
8920
|
+
id: 'ind_education',
|
|
8921
|
+
name: 'Education',
|
|
8922
|
+
sub: ['Schools', 'Universities', 'Private Tutoring', 'Online Courses', 'EdTech', 'Training & Development'],
|
|
8923
|
+
},
|
|
8924
|
+
{
|
|
8925
|
+
id: 'ind_hospitality',
|
|
8926
|
+
name: 'Hospitality & Travel',
|
|
8927
|
+
sub: ['Hotels', 'Restaurants', 'Cafes & Bars', 'Travel Agencies', 'Tourism', 'Events & Catering', 'Transportation'],
|
|
8928
|
+
},
|
|
8929
|
+
{
|
|
8930
|
+
id: 'ind_professional',
|
|
8931
|
+
name: 'Professional Services',
|
|
8932
|
+
sub: ['Legal', 'Consulting', 'HR & Recruiting', 'Accounting Firms', 'Business Services', 'Management Consulting'],
|
|
8933
|
+
},
|
|
8934
|
+
{
|
|
8935
|
+
id: 'ind_manufacturing',
|
|
8936
|
+
name: 'Manufacturing',
|
|
8937
|
+
sub: ['Automotive', 'Industrial', 'Textile', 'Electronics', 'Food Production', 'Machinery', 'Chemicals'],
|
|
8938
|
+
},
|
|
8939
|
+
{
|
|
8940
|
+
id: 'ind_nonprofit',
|
|
8941
|
+
name: 'Nonprofit & Government',
|
|
8942
|
+
sub: ['NGOs', 'Municipality', 'Government Services', 'Public Health', 'Community Organizations', 'Education Programs'],
|
|
8943
|
+
},
|
|
8944
|
+
{
|
|
8945
|
+
id: 'ind_media',
|
|
8946
|
+
name: 'Media & Entertainment',
|
|
8947
|
+
sub: ['Film & Video', 'Music', 'Publishing', 'Gaming', 'News & Journalism', 'Influencers', 'Production Studios'],
|
|
8948
|
+
},
|
|
8949
|
+
{
|
|
8950
|
+
id: 'ind_logistics',
|
|
8951
|
+
name: 'Logistics & Transportation',
|
|
8952
|
+
sub: ['Shipping', 'Trucking', 'Last-Mile Delivery', 'Warehousing', 'Freight Forwarding', 'Route Optimization'],
|
|
8953
|
+
},
|
|
8954
|
+
{
|
|
8955
|
+
id: 'ind_energy',
|
|
8956
|
+
name: 'Energy & Utilities',
|
|
8957
|
+
sub: ['Solar', 'Oil & Gas', 'Electricity Providers', 'Water Utilities', 'Environmental Services', 'Renewable Energy'],
|
|
8958
|
+
},
|
|
8959
|
+
{
|
|
8960
|
+
id: 'ind_construction',
|
|
8961
|
+
name: 'Construction & Trades',
|
|
8962
|
+
sub: ['General Contracting', 'Roofing', 'Plumbing', 'HVAC', 'Electrical', 'Renovation', 'Engineering'],
|
|
8963
|
+
},
|
|
8964
|
+
{
|
|
8965
|
+
id: 'ind_food',
|
|
8966
|
+
name: 'Food & Beverage',
|
|
8967
|
+
sub: ['Restaurants', 'Catering', 'Food Manufacturing', 'Bakeries', 'Bars & Nightlife', 'Food Delivery'],
|
|
8968
|
+
},
|
|
8969
|
+
{
|
|
8970
|
+
id: 'ind_retail',
|
|
8971
|
+
name: 'Retail',
|
|
8972
|
+
sub: ['Physical Stores', 'Boutiques', 'Supermarkets', 'Consumer Goods', 'Fashion Retail', 'Home Goods'],
|
|
8973
|
+
},
|
|
8974
|
+
];
|
|
8975
|
+
const categoryNames = categories.map((c) => c.name);
|
|
8976
|
+
const allSubCategories = categories.flatMap((c) => c.sub);
|
|
8977
|
+
|
|
8978
|
+
const business_info_ret = await submit_chat_gpt_prompt({
|
|
8979
|
+
uid,
|
|
8980
|
+
prompt: `Research the company: "${name}" (${email}).
|
|
8981
|
+
|
|
8982
|
+
REQUIRED INFORMATION:
|
|
8983
|
+
1. Company name (official name)
|
|
8984
|
+
2. Email domain name
|
|
8985
|
+
3. Professional one-sentence biography
|
|
8986
|
+
4. Industry category and sub-category
|
|
8987
|
+
5. Primary country (2-letter ISO code)
|
|
8988
|
+
6. Telephone number
|
|
8989
|
+
7. Website URL
|
|
8990
|
+
8. COMPLETE ADDRESS DETAILS:
|
|
8991
|
+
- Full street address (street number, street name, suite/apt if applicable)
|
|
8992
|
+
- City
|
|
8993
|
+
- State/Province (use abbreviation where standard)
|
|
8994
|
+
- Zip/Postal code
|
|
8995
|
+
- Country
|
|
8996
|
+
|
|
8997
|
+
ADDRESS FORMATTING EXAMPLES:
|
|
8998
|
+
- Full street: "1600 Amphitheatre Parkway"
|
|
8999
|
+
- City: "Mountain View"
|
|
9000
|
+
- State: "CA"
|
|
9001
|
+
- Zip: "94043"
|
|
9002
|
+
- Country: "US"
|
|
9003
|
+
- Full address: "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA"
|
|
9004
|
+
|
|
9005
|
+
INSTRUCTIONS:
|
|
9006
|
+
- Use web search to find accurate information
|
|
9007
|
+
- If not found online, infer from typical patterns
|
|
9008
|
+
- For unknown info, use "Not available"
|
|
9009
|
+
- For US states, use 2-letter abbreviations (CA, NY, TX, etc.)
|
|
9010
|
+
- For other countries, use standard regional names
|
|
9011
|
+
|
|
9012
|
+
Be as precise and accurate as possible.`,
|
|
9013
|
+
model: 'gpt-4o-mini',
|
|
9014
|
+
response_format: z.object({
|
|
9015
|
+
business_name: z.string().describe('Official company name'),
|
|
9016
|
+
business_domain: z.string().describe('Domain name from email'),
|
|
9017
|
+
business_bio: z.string().describe('One-sentence professional summary'),
|
|
9018
|
+
business_size: z.enum(['unknown', 'small', 'medium', 'large', 'enterprise']),
|
|
9019
|
+
business_category: z.enum(categoryNames),
|
|
9020
|
+
business_sub_category: z.enum(allSubCategories),
|
|
9021
|
+
business_country: z.string().length(2).describe('2-letter ISO country code'),
|
|
9022
|
+
business_phone: z.string().describe("Telephone number or 'Not available'"),
|
|
9023
|
+
business_website: z.string().describe("Website URL or 'Not available'"),
|
|
9024
|
+
|
|
9025
|
+
// Complete address components
|
|
9026
|
+
business_address_street: z.string().describe('Full street address (number, street, suite)'),
|
|
9027
|
+
business_address_city: z.string().describe('City name'),
|
|
9028
|
+
business_address_state: z.string().describe('State/Province (abbreviation if standard)'),
|
|
9029
|
+
business_address_zip: z.string().describe('Zip/Postal code'),
|
|
9030
|
+
business_address_country: z.string().describe('Country name'),
|
|
9031
|
+
business_address_full: z.string().describe('Complete formatted address'),
|
|
9032
|
+
}),
|
|
9033
|
+
metadata: {
|
|
9034
|
+
func: 'get_business_info',
|
|
9035
|
+
company_name: name,
|
|
9036
|
+
company_email: email,
|
|
9037
|
+
},
|
|
9038
|
+
account_profile_info,
|
|
9039
|
+
tools: [{ type: 'web_search_preview' }],
|
|
9040
|
+
});
|
|
9041
|
+
|
|
9042
|
+
try {
|
|
9043
|
+
if (business_info_ret.code > -1) {
|
|
9044
|
+
const data = typeof business_info_ret.data === 'string' ? JSON.parse(business_info_ret.data) : business_info_ret.data;
|
|
9045
|
+
|
|
9046
|
+
// Standardize country codes to uppercase
|
|
9047
|
+
if (data.business_country) data.business_country = data.business_country.toUpperCase();
|
|
9048
|
+
if (data.business_address_country) {
|
|
9049
|
+
data.business_address_country = data.business_address_country.toUpperCase();
|
|
9050
|
+
}
|
|
9051
|
+
|
|
9052
|
+
// Logic to attach the ID for your database
|
|
9053
|
+
const matched = categories.find((c) => c.name === data.business_category);
|
|
9054
|
+
data.business_category_id = matched ? matched.id : null;
|
|
9055
|
+
|
|
9056
|
+
// Validate and clean all contact information
|
|
9057
|
+
data.business_phone = validatePhoneNumber(data.business_phone);
|
|
9058
|
+
data.business_website = validateWebsite(data.business_website);
|
|
9059
|
+
|
|
9060
|
+
// Clean and standardize all address components
|
|
9061
|
+
data.business_address_street = cleanStreetAddress(data.business_address_street);
|
|
9062
|
+
data.business_address_city = cleanText(data.business_address_city);
|
|
9063
|
+
data.business_address_zip = cleanZipCode(data.business_address_zip, data.business_country);
|
|
9064
|
+
data.business_address_state = cleanStateProvince(data.business_address_state, data.business_country);
|
|
9065
|
+
data.business_address_country = cleanCountry(data.business_address_country || data.business_country);
|
|
9066
|
+
data.business_address_full = formatFullAddress(data);
|
|
9067
|
+
|
|
9068
|
+
// Create a comprehensive structured address object
|
|
9069
|
+
data.business_address = {
|
|
9070
|
+
street: data.business_address_street,
|
|
9071
|
+
city: data.business_address_city,
|
|
9072
|
+
state: data.business_address_state,
|
|
9073
|
+
zip: data.business_address_zip,
|
|
9074
|
+
country: data.business_address_country,
|
|
9075
|
+
full: data.business_address_full,
|
|
9076
|
+
coordinates: null, // Can be populated later with geocoding
|
|
9077
|
+
timezone: null, // Can be populated later
|
|
9078
|
+
};
|
|
9079
|
+
|
|
9080
|
+
// Generate additional useful fields
|
|
9081
|
+
data.business_location = {
|
|
9082
|
+
region: getRegionFromState(data.business_address_state, data.business_country),
|
|
9083
|
+
metro_area: null, // Can be populated later
|
|
9084
|
+
is_headquarters: null, // Can be determined from address pattern
|
|
9085
|
+
};
|
|
9086
|
+
|
|
9087
|
+
return data;
|
|
9088
|
+
} else {
|
|
9089
|
+
console.error('Business info API call failed:', business_info_ret);
|
|
9090
|
+
return getDefaultBusinessInfo(name, email);
|
|
9091
|
+
}
|
|
9092
|
+
} catch (error) {
|
|
9093
|
+
console.error('Error in get_business_info:', error);
|
|
9094
|
+
return getDefaultBusinessInfo(name, email, error.message);
|
|
9095
|
+
}
|
|
9096
|
+
};
|
|
9097
|
+
|
|
9098
|
+
export const get_person_info = async function (uid, name, email, account_profile_info, email_context = '') {
|
|
9099
|
+
// ========== HELPER FUNCTIONS ==========
|
|
9100
|
+
|
|
9101
|
+
async function hashString(str) {
|
|
9102
|
+
// Simple hash for context tracking
|
|
9103
|
+
const encoder = new TextEncoder();
|
|
9104
|
+
const data = encoder.encode(str);
|
|
9105
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
9106
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
9107
|
+
return hashArray
|
|
9108
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
9109
|
+
.join('')
|
|
9110
|
+
.substring(0, 16);
|
|
9111
|
+
}
|
|
9112
|
+
|
|
9113
|
+
function processPersonInfo(data, originalName, originalEmail, emailContext) {
|
|
9114
|
+
// Ensure basic fields are populated
|
|
9115
|
+
if (!data.person_first_name || !data.person_last_name) {
|
|
9116
|
+
const nameParts = originalName.trim().split(/\s+/);
|
|
9117
|
+
data.person_first_name = data.person_first_name || nameParts[0] || '';
|
|
9118
|
+
data.person_last_name = data.person_last_name || nameParts.slice(1).join(' ') || '';
|
|
9119
|
+
}
|
|
9120
|
+
|
|
9121
|
+
// Set full name if not provided
|
|
9122
|
+
if (!data.person_full_name) {
|
|
9123
|
+
data.person_full_name = `${data.person_first_name} ${data.person_last_name}`.trim();
|
|
9124
|
+
}
|
|
9125
|
+
|
|
9126
|
+
// Ensure email is set
|
|
9127
|
+
data.person_email = data.person_email || originalEmail;
|
|
9128
|
+
|
|
9129
|
+
// Process demographic information
|
|
9130
|
+
data.person_age = processAge(data.person_age);
|
|
9131
|
+
data.person_gender = data.person_gender || 'unknown';
|
|
9132
|
+
data.person_nationality = processNationality(data.person_nationality);
|
|
9133
|
+
|
|
9134
|
+
// Standardize location fields
|
|
9135
|
+
data.person_location_city = cleanText(data.person_location_city);
|
|
9136
|
+
data.person_location_state = cleanStateProvince(data.person_location_state);
|
|
9137
|
+
data.person_location_country = processCountryCode(data.person_location_country);
|
|
9138
|
+
|
|
9139
|
+
// Format full location
|
|
9140
|
+
if (!data.person_location_full || data.person_location_full === 'Not available') {
|
|
9141
|
+
const locationParts = [];
|
|
9142
|
+
if (data.person_location_city && data.person_location_city !== 'Not available') {
|
|
9143
|
+
locationParts.push(data.person_location_city);
|
|
9144
|
+
}
|
|
9145
|
+
if (data.person_location_state && data.person_location_state !== 'Not available') {
|
|
9146
|
+
locationParts.push(data.person_location_state);
|
|
9147
|
+
}
|
|
9148
|
+
if (data.person_location_country && data.person_location_country !== 'Not available') {
|
|
9149
|
+
locationParts.push(countryCodeToName(data.person_location_country));
|
|
9150
|
+
}
|
|
9151
|
+
data.person_location_full = locationParts.length > 0 ? locationParts.join(', ') : 'Not available';
|
|
9152
|
+
}
|
|
9153
|
+
|
|
9154
|
+
// Clean and validate URLs
|
|
9155
|
+
data.person_linkedin = validateURL(data.person_linkedin);
|
|
9156
|
+
data.person_twitter = validateURL(data.person_twitter);
|
|
9157
|
+
data.person_github = validateURL(data.person_github);
|
|
9158
|
+
data.person_website = validateURL(data.person_website);
|
|
9159
|
+
|
|
9160
|
+
// Clean phone number
|
|
9161
|
+
data.person_phone = validatePhoneNumber(data.person_phone);
|
|
9162
|
+
|
|
9163
|
+
// Ensure arrays are properly formatted
|
|
9164
|
+
data.person_skills = ensureArray(data.person_skills);
|
|
9165
|
+
data.person_expertise = ensureArray(data.person_expertise);
|
|
9166
|
+
data.person_education = ensureArray(data.person_education);
|
|
9167
|
+
data.person_languages = ensureArray(data.person_languages);
|
|
9168
|
+
data.person_interests = ensureArray(data.person_interests);
|
|
9169
|
+
data.person_context_insights = ensureArray(data.person_context_insights);
|
|
9170
|
+
|
|
9171
|
+
// Calculate additional metadata
|
|
9172
|
+
data.person_name_initials = getInitials(data.person_first_name, data.person_last_name);
|
|
9173
|
+
data.person_age_range = calculateAgeRange(data.person_age);
|
|
9174
|
+
data.person_seniority_score = calculateSeniorityScore(data);
|
|
9175
|
+
data.person_pronouns = getPronounsFromGender(data.person_gender);
|
|
9176
|
+
|
|
9177
|
+
// Extract insights from email context
|
|
9178
|
+
if (emailContext && !data.person_context_insights) {
|
|
9179
|
+
data.person_context_insights = extractContextInsights(emailContext);
|
|
9180
|
+
}
|
|
9181
|
+
|
|
9182
|
+
// Create structured objects for easier access
|
|
9183
|
+
data.person_demographics = {
|
|
9184
|
+
age: data.person_age,
|
|
9185
|
+
age_range: data.person_age_range,
|
|
9186
|
+
gender: data.person_gender,
|
|
9187
|
+
pronouns: data.person_pronouns,
|
|
9188
|
+
nationality: data.person_nationality,
|
|
9189
|
+
nationality_name: countryCodeToName(data.person_nationality),
|
|
9190
|
+
};
|
|
9191
|
+
|
|
9192
|
+
data.person_contact = {
|
|
9193
|
+
email: data.person_email,
|
|
9194
|
+
phone: data.person_phone,
|
|
9195
|
+
location: {
|
|
9196
|
+
city: data.person_location_city,
|
|
9197
|
+
state: data.person_location_state,
|
|
9198
|
+
country: data.person_location_country,
|
|
9199
|
+
country_name: countryCodeToName(data.person_location_country),
|
|
9200
|
+
full: data.person_location_full,
|
|
9201
|
+
},
|
|
9202
|
+
};
|
|
9203
|
+
|
|
9204
|
+
data.person_professional = {
|
|
9205
|
+
title: data.person_title,
|
|
9206
|
+
company: data.person_company,
|
|
9207
|
+
industry: data.person_industry,
|
|
9208
|
+
career_level: data.person_career_level,
|
|
9209
|
+
years_experience: data.person_years_experience,
|
|
9210
|
+
skills: data.person_skills,
|
|
9211
|
+
expertise: data.person_expertise,
|
|
9212
|
+
education: data.person_education,
|
|
9213
|
+
};
|
|
9214
|
+
|
|
9215
|
+
data.person_online = {
|
|
9216
|
+
linkedin: data.person_linkedin,
|
|
9217
|
+
twitter: data.person_twitter,
|
|
9218
|
+
github: data.person_github,
|
|
9219
|
+
website: data.person_website,
|
|
9220
|
+
other: data.person_social_other || [],
|
|
9221
|
+
};
|
|
9222
|
+
|
|
9223
|
+
// Add context metadata
|
|
9224
|
+
data.context_analysis = {
|
|
9225
|
+
has_context: !!emailContext,
|
|
9226
|
+
context_length: emailContext?.length || 0,
|
|
9227
|
+
extracted_insights: data.person_context_insights || [],
|
|
9228
|
+
context_useful: data.person_has_context_hints || false,
|
|
9229
|
+
};
|
|
9230
|
+
|
|
9231
|
+
// Add timestamp
|
|
9232
|
+
data.retrieved_at = new Date().toISOString();
|
|
9233
|
+
|
|
9234
|
+
return data;
|
|
9235
|
+
}
|
|
9236
|
+
|
|
9237
|
+
function processAge(ageInput) {
|
|
9238
|
+
if (!ageInput || ageInput === 'unknown' || ageInput === 'Not available') {
|
|
9239
|
+
return 'unknown';
|
|
9240
|
+
}
|
|
9241
|
+
|
|
9242
|
+
if (typeof ageInput === 'number') {
|
|
9243
|
+
return Math.max(18, Math.min(100, ageInput));
|
|
9244
|
+
}
|
|
9245
|
+
|
|
9246
|
+
if (typeof ageInput === 'string') {
|
|
9247
|
+
// Parse age ranges like "30-40", "35+", "mid-30s"
|
|
9248
|
+
const rangeMatch = ageInput.match(/(\d+)-(\d+)/);
|
|
9249
|
+
if (rangeMatch) {
|
|
9250
|
+
const avg = Math.floor((parseInt(rangeMatch[1]) + parseInt(rangeMatch[2])) / 2);
|
|
9251
|
+
return avg;
|
|
9252
|
+
}
|
|
9253
|
+
|
|
9254
|
+
const numberMatch = ageInput.match(/\d+/);
|
|
9255
|
+
if (numberMatch) {
|
|
9256
|
+
const age = parseInt(numberMatch[0]);
|
|
9257
|
+
if (age >= 18 && age <= 100) return age;
|
|
9258
|
+
}
|
|
9259
|
+
|
|
9260
|
+
// Handle textual age descriptions
|
|
9261
|
+
const text = ageInput.toLowerCase();
|
|
9262
|
+
if (text.includes('twent') || text.includes('20')) return 25;
|
|
9263
|
+
if (text.includes('thirt') || text.includes('30')) return 35;
|
|
9264
|
+
if (text.includes('fort') || text.includes('40')) return 45;
|
|
9265
|
+
if (text.includes('fift') || text.includes('50')) return 55;
|
|
9266
|
+
if (text.includes('sixt') || text.includes('60')) return 65;
|
|
9267
|
+
}
|
|
9268
|
+
|
|
9269
|
+
return 'unknown';
|
|
9270
|
+
}
|
|
9271
|
+
|
|
9272
|
+
function calculateAgeRange(age) {
|
|
9273
|
+
if (age === 'unknown' || typeof age !== 'number') return 'Unknown';
|
|
9274
|
+
|
|
9275
|
+
if (age < 25) return '18-24';
|
|
9276
|
+
if (age < 30) return '25-29';
|
|
9277
|
+
if (age < 35) return '30-34';
|
|
9278
|
+
if (age < 40) return '35-39';
|
|
9279
|
+
if (age < 50) return '40-49';
|
|
9280
|
+
if (age < 60) return '50-59';
|
|
9281
|
+
return '60+';
|
|
9282
|
+
}
|
|
9283
|
+
|
|
9284
|
+
function processNationality(nationality) {
|
|
9285
|
+
if (!nationality || nationality.toLowerCase() === 'unknown' || nationality.toLowerCase() === 'not available') {
|
|
9286
|
+
return 'unknown';
|
|
9287
|
+
}
|
|
9288
|
+
|
|
9289
|
+
// Convert to uppercase for country codes
|
|
9290
|
+
const upper = nationality.toUpperCase();
|
|
9291
|
+
|
|
9292
|
+
// Map common variations to ISO codes
|
|
9293
|
+
const countryMap = {
|
|
9294
|
+
USA: 'US',
|
|
9295
|
+
'UNITED STATES': 'US',
|
|
9296
|
+
AMERICA: 'US',
|
|
9297
|
+
UK: 'GB',
|
|
9298
|
+
'UNITED KINGDOM': 'GB',
|
|
9299
|
+
ENGLAND: 'GB',
|
|
9300
|
+
SCOTLAND: 'GB',
|
|
9301
|
+
CANADA: 'CA',
|
|
9302
|
+
AUSTRALIA: 'AU',
|
|
9303
|
+
INDIA: 'IN',
|
|
9304
|
+
GERMANY: 'DE',
|
|
9305
|
+
FRANCE: 'FR',
|
|
9306
|
+
CHINA: 'CN',
|
|
9307
|
+
JAPAN: 'JP',
|
|
9308
|
+
BRAZIL: 'BR',
|
|
9309
|
+
MEXICO: 'MX',
|
|
9310
|
+
SPAIN: 'ES',
|
|
9311
|
+
ITALY: 'IT',
|
|
9312
|
+
NETHERLANDS: 'NL',
|
|
9313
|
+
SWEDEN: 'SE',
|
|
9314
|
+
SWITZERLAND: 'CH',
|
|
9315
|
+
'SOUTH KOREA': 'KR',
|
|
9316
|
+
RUSSIA: 'RU',
|
|
9317
|
+
};
|
|
9318
|
+
|
|
9319
|
+
if (countryMap[upper]) {
|
|
9320
|
+
return countryMap[upper];
|
|
9321
|
+
}
|
|
9322
|
+
|
|
9323
|
+
// If it's already a 2-letter code, return it
|
|
9324
|
+
if (/^[A-Z]{2}$/.test(upper)) {
|
|
9325
|
+
return upper;
|
|
9326
|
+
}
|
|
9327
|
+
|
|
9328
|
+
return 'unknown';
|
|
9329
|
+
}
|
|
9330
|
+
|
|
9331
|
+
function processCountryCode(country) {
|
|
9332
|
+
if (!country || country.toLowerCase() === 'not available') {
|
|
9333
|
+
return 'unknown';
|
|
9334
|
+
}
|
|
9335
|
+
|
|
9336
|
+
return processNationality(country);
|
|
9337
|
+
}
|
|
9338
|
+
|
|
9339
|
+
function countryCodeToName(code) {
|
|
9340
|
+
if (!code || code === 'unknown') return 'Unknown';
|
|
9341
|
+
|
|
9342
|
+
const countryNames = {
|
|
9343
|
+
US: 'United States',
|
|
9344
|
+
GB: 'United Kingdom',
|
|
9345
|
+
CA: 'Canada',
|
|
9346
|
+
AU: 'Australia',
|
|
9347
|
+
DE: 'Germany',
|
|
9348
|
+
FR: 'France',
|
|
9349
|
+
JP: 'Japan',
|
|
9350
|
+
CN: 'China',
|
|
9351
|
+
IN: 'India',
|
|
9352
|
+
BR: 'Brazil',
|
|
9353
|
+
MX: 'Mexico',
|
|
9354
|
+
ES: 'Spain',
|
|
9355
|
+
IT: 'Italy',
|
|
9356
|
+
NL: 'Netherlands',
|
|
9357
|
+
SE: 'Sweden',
|
|
9358
|
+
CH: 'Switzerland',
|
|
9359
|
+
KR: 'South Korea',
|
|
9360
|
+
RU: 'Russia',
|
|
9361
|
+
};
|
|
9362
|
+
|
|
9363
|
+
return countryNames[code] || code;
|
|
9364
|
+
}
|
|
9365
|
+
|
|
9366
|
+
function getPronounsFromGender(gender) {
|
|
9367
|
+
switch (gender) {
|
|
9368
|
+
case 'male':
|
|
9369
|
+
return ['he/him', 'his'];
|
|
9370
|
+
case 'female':
|
|
9371
|
+
return ['she/her', 'hers'];
|
|
9372
|
+
case 'non-binary':
|
|
9373
|
+
return ['they/them', 'theirs'];
|
|
9374
|
+
default:
|
|
9375
|
+
return ['unknown'];
|
|
9376
|
+
}
|
|
9377
|
+
}
|
|
9378
|
+
|
|
9379
|
+
function extractContextInsights(emailContext) {
|
|
9380
|
+
if (!emailContext) return [];
|
|
9381
|
+
|
|
9382
|
+
const insights = [];
|
|
9383
|
+
const context = emailContext.toLowerCase();
|
|
9384
|
+
|
|
9385
|
+
// Extract potential job role hints
|
|
9386
|
+
const rolePatterns = {
|
|
9387
|
+
manager: ['manage', 'supervise', 'team lead', 'department head'],
|
|
9388
|
+
engineer: ['engineer', 'developer', 'programmer', 'software'],
|
|
9389
|
+
sales: ['sales', 'account executive', 'business development'],
|
|
9390
|
+
marketing: ['marketing', 'campaign', 'brand', 'social media'],
|
|
9391
|
+
executive: ['ceo', 'cto', 'cfo', 'director', 'vp', 'vice president'],
|
|
9392
|
+
};
|
|
9393
|
+
|
|
9394
|
+
for (const [role, patterns] of Object.entries(rolePatterns)) {
|
|
9395
|
+
if (patterns.some((pattern) => context.includes(pattern))) {
|
|
9396
|
+
insights.push(`Possible ${role} role indicated in email`);
|
|
9397
|
+
}
|
|
9398
|
+
}
|
|
9399
|
+
|
|
9400
|
+
// Extract company hints
|
|
9401
|
+
const companyMatch = context.match(/(?:at|from|of)\s+([A-Z][A-Za-z0-9\s&]+)(?:\s|$)/);
|
|
9402
|
+
if (companyMatch && companyMatch[1].length > 2) {
|
|
9403
|
+
insights.push(`Mentioned company/organization: ${companyMatch[1].trim()}`);
|
|
9404
|
+
}
|
|
9405
|
+
|
|
9406
|
+
// Extract project/technology hints
|
|
9407
|
+
const techMatch = context.match(/(?:using|with|built\s+in)\s+([A-Za-z0-9\s+#]+)(?:\s|$)/);
|
|
9408
|
+
if (techMatch) {
|
|
9409
|
+
insights.push(`Technology mentioned: ${techMatch[1].trim()}`);
|
|
9410
|
+
}
|
|
9411
|
+
|
|
9412
|
+
// Extract urgency/priority
|
|
9413
|
+
if (context.includes('urgent') || context.includes('asap') || context.includes('immediately')) {
|
|
9414
|
+
insights.push('Email suggests urgency or time sensitivity');
|
|
9415
|
+
}
|
|
9416
|
+
|
|
9417
|
+
// Extract tone
|
|
9418
|
+
if (context.includes('thank you') || context.includes('appreciate') || context.includes('grateful')) {
|
|
9419
|
+
insights.push('Email shows appreciative/grateful tone');
|
|
9420
|
+
}
|
|
9421
|
+
|
|
9422
|
+
return insights.slice(0, 5); // Limit to 5 insights
|
|
9423
|
+
}
|
|
9424
|
+
|
|
9425
|
+
// Existing helper functions (kept from previous version)
|
|
9426
|
+
function validateURL(url) {
|
|
9427
|
+
/* ... same as before ... */
|
|
9428
|
+
}
|
|
9429
|
+
function validatePhoneNumber(phone) {
|
|
9430
|
+
/* ... same as before ... */
|
|
9431
|
+
}
|
|
9432
|
+
function cleanText(text) {
|
|
9433
|
+
/* ... same as before ... */
|
|
9434
|
+
}
|
|
9435
|
+
function cleanStateProvince(state) {
|
|
9436
|
+
/* ... same as before ... */
|
|
9437
|
+
}
|
|
9438
|
+
function ensureArray(value) {
|
|
9439
|
+
/* ... same as before ... */
|
|
9440
|
+
}
|
|
9441
|
+
function getInitials(firstName, lastName) {
|
|
9442
|
+
/* ... same as before ... */
|
|
9443
|
+
}
|
|
9444
|
+
function calculateSeniorityScore(data) {
|
|
9445
|
+
/* ... same as before ... */
|
|
9446
|
+
}
|
|
9447
|
+
|
|
9448
|
+
function getDefaultPersonInfo(name, email, emailContext = '', error = null) {
|
|
9449
|
+
const nameParts = name.trim().split(/\s+/);
|
|
9450
|
+
const firstName = nameParts[0] || '';
|
|
9451
|
+
const lastName = nameParts.slice(1).join(' ') || '';
|
|
9452
|
+
const domain = email.includes('@') ? email.split('@')[1] : '';
|
|
9453
|
+
const companyGuess = domain
|
|
9454
|
+
.replace(/\..*$/, '')
|
|
9455
|
+
.replace(/[^a-z]/gi, ' ')
|
|
9456
|
+
.replace(/\b\w/g, (l) => l.toUpperCase());
|
|
9457
|
+
|
|
9458
|
+
// Extract basic insights from email context
|
|
9459
|
+
const contextInsights = emailContext ? extractContextInsights(emailContext) : [];
|
|
9460
|
+
|
|
9461
|
+
return {
|
|
9462
|
+
// Basic Information
|
|
9463
|
+
person_full_name: name,
|
|
9464
|
+
person_first_name: firstName,
|
|
9465
|
+
person_last_name: lastName,
|
|
9466
|
+
person_middle_name: '',
|
|
9467
|
+
person_preferred_name: '',
|
|
9468
|
+
|
|
9469
|
+
// Demographic Information
|
|
9470
|
+
person_age: 'unknown',
|
|
9471
|
+
person_gender: 'unknown',
|
|
9472
|
+
person_nationality: 'unknown',
|
|
9473
|
+
person_age_range: 'Unknown',
|
|
9474
|
+
person_pronouns: ['unknown'],
|
|
9475
|
+
|
|
9476
|
+
// Professional Information
|
|
9477
|
+
person_title: 'Professional',
|
|
9478
|
+
person_company: companyGuess || 'Unknown',
|
|
9479
|
+
person_industry: 'Technology',
|
|
9480
|
+
person_bio: 'Information not available',
|
|
9481
|
+
|
|
9482
|
+
// Location
|
|
9483
|
+
person_location_city: 'Not available',
|
|
9484
|
+
person_location_state: 'Not available',
|
|
9485
|
+
person_location_country: 'unknown',
|
|
9486
|
+
person_location_full: 'Not available',
|
|
9487
|
+
|
|
9488
|
+
// Contact Information
|
|
9489
|
+
person_phone: 'Not available',
|
|
9490
|
+
person_email: email,
|
|
9491
|
+
person_email_alternate: '',
|
|
9492
|
+
|
|
9493
|
+
// Education
|
|
9494
|
+
person_education: [],
|
|
9495
|
+
person_education_highest: 'Not available',
|
|
9496
|
+
|
|
9497
|
+
// Professional Details
|
|
9498
|
+
person_skills: [],
|
|
9499
|
+
person_expertise: [],
|
|
9500
|
+
person_career_level: 'unknown',
|
|
9501
|
+
person_years_experience: 0,
|
|
9502
|
+
|
|
9503
|
+
// Social & Online Presence
|
|
9504
|
+
person_linkedin: 'Not available',
|
|
9505
|
+
person_twitter: 'Not available',
|
|
9506
|
+
person_github: 'Not available',
|
|
9507
|
+
person_website: 'Not available',
|
|
9508
|
+
person_social_other: [],
|
|
9509
|
+
|
|
9510
|
+
// Additional Information
|
|
9511
|
+
person_languages: ['English'],
|
|
9512
|
+
person_interests: [],
|
|
9513
|
+
person_achievements: [],
|
|
9514
|
+
person_current_projects: [],
|
|
9515
|
+
person_context_insights: contextInsights,
|
|
9516
|
+
|
|
9517
|
+
// Metadata
|
|
9518
|
+
person_available_for_opportunities: false,
|
|
9519
|
+
person_last_updated: new Date().toISOString(),
|
|
9520
|
+
person_source_confidence: 0,
|
|
9521
|
+
person_has_context_hints: contextInsights.length > 0,
|
|
9522
|
+
|
|
9523
|
+
// Processed fields
|
|
9524
|
+
person_name_initials: getInitials(firstName, lastName),
|
|
9525
|
+
person_seniority_score: 0,
|
|
9526
|
+
|
|
9527
|
+
// Structured objects
|
|
9528
|
+
person_demographics: {
|
|
9529
|
+
age: 'unknown',
|
|
9530
|
+
age_range: 'Unknown',
|
|
9531
|
+
gender: 'unknown',
|
|
9532
|
+
pronouns: ['unknown'],
|
|
9533
|
+
nationality: 'unknown',
|
|
9534
|
+
nationality_name: 'Unknown',
|
|
9535
|
+
},
|
|
9536
|
+
|
|
9537
|
+
person_contact: {
|
|
9538
|
+
email: email,
|
|
9539
|
+
phone: 'Not available',
|
|
9540
|
+
location: {
|
|
9541
|
+
city: 'Not available',
|
|
9542
|
+
state: 'Not available',
|
|
9543
|
+
country: 'unknown',
|
|
9544
|
+
country_name: 'Unknown',
|
|
9545
|
+
full: 'Not available',
|
|
9546
|
+
},
|
|
9547
|
+
},
|
|
9548
|
+
|
|
9549
|
+
person_professional: {
|
|
9550
|
+
title: 'Professional',
|
|
9551
|
+
company: companyGuess || 'Unknown',
|
|
9552
|
+
industry: 'Technology',
|
|
9553
|
+
career_level: 'unknown',
|
|
9554
|
+
years_experience: 0,
|
|
9555
|
+
skills: [],
|
|
9556
|
+
expertise: [],
|
|
9557
|
+
education: [],
|
|
9558
|
+
},
|
|
9559
|
+
|
|
9560
|
+
person_online: {
|
|
9561
|
+
linkedin: 'Not available',
|
|
9562
|
+
twitter: 'Not available',
|
|
9563
|
+
github: 'Not available',
|
|
9564
|
+
website: 'Not available',
|
|
9565
|
+
other: [],
|
|
9566
|
+
},
|
|
9567
|
+
|
|
9568
|
+
context_analysis: {
|
|
9569
|
+
has_context: !!emailContext,
|
|
9570
|
+
context_length: emailContext?.length || 0,
|
|
9571
|
+
extracted_insights: contextInsights,
|
|
9572
|
+
context_useful: contextInsights.length > 0,
|
|
9573
|
+
},
|
|
9574
|
+
|
|
9575
|
+
retrieved_at: new Date().toISOString(),
|
|
9576
|
+
error: error || 'API call failed',
|
|
9577
|
+
};
|
|
9578
|
+
}
|
|
9579
|
+
|
|
9580
|
+
// Build context-aware prompt
|
|
9581
|
+
let context_prompt = `Research the person: "${name}" (${email}).`;
|
|
9582
|
+
|
|
9583
|
+
if (email_context) {
|
|
9584
|
+
context_prompt += `\n\nEMAIL CONTEXT PROVIDED:\n"${email_context.substring(0, 500)}${email_context.length > 500 ? '...' : ''}"`;
|
|
9585
|
+
}
|
|
9586
|
+
|
|
9587
|
+
context_prompt += `
|
|
9588
|
+
|
|
9589
|
+
REQUIRED PERSON INFORMATION:
|
|
9590
|
+
1. Full name (first, middle, last)
|
|
9591
|
+
2. Professional title/role
|
|
9592
|
+
3. Company/organization they work for
|
|
9593
|
+
4. Industry/field they work in
|
|
9594
|
+
5. Location (city, state, country)
|
|
9595
|
+
6. Professional biography (1-2 sentences)
|
|
9596
|
+
7. Education background
|
|
9597
|
+
8. Professional skills/expertise
|
|
9598
|
+
9. Social media profiles (LinkedIn, Twitter, GitHub, etc.)
|
|
9599
|
+
10. Personal website or portfolio
|
|
9600
|
+
|
|
9601
|
+
DEMOGRAPHIC INFORMATION:
|
|
9602
|
+
11. Estimated age (based on career, education, and public information)
|
|
9603
|
+
12. Gender (based on name, pronouns in content, or public profiles)
|
|
9604
|
+
13. Nationality/country of origin (if discernible)
|
|
9605
|
+
|
|
9606
|
+
CONTACT INFORMATION:
|
|
9607
|
+
14. Phone number (if available)
|
|
9608
|
+
15. Alternate email addresses (if available)
|
|
9609
|
+
16. Physical address (if available and appropriate)
|
|
9610
|
+
|
|
9611
|
+
ADDITIONAL INSIGHTS:
|
|
9612
|
+
17. Career level (entry, mid, senior, executive, etc.)
|
|
9613
|
+
18. Years of experience
|
|
9614
|
+
19. Notable achievements/awards
|
|
9615
|
+
20. Languages spoken
|
|
9616
|
+
21. Professional interests
|
|
9617
|
+
22. Current projects
|
|
9618
|
+
23. Availability for opportunities
|
|
9619
|
+
|
|
9620
|
+
INSTRUCTIONS:
|
|
9621
|
+
- Use web search to find accurate, public information
|
|
9622
|
+
- Use email context provided to infer additional details
|
|
9623
|
+
- Respect privacy - only include publicly available information
|
|
9624
|
+
- For age: provide numeric estimate or range (e.g., 35, 30-40, unknown)
|
|
9625
|
+
- For gender: use male/female/non-binary/unknown based on available cues
|
|
9626
|
+
- For country: use 2-letter ISO code (e.g., US, IN, UK)
|
|
9627
|
+
- If information is not available, use "Not available" or appropriate defaults
|
|
9628
|
+
- For location, use standard formats (e.g., "San Francisco, CA, USA")
|
|
9629
|
+
- For social media, provide full URLs when available
|
|
9630
|
+
- Focus on professional information suitable for business networking
|
|
9631
|
+
|
|
9632
|
+
Be thorough but respectful of privacy boundaries.`;
|
|
9633
|
+
|
|
9634
|
+
const person_info_ret = await submit_chat_gpt_prompt({
|
|
9635
|
+
uid,
|
|
9636
|
+
prompt: context_prompt,
|
|
9637
|
+
model: 'gpt-4o-mini',
|
|
9638
|
+
response_format: z.object({
|
|
9639
|
+
// Basic Information
|
|
9640
|
+
person_full_name: z.string().describe("Person's full name"),
|
|
9641
|
+
person_first_name: z.string().describe('First name'),
|
|
9642
|
+
person_last_name: z.string().describe('Last name'),
|
|
9643
|
+
person_middle_name: z.string().optional().describe('Middle name if available'),
|
|
9644
|
+
person_preferred_name: z.string().optional().describe('Preferred/nickname if different'),
|
|
9645
|
+
|
|
9646
|
+
// Demographic Information
|
|
9647
|
+
person_age: z.union([z.number().int().min(18).max(100), z.string().describe("Age range or 'unknown'")]).describe('Estimated age or range'),
|
|
9648
|
+
person_gender: z.enum(['male', 'female', 'non-binary', 'unknown']).describe('Gender based on available information'),
|
|
9649
|
+
person_nationality: z.string().describe('Country of origin/nationality (2-letter ISO code)'),
|
|
9650
|
+
|
|
9651
|
+
// Professional Information
|
|
9652
|
+
person_title: z.string().describe('Professional title/role'),
|
|
9653
|
+
person_company: z.string().describe('Current company/organization'),
|
|
9654
|
+
person_industry: z.string().describe('Primary industry/field'),
|
|
9655
|
+
person_bio: z.string().describe('Professional biography (1-2 sentences)'),
|
|
9656
|
+
|
|
9657
|
+
// Location
|
|
9658
|
+
person_location_city: z.string().describe('City of residence/work'),
|
|
9659
|
+
person_location_state: z.string().describe('State/province'),
|
|
9660
|
+
person_location_country: z.string().describe('Country (2-letter ISO code)'),
|
|
9661
|
+
person_location_full: z.string().describe('Full location string'),
|
|
9662
|
+
|
|
9663
|
+
// Contact Information
|
|
9664
|
+
person_phone: z.string().describe("Phone number or 'Not available'"),
|
|
9665
|
+
person_email: z.string().describe('Primary email address'),
|
|
9666
|
+
person_email_alternate: z.string().optional().describe('Alternate email if available'),
|
|
9667
|
+
|
|
9668
|
+
// Education
|
|
9669
|
+
person_education: z.array(z.string()).describe('Array of educational institutions/degrees'),
|
|
9670
|
+
person_education_highest: z.string().describe('Highest degree obtained'),
|
|
9671
|
+
|
|
9672
|
+
// Professional Details
|
|
9673
|
+
person_skills: z.array(z.string()).describe('Array of professional skills'),
|
|
9674
|
+
person_expertise: z.array(z.string()).describe('Areas of expertise'),
|
|
9675
|
+
person_career_level: z.enum(['entry', 'mid', 'senior', 'lead', 'manager', 'director', 'executive', 'founder', 'unknown']),
|
|
9676
|
+
person_years_experience: z.number().int().min(0).max(60).describe('Years of professional experience'),
|
|
9677
|
+
|
|
9678
|
+
// Social & Online Presence
|
|
9679
|
+
person_linkedin: z.string().describe("LinkedIn profile URL or 'Not available'"),
|
|
9680
|
+
person_twitter: z.string().describe("Twitter/X profile URL or 'Not available'"),
|
|
9681
|
+
person_github: z.string().describe("GitHub profile URL or 'Not available'"),
|
|
9682
|
+
person_website: z.string().describe("Personal website/portfolio or 'Not available'"),
|
|
9683
|
+
person_social_other: z.array(z.string()).optional().describe('Other social media profiles'),
|
|
9684
|
+
|
|
9685
|
+
// Additional Information
|
|
9686
|
+
person_languages: z.array(z.string()).describe('Languages spoken'),
|
|
9687
|
+
person_interests: z.array(z.string()).describe('Professional/personal interests'),
|
|
9688
|
+
person_achievements: z.array(z.string()).optional().describe('Notable achievements/awards'),
|
|
9689
|
+
person_current_projects: z.array(z.string()).optional().describe('Current projects'),
|
|
9690
|
+
|
|
9691
|
+
// Context Extracted Information
|
|
9692
|
+
person_context_insights: z.array(z.string()).optional().describe('Insights extracted from provided email context'),
|
|
9693
|
+
|
|
9694
|
+
// Metadata
|
|
9695
|
+
person_available_for_opportunities: z.boolean().describe('Open to new opportunities'),
|
|
9696
|
+
person_last_updated: z.string().describe('Date information was last verified'),
|
|
9697
|
+
person_source_confidence: z.number().min(0).max(100).describe('Confidence score for information accuracy'),
|
|
9698
|
+
person_has_context_hints: z.boolean().describe('Whether email context provided useful hints'),
|
|
9699
|
+
}),
|
|
9700
|
+
metadata: {
|
|
9701
|
+
func: 'get_person_info',
|
|
9702
|
+
person_name: name,
|
|
9703
|
+
person_email: email,
|
|
9704
|
+
has_email_context: !!email_context,
|
|
9705
|
+
email_context_length: email_context?.length || 0,
|
|
9706
|
+
context_hash: email_context ? await hashString(email_context.substring(0, 200)) : null,
|
|
9707
|
+
},
|
|
9708
|
+
account_profile_info,
|
|
9709
|
+
tools: [{ type: 'web_search_preview' }],
|
|
9710
|
+
});
|
|
9711
|
+
|
|
9712
|
+
try {
|
|
9713
|
+
if (person_info_ret.code > -1) {
|
|
9714
|
+
const data = typeof person_info_ret.data === 'string' ? JSON.parse(person_info_ret.data) : person_info_ret.data;
|
|
9715
|
+
|
|
9716
|
+
// Process and enhance the data
|
|
9717
|
+
const processedData = processPersonInfo(data, name, email, email_context);
|
|
9718
|
+
|
|
9719
|
+
return processedData;
|
|
9720
|
+
} else {
|
|
9721
|
+
console.error('Person info API call failed:', person_info_ret);
|
|
9722
|
+
return getDefaultPersonInfo(name, email, email_context);
|
|
9723
|
+
}
|
|
9724
|
+
} catch (error) {
|
|
9725
|
+
console.error('Error in get_person_info:', error);
|
|
9726
|
+
return getDefaultPersonInfo(name, email, email_context, error.message);
|
|
9727
|
+
}
|
|
9728
|
+
};
|