@elevasis/sdk 1.17.0 → 1.19.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/dist/index.js CHANGED
@@ -37,15 +37,15 @@ var ToolingError = class extends ExecutionError {
37
37
  this.details = details;
38
38
  }
39
39
  };
40
- z.string().uuid();
41
- z.string().trim().min(1).max(1e3);
40
+ var UuidSchema = z.string().uuid();
41
+ var NonEmptyStringSchema = z.string().trim().min(1).max(1e3);
42
42
  z.enum(["agent", "workflow"]);
43
43
  z.enum(["agent", "workflow", "scheduler", "api"]);
44
44
  z.string().trim().toLowerCase().min(1, "Credential name required").max(100, "Credential name too long (max 100 chars)").regex(
45
45
  /^[a-z0-9]+(-[a-z0-9]+)+$/,
46
46
  "Credential name must be lowercase letters, numbers, and hyphens in format: service-environment (e.g., gmail-prod, attio-dev)"
47
47
  );
48
- z.enum(["google-sheets", "dropbox"]);
48
+ z.enum(["google-sheets", "google-calendar", "dropbox"]);
49
49
  z.string().min(10, "Authorization code too short").max(1e3, "Authorization code too long");
50
50
  z.string().min(10, "State parameter too short").max(2048, "State parameter too long");
51
51
  z.string().trim().transform((str) => str.replace(/[<>'"]/g, ""));
@@ -62,6 +62,7 @@ z.object({
62
62
  });
63
63
  var ORGANIZATION_MODEL_ICON_TOKENS = [
64
64
  "nav.dashboard",
65
+ "nav.calendar",
65
66
  "nav.sales",
66
67
  "nav.crm",
67
68
  "nav.lead-gen",
@@ -76,6 +77,7 @@ var ORGANIZATION_MODEL_ICON_TOKENS = [
76
77
  "knowledge.strategy",
77
78
  "knowledge.reference",
78
79
  "feature.dashboard",
80
+ "feature.calendar",
79
81
  "feature.sales",
80
82
  "feature.crm",
81
83
  "feature.finance",
@@ -99,6 +101,7 @@ var ORGANIZATION_MODEL_ICON_TOKENS = [
99
101
  "integration.google-sheets",
100
102
  "integration.attio",
101
103
  "surface.dashboard",
104
+ "surface.calendar",
102
105
  "surface.overview",
103
106
  "surface.command-view",
104
107
  "surface.command-queue",
@@ -195,13 +198,468 @@ z.object({
195
198
  pipelines: z.array(SalesPipelineSchema).min(1)
196
199
  });
197
200
  var CRM_DISCOVERY_REPLIED_STATE = {
198
- stateKey: "discovery_replied"};
201
+ stateKey: "discovery_replied",
202
+ label: "Discovery Replied"
203
+ };
199
204
  var CRM_DISCOVERY_LINK_SENT_STATE = {
200
- stateKey: "discovery_link_sent"};
205
+ stateKey: "discovery_link_sent",
206
+ label: "Discovery Link Sent"
207
+ };
201
208
  var CRM_DISCOVERY_NUDGING_STATE = {
202
- stateKey: "discovery_nudging"};
209
+ stateKey: "discovery_nudging",
210
+ label: "Discovery Nudging"
211
+ };
203
212
  var CRM_DISCOVERY_BOOKING_CANCELLED_STATE = {
204
- stateKey: "discovery_booking_cancelled"};
213
+ stateKey: "discovery_booking_cancelled",
214
+ label: "Discovery Booking Cancelled"
215
+ };
216
+ var CRM_REPLY_SENT_STATE = {
217
+ stateKey: "reply_sent",
218
+ label: "Reply Sent"
219
+ };
220
+ var CRM_FOLLOWUP_1_SENT_STATE = {
221
+ stateKey: "followup_1_sent",
222
+ label: "Follow-up 1 Sent"
223
+ };
224
+ var CRM_FOLLOWUP_2_SENT_STATE = {
225
+ stateKey: "followup_2_sent",
226
+ label: "Follow-up 2 Sent"
227
+ };
228
+ var CRM_FOLLOWUP_3_SENT_STATE = {
229
+ stateKey: "followup_3_sent",
230
+ label: "Follow-up 3 Sent"
231
+ };
232
+ var CRM_PIPELINE_DEFINITION = {
233
+ pipelineKey: "crm",
234
+ label: "CRM",
235
+ entityKey: "crm.deal",
236
+ stages: [
237
+ {
238
+ stageKey: "interested",
239
+ label: "Interested",
240
+ color: "blue",
241
+ states: [
242
+ CRM_DISCOVERY_REPLIED_STATE,
243
+ CRM_DISCOVERY_LINK_SENT_STATE,
244
+ CRM_DISCOVERY_NUDGING_STATE,
245
+ CRM_DISCOVERY_BOOKING_CANCELLED_STATE,
246
+ CRM_REPLY_SENT_STATE,
247
+ CRM_FOLLOWUP_1_SENT_STATE,
248
+ CRM_FOLLOWUP_2_SENT_STATE,
249
+ CRM_FOLLOWUP_3_SENT_STATE
250
+ ]
251
+ },
252
+ { stageKey: "proposal", label: "Proposal", color: "yellow", states: [] },
253
+ { stageKey: "closing", label: "Closing", color: "orange", states: [] },
254
+ { stageKey: "closed_won", label: "Closed Won", color: "green", states: [] },
255
+ { stageKey: "closed_lost", label: "Closed Lost", color: "red", states: [] },
256
+ { stageKey: "nurturing", label: "Nurturing", color: "grape", states: [] }
257
+ ]
258
+ };
259
+ var LEAD_GEN_STAGE_CATALOG = {
260
+ // Prospecting — company population
261
+ scraped: {
262
+ key: "scraped",
263
+ label: "Scraped",
264
+ description: "Company was scraped from a source directory (Apify actor run).",
265
+ order: 1,
266
+ entity: "company"
267
+ },
268
+ populated: {
269
+ key: "populated",
270
+ label: "Companies found",
271
+ description: "Companies have been found and added to the lead-gen list.",
272
+ order: 2,
273
+ entity: "company"
274
+ },
275
+ extracted: {
276
+ key: "extracted",
277
+ label: "Websites analyzed",
278
+ description: "Company websites have been analyzed for business signals.",
279
+ order: 3,
280
+ entity: "company"
281
+ },
282
+ enriched: {
283
+ key: "enriched",
284
+ label: "Enriched",
285
+ description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
286
+ order: 4,
287
+ entity: "company"
288
+ },
289
+ "decision-makers-enriched": {
290
+ key: "decision-makers-enriched",
291
+ label: "Decision-makers found",
292
+ description: "Decision-maker contacts discovered and attached to a qualified company.",
293
+ order: 6,
294
+ entity: "company"
295
+ },
296
+ // Prospecting — contact discovery
297
+ discovered: {
298
+ key: "discovered",
299
+ label: "Decision-makers found",
300
+ description: "Decision-maker contact details have been found.",
301
+ order: 5,
302
+ entity: "contact"
303
+ },
304
+ verified: {
305
+ key: "verified",
306
+ label: "Emails verified",
307
+ description: "Contact email addresses have been checked for deliverability.",
308
+ order: 7,
309
+ entity: "contact"
310
+ },
311
+ // Qualification
312
+ qualified: {
313
+ key: "qualified",
314
+ label: "Companies qualified",
315
+ description: "Companies have been scored against the qualification criteria.",
316
+ order: 8,
317
+ entity: "company"
318
+ },
319
+ // Outreach
320
+ personalized: {
321
+ key: "personalized",
322
+ label: "Personalized",
323
+ description: "Outreach message personalized for the contact (Instantly personalization workflow).",
324
+ order: 9,
325
+ entity: "contact"
326
+ },
327
+ uploaded: {
328
+ key: "uploaded",
329
+ label: "Reviewed and exported",
330
+ description: "Approved records have been reviewed and exported for handoff.",
331
+ order: 10,
332
+ entity: "contact"
333
+ },
334
+ interested: {
335
+ key: "interested",
336
+ label: "Interested",
337
+ description: "Contact replied with a positive signal (Instantly reply-handler transition).",
338
+ order: 11,
339
+ entity: "contact"
340
+ }
341
+ };
342
+ var ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
343
+ id: ModelIdSchema,
344
+ order: z.number().int().min(0)
345
+ });
346
+ var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
347
+ id: ModelIdSchema,
348
+ primaryEntity: z.enum(["company", "contact"]),
349
+ outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
350
+ stageKey: ModelIdSchema,
351
+ dependsOn: z.array(ModelIdSchema).optional(),
352
+ dependencyMode: z.literal("per-record-eligibility"),
353
+ capabilityKey: ModelIdSchema,
354
+ defaultBatchSize: z.number().int().positive(),
355
+ maxBatchSize: z.number().int().positive()
356
+ }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
357
+ message: "defaultBatchSize must be less than or equal to maxBatchSize",
358
+ path: ["defaultBatchSize"]
359
+ });
360
+ var ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
361
+ id: ModelIdSchema,
362
+ steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
363
+ });
364
+ z.object({
365
+ id: ModelIdSchema,
366
+ label: z.string(),
367
+ description: z.string(),
368
+ resourceId: ModelIdSchema
369
+ });
370
+ var CAPABILITY_REGISTRY = [
371
+ {
372
+ id: "lead-gen.company.source",
373
+ label: "Source companies",
374
+ description: "Import source companies from a list provider.",
375
+ resourceId: "lgn-import-workflow"
376
+ },
377
+ {
378
+ id: "lead-gen.company.apollo-import",
379
+ label: "Import from Apollo",
380
+ description: "Pull companies and seed contact data from an Apollo search or list.",
381
+ resourceId: "lgn-01c-apollo-import-workflow"
382
+ },
383
+ {
384
+ id: "lead-gen.contact.discover",
385
+ label: "Discover contact emails",
386
+ description: "Find email addresses for contacts at qualified companies.",
387
+ resourceId: "lgn-04-email-discovery-workflow"
388
+ },
389
+ {
390
+ id: "lead-gen.contact.verify-email",
391
+ label: "Verify emails",
392
+ description: "Check email deliverability before outreach.",
393
+ resourceId: "lgn-05-email-verification-workflow"
394
+ },
395
+ {
396
+ id: "lead-gen.company.website-extract",
397
+ label: "Extract website signals",
398
+ description: "Scrape and analyze company websites for qualification signals.",
399
+ resourceId: "lgn-02-website-extract-workflow"
400
+ },
401
+ {
402
+ id: "lead-gen.company.qualify",
403
+ label: "Qualify companies",
404
+ description: "Score and filter companies against the ICP rubric.",
405
+ resourceId: "lgn-03-company-qualification-workflow"
406
+ },
407
+ {
408
+ id: "lead-gen.company.dtc-subscription-qualify",
409
+ label: "Qualify DTC subscription fit",
410
+ description: "Classify subscription potential and consumable-product fit for DTC brands.",
411
+ resourceId: "lgn-03b-dtc-subscription-score-workflow"
412
+ },
413
+ {
414
+ id: "lead-gen.contact.apollo-decision-maker-enrich",
415
+ label: "Enrich decision-makers",
416
+ description: "Find and enrich qualified contacts at qualified companies via Apollo.",
417
+ resourceId: "lgn-04b-apollo-decision-maker-enrich-workflow"
418
+ },
419
+ {
420
+ id: "lead-gen.contact.personalize",
421
+ label: "Personalize outreach",
422
+ description: "Generate personalized opening lines for each contact.",
423
+ resourceId: "ist-personalization-workflow"
424
+ },
425
+ {
426
+ id: "lead-gen.review.outreach-ready",
427
+ label: "Upload to outreach",
428
+ description: "Upload approved contacts to the outreach sequence after QC review.",
429
+ resourceId: "ist-upload-contacts-workflow"
430
+ },
431
+ {
432
+ id: "lead-gen.export.list",
433
+ label: "Export lead list",
434
+ description: "Export approved leads as a downloadable lead list.",
435
+ resourceId: "lgn-06-export-list-workflow"
436
+ },
437
+ {
438
+ id: "lead-gen.company.cleanup",
439
+ label: "Clean up companies",
440
+ description: "Remove disqualified or duplicate companies from the list.",
441
+ resourceId: "lgn-company-cleanup-workflow"
442
+ }
443
+ ];
444
+ var PROSPECTING_STEPS = {
445
+ localServices: {
446
+ sourceCompanies: {
447
+ id: "source-companies",
448
+ label: "Companies found",
449
+ primaryEntity: "company",
450
+ outputs: ["company"],
451
+ stageKey: "populated",
452
+ dependencyMode: "per-record-eligibility",
453
+ capabilityKey: "lead-gen.company.source",
454
+ defaultBatchSize: 100,
455
+ maxBatchSize: 250
456
+ },
457
+ analyzeWebsites: {
458
+ id: "analyze-websites",
459
+ label: "Websites analyzed",
460
+ primaryEntity: "company",
461
+ outputs: ["company"],
462
+ stageKey: "extracted",
463
+ dependsOn: ["source-companies"],
464
+ dependencyMode: "per-record-eligibility",
465
+ capabilityKey: "lead-gen.company.website-extract",
466
+ defaultBatchSize: 50,
467
+ maxBatchSize: 100
468
+ },
469
+ qualifyCompanies: {
470
+ id: "qualify-companies",
471
+ label: "Companies qualified",
472
+ primaryEntity: "company",
473
+ outputs: ["company"],
474
+ stageKey: "qualified",
475
+ dependsOn: ["analyze-websites"],
476
+ dependencyMode: "per-record-eligibility",
477
+ capabilityKey: "lead-gen.company.qualify",
478
+ defaultBatchSize: 100,
479
+ maxBatchSize: 250
480
+ },
481
+ findContacts: {
482
+ id: "find-contacts",
483
+ label: "Decision-makers found",
484
+ primaryEntity: "contact",
485
+ outputs: ["contact"],
486
+ stageKey: "discovered",
487
+ dependsOn: ["qualify-companies"],
488
+ dependencyMode: "per-record-eligibility",
489
+ capabilityKey: "lead-gen.contact.discover",
490
+ defaultBatchSize: 50,
491
+ maxBatchSize: 100
492
+ },
493
+ verifyEmails: {
494
+ id: "verify-emails",
495
+ label: "Emails verified",
496
+ primaryEntity: "contact",
497
+ outputs: ["contact"],
498
+ stageKey: "verified",
499
+ dependsOn: ["find-contacts"],
500
+ dependencyMode: "per-record-eligibility",
501
+ capabilityKey: "lead-gen.contact.verify-email",
502
+ defaultBatchSize: 100,
503
+ maxBatchSize: 500
504
+ },
505
+ personalize: {
506
+ id: "personalize",
507
+ label: "Personalize",
508
+ primaryEntity: "contact",
509
+ outputs: ["contact"],
510
+ stageKey: "personalized",
511
+ dependsOn: ["verify-emails"],
512
+ dependencyMode: "per-record-eligibility",
513
+ capabilityKey: "lead-gen.contact.personalize",
514
+ defaultBatchSize: 25,
515
+ maxBatchSize: 100
516
+ },
517
+ review: {
518
+ id: "review",
519
+ label: "Reviewed and exported",
520
+ primaryEntity: "contact",
521
+ outputs: ["export"],
522
+ stageKey: "uploaded",
523
+ dependsOn: ["personalize"],
524
+ dependencyMode: "per-record-eligibility",
525
+ capabilityKey: "lead-gen.review.outreach-ready",
526
+ defaultBatchSize: 25,
527
+ maxBatchSize: 100
528
+ }
529
+ },
530
+ dtcApolloClickup: {
531
+ importApolloSearch: {
532
+ id: "import-apollo-search",
533
+ label: "Companies found",
534
+ description: "Pull companies and seed contact data from a predefined Apollo search or list.",
535
+ primaryEntity: "company",
536
+ outputs: ["company", "contact"],
537
+ stageKey: "populated",
538
+ dependencyMode: "per-record-eligibility",
539
+ capabilityKey: "lead-gen.company.apollo-import",
540
+ defaultBatchSize: 250,
541
+ maxBatchSize: 1e3
542
+ },
543
+ analyzeWebsites: {
544
+ id: "analyze-websites",
545
+ label: "Websites analyzed",
546
+ description: "Extract subscription, product, retention, and tech-stack signals from each brand website.",
547
+ primaryEntity: "company",
548
+ outputs: ["company"],
549
+ stageKey: "extracted",
550
+ dependsOn: ["import-apollo-search"],
551
+ dependencyMode: "per-record-eligibility",
552
+ capabilityKey: "lead-gen.company.website-extract",
553
+ defaultBatchSize: 50,
554
+ maxBatchSize: 100
555
+ },
556
+ scoreDtcFit: {
557
+ id: "score-dtc-fit",
558
+ label: "Companies qualified",
559
+ description: "Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.",
560
+ primaryEntity: "company",
561
+ outputs: ["company"],
562
+ stageKey: "qualified",
563
+ dependsOn: ["analyze-websites"],
564
+ dependencyMode: "per-record-eligibility",
565
+ capabilityKey: "lead-gen.company.dtc-subscription-qualify",
566
+ defaultBatchSize: 100,
567
+ maxBatchSize: 250
568
+ },
569
+ enrichDecisionMakers: {
570
+ id: "enrich-decision-makers",
571
+ label: "Decision-makers found",
572
+ description: "Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.",
573
+ primaryEntity: "company",
574
+ outputs: ["contact"],
575
+ stageKey: "decision-makers-enriched",
576
+ dependsOn: ["score-dtc-fit"],
577
+ dependencyMode: "per-record-eligibility",
578
+ capabilityKey: "lead-gen.contact.apollo-decision-maker-enrich",
579
+ defaultBatchSize: 100,
580
+ maxBatchSize: 250
581
+ },
582
+ verifyEmails: {
583
+ id: "verify-emails",
584
+ label: "Emails verified",
585
+ description: "Verify deliverability before the QC and handoff step.",
586
+ primaryEntity: "contact",
587
+ outputs: ["contact"],
588
+ stageKey: "verified",
589
+ dependsOn: ["enrich-decision-makers"],
590
+ dependencyMode: "per-record-eligibility",
591
+ capabilityKey: "lead-gen.contact.verify-email",
592
+ defaultBatchSize: 250,
593
+ maxBatchSize: 500
594
+ },
595
+ reviewAndExport: {
596
+ id: "review-and-export",
597
+ label: "Reviewed and exported",
598
+ description: "Operator QC approves or rejects leads, then approved records are exported as a lead list.",
599
+ primaryEntity: "company",
600
+ outputs: ["export"],
601
+ stageKey: "uploaded",
602
+ dependsOn: ["verify-emails"],
603
+ dependencyMode: "per-record-eligibility",
604
+ capabilityKey: "lead-gen.export.list",
605
+ defaultBatchSize: 100,
606
+ maxBatchSize: 250
607
+ }
608
+ }
609
+ };
610
+ z.object({
611
+ listEntityId: ModelIdSchema,
612
+ companyEntityId: ModelIdSchema,
613
+ contactEntityId: ModelIdSchema,
614
+ description: DescriptionSchema.optional(),
615
+ companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
616
+ contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
617
+ defaultBuildTemplateId: ModelIdSchema,
618
+ buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
619
+ });
620
+ function toProspectingLifecycleStage(stage) {
621
+ return {
622
+ id: stage.key,
623
+ label: stage.label,
624
+ order: stage.order
625
+ };
626
+ }
627
+ function leadGenStagesForEntity(entity) {
628
+ return Object.values(LEAD_GEN_STAGE_CATALOG).filter((stage) => stage.entity === entity).sort((a, b) => a.order - b.order).map(toProspectingLifecycleStage);
629
+ }
630
+ var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
631
+ companyStages: leadGenStagesForEntity("company"),
632
+ contactStages: leadGenStagesForEntity("contact"),
633
+ buildTemplates: [
634
+ {
635
+ id: "local-services",
636
+ label: "Local Services Prospecting",
637
+ description: "Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.",
638
+ steps: [
639
+ PROSPECTING_STEPS.localServices.sourceCompanies,
640
+ PROSPECTING_STEPS.localServices.analyzeWebsites,
641
+ PROSPECTING_STEPS.localServices.qualifyCompanies,
642
+ PROSPECTING_STEPS.localServices.findContacts,
643
+ PROSPECTING_STEPS.localServices.verifyEmails,
644
+ PROSPECTING_STEPS.localServices.personalize,
645
+ PROSPECTING_STEPS.localServices.review
646
+ ]
647
+ },
648
+ {
649
+ id: "dtc-subscription-apollo-clickup",
650
+ label: "DTC Subscription Apollo Export",
651
+ description: "Prospecting pipeline for DTC subscription or subscription-ready brands where Apollo is the source and contact-enrichment layer, Elevasis handles company research and fit scoring, and approved leads export as an approved lead list.",
652
+ steps: [
653
+ PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
654
+ PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
655
+ PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
656
+ PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
657
+ PROSPECTING_STEPS.dtcApolloClickup.verifyEmails,
658
+ PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
659
+ ]
660
+ }
661
+ ]
662
+ };
205
663
 
206
664
  // ../core/src/platform/registry/reserved.ts
207
665
  var RESERVED_RESOURCE_IDS = /* @__PURE__ */ new Set(["command-center-assistant"]);
@@ -3789,6 +4247,757 @@ var ResourceRegistry = class {
3789
4247
  return cache.commandView;
3790
4248
  }
3791
4249
  };
4250
+
4251
+ // ../core/src/business/acquisition/build-templates.ts
4252
+ var PROSPECTING_BUILD_TEMPLATE_OPTIONS = DEFAULT_ORGANIZATION_MODEL_PROSPECTING.buildTemplates.map(
4253
+ ({ id, label, description }) => ({
4254
+ id,
4255
+ label,
4256
+ description
4257
+ })
4258
+ );
4259
+ function isProspectingBuildTemplateId(value) {
4260
+ return PROSPECTING_BUILD_TEMPLATE_OPTIONS.some((template) => template.id === value);
4261
+ }
4262
+
4263
+ // ../core/src/business/acquisition/deal-ownership.ts
4264
+ var INBOUND_EVENT_TYPES = ["reply_received"];
4265
+ var OUTBOUND_EVENT_TYPES = [
4266
+ "reply_sent_to_lead",
4267
+ "booking_nudge_sent",
4268
+ "reminder_sent",
4269
+ "rebook_sent",
4270
+ "followup_email_sent",
4271
+ "reply_followup_sent",
4272
+ "lead_deferred_next_step"
4273
+ ];
4274
+ var INBOUND_SET = new Set(INBOUND_EVENT_TYPES);
4275
+ var OUTBOUND_SET = new Set(OUTBOUND_EVENT_TYPES);
4276
+ function getDealOwnership(deal) {
4277
+ if (deal.state_key === "closed_won" || deal.state_key === "closed_lost") {
4278
+ return null;
4279
+ }
4280
+ if (!Array.isArray(deal.activity_log)) return null;
4281
+ let latestInboundMs = null;
4282
+ let latestOutboundMs = null;
4283
+ for (const entry of deal.activity_log) {
4284
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
4285
+ const record = entry;
4286
+ const type = typeof record.type === "string" ? record.type : null;
4287
+ if (!type) continue;
4288
+ const isInbound = INBOUND_SET.has(type);
4289
+ const isOutbound = OUTBOUND_SET.has(type);
4290
+ if (!isInbound && !isOutbound) continue;
4291
+ const occurredAt = resolveTimestamp(record);
4292
+ if (occurredAt === null) continue;
4293
+ if (isInbound && (latestInboundMs === null || occurredAt > latestInboundMs)) {
4294
+ latestInboundMs = occurredAt;
4295
+ }
4296
+ if (isOutbound && (latestOutboundMs === null || occurredAt > latestOutboundMs)) {
4297
+ latestOutboundMs = occurredAt;
4298
+ }
4299
+ }
4300
+ if (latestInboundMs === null && latestOutboundMs === null) return null;
4301
+ if (latestOutboundMs !== null && (latestInboundMs === null || latestOutboundMs >= latestInboundMs)) {
4302
+ return "them";
4303
+ }
4304
+ return "us";
4305
+ }
4306
+ function resolveTimestamp(record) {
4307
+ return parseMs(record.timestamp) ?? parseMs(record.occurredAt) ?? parseMs(record.createdAt) ?? parseMs(record.updatedAt) ?? parseMs(record.sentAt) ?? null;
4308
+ }
4309
+ function parseMs(value) {
4310
+ if (value instanceof Date) {
4311
+ const ms2 = value.getTime();
4312
+ return Number.isNaN(ms2) ? null : ms2;
4313
+ }
4314
+ if (typeof value !== "string") return null;
4315
+ const ms = new Date(value).getTime();
4316
+ return Number.isNaN(ms) ? null : ms;
4317
+ }
4318
+
4319
+ // ../core/src/business/acquisition/api-schemas.ts
4320
+ var ProcessingStageStatusSchema = z.enum(["success", "no_result", "skipped", "error"]);
4321
+ var LeadGenStageKeySchema = z.string().refine((value) => Object.prototype.hasOwnProperty.call(LEAD_GEN_STAGE_CATALOG, value), {
4322
+ message: "processing state key must match LEAD_GEN_STAGE_CATALOG"
4323
+ });
4324
+ var LeadGenCapabilityKeySchema = z.string().refine((value) => CAPABILITY_REGISTRY.some((c) => c.id === value), {
4325
+ message: "capabilityKey must match CAPABILITY_REGISTRY"
4326
+ });
4327
+ var crmStageKeys = CRM_PIPELINE_DEFINITION.stages.map((stage) => stage.stageKey);
4328
+ var crmStateKeys = CRM_PIPELINE_DEFINITION.stages.flatMap((stage) => stage.states.map((state) => state.stateKey));
4329
+ var CrmStageKeySchema = z.enum(crmStageKeys);
4330
+ var CrmStateKeySchema = z.enum(crmStateKeys);
4331
+ var ProcessingStateEntrySchema = z.object({
4332
+ status: ProcessingStageStatusSchema,
4333
+ data: z.unknown().optional()
4334
+ }).passthrough();
4335
+ var ProcessingStateSchema = z.record(LeadGenStageKeySchema, ProcessingStateEntrySchema);
4336
+ var CompanyProcessingStateSchema = ProcessingStateSchema;
4337
+ var ContactProcessingStateSchema = ProcessingStateSchema;
4338
+ var DealStageSchema = CrmStageKeySchema;
4339
+ var AcqDealTaskKindSchema = z.enum(["call", "email", "meeting", "other"]);
4340
+ z.object({
4341
+ dealId: UuidSchema
4342
+ });
4343
+ z.object({
4344
+ dealId: UuidSchema,
4345
+ taskId: UuidSchema
4346
+ });
4347
+ z.object({
4348
+ stage: DealStageSchema.optional(),
4349
+ search: z.string().optional(),
4350
+ limit: z.coerce.number().int().positive().default(50),
4351
+ offset: z.coerce.number().int().min(0).default(0)
4352
+ }).strict();
4353
+ z.object({
4354
+ search: z.string().trim().min(1).max(200).optional(),
4355
+ limit: z.coerce.number().int().min(1).max(25).default(10)
4356
+ }).strict();
4357
+ z.object({
4358
+ window: z.enum(["overdue", "today", "today_and_overdue", "upcoming"]).optional(),
4359
+ assigneeUserId: UuidSchema.optional()
4360
+ }).strict();
4361
+ z.object({
4362
+ body: z.string().trim().min(1).max(1e4)
4363
+ }).strict();
4364
+ z.object({
4365
+ title: z.string().trim().min(1).max(255),
4366
+ description: z.string().nullable().optional(),
4367
+ kind: AcqDealTaskKindSchema.optional(),
4368
+ dueAt: z.string().datetime().nullable().optional(),
4369
+ assigneeUserId: UuidSchema.nullable().optional()
4370
+ }).strict();
4371
+ z.object({
4372
+ pipelineKey: z.string().min(1),
4373
+ stageKey: z.string().min(1),
4374
+ stateKey: z.string().min(1).nullable().optional(),
4375
+ reason: z.string().optional(),
4376
+ expectedUpdatedAt: z.string().datetime().optional()
4377
+ }).strict();
4378
+ z.object({
4379
+ pipelineKey: z.literal(CRM_PIPELINE_DEFINITION.pipelineKey),
4380
+ stageKey: CrmStageKeySchema,
4381
+ stateKey: CrmStateKeySchema.nullable().optional(),
4382
+ reason: z.string().optional(),
4383
+ expectedUpdatedAt: z.string().datetime().optional()
4384
+ }).strict();
4385
+ z.object({
4386
+ stateKey: CrmStateKeySchema,
4387
+ reason: z.string().optional(),
4388
+ expectedUpdatedAt: z.string().datetime().optional()
4389
+ }).strict();
4390
+ z.object({
4391
+ dealId: UuidSchema,
4392
+ actionKey: NonEmptyStringSchema
4393
+ }).strict();
4394
+ z.object({
4395
+ payload: z.record(z.string(), z.unknown()).optional()
4396
+ }).strict();
4397
+ var DealContactSummarySchema = z.object({
4398
+ id: z.string(),
4399
+ first_name: z.string().nullable(),
4400
+ last_name: z.string().nullable(),
4401
+ email: z.string(),
4402
+ title: z.string().nullable(),
4403
+ headline: z.string().nullable(),
4404
+ linkedin_url: z.string().nullable(),
4405
+ processing_state: ProcessingStateSchema.nullable(),
4406
+ enrichment_data: z.record(z.string(), z.unknown()).nullable(),
4407
+ company: z.object({
4408
+ id: z.string(),
4409
+ name: z.string(),
4410
+ domain: z.string().nullable(),
4411
+ website: z.string().nullable(),
4412
+ linkedin_url: z.string().nullable(),
4413
+ segment: z.string().nullable(),
4414
+ category: z.string().nullable(),
4415
+ num_employees: z.number().nullable()
4416
+ }).nullable()
4417
+ });
4418
+ var DealPrioritySchema = z.object({
4419
+ bucketKey: z.enum(["needs_response", "follow_up_due", "waiting", "stale", "closed_low"]),
4420
+ rank: z.number().int(),
4421
+ label: z.string(),
4422
+ color: z.string(),
4423
+ reason: z.string(),
4424
+ latestActivityAt: z.string().nullable(),
4425
+ nextActionAt: z.string().nullable()
4426
+ });
4427
+ var DealListItemSchema = z.object({
4428
+ // acq_deals columns
4429
+ id: z.string(),
4430
+ organization_id: z.string(),
4431
+ contact_id: z.string().nullable(),
4432
+ contact_email: z.string(),
4433
+ pipeline_key: z.string(),
4434
+ stage_key: z.string().nullable(),
4435
+ state_key: z.string().nullable(),
4436
+ activity_log: z.unknown(),
4437
+ discovery_data: z.unknown().nullable(),
4438
+ discovery_submitted_at: z.string().nullable(),
4439
+ discovery_submitted_by: z.string().nullable(),
4440
+ proposal_data: z.unknown().nullable(),
4441
+ proposal_sent_at: z.string().nullable(),
4442
+ proposal_pdf_url: z.string().nullable(),
4443
+ signature_envelope_id: z.string().nullable(),
4444
+ source_list_id: z.string().nullable(),
4445
+ source_type: z.string().nullable(),
4446
+ initial_fee: z.number().nullable(),
4447
+ monthly_fee: z.number().nullable(),
4448
+ closed_lost_at: z.string().nullable(),
4449
+ closed_lost_reason: z.string().nullable(),
4450
+ created_at: z.string(),
4451
+ updated_at: z.string(),
4452
+ priority: DealPrioritySchema,
4453
+ ownership: z.enum(["us", "them"]).nullable(),
4454
+ nextAction: z.string().nullable(),
4455
+ // joined relation
4456
+ contact: DealContactSummarySchema.nullable()
4457
+ });
4458
+ z.object({
4459
+ data: z.array(DealListItemSchema),
4460
+ total: z.number().int(),
4461
+ limit: z.number().int(),
4462
+ offset: z.number().int()
4463
+ });
4464
+ var DealStageSummarySchema = z.object({
4465
+ stage: z.string(),
4466
+ count: z.number().int(),
4467
+ totalValue: z.number(),
4468
+ oldestUpdatedAt: z.string().nullable(),
4469
+ newestUpdatedAt: z.string().nullable()
4470
+ });
4471
+ var StaleDealSummarySchema = z.object({
4472
+ id: z.string(),
4473
+ contactEmail: z.string(),
4474
+ stageKey: z.string(),
4475
+ updatedAt: z.string(),
4476
+ daysStale: z.number().int()
4477
+ });
4478
+ z.object({
4479
+ totalDeals: z.number().int(),
4480
+ openDeals: z.number().int(),
4481
+ wonDeals: z.number().int(),
4482
+ lostDeals: z.number().int(),
4483
+ winRate: z.number(),
4484
+ avgDealSize: z.number(),
4485
+ totalPipelineValue: z.number(),
4486
+ stageSummary: z.array(DealStageSummarySchema),
4487
+ staleDeals: z.array(StaleDealSummarySchema)
4488
+ });
4489
+ var DealLookupItemSchema = z.object({
4490
+ id: z.string(),
4491
+ contactEmail: z.string(),
4492
+ stageKey: z.string().nullable(),
4493
+ updatedAt: z.string(),
4494
+ contactName: z.string().nullable(),
4495
+ companyName: z.string().nullable(),
4496
+ displayLabel: z.string()
4497
+ });
4498
+ z.array(DealLookupItemSchema);
4499
+ var ConversationMessageSchema = z.object({
4500
+ id: z.string(),
4501
+ direction: z.enum(["inbound", "outbound"]),
4502
+ fromEmail: z.string(),
4503
+ toEmail: z.string(),
4504
+ subject: z.string().nullable(),
4505
+ body: z.string(),
4506
+ sentAt: z.string().nullable()
4507
+ });
4508
+ var DealConversationSchema = z.object({
4509
+ messages: z.array(ConversationMessageSchema)
4510
+ });
4511
+ DealListItemSchema.extend({
4512
+ conversation: DealConversationSchema
4513
+ });
4514
+ var DealNoteResponseSchema = z.object({
4515
+ id: z.string(),
4516
+ dealId: z.string(),
4517
+ organizationId: z.string(),
4518
+ authorUserId: z.string().nullable(),
4519
+ body: z.string(),
4520
+ createdAt: z.string(),
4521
+ updatedAt: z.string()
4522
+ });
4523
+ z.array(DealNoteResponseSchema);
4524
+ var DealTaskResponseSchema = z.object({
4525
+ id: z.string(),
4526
+ organizationId: z.string(),
4527
+ dealId: z.string(),
4528
+ title: z.string(),
4529
+ description: z.string().nullable(),
4530
+ kind: AcqDealTaskKindSchema,
4531
+ dueAt: z.string().nullable(),
4532
+ assigneeUserId: z.string().nullable(),
4533
+ completedAt: z.string().nullable(),
4534
+ completedByUserId: z.string().nullable(),
4535
+ createdAt: z.string(),
4536
+ updatedAt: z.string(),
4537
+ createdByUserId: z.string().nullable()
4538
+ });
4539
+ z.array(DealTaskResponseSchema);
4540
+ var ListStatusSchema = z.enum(["draft", "enriching", "launched", "closing", "archived"]);
4541
+ var ScrapingConfigSchema = z.object({
4542
+ vertical: z.string().trim().max(255).optional(),
4543
+ geography: z.string().trim().max(500).optional(),
4544
+ size: z.string().trim().max(255).optional(),
4545
+ apifyInput: z.record(z.string(), z.unknown()).optional()
4546
+ });
4547
+ var IcpRubricSchema = z.object({
4548
+ qualificationRubricKey: z.string().trim().max(255).nullish(),
4549
+ targetDescription: z.string().optional(),
4550
+ minReviewCount: z.number().int().min(0).optional(),
4551
+ minRating: z.number().min(0).max(5).optional(),
4552
+ excludeFranchises: z.boolean().optional(),
4553
+ customRules: z.string().optional()
4554
+ });
4555
+ var PipelineStageSchema = z.object({
4556
+ key: z.string().refine((value) => Object.prototype.hasOwnProperty.call(LEAD_GEN_STAGE_CATALOG, value), {
4557
+ message: "pipeline stage key must match LEAD_GEN_STAGE_CATALOG"
4558
+ }),
4559
+ label: z.string().optional(),
4560
+ enabled: z.boolean().optional(),
4561
+ order: z.number().int().optional()
4562
+ });
4563
+ var PipelineConfigSchema = z.object({
4564
+ stages: z.array(PipelineStageSchema).optional()
4565
+ });
4566
+ var BuildPlanSnapshotStepSchema = z.object({
4567
+ id: z.string().trim().min(1).max(100),
4568
+ label: z.string().trim().min(1).max(120),
4569
+ description: z.string().trim().min(1).max(2e3).optional(),
4570
+ primaryEntity: z.enum(["company", "contact"]),
4571
+ outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
4572
+ stageKey: LeadGenStageKeySchema,
4573
+ dependsOn: z.array(z.string().trim().min(1).max(100)).optional(),
4574
+ dependencyMode: z.literal("per-record-eligibility"),
4575
+ capabilityKey: LeadGenCapabilityKeySchema,
4576
+ defaultBatchSize: z.number().int().positive(),
4577
+ maxBatchSize: z.number().int().positive()
4578
+ }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
4579
+ message: "defaultBatchSize must be less than or equal to maxBatchSize",
4580
+ path: ["defaultBatchSize"]
4581
+ });
4582
+ var BuildPlanSnapshotSchema = z.object({
4583
+ templateId: z.string().trim().min(1).max(100),
4584
+ templateLabel: z.string().trim().min(1).max(120),
4585
+ steps: z.array(BuildPlanSnapshotStepSchema).min(1)
4586
+ }).superRefine((snapshot, ctx) => {
4587
+ const stepIds = /* @__PURE__ */ new Set();
4588
+ snapshot.steps.forEach((step, index) => {
4589
+ if (stepIds.has(step.id)) {
4590
+ ctx.addIssue({
4591
+ code: z.ZodIssueCode.custom,
4592
+ message: `duplicate build-plan step id "${step.id}"`,
4593
+ path: ["steps", index, "id"]
4594
+ });
4595
+ }
4596
+ stepIds.add(step.id);
4597
+ });
4598
+ snapshot.steps.forEach((step, index) => {
4599
+ for (const dependencyId of step.dependsOn ?? []) {
4600
+ if (!stepIds.has(dependencyId)) {
4601
+ ctx.addIssue({
4602
+ code: z.ZodIssueCode.custom,
4603
+ message: `dependsOn references unknown build-plan step "${dependencyId}"`,
4604
+ path: ["steps", index, "dependsOn"]
4605
+ });
4606
+ }
4607
+ }
4608
+ });
4609
+ });
4610
+ var AcqListMetadataSchema = z.object({
4611
+ buildPlanSnapshot: BuildPlanSnapshotSchema.optional()
4612
+ }).catchall(z.unknown());
4613
+ var ProspectingBuildTemplateIdSchema = z.string().trim().min(1).max(100).refine(isProspectingBuildTemplateId, {
4614
+ message: "buildTemplateId must match a known prospecting build template"
4615
+ });
4616
+ var ListStageCountsSchema = z.object({
4617
+ // Attempted counts by canonical lead-gen stage. The detailed status
4618
+ // distribution lives on ListProgress; telemetry keeps the overview payload small.
4619
+ stageCounts: z.object({
4620
+ populated: z.number().int(),
4621
+ extracted: z.number().int(),
4622
+ qualified: z.number().int(),
4623
+ discovered: z.number().int(),
4624
+ verified: z.number().int(),
4625
+ personalized: z.number().int(),
4626
+ uploaded: z.number().int()
4627
+ }),
4628
+ deliverability: z.object({
4629
+ valid: z.number().int(),
4630
+ risky: z.number().int(),
4631
+ invalid: z.number().int(),
4632
+ unknown: z.number().int(),
4633
+ bounced: z.number().int()
4634
+ })
4635
+ });
4636
+ var ListTelemetrySchema = z.object({
4637
+ listId: UuidSchema,
4638
+ totalCompanies: z.number().int(),
4639
+ totalContacts: z.number().int(),
4640
+ stageCounts: ListStageCountsSchema.shape.stageCounts,
4641
+ deliverability: ListStageCountsSchema.shape.deliverability,
4642
+ activeWorkflows: z.array(z.string()).optional()
4643
+ });
4644
+ z.object({
4645
+ listId: UuidSchema
4646
+ });
4647
+ z.object({
4648
+ name: z.string().trim().min(1).max(255),
4649
+ description: z.string().trim().nullable().optional(),
4650
+ status: ListStatusSchema.optional(),
4651
+ buildTemplateId: ProspectingBuildTemplateIdSchema.optional(),
4652
+ scrapingConfig: ScrapingConfigSchema.optional(),
4653
+ icp: IcpRubricSchema.optional(),
4654
+ pipelineConfig: PipelineConfigSchema.optional()
4655
+ }).strict();
4656
+ z.object({
4657
+ name: z.string().trim().min(1).max(255).optional(),
4658
+ description: z.string().trim().nullable().optional(),
4659
+ batchIds: z.array(z.string()).optional(),
4660
+ buildTemplateId: ProspectingBuildTemplateIdSchema.optional(),
4661
+ confirmBuildTemplateChange: z.literal(true).optional()
4662
+ }).strict().refine(
4663
+ (data) => data.name !== void 0 || data.description !== void 0 || data.batchIds !== void 0 || data.buildTemplateId !== void 0,
4664
+ {
4665
+ message: "At least one field (name, description, batchIds, or buildTemplateId) must be provided"
4666
+ }
4667
+ ).refine((data) => data.buildTemplateId === void 0 || data.confirmBuildTemplateChange === true, {
4668
+ message: "confirmBuildTemplateChange must be true when changing buildTemplateId",
4669
+ path: ["confirmBuildTemplateChange"]
4670
+ });
4671
+ z.object({
4672
+ status: ListStatusSchema
4673
+ }).strict();
4674
+ z.object({
4675
+ scrapingConfig: ScrapingConfigSchema.partial().optional(),
4676
+ icp: IcpRubricSchema.partial().optional(),
4677
+ pipelineConfig: PipelineConfigSchema.partial().optional()
4678
+ }).strict().refine((data) => data.scrapingConfig !== void 0 || data.icp !== void 0 || data.pipelineConfig !== void 0, {
4679
+ message: "At least one of scrapingConfig, icp, or pipelineConfig must be provided"
4680
+ });
4681
+ z.object({
4682
+ companyIds: z.array(UuidSchema).min(1).max(1e3)
4683
+ }).strict();
4684
+ z.object({
4685
+ companyIds: z.array(UuidSchema).min(1).max(1e3)
4686
+ }).strict();
4687
+ z.object({
4688
+ contactIds: z.array(UuidSchema).min(1).max(1e3)
4689
+ }).strict();
4690
+ z.object({
4691
+ executionId: UuidSchema,
4692
+ configSnapshot: z.record(z.string(), z.unknown()).optional()
4693
+ }).strict();
4694
+ var AcqListResponseSchema = z.object({
4695
+ id: z.string(),
4696
+ organizationId: z.string(),
4697
+ name: z.string(),
4698
+ description: z.string().nullable(),
4699
+ batchIds: z.array(z.string()),
4700
+ instantlyCampaignId: z.string().nullable(),
4701
+ /** Lifecycle status (draft | enriching | launched | closing | archived). */
4702
+ status: ListStatusSchema,
4703
+ metadata: AcqListMetadataSchema,
4704
+ launchedAt: z.string().nullable(),
4705
+ completedAt: z.string().nullable(),
4706
+ createdAt: z.string(),
4707
+ /** Scraping criteria stored as jsonb on the row. */
4708
+ scrapingConfig: ScrapingConfigSchema,
4709
+ /** ICP / qualification rubric stored as jsonb on the row. */
4710
+ icp: IcpRubricSchema,
4711
+ /** Pipeline presentation contract stored as jsonb on the row. */
4712
+ pipelineConfig: PipelineConfigSchema
4713
+ });
4714
+ z.array(AcqListResponseSchema);
4715
+ z.array(ListTelemetrySchema);
4716
+ var ListStageProgressSchema = z.object({
4717
+ total: z.number().int().min(0),
4718
+ attempted: z.number().int().min(0),
4719
+ success: z.number().int().min(0),
4720
+ noResult: z.number().int().min(0),
4721
+ skipped: z.number().int().min(0),
4722
+ error: z.number().int().min(0),
4723
+ other: z.number().int().min(0),
4724
+ notAttempted: z.number().int().min(0)
4725
+ });
4726
+ z.object({
4727
+ totalMembers: z.number().int().min(0),
4728
+ totalCompanies: z.number().int().min(0),
4729
+ byCompanyStage: z.record(z.string(), ListStageProgressSchema),
4730
+ byContactStage: z.record(z.string(), ListStageProgressSchema)
4731
+ });
4732
+ var ListExecutionSummarySchema = z.object({
4733
+ executionId: z.string(),
4734
+ resourceId: z.string(),
4735
+ status: z.string(),
4736
+ createdAt: z.string(),
4737
+ completedAt: z.string().nullable(),
4738
+ durationMs: z.number().int().nullable(),
4739
+ input: z.unknown().nullable().optional()
4740
+ });
4741
+ z.array(ListExecutionSummarySchema);
4742
+ var QueryBooleanSchema = z.preprocess((value) => {
4743
+ if (value === "true" || value === "1" || value === true) return true;
4744
+ if (value === "false" || value === "0" || value === false) return false;
4745
+ return value;
4746
+ }, z.boolean());
4747
+ var AcqCompanyStatusSchema = z.enum(["active", "invalid"]);
4748
+ var AcqContactStatusSchema = z.enum(["active", "invalid"]);
4749
+ var AcqEmailValidSchema = z.enum(["VALID", "INVALID", "RISKY", "UNKNOWN"]);
4750
+ z.object({
4751
+ companyId: UuidSchema
4752
+ });
4753
+ z.object({
4754
+ contactId: UuidSchema
4755
+ });
4756
+ z.object({
4757
+ search: z.string().trim().min(1).max(200).optional(),
4758
+ listId: UuidSchema.optional(),
4759
+ domain: z.string().trim().min(1).max(255).optional(),
4760
+ website: z.string().trim().min(1).max(2048).optional(),
4761
+ segment: z.string().trim().min(1).max(255).optional(),
4762
+ category: z.string().trim().min(1).max(255).optional(),
4763
+ pipelineStatus: z.unknown().optional(),
4764
+ batchId: z.string().trim().min(1).max(255).optional(),
4765
+ status: AcqCompanyStatusSchema.optional(),
4766
+ includeAll: QueryBooleanSchema.optional(),
4767
+ limit: z.coerce.number().int().min(1).max(5e3).default(50),
4768
+ offset: z.coerce.number().int().min(0).default(0)
4769
+ }).strict();
4770
+ z.object({
4771
+ search: z.string().trim().min(1).max(200).optional(),
4772
+ listId: UuidSchema.optional(),
4773
+ openingLineIsNull: QueryBooleanSchema.optional(),
4774
+ batchId: z.string().trim().min(1).max(255).optional(),
4775
+ contactStatus: AcqContactStatusSchema.optional(),
4776
+ limit: z.coerce.number().int().min(1).max(5e3).default(5e3),
4777
+ offset: z.coerce.number().int().min(0).default(0)
4778
+ }).strict();
4779
+ z.object({
4780
+ name: z.string().trim().min(1).max(255),
4781
+ domain: z.string().trim().min(1).max(255).optional(),
4782
+ linkedinUrl: z.string().trim().url().optional(),
4783
+ website: z.string().trim().url().optional(),
4784
+ numEmployees: z.number().int().min(0).optional(),
4785
+ foundedYear: z.number().int().optional(),
4786
+ locationCity: z.string().trim().min(1).max(255).optional(),
4787
+ locationState: z.string().trim().min(1).max(255).optional(),
4788
+ category: z.string().trim().min(1).max(255).optional(),
4789
+ source: z.string().trim().min(1).max(255).optional(),
4790
+ batchId: z.string().trim().min(1).max(255).optional(),
4791
+ pipelineStatus: z.unknown().optional(),
4792
+ verticalResearch: z.string().trim().min(1).max(5e3).optional()
4793
+ }).strict();
4794
+ z.object({
4795
+ name: z.string().trim().min(1).max(255).optional(),
4796
+ domain: z.string().trim().min(1).max(255).optional(),
4797
+ linkedinUrl: z.string().trim().url().optional(),
4798
+ website: z.string().trim().url().optional(),
4799
+ numEmployees: z.number().int().min(0).optional(),
4800
+ foundedYear: z.number().int().optional(),
4801
+ locationCity: z.string().trim().min(1).max(255).optional(),
4802
+ locationState: z.string().trim().min(1).max(255).optional(),
4803
+ category: z.string().trim().min(1).max(255).optional(),
4804
+ segment: z.string().trim().min(1).max(255).optional(),
4805
+ processingState: CompanyProcessingStateSchema.optional(),
4806
+ pipelineStatus: z.unknown().optional(),
4807
+ enrichmentData: z.record(z.string(), z.unknown()).optional(),
4808
+ source: z.string().trim().min(1).max(255).optional(),
4809
+ batchId: z.string().trim().min(1).max(255).optional(),
4810
+ status: AcqCompanyStatusSchema.optional(),
4811
+ verticalResearch: z.string().trim().min(1).max(5e3).nullable().optional()
4812
+ }).strict().refine(
4813
+ (data) => data.name !== void 0 || data.domain !== void 0 || data.linkedinUrl !== void 0 || data.website !== void 0 || data.numEmployees !== void 0 || data.foundedYear !== void 0 || data.locationCity !== void 0 || data.locationState !== void 0 || data.category !== void 0 || data.segment !== void 0 || data.processingState !== void 0 || data.pipelineStatus !== void 0 || data.enrichmentData !== void 0 || data.source !== void 0 || data.batchId !== void 0 || data.status !== void 0 || data.verticalResearch !== void 0,
4814
+ {
4815
+ message: "At least one field must be provided"
4816
+ }
4817
+ );
4818
+ z.object({
4819
+ email: z.string().trim().email(),
4820
+ companyId: UuidSchema.optional(),
4821
+ firstName: z.string().trim().min(1).max(255).optional(),
4822
+ lastName: z.string().trim().min(1).max(255).optional(),
4823
+ linkedinUrl: z.string().trim().url().optional(),
4824
+ title: z.string().trim().min(1).max(255).optional(),
4825
+ source: z.string().trim().min(1).max(255).optional(),
4826
+ sourceId: z.string().trim().min(1).max(255).optional(),
4827
+ batchId: z.string().trim().min(1).max(255).optional(),
4828
+ pipelineStatus: z.unknown().optional()
4829
+ }).strict();
4830
+ z.object({
4831
+ companyId: UuidSchema.optional(),
4832
+ emailValid: AcqEmailValidSchema.optional(),
4833
+ firstName: z.string().trim().min(1).max(255).optional(),
4834
+ lastName: z.string().trim().min(1).max(255).optional(),
4835
+ linkedinUrl: z.string().trim().url().optional(),
4836
+ title: z.string().trim().min(1).max(255).optional(),
4837
+ headline: z.string().trim().min(1).max(5e3).optional(),
4838
+ filterReason: z.string().trim().min(1).max(5e3).optional(),
4839
+ openingLine: z.string().trim().min(1).max(5e3).optional(),
4840
+ processingState: ContactProcessingStateSchema.optional(),
4841
+ pipelineStatus: z.unknown().optional(),
4842
+ enrichmentData: z.record(z.string(), z.unknown()).optional(),
4843
+ status: AcqContactStatusSchema.optional()
4844
+ }).strict().refine(
4845
+ (data) => data.companyId !== void 0 || data.emailValid !== void 0 || data.firstName !== void 0 || data.lastName !== void 0 || data.linkedinUrl !== void 0 || data.title !== void 0 || data.headline !== void 0 || data.filterReason !== void 0 || data.openingLine !== void 0 || data.processingState !== void 0 || data.pipelineStatus !== void 0 || data.enrichmentData !== void 0 || data.status !== void 0,
4846
+ {
4847
+ message: "At least one field must be provided"
4848
+ }
4849
+ );
4850
+ var AcqCompanyResponseSchema = z.object({
4851
+ id: z.string(),
4852
+ organizationId: z.string(),
4853
+ name: z.string(),
4854
+ domain: z.string().nullable(),
4855
+ linkedinUrl: z.string().nullable(),
4856
+ website: z.string().nullable(),
4857
+ numEmployees: z.number().nullable(),
4858
+ foundedYear: z.number().nullable(),
4859
+ locationCity: z.string().nullable(),
4860
+ locationState: z.string().nullable(),
4861
+ category: z.string().nullable(),
4862
+ categoryPain: z.string().nullable(),
4863
+ segment: z.string().nullable(),
4864
+ processingState: CompanyProcessingStateSchema.nullable(),
4865
+ pipelineStatus: z.unknown().nullable().optional(),
4866
+ enrichmentData: z.record(z.string(), z.unknown()).nullable(),
4867
+ source: z.string().nullable(),
4868
+ batchId: z.string().nullable(),
4869
+ status: AcqCompanyStatusSchema,
4870
+ contactCount: z.number().int().min(0),
4871
+ verticalResearch: z.string().nullable(),
4872
+ createdAt: z.string(),
4873
+ updatedAt: z.string()
4874
+ });
4875
+ z.object({
4876
+ data: z.array(AcqCompanyResponseSchema),
4877
+ total: z.number().int(),
4878
+ limit: z.number().int(),
4879
+ offset: z.number().int()
4880
+ });
4881
+ z.object({
4882
+ segments: z.array(z.string()),
4883
+ categories: z.array(z.string()),
4884
+ statuses: z.array(AcqCompanyStatusSchema)
4885
+ });
4886
+ var AcqContactCompanySummarySchema = z.object({
4887
+ id: z.string(),
4888
+ name: z.string(),
4889
+ domain: z.string().nullable(),
4890
+ website: z.string().nullable(),
4891
+ linkedinUrl: z.string().nullable(),
4892
+ segment: z.string().nullable(),
4893
+ category: z.string().nullable(),
4894
+ status: AcqCompanyStatusSchema
4895
+ });
4896
+ var AcqContactResponseSchema = z.object({
4897
+ id: z.string(),
4898
+ organizationId: z.string(),
4899
+ companyId: z.string().nullable(),
4900
+ email: z.string(),
4901
+ emailValid: AcqEmailValidSchema.nullable(),
4902
+ firstName: z.string().nullable(),
4903
+ lastName: z.string().nullable(),
4904
+ linkedinUrl: z.string().nullable(),
4905
+ title: z.string().nullable(),
4906
+ headline: z.string().nullable(),
4907
+ filterReason: z.string().nullable(),
4908
+ openingLine: z.string().nullable(),
4909
+ source: z.string().nullable(),
4910
+ sourceId: z.string().nullable(),
4911
+ processingState: ContactProcessingStateSchema.nullable(),
4912
+ pipelineStatus: z.unknown().nullable().optional(),
4913
+ enrichmentData: z.record(z.string(), z.unknown()).nullable(),
4914
+ attioPersonId: z.string().nullable(),
4915
+ batchId: z.string().nullable(),
4916
+ status: AcqContactStatusSchema,
4917
+ company: AcqContactCompanySummarySchema.nullable().optional(),
4918
+ createdAt: z.string(),
4919
+ updatedAt: z.string()
4920
+ });
4921
+ z.object({
4922
+ data: z.array(AcqContactResponseSchema),
4923
+ total: z.number().int(),
4924
+ limit: z.number().int(),
4925
+ offset: z.number().int()
4926
+ });
4927
+ var AcqArtifactOwnerKindSchema = z.enum(["company", "contact", "deal", "list", "list_member"]);
4928
+ z.object({
4929
+ ownerKind: AcqArtifactOwnerKindSchema,
4930
+ ownerId: UuidSchema
4931
+ }).strict();
4932
+ z.object({
4933
+ ownerKind: AcqArtifactOwnerKindSchema,
4934
+ ownerId: UuidSchema,
4935
+ kind: z.string().trim().min(1).max(255),
4936
+ content: z.record(z.string(), z.unknown()),
4937
+ sourceExecutionId: UuidSchema.optional()
4938
+ }).strict();
4939
+ var AcqArtifactResponseSchema = z.object({
4940
+ id: z.string(),
4941
+ organizationId: z.string(),
4942
+ ownerKind: z.string(),
4943
+ ownerId: z.string(),
4944
+ kind: z.string(),
4945
+ content: z.record(z.string(), z.unknown()),
4946
+ sourceExecutionId: z.string().nullable(),
4947
+ createdBy: z.string().nullable(),
4948
+ createdAt: z.string(),
4949
+ version: z.number().int()
4950
+ });
4951
+ z.object({
4952
+ artifacts: z.array(AcqArtifactResponseSchema)
4953
+ });
4954
+ z.object({
4955
+ limit: z.coerce.number().int().min(1).max(500).default(50),
4956
+ offset: z.coerce.number().int().min(0).default(0)
4957
+ }).strict();
4958
+ z.object({
4959
+ memberId: UuidSchema
4960
+ });
4961
+ var AcqListMemberContactSummarySchema = z.object({
4962
+ id: z.string(),
4963
+ email: z.string(),
4964
+ firstName: z.string().nullable(),
4965
+ lastName: z.string().nullable(),
4966
+ title: z.string().nullable(),
4967
+ linkedinUrl: z.string().nullable(),
4968
+ companyId: z.string().nullable()
4969
+ });
4970
+ var AcqListMemberResponseSchema = z.object({
4971
+ id: z.string(),
4972
+ listId: z.string(),
4973
+ contactId: z.string(),
4974
+ pipelineKey: z.string(),
4975
+ stageKey: z.string(),
4976
+ stateKey: z.string(),
4977
+ activityLog: z.unknown(),
4978
+ addedAt: z.string(),
4979
+ addedBy: z.string().nullable(),
4980
+ sourceExecutionId: z.string().nullable(),
4981
+ contact: AcqListMemberContactSummarySchema.nullable()
4982
+ });
4983
+ z.object({
4984
+ members: z.array(AcqListMemberResponseSchema)
4985
+ });
4986
+ z.object({
4987
+ listCompanyId: UuidSchema
4988
+ });
4989
+ z.object({
4990
+ id: z.string(),
4991
+ listId: z.string(),
4992
+ companyId: z.string(),
4993
+ pipelineKey: z.string(),
4994
+ stageKey: z.string(),
4995
+ stateKey: z.string(),
4996
+ activityLog: z.unknown(),
4997
+ addedAt: z.string(),
4998
+ addedBy: z.string().nullable(),
4999
+ sourceExecutionId: z.string().nullable()
5000
+ });
3792
5001
  var StageChangeEventSchema = z.object({
3793
5002
  type: z.literal("stage_change"),
3794
5003
  timestamp: z.string().datetime(),
@@ -3857,64 +5066,6 @@ var ActivityEventSchema = z.discriminatedUnion("type", [
3857
5066
  DealCreatedEventSchema,
3858
5067
  ActionFailedEventSchema
3859
5068
  ]);
3860
-
3861
- // ../core/src/business/acquisition/deal-ownership.ts
3862
- var INBOUND_EVENT_TYPES = ["reply_received"];
3863
- var OUTBOUND_EVENT_TYPES = [
3864
- "reply_sent_to_lead",
3865
- "booking_nudge_sent",
3866
- "reminder_sent",
3867
- "rebook_sent",
3868
- "followup_email_sent",
3869
- "reply_followup_sent",
3870
- "lead_deferred_next_step"
3871
- ];
3872
- var INBOUND_SET = new Set(INBOUND_EVENT_TYPES);
3873
- var OUTBOUND_SET = new Set(OUTBOUND_EVENT_TYPES);
3874
- function getDealOwnership(deal) {
3875
- if (deal.state_key === "closed_won" || deal.state_key === "closed_lost") {
3876
- return null;
3877
- }
3878
- if (!Array.isArray(deal.activity_log)) return null;
3879
- let latestInboundMs = null;
3880
- let latestOutboundMs = null;
3881
- for (const entry of deal.activity_log) {
3882
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
3883
- const record = entry;
3884
- const type = typeof record.type === "string" ? record.type : null;
3885
- if (!type) continue;
3886
- const isInbound = INBOUND_SET.has(type);
3887
- const isOutbound = OUTBOUND_SET.has(type);
3888
- if (!isInbound && !isOutbound) continue;
3889
- const occurredAt = resolveTimestamp(record);
3890
- if (occurredAt === null) continue;
3891
- if (isInbound && (latestInboundMs === null || occurredAt > latestInboundMs)) {
3892
- latestInboundMs = occurredAt;
3893
- }
3894
- if (isOutbound && (latestOutboundMs === null || occurredAt > latestOutboundMs)) {
3895
- latestOutboundMs = occurredAt;
3896
- }
3897
- }
3898
- if (latestInboundMs === null && latestOutboundMs === null) return null;
3899
- if (latestOutboundMs !== null && (latestInboundMs === null || latestOutboundMs >= latestInboundMs)) {
3900
- return "them";
3901
- }
3902
- return "us";
3903
- }
3904
- function resolveTimestamp(record) {
3905
- return parseMs(record.timestamp) ?? parseMs(record.occurredAt) ?? parseMs(record.createdAt) ?? parseMs(record.updatedAt) ?? parseMs(record.sentAt) ?? null;
3906
- }
3907
- function parseMs(value) {
3908
- if (value instanceof Date) {
3909
- const ms2 = value.getTime();
3910
- return Number.isNaN(ms2) ? null : ms2;
3911
- }
3912
- if (typeof value !== "string") return null;
3913
- const ms = new Date(value).getTime();
3914
- return Number.isNaN(ms) ? null : ms;
3915
- }
3916
-
3917
- // ../core/src/business/acquisition/derive-actions.ts
3918
5069
  var SendReplyActionPayloadSchema = z.object({
3919
5070
  replyBody: z.string().trim().min(1).max(1e4)
3920
5071
  }).strict();
@@ -3993,5 +5144,7 @@ function isOurReplyAction(deal) {
3993
5144
  }
3994
5145
  return (deal.ownership ?? getDealOwnership(deal)) === "us";
3995
5146
  }
5147
+ var listBuilderStageKeys = Object.keys(LEAD_GEN_STAGE_CATALOG);
5148
+ var ListBuilderStageKeySchema = z.enum(listBuilderStageKeys);
3996
5149
 
3997
- export { ActivityEventSchema, DEFAULT_CRM_ACTIONS, EmailSchema, ExecutionError, RegistryValidationError, ResourceRegistry, StepType, ToolingError, deriveActions };
5150
+ export { ActivityEventSchema, BuildPlanSnapshotStepSchema, ProspectingBuildTemplateSchema as BuildTemplateSchema, CRM_PIPELINE_DEFINITION, CrmStageKeySchema, CrmStateKeySchema, DEFAULT_CRM_ACTIONS, EmailSchema, ExecutionError, LEAD_GEN_STAGE_CATALOG, ListBuilderStageKeySchema, ProcessingStageStatusSchema, RegistryValidationError, ResourceRegistry, StepType, ToolingError, deriveActions };