@maestrogtm/maestro-gtm 0.10.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/dist/ai-RNHSWSNV.js +158 -0
  2. package/dist/ai-RNHSWSNV.js.map +1 -0
  3. package/dist/app-PSZH2J56.js +54 -0
  4. package/dist/app-PSZH2J56.js.map +1 -0
  5. package/dist/batch-ZCHN54YJ.js +28 -0
  6. package/dist/batch-ZCHN54YJ.js.map +1 -0
  7. package/dist/campaign-XDXQA7KX.js +119 -0
  8. package/dist/campaign-XDXQA7KX.js.map +1 -0
  9. package/dist/chunk-365Q36GF.js +54 -0
  10. package/dist/chunk-365Q36GF.js.map +1 -0
  11. package/dist/chunk-4IV6QS4U.js +122 -0
  12. package/dist/chunk-4IV6QS4U.js.map +1 -0
  13. package/dist/chunk-6GLLK5KO.js +64 -0
  14. package/dist/chunk-6GLLK5KO.js.map +1 -0
  15. package/dist/chunk-6UNBW5SN.js +686 -0
  16. package/dist/chunk-6UNBW5SN.js.map +1 -0
  17. package/dist/chunk-A7JD6EYV.js +92 -0
  18. package/dist/chunk-A7JD6EYV.js.map +1 -0
  19. package/dist/chunk-ARNVJPFM.js +139 -0
  20. package/dist/chunk-ARNVJPFM.js.map +1 -0
  21. package/dist/chunk-AX6BOEF2.js +345 -0
  22. package/dist/chunk-AX6BOEF2.js.map +1 -0
  23. package/dist/chunk-C3T7QPSO.js +507 -0
  24. package/dist/chunk-C3T7QPSO.js.map +1 -0
  25. package/dist/chunk-FG43GILY.js +46 -0
  26. package/dist/chunk-FG43GILY.js.map +1 -0
  27. package/dist/chunk-FS6DCNCA.js +139 -0
  28. package/dist/chunk-FS6DCNCA.js.map +1 -0
  29. package/dist/chunk-I6GRD4X7.js +1144 -0
  30. package/dist/chunk-I6GRD4X7.js.map +1 -0
  31. package/dist/chunk-IP34URKR.js +621 -0
  32. package/dist/chunk-IP34URKR.js.map +1 -0
  33. package/dist/chunk-JFSKOY7Z.js +252 -0
  34. package/dist/chunk-JFSKOY7Z.js.map +1 -0
  35. package/dist/chunk-M25KLO7T.js +3272 -0
  36. package/dist/chunk-M25KLO7T.js.map +1 -0
  37. package/dist/chunk-M3G2WREL.js +57 -0
  38. package/dist/chunk-M3G2WREL.js.map +1 -0
  39. package/dist/chunk-MFFACSBE.js +4266 -0
  40. package/dist/chunk-MFFACSBE.js.map +1 -0
  41. package/dist/chunk-PZ5AY32C.js +10 -0
  42. package/dist/chunk-PZ5AY32C.js.map +1 -0
  43. package/dist/chunk-QZH3XFOQ.js +2636 -0
  44. package/dist/chunk-QZH3XFOQ.js.map +1 -0
  45. package/dist/chunk-SPWDMOEU.js +1940 -0
  46. package/dist/chunk-SPWDMOEU.js.map +1 -0
  47. package/dist/chunk-TP3BZDVV.js +28 -0
  48. package/dist/chunk-TP3BZDVV.js.map +1 -0
  49. package/dist/chunk-UBJUBYSQ.js +18 -0
  50. package/dist/chunk-UBJUBYSQ.js.map +1 -0
  51. package/dist/chunk-VNKXGHWY.js +20 -0
  52. package/dist/chunk-VNKXGHWY.js.map +1 -0
  53. package/dist/chunk-WKLCPIFB.js +9862 -0
  54. package/dist/chunk-WKLCPIFB.js.map +1 -0
  55. package/dist/chunk-YV5XOXRQ.js +7 -0
  56. package/dist/chunk-YV5XOXRQ.js.map +1 -0
  57. package/dist/cli-Z3BNNJYQ.js +852 -0
  58. package/dist/cli-Z3BNNJYQ.js.map +1 -0
  59. package/dist/client-Y34LNEWN.js +8 -0
  60. package/dist/client-Y34LNEWN.js.map +1 -0
  61. package/dist/config.js +17 -0
  62. package/dist/config.js.map +1 -0
  63. package/dist/configure-XSENK4X5.js +64 -0
  64. package/dist/configure-XSENK4X5.js.map +1 -0
  65. package/dist/context.js +10 -0
  66. package/dist/context.js.map +1 -0
  67. package/dist/crm-QBNHVBYV.js +86 -0
  68. package/dist/crm-QBNHVBYV.js.map +1 -0
  69. package/dist/dfy-X3OXIYRA.js +356 -0
  70. package/dist/dfy-X3OXIYRA.js.map +1 -0
  71. package/dist/dist-LGCJKGBS.js +121 -0
  72. package/dist/dist-LGCJKGBS.js.map +1 -0
  73. package/dist/engagement-C4U7LPJH.js +463 -0
  74. package/dist/engagement-C4U7LPJH.js.map +1 -0
  75. package/dist/enrich-F5GPVZFE.js +226 -0
  76. package/dist/enrich-F5GPVZFE.js.map +1 -0
  77. package/dist/extract-DS5N6SSJ.js +155 -0
  78. package/dist/extract-DS5N6SSJ.js.map +1 -0
  79. package/dist/feedback-AIXKXNM5.js +51 -0
  80. package/dist/feedback-AIXKXNM5.js.map +1 -0
  81. package/dist/fetch-QJDSPI63.js +87 -0
  82. package/dist/fetch-QJDSPI63.js.map +1 -0
  83. package/dist/handlers.js +13 -0
  84. package/dist/handlers.js.map +1 -0
  85. package/dist/index.js +38 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/list-HL7NQQJX.js +236 -0
  88. package/dist/list-HL7NQQJX.js.map +1 -0
  89. package/dist/maestro-N7Q2JX22.js +903 -0
  90. package/dist/maestro-N7Q2JX22.js.map +1 -0
  91. package/dist/prospect-RUOT43H6.js +532 -0
  92. package/dist/prospect-RUOT43H6.js.map +1 -0
  93. package/dist/providers/factory.js +10 -0
  94. package/dist/providers/factory.js.map +1 -0
  95. package/dist/providers/registry.js +8 -0
  96. package/dist/providers/registry.js.map +1 -0
  97. package/dist/provision-FT5NWN77.js +394 -0
  98. package/dist/provision-FT5NWN77.js.map +1 -0
  99. package/dist/recipe-JU3SXMZF.js +137 -0
  100. package/dist/recipe-JU3SXMZF.js.map +1 -0
  101. package/dist/review-5SB6DYDZ.js +70 -0
  102. package/dist/review-5SB6DYDZ.js.map +1 -0
  103. package/dist/sdk-LVBHNQ6T.js +3852 -0
  104. package/dist/sdk-LVBHNQ6T.js.map +1 -0
  105. package/dist/server-REKYQZ2E.js +22 -0
  106. package/dist/server-REKYQZ2E.js.map +1 -0
  107. package/dist/status-V3EEFS7S.js +114 -0
  108. package/dist/status-V3EEFS7S.js.map +1 -0
  109. package/dist/tam-J6NDBP5W.js +682 -0
  110. package/dist/tam-J6NDBP5W.js.map +1 -0
  111. package/dist/tools.js +80 -0
  112. package/dist/tools.js.map +1 -0
  113. package/dist/validation.js +12 -0
  114. package/dist/validation.js.map +1 -0
  115. package/package.json +77 -0
@@ -0,0 +1,1144 @@
1
+ // src/validation.ts
2
+ import { z } from "zod";
3
+ var contactInputSchema = z.object({
4
+ first_name: z.string().min(1, "first_name is required"),
5
+ last_name: z.string().min(1, "last_name is required"),
6
+ company: z.string().optional(),
7
+ company_domain: z.string().optional(),
8
+ linkedin_url: z.string().optional()
9
+ });
10
+ var campaignLeadSchema = z.object({
11
+ email: z.string().email("email must be a valid email address").optional(),
12
+ linkedin_url: z.string().min(1, "linkedin_url is required").optional(),
13
+ first_name: z.string().optional(),
14
+ last_name: z.string().optional(),
15
+ company: z.string().optional(),
16
+ custom_fields: z.record(z.string()).optional()
17
+ }).refine((data) => !!data.email || !!data.linkedin_url, {
18
+ message: "At least one of email or linkedin_url is required"
19
+ });
20
+ var detailSchema = z.enum(["summary", "full"]).optional();
21
+ var toolSchemas = {
22
+ // 1. Company discovery
23
+ find_companies: z.object({
24
+ icp_text: z.string().optional(),
25
+ domain: z.string().optional(),
26
+ domains: z.array(z.string()).optional(),
27
+ limit: z.number().int().min(1).max(1e3).optional(),
28
+ country: z.string().optional(),
29
+ min_employees: z.number().int().min(0).optional(),
30
+ max_employees: z.number().int().min(1).optional(),
31
+ tech_stack: z.array(z.string()).optional(),
32
+ category: z.string().optional(),
33
+ negate_domains: z.array(z.string()).optional(),
34
+ min_digital_footprint: z.number().min(0).optional(),
35
+ max_digital_footprint: z.number().min(0).optional(),
36
+ offset: z.number().int().min(0).optional(),
37
+ provider: z.string().optional(),
38
+ fields: z.union([z.literal("all"), z.array(z.string())]).optional(),
39
+ search: z.string().optional(),
40
+ state: z.string().optional(),
41
+ platform: z.string().optional(),
42
+ min_revenue: z.number().optional(),
43
+ max_revenue: z.number().optional(),
44
+ output: z.enum(["file", "inline", "csv"]).optional(),
45
+ detail: detailSchema,
46
+ review: z.boolean().optional()
47
+ }),
48
+ // 2. People/contact search
49
+ find_people: z.object({
50
+ job_title: z.string().optional(),
51
+ company_name: z.string().optional(),
52
+ company_domain: z.string().optional(),
53
+ location: z.string().optional(),
54
+ limit: z.number().int().min(1).max(1e3).optional(),
55
+ seniority: z.array(
56
+ z.enum([
57
+ "owner",
58
+ "founder",
59
+ "c_suite",
60
+ "partner",
61
+ "vp",
62
+ "head",
63
+ "director",
64
+ "manager",
65
+ "senior",
66
+ "entry",
67
+ "intern"
68
+ ])
69
+ ).optional(),
70
+ department: z.array(z.string()).optional(),
71
+ has_email: z.boolean().optional(),
72
+ has_phone: z.boolean().optional(),
73
+ has_linkedin: z.boolean().optional(),
74
+ min_connections: z.number().int().min(0).optional(),
75
+ offset: z.number().int().min(0).optional(),
76
+ provider: z.string().optional(),
77
+ // ─── DiscoLike filters ───
78
+ company_domains: z.array(z.string().min(1)).optional(),
79
+ skills: z.array(z.string()).optional(),
80
+ filter_industry: z.array(z.string()).optional(),
81
+ email_validated: z.boolean().optional(),
82
+ min_employees: z.number().int().min(0).optional(),
83
+ max_employees: z.number().int().min(1).optional(),
84
+ revenue_range: z.string().optional(),
85
+ enrich: z.boolean().optional(),
86
+ review: z.boolean().optional(),
87
+ fields: z.union([z.literal("all"), z.array(z.string())]).optional(),
88
+ output: z.enum(["file", "inline", "csv"]).optional(),
89
+ detail: detailSchema
90
+ }).refine(
91
+ (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),
92
+ {
93
+ message: "At least one search filter required (job_title, company_name, company_domain, company_domains, seniority, filter_industry, skills, or location)"
94
+ }
95
+ ),
96
+ // 3. Enrichment waterfall + verification (absorbs: verify)
97
+ enrich: z.object({
98
+ action: z.enum(["enrich", "verify"]).optional(),
99
+ contacts: z.array(contactInputSchema).max(100, "contacts must contain at most 100 contacts").optional(),
100
+ find: z.array(z.enum(["email", "phone", "title", "company", "funding", "tech_stack"])).optional(),
101
+ waterfall: z.array(z.string()).optional(),
102
+ verify: z.boolean().optional(),
103
+ dry_run: z.boolean().optional(),
104
+ detail: detailSchema,
105
+ table_id: z.string().optional(),
106
+ review: z.boolean().optional(),
107
+ // ─── Verify params (absorbed from verify tool) ───
108
+ email: z.string().email("email must be a valid email address").optional()
109
+ }).refine(
110
+ (data) => {
111
+ if (data.action === "verify") return !!data.email;
112
+ return !!(data.contacts?.length || data.table_id);
113
+ },
114
+ {
115
+ message: "verify action requires email; enrich action requires contacts or table_id"
116
+ }
117
+ ),
118
+ // 5. Extract/scrape — web pages + all LinkedIn intelligence
119
+ extract: z.object({
120
+ type: z.enum(
121
+ [
122
+ "linkedin_profile",
123
+ "linkedin_posts",
124
+ "linkedin_engagement",
125
+ "linkedin_search",
126
+ "linkedin_company_posts",
127
+ "web_page"
128
+ ],
129
+ {
130
+ message: "type must be one of: linkedin_profile, linkedin_posts, linkedin_engagement, linkedin_search, linkedin_company_posts, web_page"
131
+ }
132
+ ),
133
+ url: z.string().url("url must be a valid URL").optional(),
134
+ linkedin_url: z.string().optional(),
135
+ find_email: z.boolean().optional(),
136
+ profile: z.string().optional(),
137
+ company: z.string().optional(),
138
+ posted_within: z.enum(["24h", "week", "month"]).optional(),
139
+ post_url: z.string().optional(),
140
+ engagement_type: z.enum(["comments", "reactions", "both"]).optional(),
141
+ query: z.string().optional(),
142
+ sort: z.enum(["relevance", "date"]).optional(),
143
+ limit: z.number().int().min(1).max(100).optional(),
144
+ fields: z.array(z.string()).optional(),
145
+ detail: detailSchema
146
+ }).refine(
147
+ (data) => {
148
+ switch (data.type) {
149
+ case "linkedin_profile":
150
+ return !!(data.linkedin_url || data.url);
151
+ case "linkedin_posts":
152
+ return !!data.profile;
153
+ case "linkedin_engagement":
154
+ return !!data.post_url;
155
+ case "linkedin_search":
156
+ return !!data.query;
157
+ case "linkedin_company_posts":
158
+ return !!data.company;
159
+ case "web_page":
160
+ return !!data.url;
161
+ default:
162
+ return true;
163
+ }
164
+ },
165
+ { message: "Missing required field for the specified type" }
166
+ ),
167
+ // 6. Raw HTTP fetch
168
+ fetch: z.object({
169
+ url: z.string().url("url must be a valid URL"),
170
+ method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).optional(),
171
+ headers: z.record(z.string()).optional(),
172
+ body: z.record(z.unknown()).optional(),
173
+ params: z.record(z.string()).optional(),
174
+ detail: detailSchema
175
+ }),
176
+ // 7. AI data operations
177
+ ai: z.object({
178
+ action: z.enum(["personalize", "classify", "clean", "score", "write_copy"], {
179
+ message: "action must be one of: personalize, classify, clean, score, write_copy"
180
+ }),
181
+ data: z.unknown().refine((val) => val !== void 0 && val !== null, {
182
+ message: "data is required"
183
+ }),
184
+ prompt: z.string().optional(),
185
+ model: z.string().optional(),
186
+ enrich_with_graph: z.boolean().optional()
187
+ }),
188
+ // 8. Campaign management + engagement monitoring (absorbs: engagement)
189
+ campaign: z.object({
190
+ action: z.enum(
191
+ [
192
+ "list",
193
+ "stats",
194
+ "add_leads",
195
+ "create",
196
+ "monitor",
197
+ "engagement_status",
198
+ "engagers",
199
+ "push"
200
+ ],
201
+ {
202
+ message: "action must be one of: list, stats, add_leads, create, monitor, engagement_status, engagers, push"
203
+ }
204
+ ),
205
+ channel: z.enum(["email", "linkedin"], {
206
+ message: 'channel must be "email" or "linkedin"'
207
+ }).optional(),
208
+ campaign_id: z.string().optional(),
209
+ leads: z.array(campaignLeadSchema).optional(),
210
+ name: z.string().optional(),
211
+ provider: z.string().optional(),
212
+ detail: detailSchema,
213
+ table_id: z.string().optional(),
214
+ // ─── Engagement params (absorbed from engagement tool) ───
215
+ post_url: z.string().min(1).optional(),
216
+ enabled: z.boolean().optional(),
217
+ plusvibe_campaign_id: z.string().min(1).optional(),
218
+ opt_in_url: z.string().url().optional(),
219
+ post_topic: z.string().min(1).optional(),
220
+ creator_name: z.string().min(1).optional(),
221
+ filter: z.enum(["all", "enriched", "unenriched", "pushed", "unpushed"]).optional(),
222
+ limit: z.number().int().min(1).max(200).optional()
223
+ }).refine(
224
+ (data) => {
225
+ if (data.action === "monitor" || data.action === "engagers" || data.action === "push") {
226
+ return !!data.post_url;
227
+ }
228
+ return true;
229
+ },
230
+ { message: "post_url is required for monitor, engagers, and push actions" }
231
+ ).refine(
232
+ (data) => {
233
+ if (data.action === "push") return !!data.campaign_id;
234
+ return true;
235
+ },
236
+ { message: "campaign_id is required for push action" }
237
+ ),
238
+ // 10. CRM read/write
239
+ crm: z.object({
240
+ action: z.enum(["find", "create", "update", "find_company", "create_deal"], {
241
+ message: "action must be one of: find, create, update, find_company, create_deal"
242
+ }),
243
+ query: z.record(z.unknown()).optional(),
244
+ data: z.record(z.unknown()).optional(),
245
+ id: z.string().optional(),
246
+ table_id: z.string().optional()
247
+ }),
248
+ // 11. Provider status/credits (absorbed into configure — kept for backward compat)
249
+ status: z.object({
250
+ provider: z.string().optional(),
251
+ detail: detailSchema
252
+ }),
253
+ // 12. Configuration management + status (absorbs: status)
254
+ configure: z.object({
255
+ action: z.enum(
256
+ ["switch_client", "list_clients", "show_config", "set_waterfall", "add_client", "status"],
257
+ {
258
+ message: "action must be one of: switch_client, list_clients, show_config, set_waterfall, add_client, status"
259
+ }
260
+ ),
261
+ client: z.string().optional(),
262
+ email: z.array(z.string()).optional(),
263
+ phone: z.array(z.string()).optional(),
264
+ // ─── Status params (absorbed from status tool) ───
265
+ check: z.string().optional(),
266
+ provider: z.string().optional(),
267
+ detail: detailSchema
268
+ }),
269
+ // 13. Engagement monitoring (absorbed into campaign — kept for backward compat)
270
+ engagement: z.object({
271
+ action: z.enum(["monitor", "status", "engagers", "push"], {
272
+ message: "action must be one of: monitor, status, engagers, push"
273
+ }),
274
+ post_url: z.string().min(1).optional(),
275
+ enabled: z.boolean().optional(),
276
+ plusvibe_campaign_id: z.string().min(1).optional(),
277
+ opt_in_url: z.string().url().optional(),
278
+ post_topic: z.string().min(1).optional(),
279
+ creator_name: z.string().min(1).optional(),
280
+ filter: z.enum(["all", "enriched", "unenriched", "pushed", "unpushed"]).optional(),
281
+ campaign_id: z.string().min(1).optional(),
282
+ limit: z.number().int().min(1).max(200).optional()
283
+ }).refine(
284
+ (data) => {
285
+ if (data.action === "monitor" || data.action === "engagers" || data.action === "push") {
286
+ return !!data.post_url;
287
+ }
288
+ return true;
289
+ },
290
+ { message: "post_url is required for monitor, engagers, and push actions" }
291
+ ).refine(
292
+ (data) => {
293
+ if (data.action === "push") return !!data.campaign_id;
294
+ return true;
295
+ },
296
+ { message: "campaign_id is required for push action" }
297
+ ),
298
+ // 14. Workflow guide
299
+ guide: z.object({
300
+ task: z.enum([
301
+ "build_tam",
302
+ "enrich_list",
303
+ "cold_outreach",
304
+ "linkedin_outreach",
305
+ "crm_sync",
306
+ "export_to_webhook",
307
+ "engagement_cold_email",
308
+ "create_magnet",
309
+ "content_pipeline",
310
+ "dm_coaching",
311
+ "qualify_inbox",
312
+ "list_tasks"
313
+ ])
314
+ }),
315
+ // 14. Tool help lookup (tool, provider, or topic — at least one required)
316
+ tool_help: z.object({
317
+ tool: z.string().min(1).optional(),
318
+ provider: z.string().min(1).optional(),
319
+ topic: z.enum(["waterfall_ordering", "csv_best_practices"]).optional()
320
+ }),
321
+ // 15. Execute gateway
322
+ execute: z.object({
323
+ tool: z.string().min(1, "tool is required"),
324
+ arguments: z.record(z.unknown()).optional()
325
+ }),
326
+ // 16. Feedback
327
+ feedback: z.object({
328
+ type: z.enum(["bug", "feature_request", "provider_request"], {
329
+ message: "type must be one of: bug, feature_request, provider_request"
330
+ }),
331
+ message: z.string().min(1, "message is required"),
332
+ context: z.record(z.unknown()).optional()
333
+ }),
334
+ // 17. Provision infrastructure
335
+ provision: z.object({
336
+ action: z.enum(
337
+ [
338
+ "check_domains",
339
+ "check_balance",
340
+ "buy_domains",
341
+ "list_domains",
342
+ "list_mailboxes",
343
+ "setup_dmarc",
344
+ "create_mailboxes",
345
+ "export_mailboxes",
346
+ "create_plusvibe_client",
347
+ "save_config",
348
+ "deploy_crm",
349
+ "start_provision",
350
+ "status"
351
+ ],
352
+ {
353
+ message: "action must be one of: check_domains, check_balance, buy_domains, list_domains, list_mailboxes, setup_dmarc, create_mailboxes, export_mailboxes, create_plusvibe_client, save_config, deploy_crm, start_provision, status"
354
+ }
355
+ ),
356
+ domains: z.array(z.string()).optional(),
357
+ domain_ids: z.array(z.string()).optional(),
358
+ mailboxes: z.array(
359
+ z.object({
360
+ username: z.string(),
361
+ firstName: z.string(),
362
+ lastName: z.string()
363
+ })
364
+ ).optional(),
365
+ name: z.string().optional(),
366
+ email: z.string().optional(),
367
+ dmarc_email: z.string().optional(),
368
+ dmarc_status: z.array(z.string()).optional(),
369
+ workspace_id: z.string().optional(),
370
+ provider: z.string().optional(),
371
+ config_values: z.record(z.string()).optional(),
372
+ client_name: z.string().optional(),
373
+ client_context: z.object({
374
+ id: z.string(),
375
+ email: z.string(),
376
+ name: z.string(),
377
+ source: z.enum(["student", "dfy_client", "self_serve"])
378
+ }).optional(),
379
+ provision_id: z.string().optional(),
380
+ provision_type: z.enum(["full", "outreach"]).optional()
381
+ }),
382
+ // 18. Review table
383
+ review: z.discriminatedUnion("action", [
384
+ z.object({
385
+ action: z.literal("create"),
386
+ title: z.string().optional(),
387
+ data: z.array(z.record(z.unknown())).min(1, "data must contain at least 1 row"),
388
+ table_id: z.string().optional(),
389
+ ttl_seconds: z.number().optional()
390
+ }),
391
+ z.object({
392
+ action: z.literal("update"),
393
+ table_id: z.string().min(1, "table_id is required for update"),
394
+ rows: z.array(z.record(z.unknown())).min(1, "rows must contain at least 1 row")
395
+ }),
396
+ z.object({
397
+ action: z.literal("get_selected"),
398
+ table_id: z.string().min(1, "table_id is required for get_selected")
399
+ })
400
+ ]),
401
+ // 18. Batch processing + recipes (absorbs: recipe)
402
+ batch: z.object({
403
+ action: z.enum(["run", "save_recipe", "list_recipes", "run_recipe", "show_recipe", "delete_recipe"]).optional(),
404
+ input_csv: z.string().min(1).optional(),
405
+ output_csv: z.string().optional(),
406
+ steps: z.array(
407
+ z.object({
408
+ alias: z.string().min(1, "alias is required"),
409
+ tool: z.string().min(1, "tool is required"),
410
+ payload_template: z.record(z.unknown()),
411
+ extract: z.array(z.string()).min(1, "extract must have at least 1 field"),
412
+ waterfall: z.boolean().optional(),
413
+ skip_if: z.string().optional(),
414
+ stop_if: z.string().optional()
415
+ })
416
+ ).optional(),
417
+ rows: z.string().optional(),
418
+ dry_run: z.boolean().optional(),
419
+ concurrency: z.number().int().min(1).max(5).optional(),
420
+ maestro_strategy: z.enum([
421
+ "call_prep",
422
+ "content_generation",
423
+ "lead_scoring",
424
+ "personalization",
425
+ "campaign_planning",
426
+ "general"
427
+ ]).optional(),
428
+ post_process: z.string().optional(),
429
+ ai_answers: z.array(
430
+ z.object({
431
+ row_index: z.number().int().min(0),
432
+ step_alias: z.string().min(1),
433
+ result: z.record(z.unknown())
434
+ })
435
+ ).optional(),
436
+ output: z.discriminatedUnion("type", [
437
+ z.object({
438
+ type: z.literal("review"),
439
+ title: z.string().optional()
440
+ }),
441
+ z.object({
442
+ type: z.literal("campaign"),
443
+ campaign_id: z.string().min(1, "campaign_id is required for campaign output"),
444
+ provider: z.string().optional(),
445
+ lead_mapping: z.record(z.string()).optional()
446
+ }),
447
+ z.object({
448
+ type: z.literal("crm"),
449
+ action: z.enum(["create", "update"]).optional()
450
+ })
451
+ ]).optional(),
452
+ // ─── Recipe params (absorbed from recipe tool) ───
453
+ recipe_name: z.string().min(1).optional(),
454
+ recipe_description: z.string().optional(),
455
+ config: z.record(z.unknown()).optional(),
456
+ schedule: z.string().optional()
457
+ }).refine(
458
+ (data) => {
459
+ const action = data.action ?? "run";
460
+ if (action === "run" || action === "run_recipe") {
461
+ if (action === "run") return !!(data.input_csv && data.steps?.length);
462
+ return !!(data.recipe_name && data.input_csv);
463
+ }
464
+ if (action === "save_recipe") return !!data.recipe_name;
465
+ if (action === "show_recipe" || action === "delete_recipe") return !!data.recipe_name;
466
+ return true;
467
+ },
468
+ {
469
+ message: "run requires input_csv + steps; run_recipe requires recipe_name + input_csv; save_recipe/show_recipe/delete_recipe require recipe_name"
470
+ }
471
+ ),
472
+ // 20. List management (renamed from manage_list)
473
+ list: z.object({
474
+ action: z.enum(["create", "import_csv", "add", "query", "view", "stats", "lists", "delete"]),
475
+ list_id: z.string().uuid().optional(),
476
+ name: z.string().optional(),
477
+ description: z.string().optional(),
478
+ list_type: z.enum(["contacts", "companies", "mixed"]).optional(),
479
+ tags: z.array(z.string()).optional(),
480
+ client_id: z.string().optional(),
481
+ csv_path: z.string().optional(),
482
+ csv_text: z.string().optional(),
483
+ column_mapping: z.record(z.string()).optional(),
484
+ items: z.array(
485
+ z.object({
486
+ email: z.string().optional(),
487
+ linkedin_url: z.string().optional(),
488
+ first_name: z.string().optional(),
489
+ last_name: z.string().optional(),
490
+ company: z.string().optional(),
491
+ company_domain: z.string().optional(),
492
+ title: z.string().optional(),
493
+ phone: z.string().optional(),
494
+ location: z.string().optional(),
495
+ custom_fields: z.record(z.unknown()).optional()
496
+ })
497
+ ).optional(),
498
+ enrichment_status: z.enum(["pending", "enriched", "failed", "skipped"]).optional(),
499
+ has_email: z.boolean().optional(),
500
+ has_linkedin: z.boolean().optional(),
501
+ search: z.string().optional(),
502
+ limit: z.number().int().min(1).max(1e3).optional(),
503
+ offset: z.number().int().min(0).optional(),
504
+ tenant_id: z.string().optional()
505
+ }),
506
+ // 20b. List management (backward compat alias)
507
+ manage_list: z.object({
508
+ action: z.enum(["create", "import_csv", "add", "query", "view", "stats", "lists", "delete"]),
509
+ list_id: z.string().uuid().optional(),
510
+ name: z.string().optional(),
511
+ description: z.string().optional(),
512
+ list_type: z.enum(["contacts", "companies", "mixed"]).optional(),
513
+ tags: z.array(z.string()).optional(),
514
+ client_id: z.string().optional(),
515
+ csv_path: z.string().optional(),
516
+ csv_text: z.string().optional(),
517
+ column_mapping: z.record(z.string()).optional(),
518
+ items: z.array(
519
+ z.object({
520
+ email: z.string().optional(),
521
+ linkedin_url: z.string().optional(),
522
+ first_name: z.string().optional(),
523
+ last_name: z.string().optional(),
524
+ company: z.string().optional(),
525
+ company_domain: z.string().optional(),
526
+ title: z.string().optional(),
527
+ phone: z.string().optional(),
528
+ location: z.string().optional(),
529
+ custom_fields: z.record(z.unknown()).optional()
530
+ })
531
+ ).optional(),
532
+ enrichment_status: z.enum(["pending", "enriched", "failed", "skipped"]).optional(),
533
+ has_email: z.boolean().optional(),
534
+ has_linkedin: z.boolean().optional(),
535
+ search: z.string().optional(),
536
+ limit: z.number().int().min(1).max(1e3).optional(),
537
+ offset: z.number().int().min(0).optional(),
538
+ tenant_id: z.string().optional()
539
+ }),
540
+ // 21. TAM waterfall discovery
541
+ build_tam: z.object({
542
+ icp_text: z.string(),
543
+ domains: z.array(z.string()).optional(),
544
+ budget_usd: z.number().optional(),
545
+ session: z.string().optional(),
546
+ providers: z.array(z.string()).optional(),
547
+ max_per_provider: z.number().optional(),
548
+ limit: z.number().optional(),
549
+ country: z.string().optional(),
550
+ min_employees: z.number().optional(),
551
+ max_employees: z.number().optional(),
552
+ tech_stack: z.array(z.string()).optional(),
553
+ category: z.string().optional(),
554
+ negate_domains: z.array(z.string()).optional(),
555
+ output: z.enum(["summary", "file", "inline"]).optional(),
556
+ dry_run: z.boolean().optional()
557
+ }),
558
+ // ─── DFY (Done-For-You) ──────────────────────────────────
559
+ dfy: z.object({
560
+ action: z.enum(["list", "status", "content", "pipeline", "diagnose", "queue"], {
561
+ message: "action must be one of: list, status, content, pipeline, diagnose, queue"
562
+ }),
563
+ engagement_id: z.string().optional(),
564
+ name: z.string().optional(),
565
+ status_filter: z.enum([
566
+ "pending_payment",
567
+ "onboarding",
568
+ "active",
569
+ "paused",
570
+ "completed",
571
+ "cancelled",
572
+ "churned"
573
+ ]).optional(),
574
+ engagement_type: z.enum(["intro_offer", "full_dfy"]).optional(),
575
+ tenant_id: z.string().optional()
576
+ }).refine(
577
+ (data) => {
578
+ if (data.action === "status" || data.action === "content" || data.action === "diagnose") {
579
+ return !!(data.engagement_id || data.name);
580
+ }
581
+ return true;
582
+ },
583
+ {
584
+ message: "engagement_id or name is required for status, content, and diagnose actions"
585
+ }
586
+ ),
587
+ // ─── Intel (Knowledge Graph) — consolidated action-based tool ─
588
+ intel: z.object({
589
+ action: z.enum([
590
+ "context",
591
+ "product",
592
+ "persona",
593
+ "get_persona",
594
+ "segment",
595
+ "proof",
596
+ "competitor",
597
+ "outcome",
598
+ "gaps",
599
+ "propose",
600
+ "ingest",
601
+ "ingest_linkedin",
602
+ "refresh_competitor",
603
+ "changelog",
604
+ "score"
605
+ ]),
606
+ // Context params
607
+ strategy: z.enum([
608
+ "call_prep",
609
+ "content_generation",
610
+ "lead_scoring",
611
+ "personalization",
612
+ "campaign_planning",
613
+ "general"
614
+ ]).optional(),
615
+ query: z.string().optional(),
616
+ // Entity shared params
617
+ name: z.string().optional(),
618
+ description: z.string().optional(),
619
+ // Product params
620
+ category: z.string().optional(),
621
+ value_proposition: z.string().optional(),
622
+ key_features: z.array(z.unknown()).optional(),
623
+ pricing_summary: z.string().optional(),
624
+ // Persona params
625
+ persona_id: z.string().uuid().optional(),
626
+ title_patterns: z.array(z.string()).optional(),
627
+ industries: z.array(z.string()).optional(),
628
+ company_size_min: z.number().int().min(0).optional(),
629
+ company_size_max: z.number().int().min(1).optional(),
630
+ pain_points: z.array(z.string()).optional(),
631
+ goals: z.array(z.string()).optional(),
632
+ objections: z.array(z.string()).optional(),
633
+ buying_signals: z.array(z.string()).optional(),
634
+ geographic_focus: z.array(z.string()).optional(),
635
+ budget_range: z.string().optional(),
636
+ is_primary: z.boolean().optional(),
637
+ // Segment params
638
+ qualification_criteria: z.unknown().optional(),
639
+ market_size_estimate: z.string().optional(),
640
+ // Proof params
641
+ type: z.enum(["case_study", "testimonial", "metric", "quote", "before_after"]).optional(),
642
+ title: z.string().optional(),
643
+ content: z.string().optional(),
644
+ metric_value: z.string().optional(),
645
+ source_type: z.string().optional(),
646
+ source_id: z.string().optional(),
647
+ product_id: z.string().uuid().optional(),
648
+ // Competitor params
649
+ website: z.string().optional(),
650
+ positioning: z.string().optional(),
651
+ strengths: z.array(z.string()).optional(),
652
+ weaknesses: z.array(z.string()).optional(),
653
+ differentiation_notes: z.string().optional(),
654
+ // Outcome params
655
+ outcome_type: z.enum([
656
+ "deal_won",
657
+ "deal_lost",
658
+ "meeting_booked",
659
+ "reply_positive",
660
+ "reply_negative",
661
+ "content_high_engagement",
662
+ "content_low_engagement",
663
+ "campaign_result"
664
+ ]).optional(),
665
+ entity_type: z.string().optional(),
666
+ entity_id: z.string().optional(),
667
+ detail: z.string().optional(),
668
+ metrics: z.record(z.unknown()).optional(),
669
+ occurred_at: z.string().optional(),
670
+ // Propose params
671
+ min_entries_per_topic: z.number().int().min(1).optional(),
672
+ max_clusters: z.number().int().min(1).optional(),
673
+ // Ingest params
674
+ filename: z.string().optional(),
675
+ document_type: z.string().optional(),
676
+ // LinkedIn ingest params
677
+ linkedin_url: z.string().optional(),
678
+ include_posts: z.boolean().optional(),
679
+ // Refresh competitor params
680
+ competitor_name: z.string().optional(),
681
+ search_query: z.string().optional(),
682
+ // Changelog params
683
+ limit: z.number().int().min(1).max(200).optional(),
684
+ source: z.string().optional(),
685
+ // Score params
686
+ headline: z.string().optional(),
687
+ location: z.string().optional(),
688
+ company_name: z.string().optional(),
689
+ company_size: z.string().optional(),
690
+ industry: z.string().optional(),
691
+ base_score: z.number().min(0).max(100).optional(),
692
+ // Ownership (shared)
693
+ owner_id: z.string().optional(),
694
+ owner_type: z.enum(["user", "tenant"]).optional()
695
+ }).refine(
696
+ (data) => {
697
+ if (data.action === "context") return !!data.strategy;
698
+ if (data.action === "product" || data.action === "persona" || data.action === "segment" || data.action === "competitor")
699
+ return !!data.name;
700
+ if (data.action === "proof") return !!data.type && !!data.title && !!data.content;
701
+ if (data.action === "outcome")
702
+ return !!data.outcome_type && !!data.entity_type && !!data.entity_id;
703
+ if (data.action === "ingest") return !!data.filename;
704
+ if (data.action === "ingest_linkedin") return !!data.linkedin_url;
705
+ return true;
706
+ },
707
+ {
708
+ message: "Missing required fields for this action. context requires strategy; product/persona/segment/competitor require name; proof requires type+title+content; outcome requires outcome_type+entity_type+entity_id; ingest requires filename; ingest_linkedin requires linkedin_url."
709
+ }
710
+ ),
711
+ // ─── App Tools ─────────────────────────────────────────
712
+ // Lead magnet CRUD + sequences + launch (absorbs: email_sequence, launch)
713
+ magnet: z.object({
714
+ action: z.enum(
715
+ [
716
+ "list",
717
+ "get",
718
+ "create",
719
+ "update",
720
+ "delete",
721
+ "publish",
722
+ "get_sequence",
723
+ "save_sequence",
724
+ "activate_sequence",
725
+ "launch",
726
+ "schedule_week"
727
+ ],
728
+ {
729
+ message: "action must be one of: list, get, create, update, delete, publish, get_sequence, save_sequence, activate_sequence, launch, schedule_week"
730
+ }
731
+ ),
732
+ id: z.string().optional(),
733
+ title: z.string().optional(),
734
+ archetype: z.enum([
735
+ "single-breakdown",
736
+ "single-system",
737
+ "focused-toolkit",
738
+ "single-calculator",
739
+ "focused-directory",
740
+ "mini-training",
741
+ "one-story",
742
+ "prompt",
743
+ "assessment",
744
+ "workflow"
745
+ ]).optional(),
746
+ content: z.record(z.unknown()).optional(),
747
+ status: z.enum(["draft", "published", "archived"]).optional(),
748
+ limit: z.number().int().min(1).max(100).optional(),
749
+ offset: z.number().int().min(0).optional(),
750
+ team_id: z.string().optional(),
751
+ // ─── Sequence params (absorbed from email_sequence) ─────
752
+ emails: z.array(
753
+ z.object({
754
+ day: z.number(),
755
+ subject: z.string(),
756
+ body: z.string()
757
+ })
758
+ ).optional(),
759
+ // ─── Launch params (absorbed from launch) ───────────────
760
+ slug: z.string().optional(),
761
+ funnel_theme: z.enum(["dark", "light", "modern"]).optional(),
762
+ email_sequence: z.record(z.unknown()).optional(),
763
+ // ─── Schedule week params (absorbed from launch) ────────
764
+ posts: z.array(
765
+ z.object({
766
+ body: z.string().min(1, "body is required"),
767
+ title: z.string().optional(),
768
+ pillar: z.string().optional(),
769
+ content_type: z.string().optional()
770
+ })
771
+ ).optional(),
772
+ week_start: z.string().optional()
773
+ }).refine(
774
+ (data) => {
775
+ if (data.action === "save_sequence") return !!(data.id && data.emails?.length);
776
+ if (data.action === "get_sequence" || data.action === "activate_sequence") {
777
+ return !!data.id;
778
+ }
779
+ if (data.action === "launch") return !!data.title;
780
+ return true;
781
+ },
782
+ {
783
+ message: "Sequence actions require id; save_sequence requires id + emails; launch requires title"
784
+ }
785
+ ),
786
+ // Funnel management
787
+ funnel: z.object({
788
+ action: z.enum(
789
+ [
790
+ "list",
791
+ "get",
792
+ "create",
793
+ "update",
794
+ "delete",
795
+ "publish",
796
+ "unpublish",
797
+ "list_forms",
798
+ "get_form",
799
+ "get_questions"
800
+ ],
801
+ {
802
+ message: "action must be one of: list, get, create, update, delete, publish, unpublish, list_forms, get_form, get_questions"
803
+ }
804
+ ),
805
+ id: z.string().optional(),
806
+ lead_magnet_id: z.string().optional(),
807
+ theme: z.enum(["dark", "light", "modern"]).optional(),
808
+ content: z.record(z.unknown()).optional(),
809
+ // Updatable funnel fields
810
+ optinSubline: z.string().optional(),
811
+ optinSocialProof: z.string().optional(),
812
+ thankyouSubline: z.string().optional(),
813
+ qualificationFormId: z.string().optional(),
814
+ vslUrl: z.string().optional(),
815
+ calendlyUrl: z.string().optional(),
816
+ qualificationPassMessage: z.string().optional(),
817
+ qualificationFailMessage: z.string().optional(),
818
+ // Qualification form params
819
+ form_id: z.string().optional(),
820
+ team_id: z.string().optional()
821
+ }),
822
+ // Unified post tool — CRUD + generation + formats
823
+ post: z.object({
824
+ action: z.enum(
825
+ [
826
+ "list",
827
+ "get",
828
+ "create",
829
+ "update",
830
+ "delete",
831
+ "publish",
832
+ "publish_linkedin",
833
+ "list_accounts",
834
+ "generate",
835
+ "queue_list",
836
+ "queue_update",
837
+ "queue_submit",
838
+ "formats",
839
+ "ingredients",
840
+ "recipes",
841
+ "trends",
842
+ "performance"
843
+ ],
844
+ {
845
+ message: "action must be one of: list, get, create, update, delete, publish, publish_linkedin, list_accounts, generate, queue_list, queue_update, queue_submit, formats, ingredients, recipes, trends, performance"
846
+ }
847
+ ),
848
+ id: z.string().optional(),
849
+ body: z.string().optional(),
850
+ title: z.string().optional(),
851
+ pillar: z.string().optional(),
852
+ content_type: z.string().optional(),
853
+ status: z.string().optional(),
854
+ limit: z.number().int().min(1).max(100).optional(),
855
+ offset: z.number().int().min(0).optional(),
856
+ account_id: z.string().optional(),
857
+ exploit_id: z.string().optional(),
858
+ knowledge_topic: z.string().optional(),
859
+ knowledge_query: z.string().optional(),
860
+ knowledge_ids: z.array(z.string()).optional(),
861
+ style_id: z.string().optional(),
862
+ template_id: z.string().optional(),
863
+ creative_id: z.string().optional(),
864
+ trend_topic: z.string().optional(),
865
+ hook: z.string().optional(),
866
+ instructions: z.string().optional(),
867
+ count: z.number().int().min(1).max(10).optional(),
868
+ output: z.enum(["drafts", "ideas"]).optional(),
869
+ category: z.enum(["regular_post", "lead_magnet"]).optional(),
870
+ with_stats: z.boolean().optional(),
871
+ team_id: z.string().optional()
872
+ }),
873
+ // Email sequence management
874
+ email_sequence: z.object({
875
+ action: z.enum(["get", "save", "activate"], {
876
+ message: "action must be one of: get, save, activate"
877
+ }),
878
+ lead_magnet_id: z.string().min(1, "lead_magnet_id is required"),
879
+ emails: z.array(
880
+ z.object({
881
+ day: z.number(),
882
+ subject: z.string(),
883
+ body: z.string()
884
+ })
885
+ ).optional(),
886
+ team_id: z.string().optional()
887
+ }),
888
+ // Leads captured by lead magnets
889
+ leads: z.object({
890
+ action: z.enum(["list", "get", "export"], {
891
+ message: "action must be one of: list, get, export"
892
+ }),
893
+ id: z.string().optional(),
894
+ lead_magnet_id: z.string().optional(),
895
+ status: z.string().optional(),
896
+ limit: z.number().int().min(1).max(1e3).optional(),
897
+ offset: z.number().int().min(0).optional(),
898
+ format: z.enum(["csv", "json"]).optional(),
899
+ team_id: z.string().optional()
900
+ }),
901
+ // Performance analytics
902
+ analytics: z.object({
903
+ action: z.enum(["insights", "recommendations"], {
904
+ message: "action must be one of: insights, recommendations"
905
+ }),
906
+ team_id: z.string().optional()
907
+ }),
908
+ // Knowledge base search, Q&A, and transcript ingestion
909
+ knowledge: z.object({
910
+ action: z.enum(["search", "browse", "clusters", "ask", "submit"], {
911
+ message: "action must be one of: search, browse, clusters, ask, submit"
912
+ }),
913
+ query: z.string().optional(),
914
+ question: z.string().optional(),
915
+ transcript: z.string().min(100, "transcript must be at least 100 characters").optional(),
916
+ title: z.string().optional(),
917
+ category: z.enum(["insight", "question", "product_intel"]).optional(),
918
+ type: z.string().optional(),
919
+ tag: z.string().optional(),
920
+ min_quality: z.number().min(1).max(5).optional(),
921
+ limit: z.number().int().min(1).max(100).optional(),
922
+ team_id: z.string().optional()
923
+ }),
924
+ // Content generation by combining ingredients
925
+ mixer: z.object({
926
+ action: z.enum(["mix", "inventory", "recipes", "performance"], {
927
+ message: "action must be one of: mix, inventory, recipes, performance"
928
+ }),
929
+ team_profile_id: z.string().optional(),
930
+ exploit_id: z.string().optional(),
931
+ knowledge_topic: z.string().optional(),
932
+ knowledge_query: z.string().optional(),
933
+ style_id: z.string().optional(),
934
+ template_id: z.string().optional(),
935
+ creative_id: z.string().optional(),
936
+ trend_topic: z.string().optional(),
937
+ hook: z.string().optional(),
938
+ instructions: z.string().optional(),
939
+ count: z.number().int().min(1).max(10).optional(),
940
+ output: z.enum(["drafts", "ideas"]).optional(),
941
+ limit: z.number().int().min(1).max(100).optional()
942
+ }),
943
+ // AI-powered LinkedIn DM conversation coaching (renamed from dm_coach)
944
+ dm: z.object({
945
+ action: z.enum(["suggest", "list", "get", "create", "update", "delete", "messages"], {
946
+ message: "action must be one of: suggest, list, get, create, update, delete, messages"
947
+ }),
948
+ id: z.string().optional(),
949
+ name: z.string().optional(),
950
+ linkedin_url: z.string().optional(),
951
+ headline: z.string().optional(),
952
+ company: z.string().optional(),
953
+ conversation_goal: z.enum([
954
+ "book_meeting",
955
+ "build_relationship",
956
+ "promote_content",
957
+ "explore_partnership",
958
+ "nurture_lead",
959
+ "close_deal"
960
+ ]).optional(),
961
+ status: z.enum(["active", "paused", "closed_won", "closed_lost"]).optional(),
962
+ messages: z.array(
963
+ z.object({
964
+ role: z.enum(["them", "me"]),
965
+ content: z.string().min(1),
966
+ timestamp: z.string().optional()
967
+ })
968
+ ).optional(),
969
+ notes: z.string().optional(),
970
+ search: z.string().optional(),
971
+ team_id: z.string().optional()
972
+ }),
973
+ // AI-powered LinkedIn DM conversation coaching (backward compat alias)
974
+ dm_coach: z.object({
975
+ action: z.enum(["suggest", "list", "get", "create", "update", "delete", "messages"], {
976
+ message: "action must be one of: suggest, list, get, create, update, delete, messages"
977
+ }),
978
+ id: z.string().optional(),
979
+ name: z.string().optional(),
980
+ linkedin_url: z.string().optional(),
981
+ headline: z.string().optional(),
982
+ company: z.string().optional(),
983
+ conversation_goal: z.enum([
984
+ "book_meeting",
985
+ "build_relationship",
986
+ "promote_content",
987
+ "explore_partnership",
988
+ "nurture_lead",
989
+ "close_deal"
990
+ ]).optional(),
991
+ status: z.enum(["active", "paused", "closed_won", "closed_lost"]).optional(),
992
+ messages: z.array(
993
+ z.object({
994
+ role: z.enum(["them", "me"]),
995
+ content: z.string().min(1),
996
+ timestamp: z.string().optional()
997
+ })
998
+ ).optional(),
999
+ notes: z.string().optional(),
1000
+ search: z.string().optional(),
1001
+ team_id: z.string().optional()
1002
+ }),
1003
+ // Multi-step orchestration for content creation and publishing
1004
+ launch: z.object({
1005
+ action: z.enum(["magnet", "schedule_week"], {
1006
+ message: "action must be one of: magnet, schedule_week"
1007
+ }),
1008
+ title: z.string().optional(),
1009
+ archetype: z.enum([
1010
+ "single-breakdown",
1011
+ "single-system",
1012
+ "focused-toolkit",
1013
+ "single-calculator",
1014
+ "focused-directory",
1015
+ "mini-training",
1016
+ "one-story",
1017
+ "prompt",
1018
+ "assessment",
1019
+ "workflow"
1020
+ ]).optional(),
1021
+ content: z.record(z.unknown()).optional(),
1022
+ slug: z.string().optional(),
1023
+ funnel_theme: z.enum(["dark", "light", "modern"]).optional(),
1024
+ email_sequence: z.record(z.unknown()).optional(),
1025
+ posts: z.array(
1026
+ z.object({
1027
+ body: z.string().min(1, "body is required"),
1028
+ title: z.string().optional(),
1029
+ pillar: z.string().optional(),
1030
+ content_type: z.string().optional()
1031
+ })
1032
+ ).optional(),
1033
+ week_start: z.string().optional(),
1034
+ team_id: z.string().optional()
1035
+ }),
1036
+ // Proven LinkedIn post format generation
1037
+ exploit: z.object({
1038
+ action: z.enum(["list", "generate", "trends"], {
1039
+ message: "action must be one of: list, generate, trends"
1040
+ }),
1041
+ category: z.enum(["regular_post", "lead_magnet"]).optional(),
1042
+ with_stats: z.boolean().optional(),
1043
+ exploit_id: z.string().optional(),
1044
+ creative_id: z.string().optional(),
1045
+ knowledge_ids: z.array(z.string()).optional(),
1046
+ template_id: z.string().optional(),
1047
+ style_id: z.string().optional(),
1048
+ hook: z.string().optional(),
1049
+ instructions: z.string().optional(),
1050
+ limit: z.number().int().min(1).max(100).optional()
1051
+ }),
1052
+ // ─── New App Tools (Phase 3) ────────────────────────────
1053
+ // App-managed LinkedIn outreach campaigns
1054
+ outreach: z.object({
1055
+ action: z.enum(
1056
+ ["list", "get", "create", "update", "activate", "pause", "delete", "add_leads"],
1057
+ {
1058
+ message: "action must be one of: list, get, create, update, activate, pause, delete, add_leads"
1059
+ }
1060
+ ),
1061
+ id: z.string().optional(),
1062
+ name: z.string().optional(),
1063
+ message_template: z.string().optional(),
1064
+ follow_up_template: z.string().optional(),
1065
+ follow_up_delay_days: z.number().int().min(1).optional(),
1066
+ leads: z.array(
1067
+ z.object({
1068
+ linkedin_url: z.string().min(1, "linkedin_url is required"),
1069
+ first_name: z.string().optional(),
1070
+ last_name: z.string().optional(),
1071
+ company: z.string().optional(),
1072
+ headline: z.string().optional()
1073
+ })
1074
+ ).optional(),
1075
+ team_id: z.string().optional()
1076
+ }).refine(
1077
+ (data) => {
1078
+ if (["get", "update", "activate", "pause", "delete", "add_leads"].includes(data.action)) {
1079
+ return !!data.id;
1080
+ }
1081
+ return true;
1082
+ },
1083
+ { message: "id is required for get, update, activate, pause, delete, and add_leads actions" }
1084
+ ),
1085
+ // Swipe file management for content generation
1086
+ creative: z.object({
1087
+ action: z.enum(["list", "create", "scan", "configure_sources"], {
1088
+ message: "action must be one of: list, create, scan, configure_sources"
1089
+ }),
1090
+ url: z.string().optional(),
1091
+ body: z.string().optional(),
1092
+ source: z.string().optional(),
1093
+ tags: z.array(z.string()).optional(),
1094
+ sources: z.array(
1095
+ z.object({
1096
+ type: z.string().min(1),
1097
+ url: z.string().min(1)
1098
+ })
1099
+ ).optional(),
1100
+ limit: z.number().int().min(1).max(100).optional(),
1101
+ team_id: z.string().optional()
1102
+ }),
1103
+ // Account safety settings for LinkedIn
1104
+ safety: z.object({
1105
+ action: z.enum(["get", "update"], {
1106
+ message: "action must be one of: get, update"
1107
+ }),
1108
+ account_id: z.string().min(1, "account_id is required"),
1109
+ daily_connection_limit: z.number().int().min(0).optional(),
1110
+ daily_message_limit: z.number().int().min(0).optional(),
1111
+ daily_view_limit: z.number().int().min(0).optional(),
1112
+ cooldown_minutes: z.number().int().min(0).optional(),
1113
+ risk_level: z.enum(["conservative", "moderate", "aggressive"]).optional(),
1114
+ team_id: z.string().optional()
1115
+ }),
1116
+ // ─── Mode Switching ─────────────────────────────────────
1117
+ switch_mode: z.object({
1118
+ profile: z.enum(["core", "discover", "create", "campaign", "intel", "manage", "full"]),
1119
+ show: z.boolean().optional()
1120
+ })
1121
+ };
1122
+ var TOOL_NAMES = Object.keys(toolSchemas);
1123
+ function validateToolArgs(toolName, args) {
1124
+ const schema = toolSchemas[toolName];
1125
+ if (!schema) {
1126
+ return { success: false, error: `Unknown tool: "${toolName}"` };
1127
+ }
1128
+ const result = schema.safeParse(args);
1129
+ if (!result.success) {
1130
+ const issues = result.error.issues || [];
1131
+ const errors = issues.map(
1132
+ (e) => e.path.length > 0 ? `${e.path.join(".")}: ${e.message}` : e.message
1133
+ ).join(", ");
1134
+ return { success: false, error: errors || "Validation failed" };
1135
+ }
1136
+ return { success: true, data: result.data };
1137
+ }
1138
+
1139
+ export {
1140
+ toolSchemas,
1141
+ TOOL_NAMES,
1142
+ validateToolArgs
1143
+ };
1144
+ //# sourceMappingURL=chunk-I6GRD4X7.js.map