gtm-now 0.10.0 → 0.10.1
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/dist/index.js +101 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10713,8 +10713,8 @@ var init_prospect = __esm({
|
|
|
10713
10713
|
},
|
|
10714
10714
|
output: {
|
|
10715
10715
|
type: "string",
|
|
10716
|
-
enum: ["file", "inline"],
|
|
10717
|
-
description: 'Output mode. "file" writes
|
|
10716
|
+
enum: ["file", "inline", "csv"],
|
|
10717
|
+
description: 'Output mode. "file" writes JSONL (auto when >20 results). "csv" writes a CSV file for spreadsheet review. "inline" returns in response.'
|
|
10718
10718
|
},
|
|
10719
10719
|
detail: {
|
|
10720
10720
|
type: "string",
|
|
@@ -10825,8 +10825,8 @@ var init_prospect = __esm({
|
|
|
10825
10825
|
},
|
|
10826
10826
|
output: {
|
|
10827
10827
|
type: "string",
|
|
10828
|
-
enum: ["file", "inline"],
|
|
10829
|
-
description: 'Output mode. "file" writes
|
|
10828
|
+
enum: ["file", "inline", "csv"],
|
|
10829
|
+
description: 'Output mode. "file" writes JSONL (auto when >20 results). "csv" writes a CSV file for spreadsheet review. "inline" returns in response.'
|
|
10830
10830
|
},
|
|
10831
10831
|
detail: {
|
|
10832
10832
|
type: "string",
|
|
@@ -10849,7 +10849,7 @@ var init_enrich = __esm({
|
|
|
10849
10849
|
enrichTools = [
|
|
10850
10850
|
{
|
|
10851
10851
|
name: "gtm_enrich",
|
|
10852
|
-
description:
|
|
10852
|
+
description: 'Email enrichment via waterfall \u2014 tries providers in order, stops on first match. Always dry_run first for batches > 5. Defaults to email only. Phone costs extra \u2014 only add find: ["email", "phone"] when the user explicitly requests phone numbers.',
|
|
10853
10853
|
inputSchema: {
|
|
10854
10854
|
type: "object",
|
|
10855
10855
|
properties: {
|
|
@@ -10876,7 +10876,7 @@ var init_enrich = __esm({
|
|
|
10876
10876
|
enum: ["email", "phone", "title", "company", "funding", "tech_stack"]
|
|
10877
10877
|
},
|
|
10878
10878
|
default: ["email"],
|
|
10879
|
-
description:
|
|
10879
|
+
description: 'Fields to find. Defaults to ["email"] only. Add "phone" ONLY when explicitly requested \u2014 phone lookups cost extra. Additional fields (title, company, funding, tech_stack) return an informative error until Phase 2.'
|
|
10880
10880
|
},
|
|
10881
10881
|
waterfall: {
|
|
10882
10882
|
type: "array",
|
|
@@ -11347,7 +11347,9 @@ After finding people, use:
|
|
|
11347
11347
|
|
|
11348
11348
|
Known limitations:
|
|
11349
11349
|
- department + seniority filters combined may return 0 results (Disco API uses strict AND). Use one or the other.`,
|
|
11350
|
-
gtm_enrich: `Email
|
|
11350
|
+
gtm_enrich: `Email enrichment via waterfall \u2014 tries multiple providers in order, stops on first match. Supports 1-100 contacts per call.
|
|
11351
|
+
|
|
11352
|
+
IMPORTANT: Defaults to email only. Phone enrichment costs extra per lookup \u2014 only include when the user explicitly asks for phone numbers.
|
|
11351
11353
|
|
|
11352
11354
|
Always do a dry_run first for batches > 5 to preview cost.
|
|
11353
11355
|
|
|
@@ -11444,6 +11446,7 @@ var init_tools = __esm({
|
|
|
11444
11446
|
"cold_outreach",
|
|
11445
11447
|
"linkedin_outreach",
|
|
11446
11448
|
"crm_sync",
|
|
11449
|
+
"export_to_webhook",
|
|
11447
11450
|
"list_tasks"
|
|
11448
11451
|
],
|
|
11449
11452
|
description: "The workflow to get guidance for"
|
|
@@ -11536,6 +11539,12 @@ Start by identifying what kind of companies you're targeting:
|
|
|
11536
11539
|
3. gtm_enrich \u2014 get emails
|
|
11537
11540
|
4. gtm_campaign \u2014 personalized outreach referencing their engagement
|
|
11538
11541
|
|
|
11542
|
+
## Review before enriching
|
|
11543
|
+
After finding companies, review the list before spending enrichment credits:
|
|
11544
|
+
- Use output: 'csv' to write results to a spreadsheet for visual review
|
|
11545
|
+
- Or export to Clay/webhook via gtm_fetch POST for team review (see export_to_webhook guide)
|
|
11546
|
+
- Use gtm_ai with action: 'classify' to auto-filter competitors or bad fits
|
|
11547
|
+
|
|
11539
11548
|
## Key principle
|
|
11540
11549
|
Always dry_run enrichment first. Credits are spent per successful find \u2014 previewing cost avoids surprises.`,
|
|
11541
11550
|
enrich_list: `# Enrich a Contact List \u2014 Workflow
|
|
@@ -11611,6 +11620,26 @@ LinkedIn outreach requires LinkedIn profile URLs \u2014 not emails. Extract prof
|
|
|
11611
11620
|
|
|
11612
11621
|
## Key principle
|
|
11613
11622
|
Always search before creating to avoid duplicates. Most CRMs have built-in email dedup but better to check first.`,
|
|
11623
|
+
export_to_webhook: `# Export Data to Webhook \u2014 Workflow
|
|
11624
|
+
|
|
11625
|
+
Push GTM data to Clay, Make, Zapier, or any webhook endpoint for visual review or further processing.
|
|
11626
|
+
|
|
11627
|
+
## Steps
|
|
11628
|
+
1. FIND \u2014 Get your companies or contacts
|
|
11629
|
+
\u2192 gtm_find_companies({ icp_text: "...", limit: 50 })
|
|
11630
|
+
\u2192 gtm_find_people({ company_domain: "...", job_title: "CEO" })
|
|
11631
|
+
|
|
11632
|
+
2. EXPORT \u2014 Push to webhook via gtm_fetch
|
|
11633
|
+
\u2192 gtm_fetch({ url: "https://your-webhook-url", method: "POST", body: { results: [...] } })
|
|
11634
|
+
|
|
11635
|
+
## Clay Integration
|
|
11636
|
+
Clay table webhooks accept JSON directly:
|
|
11637
|
+
\u2192 gtm_fetch({ url: "https://api.clay.com/v3/sources/webhook/...", method: "POST", body: { first_name: "...", last_name: "...", company: "...", ... } })
|
|
11638
|
+
|
|
11639
|
+
Send one record per request, or batch them depending on the webhook's format.
|
|
11640
|
+
|
|
11641
|
+
## Key principle
|
|
11642
|
+
Review data visually before spending enrichment credits. Export \u2192 review \u2192 enrich only the good leads.`,
|
|
11614
11643
|
list_tasks: `# Available GTM Workflows
|
|
11615
11644
|
|
|
11616
11645
|
Call gtm_guide with one of these tasks:
|
|
@@ -11620,6 +11649,7 @@ Call gtm_guide with one of these tasks:
|
|
|
11620
11649
|
- cold_outreach \u2014 Enrich + personalize + push to cold email campaign
|
|
11621
11650
|
- linkedin_outreach \u2014 Extract profiles + personalize + push to LinkedIn campaign
|
|
11622
11651
|
- crm_sync \u2014 Find/create/update people and deals in CRM
|
|
11652
|
+
- export_to_webhook \u2014 Push data to Clay, Make, Zapier, or any webhook for review
|
|
11623
11653
|
|
|
11624
11654
|
New tools available:
|
|
11625
11655
|
- gtm_find_companies (provider: storeleads) \u2014 Search 1.2M+ e-commerce stores by category, revenue, platform
|
|
@@ -11703,6 +11733,7 @@ import * as os from "os";
|
|
|
11703
11733
|
function shouldWriteToFile(count, output) {
|
|
11704
11734
|
if (output === "file") return true;
|
|
11705
11735
|
if (output === "inline") return false;
|
|
11736
|
+
if (output === "csv") return false;
|
|
11706
11737
|
return count > FILE_OUTPUT_THRESHOLD;
|
|
11707
11738
|
}
|
|
11708
11739
|
function writeResultsFile(tool, results, meta, resultsDir = DEFAULT_RESULTS_DIR) {
|
|
@@ -11720,6 +11751,40 @@ function writeResultsFile(tool, results, meta, resultsDir = DEFAULT_RESULTS_DIR)
|
|
|
11720
11751
|
}
|
|
11721
11752
|
return filePath;
|
|
11722
11753
|
}
|
|
11754
|
+
function writeResultsCsv(tool, results, resultsDir = DEFAULT_RESULTS_DIR) {
|
|
11755
|
+
fs.mkdirSync(resultsDir, { recursive: true });
|
|
11756
|
+
const timestamp = formatTimestamp(/* @__PURE__ */ new Date());
|
|
11757
|
+
const filename = `${tool}-${timestamp}.csv`;
|
|
11758
|
+
const filePath = path.join(resultsDir, filename);
|
|
11759
|
+
if (results.length === 0) {
|
|
11760
|
+
fs.writeFileSync(filePath, "", "utf-8");
|
|
11761
|
+
return filePath;
|
|
11762
|
+
}
|
|
11763
|
+
const headers = Object.keys(results[0]);
|
|
11764
|
+
const headerLine = headers.map(escapeCsvField).join(",");
|
|
11765
|
+
const dataLines = results.map(
|
|
11766
|
+
(row) => headers.map((h) => escapeCsvField(formatCsvValue(row[h]))).join(",")
|
|
11767
|
+
);
|
|
11768
|
+
const content = [headerLine, ...dataLines].join("\n") + "\n";
|
|
11769
|
+
fs.writeFileSync(filePath, content, "utf-8");
|
|
11770
|
+
try {
|
|
11771
|
+
cleanOldResults(7, resultsDir);
|
|
11772
|
+
} catch {
|
|
11773
|
+
}
|
|
11774
|
+
return filePath;
|
|
11775
|
+
}
|
|
11776
|
+
function formatCsvValue(value) {
|
|
11777
|
+
if (value === null || value === void 0) return "";
|
|
11778
|
+
if (Array.isArray(value)) return value.join(";");
|
|
11779
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
11780
|
+
return String(value);
|
|
11781
|
+
}
|
|
11782
|
+
function escapeCsvField(value) {
|
|
11783
|
+
if (value.includes(",") || value.includes('"') || value.includes("\n")) {
|
|
11784
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
11785
|
+
}
|
|
11786
|
+
return value;
|
|
11787
|
+
}
|
|
11723
11788
|
function cleanOldResults(maxAgeDays, resultsDir = DEFAULT_RESULTS_DIR) {
|
|
11724
11789
|
let entries;
|
|
11725
11790
|
try {
|
|
@@ -11843,6 +11908,19 @@ async function findCompanies(args, ctx) {
|
|
|
11843
11908
|
if (query.max_revenue != null) applied_filters.max_revenue = query.max_revenue;
|
|
11844
11909
|
const providerUsed = provider.name;
|
|
11845
11910
|
const output = args.output;
|
|
11911
|
+
if (output === "csv") {
|
|
11912
|
+
const filePath = writeResultsCsv("find_companies", slimmedResults);
|
|
11913
|
+
return {
|
|
11914
|
+
provider: providerUsed,
|
|
11915
|
+
count: results.length,
|
|
11916
|
+
has_more,
|
|
11917
|
+
output: "csv",
|
|
11918
|
+
file: filePath,
|
|
11919
|
+
preview: slimmedResults.slice(0, 3),
|
|
11920
|
+
columns: slimmedResults.length > 0 ? Object.keys(slimmedResults[0]) : [],
|
|
11921
|
+
...warnings?.length ? { warnings } : {}
|
|
11922
|
+
};
|
|
11923
|
+
}
|
|
11846
11924
|
if (shouldWriteToFile(results.length, output)) {
|
|
11847
11925
|
const meta = {
|
|
11848
11926
|
query: applied_filters,
|
|
@@ -11936,6 +12014,19 @@ async function findPeople(args, ctx) {
|
|
|
11936
12014
|
if (query.revenue_range) applied_filters.revenue_range = query.revenue_range;
|
|
11937
12015
|
const providerUsed = provider.name;
|
|
11938
12016
|
const output = args.output;
|
|
12017
|
+
if (output === "csv") {
|
|
12018
|
+
const filePath = writeResultsCsv("find_people", slimmedResults);
|
|
12019
|
+
return {
|
|
12020
|
+
provider: providerUsed,
|
|
12021
|
+
count: dedupedResults.length,
|
|
12022
|
+
has_more,
|
|
12023
|
+
output: "csv",
|
|
12024
|
+
file: filePath,
|
|
12025
|
+
preview: slimmedResults.slice(0, 3),
|
|
12026
|
+
columns: slimmedResults.length > 0 ? Object.keys(slimmedResults[0]) : [],
|
|
12027
|
+
...warnings?.length ? { warnings } : {}
|
|
12028
|
+
};
|
|
12029
|
+
}
|
|
11939
12030
|
if (shouldWriteToFile(dedupedResults.length, output)) {
|
|
11940
12031
|
const meta = {
|
|
11941
12032
|
query: applied_filters,
|
|
@@ -13344,7 +13435,7 @@ var init_validation = __esm({
|
|
|
13344
13435
|
platform: z2.string().optional(),
|
|
13345
13436
|
min_revenue: z2.number().optional(),
|
|
13346
13437
|
max_revenue: z2.number().optional(),
|
|
13347
|
-
output: z2.enum(["file", "inline"]).optional(),
|
|
13438
|
+
output: z2.enum(["file", "inline", "csv"]).optional(),
|
|
13348
13439
|
detail: detailSchema
|
|
13349
13440
|
}),
|
|
13350
13441
|
// 2. People/contact search
|
|
@@ -13385,7 +13476,7 @@ var init_validation = __esm({
|
|
|
13385
13476
|
max_employees: z2.number().int().min(1).optional(),
|
|
13386
13477
|
revenue_range: z2.string().optional(),
|
|
13387
13478
|
fields: z2.union([z2.literal("all"), z2.array(z2.string())]).optional(),
|
|
13388
|
-
output: z2.enum(["file", "inline"]).optional(),
|
|
13479
|
+
output: z2.enum(["file", "inline", "csv"]).optional(),
|
|
13389
13480
|
detail: detailSchema
|
|
13390
13481
|
}).refine(
|
|
13391
13482
|
(data) => !!(data.job_title || data.company_name || data.company_domain || data.company_domains && data.company_domains.length > 0 || data.seniority && data.seniority.length > 0 || data.filter_industry && data.filter_industry.length > 0 || data.skills && data.skills.length > 0 || data.location),
|
|
@@ -13520,6 +13611,7 @@ var init_validation = __esm({
|
|
|
13520
13611
|
"cold_outreach",
|
|
13521
13612
|
"linkedin_outreach",
|
|
13522
13613
|
"crm_sync",
|
|
13614
|
+
"export_to_webhook",
|
|
13523
13615
|
"list_tasks"
|
|
13524
13616
|
])
|
|
13525
13617
|
}),
|