@skillhq/concierge 1.5.0
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/README.md +91 -0
- package/dist/cli/program.d.ts +3 -0
- package/dist/cli/program.d.ts.map +1 -0
- package/dist/cli/program.js +46 -0
- package/dist/cli/program.js.map +1 -0
- package/dist/cli/shared.d.ts +18 -0
- package/dist/cli/shared.d.ts.map +1 -0
- package/dist/cli/shared.js +2 -0
- package/dist/cli/shared.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +5 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/call.d.ts +7 -0
- package/dist/commands/call.d.ts.map +1 -0
- package/dist/commands/call.js +409 -0
- package/dist/commands/call.js.map +1 -0
- package/dist/commands/config.d.ts +4 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +120 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/find-contact.d.ts +4 -0
- package/dist/commands/find-contact.d.ts.map +1 -0
- package/dist/commands/find-contact.js +57 -0
- package/dist/commands/find-contact.js.map +1 -0
- package/dist/commands/server.d.ts +7 -0
- package/dist/commands/server.d.ts.map +1 -0
- package/dist/commands/server.js +212 -0
- package/dist/commands/server.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/call/audio/mulaw.d.ts +35 -0
- package/dist/lib/call/audio/mulaw.d.ts.map +1 -0
- package/dist/lib/call/audio/mulaw.js +109 -0
- package/dist/lib/call/audio/mulaw.js.map +1 -0
- package/dist/lib/call/audio/pcm-utils.d.ts +62 -0
- package/dist/lib/call/audio/pcm-utils.d.ts.map +1 -0
- package/dist/lib/call/audio/pcm-utils.js +149 -0
- package/dist/lib/call/audio/pcm-utils.js.map +1 -0
- package/dist/lib/call/audio/resample.d.ts +34 -0
- package/dist/lib/call/audio/resample.d.ts.map +1 -0
- package/dist/lib/call/audio/resample.js +97 -0
- package/dist/lib/call/audio/resample.js.map +1 -0
- package/dist/lib/call/audio/streaming-decoder.d.ts +45 -0
- package/dist/lib/call/audio/streaming-decoder.d.ts.map +1 -0
- package/dist/lib/call/audio/streaming-decoder.js +110 -0
- package/dist/lib/call/audio/streaming-decoder.js.map +1 -0
- package/dist/lib/call/call-server.d.ts +110 -0
- package/dist/lib/call/call-server.d.ts.map +1 -0
- package/dist/lib/call/call-server.js +681 -0
- package/dist/lib/call/call-server.js.map +1 -0
- package/dist/lib/call/call-session.d.ts +133 -0
- package/dist/lib/call/call-session.d.ts.map +1 -0
- package/dist/lib/call/call-session.js +890 -0
- package/dist/lib/call/call-session.js.map +1 -0
- package/dist/lib/call/call-types.d.ts +133 -0
- package/dist/lib/call/call-types.d.ts.map +1 -0
- package/dist/lib/call/call-types.js +16 -0
- package/dist/lib/call/call-types.js.map +1 -0
- package/dist/lib/call/conversation-ai.d.ts +56 -0
- package/dist/lib/call/conversation-ai.d.ts.map +1 -0
- package/dist/lib/call/conversation-ai.js +276 -0
- package/dist/lib/call/conversation-ai.js.map +1 -0
- package/dist/lib/call/eval/codec-test.d.ts +45 -0
- package/dist/lib/call/eval/codec-test.d.ts.map +1 -0
- package/dist/lib/call/eval/codec-test.js +169 -0
- package/dist/lib/call/eval/codec-test.js.map +1 -0
- package/dist/lib/call/eval/conversation-scripts.d.ts +55 -0
- package/dist/lib/call/eval/conversation-scripts.d.ts.map +1 -0
- package/dist/lib/call/eval/conversation-scripts.js +359 -0
- package/dist/lib/call/eval/conversation-scripts.js.map +1 -0
- package/dist/lib/call/eval/eval-runner.d.ts +64 -0
- package/dist/lib/call/eval/eval-runner.d.ts.map +1 -0
- package/dist/lib/call/eval/eval-runner.js +369 -0
- package/dist/lib/call/eval/eval-runner.js.map +1 -0
- package/dist/lib/call/eval/index.d.ts +9 -0
- package/dist/lib/call/eval/index.d.ts.map +1 -0
- package/dist/lib/call/eval/index.js +9 -0
- package/dist/lib/call/eval/index.js.map +1 -0
- package/dist/lib/call/eval/integration-test-suite.d.ts +71 -0
- package/dist/lib/call/eval/integration-test-suite.d.ts.map +1 -0
- package/dist/lib/call/eval/integration-test-suite.js +519 -0
- package/dist/lib/call/eval/integration-test-suite.js.map +1 -0
- package/dist/lib/call/eval/turn-taking-test.d.ts +84 -0
- package/dist/lib/call/eval/turn-taking-test.d.ts.map +1 -0
- package/dist/lib/call/eval/turn-taking-test.js +260 -0
- package/dist/lib/call/eval/turn-taking-test.js.map +1 -0
- package/dist/lib/call/index.d.ts +12 -0
- package/dist/lib/call/index.d.ts.map +1 -0
- package/dist/lib/call/index.js +17 -0
- package/dist/lib/call/index.js.map +1 -0
- package/dist/lib/call/providers/deepgram.d.ts +81 -0
- package/dist/lib/call/providers/deepgram.d.ts.map +1 -0
- package/dist/lib/call/providers/deepgram.js +279 -0
- package/dist/lib/call/providers/deepgram.js.map +1 -0
- package/dist/lib/call/providers/elevenlabs.d.ts +78 -0
- package/dist/lib/call/providers/elevenlabs.d.ts.map +1 -0
- package/dist/lib/call/providers/elevenlabs.js +272 -0
- package/dist/lib/call/providers/elevenlabs.js.map +1 -0
- package/dist/lib/call/providers/local-deps.d.ts +18 -0
- package/dist/lib/call/providers/local-deps.d.ts.map +1 -0
- package/dist/lib/call/providers/local-deps.js +114 -0
- package/dist/lib/call/providers/local-deps.js.map +1 -0
- package/dist/lib/call/providers/twilio.d.ts +53 -0
- package/dist/lib/call/providers/twilio.d.ts.map +1 -0
- package/dist/lib/call/providers/twilio.js +173 -0
- package/dist/lib/call/providers/twilio.js.map +1 -0
- package/dist/lib/concierge-client-types.d.ts +68 -0
- package/dist/lib/concierge-client-types.d.ts.map +1 -0
- package/dist/lib/concierge-client-types.js +2 -0
- package/dist/lib/concierge-client-types.js.map +1 -0
- package/dist/lib/concierge-client.d.ts +29 -0
- package/dist/lib/concierge-client.d.ts.map +1 -0
- package/dist/lib/concierge-client.js +534 -0
- package/dist/lib/concierge-client.js.map +1 -0
- package/dist/lib/config.d.ts +9 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +66 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/output.d.ts +7 -0
- package/dist/lib/output.d.ts.map +1 -0
- package/dist/lib/output.js +114 -0
- package/dist/lib/output.js.map +1 -0
- package/dist/lib/utils/contact-extractor.d.ts +12 -0
- package/dist/lib/utils/contact-extractor.d.ts.map +1 -0
- package/dist/lib/utils/contact-extractor.js +159 -0
- package/dist/lib/utils/contact-extractor.js.map +1 -0
- package/dist/lib/utils/formatters.d.ts +15 -0
- package/dist/lib/utils/formatters.d.ts.map +1 -0
- package/dist/lib/utils/formatters.js +107 -0
- package/dist/lib/utils/formatters.js.map +1 -0
- package/dist/lib/utils/url-parser.d.ts +11 -0
- package/dist/lib/utils/url-parser.d.ts.map +1 -0
- package/dist/lib/utils/url-parser.js +103 -0
- package/dist/lib/utils/url-parser.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,6BAA6B,CAAC;AAE9E,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,CA2G9E;AAaD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,CAKlE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,CAKnE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,CAKtE"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export function formatDossier(dossier, ctx) {
|
|
2
|
+
if (ctx.json) {
|
|
3
|
+
return JSON.stringify(dossier, null, 2);
|
|
4
|
+
}
|
|
5
|
+
const { colors } = ctx;
|
|
6
|
+
const lines = [];
|
|
7
|
+
// Header
|
|
8
|
+
lines.push('');
|
|
9
|
+
lines.push(colors.highlight('═══════════════════════════════════════════════════════════'));
|
|
10
|
+
lines.push(colors.highlight(` CONTACT DOSSIER: ${dossier.property.name}`));
|
|
11
|
+
lines.push(colors.highlight('═══════════════════════════════════════════════════════════'));
|
|
12
|
+
lines.push('');
|
|
13
|
+
// Property Info
|
|
14
|
+
lines.push(colors.primary('▸ Property Information'));
|
|
15
|
+
lines.push(` ${colors.muted('Platform:')} ${dossier.property.platform}`);
|
|
16
|
+
lines.push(` ${colors.muted('Name:')} ${dossier.property.name}`);
|
|
17
|
+
if (dossier.property.location.city || dossier.property.location.country) {
|
|
18
|
+
const location = [
|
|
19
|
+
dossier.property.location.city,
|
|
20
|
+
dossier.property.location.region,
|
|
21
|
+
dossier.property.location.country,
|
|
22
|
+
]
|
|
23
|
+
.filter(Boolean)
|
|
24
|
+
.join(', ');
|
|
25
|
+
lines.push(` ${colors.muted('Location:')} ${location}`);
|
|
26
|
+
}
|
|
27
|
+
if (dossier.property.location.address) {
|
|
28
|
+
lines.push(` ${colors.muted('Address:')} ${dossier.property.location.address}`);
|
|
29
|
+
}
|
|
30
|
+
if (dossier.property.hostName) {
|
|
31
|
+
lines.push(` ${colors.muted('Host:')} ${dossier.property.hostName}`);
|
|
32
|
+
}
|
|
33
|
+
lines.push(` ${colors.muted('Listing:')} ${dossier.property.listingUrl}`);
|
|
34
|
+
lines.push('');
|
|
35
|
+
// Contact Info
|
|
36
|
+
lines.push(colors.primary('▸ Contact Information'));
|
|
37
|
+
const { contacts } = dossier;
|
|
38
|
+
if (contacts.phone.length > 0) {
|
|
39
|
+
lines.push(` ${colors.success('📞 Phone:')} ${contacts.phone.join(', ')}`);
|
|
40
|
+
}
|
|
41
|
+
if (contacts.email.length > 0) {
|
|
42
|
+
lines.push(` ${colors.success('📧 Email:')} ${contacts.email.join(', ')}`);
|
|
43
|
+
}
|
|
44
|
+
if (contacts.whatsapp) {
|
|
45
|
+
lines.push(` ${colors.success('💬 WhatsApp:')} ${contacts.whatsapp}`);
|
|
46
|
+
}
|
|
47
|
+
if (contacts.website) {
|
|
48
|
+
lines.push(` ${colors.success('🌐 Website:')} ${contacts.website}`);
|
|
49
|
+
}
|
|
50
|
+
if (contacts.instagram) {
|
|
51
|
+
lines.push(` ${colors.success('📸 Instagram:')} ${contacts.instagram}`);
|
|
52
|
+
}
|
|
53
|
+
if (contacts.facebook) {
|
|
54
|
+
lines.push(` ${colors.success('📘 Facebook:')} ${contacts.facebook}`);
|
|
55
|
+
}
|
|
56
|
+
if (contacts.googleMapsUrl) {
|
|
57
|
+
lines.push(` ${colors.success('📍 Google Maps:')} ${contacts.googleMapsUrl}`);
|
|
58
|
+
}
|
|
59
|
+
// Check if any contacts found
|
|
60
|
+
const hasContacts = contacts.phone.length > 0 ||
|
|
61
|
+
contacts.email.length > 0 ||
|
|
62
|
+
contacts.whatsapp ||
|
|
63
|
+
contacts.website ||
|
|
64
|
+
contacts.instagram ||
|
|
65
|
+
contacts.facebook;
|
|
66
|
+
if (!hasContacts) {
|
|
67
|
+
lines.push(` ${colors.warning('No contact information found')}`);
|
|
68
|
+
}
|
|
69
|
+
lines.push('');
|
|
70
|
+
// Sources
|
|
71
|
+
if (dossier.sources.length > 0) {
|
|
72
|
+
lines.push(colors.primary('▸ Sources'));
|
|
73
|
+
for (const source of dossier.sources) {
|
|
74
|
+
const confidence = formatConfidence(source.confidence, colors);
|
|
75
|
+
const url = source.url ? ` - ${colors.muted(source.url)}` : '';
|
|
76
|
+
const note = source.note ? ` (${source.note})` : '';
|
|
77
|
+
lines.push(` ${confidence} ${source.type}${url}${note}`);
|
|
78
|
+
}
|
|
79
|
+
lines.push('');
|
|
80
|
+
}
|
|
81
|
+
// Footer
|
|
82
|
+
lines.push(colors.muted(`Searched at: ${dossier.searchedAt}`));
|
|
83
|
+
lines.push('');
|
|
84
|
+
return lines.join('\n');
|
|
85
|
+
}
|
|
86
|
+
function formatConfidence(confidence, colors) {
|
|
87
|
+
switch (confidence) {
|
|
88
|
+
case 'high':
|
|
89
|
+
return colors.success('●');
|
|
90
|
+
case 'medium':
|
|
91
|
+
return colors.warning('●');
|
|
92
|
+
case 'low':
|
|
93
|
+
return colors.muted('●');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export function formatError(error, ctx) {
|
|
97
|
+
if (ctx.json) {
|
|
98
|
+
return JSON.stringify({ success: false, error }, null, 2);
|
|
99
|
+
}
|
|
100
|
+
return ctx.colors.error(`Error: ${error}`);
|
|
101
|
+
}
|
|
102
|
+
export function formatInfo(message, ctx) {
|
|
103
|
+
if (ctx.json) {
|
|
104
|
+
return '';
|
|
105
|
+
}
|
|
106
|
+
return ctx.colors.info(message);
|
|
107
|
+
}
|
|
108
|
+
export function formatVerbose(message, ctx) {
|
|
109
|
+
if (ctx.json || !ctx.verbose) {
|
|
110
|
+
return '';
|
|
111
|
+
}
|
|
112
|
+
return ctx.colors.muted(`[verbose] ${message}`);
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/lib/output.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ExtractedContacts {
|
|
2
|
+
emails: string[];
|
|
3
|
+
phones: string[];
|
|
4
|
+
whatsapp: string[];
|
|
5
|
+
instagram: string[];
|
|
6
|
+
facebook: string[];
|
|
7
|
+
websites: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare function extractContacts(html: string): ExtractedContacts;
|
|
10
|
+
export declare function extractWhatsAppFromText(text: string): string | null;
|
|
11
|
+
export declare function extractEmailFromText(text: string): string[];
|
|
12
|
+
//# sourceMappingURL=contact-extractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contact-extractor.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/contact-extractor.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAgED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAwE/D;AA8BD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAenE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAG3D"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// Email pattern - standard email format
|
|
2
|
+
const EMAIL_PATTERN = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
|
|
3
|
+
// Phone pattern - international format with various separators
|
|
4
|
+
const PHONE_PATTERN = /(?:\+|00)?[\d\s\-().]{10,20}/g;
|
|
5
|
+
// WhatsApp patterns
|
|
6
|
+
const WHATSAPP_PATTERNS = [
|
|
7
|
+
/wa\.me\/(\d+)/gi,
|
|
8
|
+
/api\.whatsapp\.com\/send\?phone=(\d+)/gi,
|
|
9
|
+
/whatsapp(?:\.com)?[^\d]*(\+?\d[\d\s-]{8,})/gi,
|
|
10
|
+
];
|
|
11
|
+
// Instagram patterns
|
|
12
|
+
const INSTAGRAM_PATTERNS = [
|
|
13
|
+
/(?:instagram\.com|instagr\.am)\/([a-zA-Z0-9_.]+)/gi,
|
|
14
|
+
/@([a-zA-Z0-9_.]+)(?:\s+(?:on\s+)?instagram)/gi,
|
|
15
|
+
];
|
|
16
|
+
// Facebook patterns
|
|
17
|
+
const FACEBOOK_PATTERNS = [/(?:facebook\.com|fb\.com)\/([a-zA-Z0-9.]+)/gi, /facebook\.com\/pages\/[^/]+\/(\d+)/gi];
|
|
18
|
+
// Common false positives to filter
|
|
19
|
+
const EMAIL_BLACKLIST = [
|
|
20
|
+
'example.com',
|
|
21
|
+
'test.com',
|
|
22
|
+
'localhost',
|
|
23
|
+
'domain.com',
|
|
24
|
+
'email.com',
|
|
25
|
+
'yoursite.com',
|
|
26
|
+
'website.com',
|
|
27
|
+
'sentry.io',
|
|
28
|
+
'wixpress.com',
|
|
29
|
+
'w3.org',
|
|
30
|
+
];
|
|
31
|
+
const INSTAGRAM_BLACKLIST = [
|
|
32
|
+
'instagram',
|
|
33
|
+
'about',
|
|
34
|
+
'explore',
|
|
35
|
+
'p',
|
|
36
|
+
'reel',
|
|
37
|
+
'reels',
|
|
38
|
+
'stories',
|
|
39
|
+
'tv',
|
|
40
|
+
'direct',
|
|
41
|
+
'accounts',
|
|
42
|
+
];
|
|
43
|
+
const FACEBOOK_BLACKLIST = [
|
|
44
|
+
'facebook',
|
|
45
|
+
'sharer',
|
|
46
|
+
'share',
|
|
47
|
+
'login',
|
|
48
|
+
'groups',
|
|
49
|
+
'events',
|
|
50
|
+
'marketplace',
|
|
51
|
+
'watch',
|
|
52
|
+
'gaming',
|
|
53
|
+
'plugins',
|
|
54
|
+
];
|
|
55
|
+
export function extractContacts(html) {
|
|
56
|
+
const result = {
|
|
57
|
+
emails: [],
|
|
58
|
+
phones: [],
|
|
59
|
+
whatsapp: [],
|
|
60
|
+
instagram: [],
|
|
61
|
+
facebook: [],
|
|
62
|
+
websites: [],
|
|
63
|
+
};
|
|
64
|
+
// Extract emails
|
|
65
|
+
const emailMatches = html.match(EMAIL_PATTERN) || [];
|
|
66
|
+
result.emails = [
|
|
67
|
+
...new Set(emailMatches
|
|
68
|
+
.map((e) => e.toLowerCase())
|
|
69
|
+
.filter((e) => !EMAIL_BLACKLIST.some((bl) => e.includes(bl)))
|
|
70
|
+
.filter((e) => !e.includes('png') && !e.includes('jpg') && !e.includes('gif'))),
|
|
71
|
+
];
|
|
72
|
+
// Extract phones
|
|
73
|
+
const phoneMatches = html.match(PHONE_PATTERN) || [];
|
|
74
|
+
result.phones = [
|
|
75
|
+
...new Set(phoneMatches
|
|
76
|
+
.map((p) => normalizePhone(p))
|
|
77
|
+
.filter((p) => p.length >= 10 && p.length <= 15)
|
|
78
|
+
.filter((p) => !isLikelyNotPhone(p))),
|
|
79
|
+
];
|
|
80
|
+
// Extract WhatsApp
|
|
81
|
+
for (const pattern of WHATSAPP_PATTERNS) {
|
|
82
|
+
pattern.lastIndex = 0; // Reset state for global regex
|
|
83
|
+
let match;
|
|
84
|
+
while ((match = pattern.exec(html)) !== null) {
|
|
85
|
+
const number = match[1].replace(/\D/g, '');
|
|
86
|
+
if (number.length >= 10) {
|
|
87
|
+
result.whatsapp.push(`+${number}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
result.whatsapp = [...new Set(result.whatsapp)];
|
|
92
|
+
// Extract Instagram
|
|
93
|
+
for (const pattern of INSTAGRAM_PATTERNS) {
|
|
94
|
+
pattern.lastIndex = 0; // Reset state for global regex
|
|
95
|
+
let match;
|
|
96
|
+
while ((match = pattern.exec(html)) !== null) {
|
|
97
|
+
const handle = match[1].toLowerCase();
|
|
98
|
+
if (!INSTAGRAM_BLACKLIST.includes(handle) && handle.length > 1 && handle.length < 30) {
|
|
99
|
+
result.instagram.push(`@${handle}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
result.instagram = [...new Set(result.instagram)];
|
|
104
|
+
// Extract Facebook
|
|
105
|
+
for (const pattern of FACEBOOK_PATTERNS) {
|
|
106
|
+
pattern.lastIndex = 0; // Reset state for global regex
|
|
107
|
+
let match;
|
|
108
|
+
while ((match = pattern.exec(html)) !== null) {
|
|
109
|
+
const page = match[1];
|
|
110
|
+
if (!FACEBOOK_BLACKLIST.includes(page.toLowerCase()) && page.length > 1) {
|
|
111
|
+
result.facebook.push(page);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
result.facebook = [...new Set(result.facebook)];
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
function normalizePhone(phone) {
|
|
119
|
+
// Remove all non-digit characters except leading +
|
|
120
|
+
const hasPlus = phone.startsWith('+') || phone.startsWith('00');
|
|
121
|
+
const digits = phone.replace(/\D/g, '');
|
|
122
|
+
// Remove leading 00 and treat as +
|
|
123
|
+
const cleanDigits = digits.startsWith('00') ? digits.slice(2) : digits;
|
|
124
|
+
return hasPlus ? `+${cleanDigits}` : cleanDigits;
|
|
125
|
+
}
|
|
126
|
+
function isLikelyNotPhone(phone) {
|
|
127
|
+
const digits = phone.replace(/\D/g, '');
|
|
128
|
+
// All same digits
|
|
129
|
+
if (/^(.)\1+$/.test(digits))
|
|
130
|
+
return true;
|
|
131
|
+
// Sequential numbers
|
|
132
|
+
if ('1234567890'.includes(digits) || '0987654321'.includes(digits))
|
|
133
|
+
return true;
|
|
134
|
+
// Common non-phone numbers (years, dimensions, etc.)
|
|
135
|
+
if (digits.startsWith('19') || digits.startsWith('20')) {
|
|
136
|
+
if (digits.length === 4)
|
|
137
|
+
return true; // Years
|
|
138
|
+
}
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
export function extractWhatsAppFromText(text) {
|
|
142
|
+
// Look for WhatsApp mentions with numbers
|
|
143
|
+
const patterns = [/whatsapp[:\s]+(\+?\d[\d\s-]{8,})/i, /wa[:\s]+(\+?\d[\d\s-]{8,})/i];
|
|
144
|
+
for (const pattern of patterns) {
|
|
145
|
+
const match = text.match(pattern);
|
|
146
|
+
if (match) {
|
|
147
|
+
const number = match[1].replace(/\D/g, '');
|
|
148
|
+
if (number.length >= 10) {
|
|
149
|
+
return `+${number}`;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
export function extractEmailFromText(text) {
|
|
156
|
+
const matches = text.match(EMAIL_PATTERN) || [];
|
|
157
|
+
return [...new Set(matches.map((e) => e.toLowerCase()).filter((e) => !EMAIL_BLACKLIST.some((bl) => e.includes(bl))))];
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=contact-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contact-extractor.js","sourceRoot":"","sources":["../../../src/lib/utils/contact-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ContactInfo, Platform } from '../concierge-client-types.js';
|
|
2
|
+
export declare function formatPlatformName(platform: Platform): string;
|
|
3
|
+
export declare function formatPhoneNumber(phone: string): string;
|
|
4
|
+
export declare function formatInstagramHandle(handle: string): string;
|
|
5
|
+
export declare function formatInstagramUrl(handle: string): string;
|
|
6
|
+
export declare function formatFacebookUrl(page: string): string;
|
|
7
|
+
export declare function formatWhatsAppUrl(phone: string): string;
|
|
8
|
+
export declare function formatGoogleMapsUrl(query: string): string;
|
|
9
|
+
export declare function mergeContacts(a: ContactInfo, b: Partial<ContactInfo>): ContactInfo;
|
|
10
|
+
export declare function emptyContacts(): ContactInfo;
|
|
11
|
+
export declare function hasAnyContact(contacts: ContactInfo): boolean;
|
|
12
|
+
export declare function truncate(str: string, maxLength: number): string;
|
|
13
|
+
export declare function cleanPropertyName(name: string): string;
|
|
14
|
+
export declare function escapeHtml(text: string): string;
|
|
15
|
+
//# sourceMappingURL=formatters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/formatters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAE1E,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAS7D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAmBvD;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW,CAUlF;AAED,wBAAgB,aAAa,IAAI,WAAW,CAU3C;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAS5D;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoBtD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO/C"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export function formatPlatformName(platform) {
|
|
2
|
+
const names = {
|
|
3
|
+
airbnb: 'Airbnb',
|
|
4
|
+
booking: 'Booking.com',
|
|
5
|
+
vrbo: 'VRBO',
|
|
6
|
+
expedia: 'Expedia',
|
|
7
|
+
unknown: 'Unknown',
|
|
8
|
+
};
|
|
9
|
+
return names[platform];
|
|
10
|
+
}
|
|
11
|
+
export function formatPhoneNumber(phone) {
|
|
12
|
+
const digits = phone.replace(/\D/g, '');
|
|
13
|
+
// Already has country code
|
|
14
|
+
if (phone.startsWith('+')) {
|
|
15
|
+
return phone;
|
|
16
|
+
}
|
|
17
|
+
// US/Canada format
|
|
18
|
+
if (digits.length === 10) {
|
|
19
|
+
return `+1 ${digits.slice(0, 3)}-${digits.slice(3, 6)}-${digits.slice(6)}`;
|
|
20
|
+
}
|
|
21
|
+
// International format with country code
|
|
22
|
+
if (digits.length > 10) {
|
|
23
|
+
return `+${digits}`;
|
|
24
|
+
}
|
|
25
|
+
return phone;
|
|
26
|
+
}
|
|
27
|
+
export function formatInstagramHandle(handle) {
|
|
28
|
+
const clean = handle.replace(/^@/, '').toLowerCase();
|
|
29
|
+
return `@${clean}`;
|
|
30
|
+
}
|
|
31
|
+
export function formatInstagramUrl(handle) {
|
|
32
|
+
const clean = handle.replace(/^@/, '').toLowerCase();
|
|
33
|
+
return `https://instagram.com/${clean}`;
|
|
34
|
+
}
|
|
35
|
+
export function formatFacebookUrl(page) {
|
|
36
|
+
if (page.startsWith('http')) {
|
|
37
|
+
return page;
|
|
38
|
+
}
|
|
39
|
+
return `https://facebook.com/${page}`;
|
|
40
|
+
}
|
|
41
|
+
export function formatWhatsAppUrl(phone) {
|
|
42
|
+
const digits = phone.replace(/\D/g, '');
|
|
43
|
+
return `https://wa.me/${digits}`;
|
|
44
|
+
}
|
|
45
|
+
export function formatGoogleMapsUrl(query) {
|
|
46
|
+
return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(query)}`;
|
|
47
|
+
}
|
|
48
|
+
export function mergeContacts(a, b) {
|
|
49
|
+
return {
|
|
50
|
+
phone: [...new Set([...(a.phone || []), ...(b.phone || [])])],
|
|
51
|
+
email: [...new Set([...(a.email || []), ...(b.email || [])])],
|
|
52
|
+
whatsapp: b.whatsapp || a.whatsapp,
|
|
53
|
+
instagram: b.instagram || a.instagram,
|
|
54
|
+
facebook: b.facebook || a.facebook,
|
|
55
|
+
website: b.website || a.website,
|
|
56
|
+
googleMapsUrl: b.googleMapsUrl || a.googleMapsUrl,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export function emptyContacts() {
|
|
60
|
+
return {
|
|
61
|
+
phone: [],
|
|
62
|
+
email: [],
|
|
63
|
+
whatsapp: undefined,
|
|
64
|
+
instagram: undefined,
|
|
65
|
+
facebook: undefined,
|
|
66
|
+
website: undefined,
|
|
67
|
+
googleMapsUrl: undefined,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function hasAnyContact(contacts) {
|
|
71
|
+
return (contacts.phone.length > 0 ||
|
|
72
|
+
contacts.email.length > 0 ||
|
|
73
|
+
!!contacts.whatsapp ||
|
|
74
|
+
!!contacts.instagram ||
|
|
75
|
+
!!contacts.facebook ||
|
|
76
|
+
!!contacts.website);
|
|
77
|
+
}
|
|
78
|
+
export function truncate(str, maxLength) {
|
|
79
|
+
if (str.length <= maxLength)
|
|
80
|
+
return str;
|
|
81
|
+
return `${str.slice(0, maxLength - 3)}...`;
|
|
82
|
+
}
|
|
83
|
+
export function cleanPropertyName(name) {
|
|
84
|
+
return (name
|
|
85
|
+
// Normalize whitespace
|
|
86
|
+
.replace(/[\r\n\t]+/g, ' ')
|
|
87
|
+
.replace(/\s+/g, ' ')
|
|
88
|
+
// Strip platform suffixes
|
|
89
|
+
.replace(/\s*[-·|]\s*Airbnb.*$/i, '')
|
|
90
|
+
.replace(/\s*[-·|]\s*Booking\.com.*$/i, '')
|
|
91
|
+
.replace(/\s*[-·|]\s*VRBO.*$/i, '')
|
|
92
|
+
.replace(/\s*[-·|]\s*Expedia.*$/i, '')
|
|
93
|
+
// Strip generic listing descriptions (Airbnb pattern)
|
|
94
|
+
.replace(/\s*-\s*(?:Villas?|Houses?|Apartments?|Condos?|Cabins?|Cottages?|Rooms?)\s+for\s+Rent\s+in\s+[^-]+$/i, '')
|
|
95
|
+
// Strip location suffix patterns
|
|
96
|
+
.replace(/\s*-\s*[^-]+,\s*[^-]+,\s*[A-Za-z]+$/i, '')
|
|
97
|
+
.trim());
|
|
98
|
+
}
|
|
99
|
+
export function escapeHtml(text) {
|
|
100
|
+
return text
|
|
101
|
+
.replace(/&/g, '&')
|
|
102
|
+
.replace(/</g, '<')
|
|
103
|
+
.replace(/>/g, '>')
|
|
104
|
+
.replace(/"/g, '"')
|
|
105
|
+
.replace(/'/g, ''');
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=formatters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../../src/lib/utils/formatters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Platform } from '../concierge-client-types.js';
|
|
2
|
+
export interface ParsedUrl {
|
|
3
|
+
platform: Platform;
|
|
4
|
+
listingId?: string;
|
|
5
|
+
url: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function parseListingUrl(url: string): ParsedUrl;
|
|
8
|
+
export declare function isValidUrl(url: string): boolean;
|
|
9
|
+
export declare function extractDomain(url: string): string | null;
|
|
10
|
+
export declare function cleanUrl(url: string): string;
|
|
11
|
+
//# sourceMappingURL=url-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-parser.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/url-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAE7D,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb;AAgBD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CA+CtD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/C;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOxD;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA0B5C"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const PLATFORM_PATTERNS = {
|
|
2
|
+
airbnb: [
|
|
3
|
+
/airbnb\.(com|[a-z]{2}|co\.[a-z]{2})\/rooms\/(\d+)/i,
|
|
4
|
+
/airbnb\.(com|[a-z]{2}|co\.[a-z]{2})\/h\/([a-zA-Z0-9-]+)/i,
|
|
5
|
+
],
|
|
6
|
+
booking: [/booking\.com\/hotel\/[a-z]{2}\/([^/?]+)/i, /booking\.com\/[a-z]{2}\/hotel\/[a-z]{2}\/([^/?]+)/i],
|
|
7
|
+
vrbo: [/vrbo\.com\/(\d+)/i, /vrbo\.com\/[a-z]{2}\/vacation-rentals\/[^/]+\/(\d+)/i],
|
|
8
|
+
expedia: [
|
|
9
|
+
/expedia\.(com|[a-z]{2}|co\.[a-z]{2})\/[^/]*[Hh]otel[^/]*\/([^/?]+)/i,
|
|
10
|
+
/expedia\.(com|[a-z]{2}|co\.[a-z]{2})\/[^/]+\.h(\d+)\./i,
|
|
11
|
+
],
|
|
12
|
+
unknown: [],
|
|
13
|
+
};
|
|
14
|
+
export function parseListingUrl(url) {
|
|
15
|
+
// Normalize URL
|
|
16
|
+
let normalizedUrl = url.trim();
|
|
17
|
+
if (!normalizedUrl.startsWith('http://') && !normalizedUrl.startsWith('https://')) {
|
|
18
|
+
normalizedUrl = `https://${normalizedUrl}`;
|
|
19
|
+
}
|
|
20
|
+
// Try to parse as URL
|
|
21
|
+
let parsedUrl;
|
|
22
|
+
try {
|
|
23
|
+
parsedUrl = new URL(normalizedUrl);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return { platform: 'unknown', url: normalizedUrl };
|
|
27
|
+
}
|
|
28
|
+
// Detect platform
|
|
29
|
+
for (const [platform, patterns] of Object.entries(PLATFORM_PATTERNS)) {
|
|
30
|
+
if (platform === 'unknown')
|
|
31
|
+
continue;
|
|
32
|
+
for (const pattern of patterns) {
|
|
33
|
+
const match = normalizedUrl.match(pattern);
|
|
34
|
+
if (match) {
|
|
35
|
+
return {
|
|
36
|
+
platform: platform,
|
|
37
|
+
listingId: match[2] || match[1],
|
|
38
|
+
url: normalizedUrl,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Try to detect by hostname alone
|
|
44
|
+
const hostname = parsedUrl.hostname.toLowerCase();
|
|
45
|
+
if (hostname.includes('airbnb')) {
|
|
46
|
+
return { platform: 'airbnb', url: normalizedUrl };
|
|
47
|
+
}
|
|
48
|
+
if (hostname.includes('booking.com')) {
|
|
49
|
+
return { platform: 'booking', url: normalizedUrl };
|
|
50
|
+
}
|
|
51
|
+
if (hostname.includes('vrbo')) {
|
|
52
|
+
return { platform: 'vrbo', url: normalizedUrl };
|
|
53
|
+
}
|
|
54
|
+
if (hostname.includes('expedia')) {
|
|
55
|
+
return { platform: 'expedia', url: normalizedUrl };
|
|
56
|
+
}
|
|
57
|
+
return { platform: 'unknown', url: normalizedUrl };
|
|
58
|
+
}
|
|
59
|
+
export function isValidUrl(url) {
|
|
60
|
+
try {
|
|
61
|
+
new URL(url.startsWith('http') ? url : `https://${url}`);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function extractDomain(url) {
|
|
69
|
+
try {
|
|
70
|
+
const parsed = new URL(url.startsWith('http') ? url : `https://${url}`);
|
|
71
|
+
return parsed.hostname;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export function cleanUrl(url) {
|
|
78
|
+
try {
|
|
79
|
+
const parsed = new URL(url.startsWith('http') ? url : `https://${url}`);
|
|
80
|
+
// Remove tracking parameters
|
|
81
|
+
const cleanParams = new URLSearchParams();
|
|
82
|
+
const trackingParams = [
|
|
83
|
+
'utm_source',
|
|
84
|
+
'utm_medium',
|
|
85
|
+
'utm_campaign',
|
|
86
|
+
'utm_content',
|
|
87
|
+
'utm_term',
|
|
88
|
+
'ref',
|
|
89
|
+
'affiliate_id',
|
|
90
|
+
];
|
|
91
|
+
parsed.searchParams.forEach((value, key) => {
|
|
92
|
+
if (!trackingParams.includes(key.toLowerCase())) {
|
|
93
|
+
cleanParams.set(key, value);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
parsed.search = cleanParams.toString();
|
|
97
|
+
return parsed.toString();
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return url;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=url-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-parser.js","sourceRoot":"","sources":["../../../src/lib/utils/url-parser.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skillhq/concierge",
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "Find contact details for accommodation listings (Airbnb, Booking.com, VRBO, Expedia)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"concierge": "./dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"dev": "tsc --watch",
|
|
14
|
+
"start": "node dist/cli.js",
|
|
15
|
+
"clean": "rm -rf dist",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"test:watch": "vitest",
|
|
19
|
+
"lint": "biome check .",
|
|
20
|
+
"lint:fix": "biome check --write .",
|
|
21
|
+
"format": "biome format --write ."
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"travel",
|
|
25
|
+
"concierge",
|
|
26
|
+
"airbnb",
|
|
27
|
+
"booking",
|
|
28
|
+
"vrbo",
|
|
29
|
+
"expedia",
|
|
30
|
+
"contact",
|
|
31
|
+
"cli"
|
|
32
|
+
],
|
|
33
|
+
"author": "",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/skillhq/concierge.git"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/skillhq/concierge#readme",
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/skillhq/concierge/issues"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist"
|
|
45
|
+
],
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@anthropic-ai/sdk": "^0.72.0",
|
|
48
|
+
"@deepgram/sdk": "^3.5.0",
|
|
49
|
+
"@elevenlabs/elevenlabs-js": "^2.33.0",
|
|
50
|
+
"commander": "^14.0.0",
|
|
51
|
+
"json5": "^2.2.3",
|
|
52
|
+
"kleur": "^4.1.5",
|
|
53
|
+
"twilio": "^5.0.0",
|
|
54
|
+
"ws": "^8.16.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@biomejs/biome": "^2.3.0",
|
|
58
|
+
"@types/node": "^22.0.0",
|
|
59
|
+
"@types/ws": "^8.5.10",
|
|
60
|
+
"typescript": "^5.4.0",
|
|
61
|
+
"vitest": "^4.0.0"
|
|
62
|
+
},
|
|
63
|
+
"engines": {
|
|
64
|
+
"node": ">=18.0.0"
|
|
65
|
+
},
|
|
66
|
+
"packageManager": "pnpm@10.25.0"
|
|
67
|
+
}
|