gtm-now 0.10.0 → 0.10.2
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 +233 -12
- 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",
|
|
@@ -11307,6 +11307,43 @@ var init_feedback = __esm({
|
|
|
11307
11307
|
}
|
|
11308
11308
|
});
|
|
11309
11309
|
|
|
11310
|
+
// src/tools/review.ts
|
|
11311
|
+
var reviewTools;
|
|
11312
|
+
var init_review = __esm({
|
|
11313
|
+
"src/tools/review.ts"() {
|
|
11314
|
+
"use strict";
|
|
11315
|
+
reviewTools = [
|
|
11316
|
+
{
|
|
11317
|
+
name: "gtm_review",
|
|
11318
|
+
description: "Push data to a visual review table. Users see an interactive grid in their browser and can select/deselect rows. Use after finding companies or contacts to let the user review before enrichment.",
|
|
11319
|
+
inputSchema: {
|
|
11320
|
+
type: "object",
|
|
11321
|
+
properties: {
|
|
11322
|
+
action: {
|
|
11323
|
+
type: "string",
|
|
11324
|
+
enum: ["create", "update", "get_selected"],
|
|
11325
|
+
description: "create: new table from data. update: modify existing table rows. get_selected: fetch user-approved rows."
|
|
11326
|
+
},
|
|
11327
|
+
title: { type: "string", description: "Table title (for create)" },
|
|
11328
|
+
data: {
|
|
11329
|
+
type: "array",
|
|
11330
|
+
items: { type: "object" },
|
|
11331
|
+
description: "Array of row objects (for create)"
|
|
11332
|
+
},
|
|
11333
|
+
table_id: { type: "string", description: "Table ID (for update, get_selected)" },
|
|
11334
|
+
rows: {
|
|
11335
|
+
type: "array",
|
|
11336
|
+
items: { type: "object" },
|
|
11337
|
+
description: "Updated row objects with _row_id (for update)"
|
|
11338
|
+
}
|
|
11339
|
+
},
|
|
11340
|
+
required: ["action"]
|
|
11341
|
+
}
|
|
11342
|
+
}
|
|
11343
|
+
];
|
|
11344
|
+
}
|
|
11345
|
+
});
|
|
11346
|
+
|
|
11310
11347
|
// src/tools/descriptions.ts
|
|
11311
11348
|
var TOOL_DESCRIPTIONS;
|
|
11312
11349
|
var init_descriptions = __esm({
|
|
@@ -11347,7 +11384,9 @@ After finding people, use:
|
|
|
11347
11384
|
|
|
11348
11385
|
Known limitations:
|
|
11349
11386
|
- department + seniority filters combined may return 0 results (Disco API uses strict AND). Use one or the other.`,
|
|
11350
|
-
gtm_enrich: `Email
|
|
11387
|
+
gtm_enrich: `Email enrichment via waterfall \u2014 tries multiple providers in order, stops on first match. Supports 1-100 contacts per call.
|
|
11388
|
+
|
|
11389
|
+
IMPORTANT: Defaults to email only. Phone enrichment costs extra per lookup \u2014 only include when the user explicitly asks for phone numbers.
|
|
11351
11390
|
|
|
11352
11391
|
Always do a dry_run first for batches > 5 to preview cost.
|
|
11353
11392
|
|
|
@@ -11388,7 +11427,8 @@ Note: HarvestAPI charges per request. For engagement mining, each post lookup co
|
|
|
11388
11427
|
gtm_guide: "CALL THIS FIRST before any multi-step GTM task. Returns step-by-step workflow recipes for common tasks like building a TAM list, running enrichment, or launching cold outreach. Always check the guide before starting work to ensure you follow the correct sequence and avoid wasting credits.",
|
|
11389
11428
|
gtm_tool_help: "Get the full parameter schema for a specific GTM tool. Use this to see exactly what arguments a tool accepts before calling gtm_execute.",
|
|
11390
11429
|
gtm_execute: "Gateway to execute any GTM tool by name. Use gtm_guide for workflow recipes, gtm_tool_help for parameter schemas, then this to execute.",
|
|
11391
|
-
gtm_feedback: "Submit feedback, bug reports, feature requests, or provider requests. Feedback is stored for the gtm-now maintainers to review."
|
|
11430
|
+
gtm_feedback: "Submit feedback, bug reports, feature requests, or provider requests. Feedback is stored for the gtm-now maintainers to review.",
|
|
11431
|
+
gtm_review: "Push data to a visual review table hosted at view.gtmnow.com. Users see an interactive AG Grid in their browser with checkboxes to select/deselect rows. Creates a temporary table (24h TTL) with a shareable URL. Use after finding companies or contacts to let the user review before spending enrichment credits. Three actions: create (new table from data array), update (modify existing table \u2014 add columns, update rows), get_selected (fetch only the rows the user has checked)."
|
|
11392
11432
|
};
|
|
11393
11433
|
}
|
|
11394
11434
|
});
|
|
@@ -11408,6 +11448,7 @@ var init_tools = __esm({
|
|
|
11408
11448
|
init_status();
|
|
11409
11449
|
init_configure();
|
|
11410
11450
|
init_feedback();
|
|
11451
|
+
init_review();
|
|
11411
11452
|
init_prospect();
|
|
11412
11453
|
init_enrich();
|
|
11413
11454
|
init_extract();
|
|
@@ -11417,6 +11458,7 @@ var init_tools = __esm({
|
|
|
11417
11458
|
init_crm();
|
|
11418
11459
|
init_status();
|
|
11419
11460
|
init_configure();
|
|
11461
|
+
init_review();
|
|
11420
11462
|
init_descriptions();
|
|
11421
11463
|
capabilityTools = [
|
|
11422
11464
|
...prospectTools,
|
|
@@ -11428,7 +11470,8 @@ var init_tools = __esm({
|
|
|
11428
11470
|
...crmTools,
|
|
11429
11471
|
...statusTools,
|
|
11430
11472
|
...configureTools,
|
|
11431
|
-
...feedbackTools
|
|
11473
|
+
...feedbackTools,
|
|
11474
|
+
...reviewTools
|
|
11432
11475
|
];
|
|
11433
11476
|
guideTool = {
|
|
11434
11477
|
name: "gtm_guide",
|
|
@@ -11444,6 +11487,7 @@ var init_tools = __esm({
|
|
|
11444
11487
|
"cold_outreach",
|
|
11445
11488
|
"linkedin_outreach",
|
|
11446
11489
|
"crm_sync",
|
|
11490
|
+
"export_to_webhook",
|
|
11447
11491
|
"list_tasks"
|
|
11448
11492
|
],
|
|
11449
11493
|
description: "The workflow to get guidance for"
|
|
@@ -11536,6 +11580,12 @@ Start by identifying what kind of companies you're targeting:
|
|
|
11536
11580
|
3. gtm_enrich \u2014 get emails
|
|
11537
11581
|
4. gtm_campaign \u2014 personalized outreach referencing their engagement
|
|
11538
11582
|
|
|
11583
|
+
## Review before enriching
|
|
11584
|
+
After finding companies, review the list before spending enrichment credits:
|
|
11585
|
+
- Use output: 'csv' to write results to a spreadsheet for visual review
|
|
11586
|
+
- Or export to Clay/webhook via gtm_fetch POST for team review (see export_to_webhook guide)
|
|
11587
|
+
- Use gtm_ai with action: 'classify' to auto-filter competitors or bad fits
|
|
11588
|
+
|
|
11539
11589
|
## Key principle
|
|
11540
11590
|
Always dry_run enrichment first. Credits are spent per successful find \u2014 previewing cost avoids surprises.`,
|
|
11541
11591
|
enrich_list: `# Enrich a Contact List \u2014 Workflow
|
|
@@ -11611,6 +11661,26 @@ LinkedIn outreach requires LinkedIn profile URLs \u2014 not emails. Extract prof
|
|
|
11611
11661
|
|
|
11612
11662
|
## Key principle
|
|
11613
11663
|
Always search before creating to avoid duplicates. Most CRMs have built-in email dedup but better to check first.`,
|
|
11664
|
+
export_to_webhook: `# Export Data to Webhook \u2014 Workflow
|
|
11665
|
+
|
|
11666
|
+
Push GTM data to Clay, Make, Zapier, or any webhook endpoint for visual review or further processing.
|
|
11667
|
+
|
|
11668
|
+
## Steps
|
|
11669
|
+
1. FIND \u2014 Get your companies or contacts
|
|
11670
|
+
\u2192 gtm_find_companies({ icp_text: "...", limit: 50 })
|
|
11671
|
+
\u2192 gtm_find_people({ company_domain: "...", job_title: "CEO" })
|
|
11672
|
+
|
|
11673
|
+
2. EXPORT \u2014 Push to webhook via gtm_fetch
|
|
11674
|
+
\u2192 gtm_fetch({ url: "https://your-webhook-url", method: "POST", body: { results: [...] } })
|
|
11675
|
+
|
|
11676
|
+
## Clay Integration
|
|
11677
|
+
Clay table webhooks accept JSON directly:
|
|
11678
|
+
\u2192 gtm_fetch({ url: "https://api.clay.com/v3/sources/webhook/...", method: "POST", body: { first_name: "...", last_name: "...", company: "...", ... } })
|
|
11679
|
+
|
|
11680
|
+
Send one record per request, or batch them depending on the webhook's format.
|
|
11681
|
+
|
|
11682
|
+
## Key principle
|
|
11683
|
+
Review data visually before spending enrichment credits. Export \u2192 review \u2192 enrich only the good leads.`,
|
|
11614
11684
|
list_tasks: `# Available GTM Workflows
|
|
11615
11685
|
|
|
11616
11686
|
Call gtm_guide with one of these tasks:
|
|
@@ -11620,6 +11690,7 @@ Call gtm_guide with one of these tasks:
|
|
|
11620
11690
|
- cold_outreach \u2014 Enrich + personalize + push to cold email campaign
|
|
11621
11691
|
- linkedin_outreach \u2014 Extract profiles + personalize + push to LinkedIn campaign
|
|
11622
11692
|
- crm_sync \u2014 Find/create/update people and deals in CRM
|
|
11693
|
+
- export_to_webhook \u2014 Push data to Clay, Make, Zapier, or any webhook for review
|
|
11623
11694
|
|
|
11624
11695
|
New tools available:
|
|
11625
11696
|
- gtm_find_companies (provider: storeleads) \u2014 Search 1.2M+ e-commerce stores by category, revenue, platform
|
|
@@ -11703,6 +11774,7 @@ import * as os from "os";
|
|
|
11703
11774
|
function shouldWriteToFile(count, output) {
|
|
11704
11775
|
if (output === "file") return true;
|
|
11705
11776
|
if (output === "inline") return false;
|
|
11777
|
+
if (output === "csv") return false;
|
|
11706
11778
|
return count > FILE_OUTPUT_THRESHOLD;
|
|
11707
11779
|
}
|
|
11708
11780
|
function writeResultsFile(tool, results, meta, resultsDir = DEFAULT_RESULTS_DIR) {
|
|
@@ -11720,6 +11792,40 @@ function writeResultsFile(tool, results, meta, resultsDir = DEFAULT_RESULTS_DIR)
|
|
|
11720
11792
|
}
|
|
11721
11793
|
return filePath;
|
|
11722
11794
|
}
|
|
11795
|
+
function writeResultsCsv(tool, results, resultsDir = DEFAULT_RESULTS_DIR) {
|
|
11796
|
+
fs.mkdirSync(resultsDir, { recursive: true });
|
|
11797
|
+
const timestamp = formatTimestamp(/* @__PURE__ */ new Date());
|
|
11798
|
+
const filename = `${tool}-${timestamp}.csv`;
|
|
11799
|
+
const filePath = path.join(resultsDir, filename);
|
|
11800
|
+
if (results.length === 0) {
|
|
11801
|
+
fs.writeFileSync(filePath, "", "utf-8");
|
|
11802
|
+
return filePath;
|
|
11803
|
+
}
|
|
11804
|
+
const headers = Object.keys(results[0]);
|
|
11805
|
+
const headerLine = headers.map(escapeCsvField).join(",");
|
|
11806
|
+
const dataLines = results.map(
|
|
11807
|
+
(row) => headers.map((h) => escapeCsvField(formatCsvValue(row[h]))).join(",")
|
|
11808
|
+
);
|
|
11809
|
+
const content = [headerLine, ...dataLines].join("\n") + "\n";
|
|
11810
|
+
fs.writeFileSync(filePath, content, "utf-8");
|
|
11811
|
+
try {
|
|
11812
|
+
cleanOldResults(7, resultsDir);
|
|
11813
|
+
} catch {
|
|
11814
|
+
}
|
|
11815
|
+
return filePath;
|
|
11816
|
+
}
|
|
11817
|
+
function formatCsvValue(value) {
|
|
11818
|
+
if (value === null || value === void 0) return "";
|
|
11819
|
+
if (Array.isArray(value)) return value.join(";");
|
|
11820
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
11821
|
+
return String(value);
|
|
11822
|
+
}
|
|
11823
|
+
function escapeCsvField(value) {
|
|
11824
|
+
if (value.includes(",") || value.includes('"') || value.includes("\n")) {
|
|
11825
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
11826
|
+
}
|
|
11827
|
+
return value;
|
|
11828
|
+
}
|
|
11723
11829
|
function cleanOldResults(maxAgeDays, resultsDir = DEFAULT_RESULTS_DIR) {
|
|
11724
11830
|
let entries;
|
|
11725
11831
|
try {
|
|
@@ -11843,6 +11949,19 @@ async function findCompanies(args, ctx) {
|
|
|
11843
11949
|
if (query.max_revenue != null) applied_filters.max_revenue = query.max_revenue;
|
|
11844
11950
|
const providerUsed = provider.name;
|
|
11845
11951
|
const output = args.output;
|
|
11952
|
+
if (output === "csv") {
|
|
11953
|
+
const filePath = writeResultsCsv("find_companies", slimmedResults);
|
|
11954
|
+
return {
|
|
11955
|
+
provider: providerUsed,
|
|
11956
|
+
count: results.length,
|
|
11957
|
+
has_more,
|
|
11958
|
+
output: "csv",
|
|
11959
|
+
file: filePath,
|
|
11960
|
+
preview: slimmedResults.slice(0, 3),
|
|
11961
|
+
columns: slimmedResults.length > 0 ? Object.keys(slimmedResults[0]) : [],
|
|
11962
|
+
...warnings?.length ? { warnings } : {}
|
|
11963
|
+
};
|
|
11964
|
+
}
|
|
11846
11965
|
if (shouldWriteToFile(results.length, output)) {
|
|
11847
11966
|
const meta = {
|
|
11848
11967
|
query: applied_filters,
|
|
@@ -11936,6 +12055,19 @@ async function findPeople(args, ctx) {
|
|
|
11936
12055
|
if (query.revenue_range) applied_filters.revenue_range = query.revenue_range;
|
|
11937
12056
|
const providerUsed = provider.name;
|
|
11938
12057
|
const output = args.output;
|
|
12058
|
+
if (output === "csv") {
|
|
12059
|
+
const filePath = writeResultsCsv("find_people", slimmedResults);
|
|
12060
|
+
return {
|
|
12061
|
+
provider: providerUsed,
|
|
12062
|
+
count: dedupedResults.length,
|
|
12063
|
+
has_more,
|
|
12064
|
+
output: "csv",
|
|
12065
|
+
file: filePath,
|
|
12066
|
+
preview: slimmedResults.slice(0, 3),
|
|
12067
|
+
columns: slimmedResults.length > 0 ? Object.keys(slimmedResults[0]) : [],
|
|
12068
|
+
...warnings?.length ? { warnings } : {}
|
|
12069
|
+
};
|
|
12070
|
+
}
|
|
11939
12071
|
if (shouldWriteToFile(dedupedResults.length, output)) {
|
|
11940
12072
|
const meta = {
|
|
11941
12073
|
query: applied_filters,
|
|
@@ -13111,6 +13243,73 @@ var init_feedback2 = __esm({
|
|
|
13111
13243
|
}
|
|
13112
13244
|
});
|
|
13113
13245
|
|
|
13246
|
+
// src/handlers/review.ts
|
|
13247
|
+
var review_exports = {};
|
|
13248
|
+
__export(review_exports, {
|
|
13249
|
+
handleReview: () => handleReview
|
|
13250
|
+
});
|
|
13251
|
+
async function handleReview(args) {
|
|
13252
|
+
const action = args.action;
|
|
13253
|
+
switch (action) {
|
|
13254
|
+
case "create":
|
|
13255
|
+
return createTable(args);
|
|
13256
|
+
case "update":
|
|
13257
|
+
return updateTable(args);
|
|
13258
|
+
case "get_selected":
|
|
13259
|
+
return getSelected(args);
|
|
13260
|
+
default:
|
|
13261
|
+
throw new Error(`Unknown review action: ${action}`);
|
|
13262
|
+
}
|
|
13263
|
+
}
|
|
13264
|
+
async function createTable(args) {
|
|
13265
|
+
const data = args.data;
|
|
13266
|
+
const title = args.title ?? "Review Table";
|
|
13267
|
+
const rows = data.map((row, i) => ({
|
|
13268
|
+
...row,
|
|
13269
|
+
_row_id: row._row_id ?? `r${i + 1}`
|
|
13270
|
+
}));
|
|
13271
|
+
const response = await fetch(`${VIEWER_URL}/api/tables`, {
|
|
13272
|
+
method: "POST",
|
|
13273
|
+
headers: { "Content-Type": "application/json" },
|
|
13274
|
+
body: JSON.stringify({ title, rows })
|
|
13275
|
+
});
|
|
13276
|
+
if (!response.ok) {
|
|
13277
|
+
const body = await response.json().catch(() => ({}));
|
|
13278
|
+
throw new Error(`Viewer API error ${response.status}: ${JSON.stringify(body)}`);
|
|
13279
|
+
}
|
|
13280
|
+
return response.json();
|
|
13281
|
+
}
|
|
13282
|
+
async function updateTable(args) {
|
|
13283
|
+
const tableId = args.table_id;
|
|
13284
|
+
const rows = args.rows;
|
|
13285
|
+
const response = await fetch(`${VIEWER_URL}/api/tables/${tableId}`, {
|
|
13286
|
+
method: "PATCH",
|
|
13287
|
+
headers: { "Content-Type": "application/json" },
|
|
13288
|
+
body: JSON.stringify({ rows })
|
|
13289
|
+
});
|
|
13290
|
+
if (!response.ok) {
|
|
13291
|
+
const body = await response.json().catch(() => ({}));
|
|
13292
|
+
throw new Error(`Viewer API error ${response.status}: ${JSON.stringify(body)}`);
|
|
13293
|
+
}
|
|
13294
|
+
return response.json();
|
|
13295
|
+
}
|
|
13296
|
+
async function getSelected(args) {
|
|
13297
|
+
const tableId = args.table_id;
|
|
13298
|
+
const response = await fetch(`${VIEWER_URL}/api/tables/${tableId}/selected`);
|
|
13299
|
+
if (!response.ok) {
|
|
13300
|
+
const body = await response.json().catch(() => ({}));
|
|
13301
|
+
throw new Error(`Viewer API error ${response.status}: ${JSON.stringify(body)}`);
|
|
13302
|
+
}
|
|
13303
|
+
return response.json();
|
|
13304
|
+
}
|
|
13305
|
+
var VIEWER_URL;
|
|
13306
|
+
var init_review2 = __esm({
|
|
13307
|
+
"src/handlers/review.ts"() {
|
|
13308
|
+
"use strict";
|
|
13309
|
+
VIEWER_URL = process.env.GTM_VIEWER_URL ?? "https://view.gtmnow.com";
|
|
13310
|
+
}
|
|
13311
|
+
});
|
|
13312
|
+
|
|
13114
13313
|
// src/handlers/index.ts
|
|
13115
13314
|
function isRateLimitError2(error) {
|
|
13116
13315
|
if (error instanceof Error && "status" in error) {
|
|
@@ -13230,6 +13429,10 @@ async function dispatch(name, args, ctx) {
|
|
|
13230
13429
|
const { handleFeedback: handleFeedback2 } = await Promise.resolve().then(() => (init_feedback2(), feedback_exports));
|
|
13231
13430
|
return handleFeedback2(args);
|
|
13232
13431
|
}
|
|
13432
|
+
case "gtm_review": {
|
|
13433
|
+
const { handleReview: handleReview2 } = await Promise.resolve().then(() => (init_review2(), review_exports));
|
|
13434
|
+
return handleReview2(args);
|
|
13435
|
+
}
|
|
13233
13436
|
// ─── Meta-Tools ───────────────────────────────────────
|
|
13234
13437
|
case "gtm_guide": {
|
|
13235
13438
|
const task = args.task;
|
|
@@ -13344,7 +13547,7 @@ var init_validation = __esm({
|
|
|
13344
13547
|
platform: z2.string().optional(),
|
|
13345
13548
|
min_revenue: z2.number().optional(),
|
|
13346
13549
|
max_revenue: z2.number().optional(),
|
|
13347
|
-
output: z2.enum(["file", "inline"]).optional(),
|
|
13550
|
+
output: z2.enum(["file", "inline", "csv"]).optional(),
|
|
13348
13551
|
detail: detailSchema
|
|
13349
13552
|
}),
|
|
13350
13553
|
// 2. People/contact search
|
|
@@ -13385,7 +13588,7 @@ var init_validation = __esm({
|
|
|
13385
13588
|
max_employees: z2.number().int().min(1).optional(),
|
|
13386
13589
|
revenue_range: z2.string().optional(),
|
|
13387
13590
|
fields: z2.union([z2.literal("all"), z2.array(z2.string())]).optional(),
|
|
13388
|
-
output: z2.enum(["file", "inline"]).optional(),
|
|
13591
|
+
output: z2.enum(["file", "inline", "csv"]).optional(),
|
|
13389
13592
|
detail: detailSchema
|
|
13390
13593
|
}).refine(
|
|
13391
13594
|
(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 +13723,7 @@ var init_validation = __esm({
|
|
|
13520
13723
|
"cold_outreach",
|
|
13521
13724
|
"linkedin_outreach",
|
|
13522
13725
|
"crm_sync",
|
|
13726
|
+
"export_to_webhook",
|
|
13523
13727
|
"list_tasks"
|
|
13524
13728
|
])
|
|
13525
13729
|
}),
|
|
@@ -13539,7 +13743,24 @@ var init_validation = __esm({
|
|
|
13539
13743
|
}),
|
|
13540
13744
|
message: z2.string().min(1, "message is required"),
|
|
13541
13745
|
context: z2.record(z2.unknown()).optional()
|
|
13542
|
-
})
|
|
13746
|
+
}),
|
|
13747
|
+
// 17. Review table
|
|
13748
|
+
gtm_review: z2.discriminatedUnion("action", [
|
|
13749
|
+
z2.object({
|
|
13750
|
+
action: z2.literal("create"),
|
|
13751
|
+
title: z2.string().optional(),
|
|
13752
|
+
data: z2.array(z2.record(z2.unknown())).min(1, "data must contain at least 1 row")
|
|
13753
|
+
}),
|
|
13754
|
+
z2.object({
|
|
13755
|
+
action: z2.literal("update"),
|
|
13756
|
+
table_id: z2.string().min(1, "table_id is required for update"),
|
|
13757
|
+
rows: z2.array(z2.record(z2.unknown())).min(1, "rows must contain at least 1 row")
|
|
13758
|
+
}),
|
|
13759
|
+
z2.object({
|
|
13760
|
+
action: z2.literal("get_selected"),
|
|
13761
|
+
table_id: z2.string().min(1, "table_id is required for get_selected")
|
|
13762
|
+
})
|
|
13763
|
+
])
|
|
13543
13764
|
};
|
|
13544
13765
|
TOOL_NAMES = Object.keys(toolSchemas);
|
|
13545
13766
|
}
|