@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/cli.cjs +587 -175
- package/dist/index.d.ts +555 -83
- package/dist/index.js +1219 -66
- package/dist/node/index.d.ts +3 -0
- package/dist/node/index.js +34 -1
- package/dist/test-utils/index.d.ts +128 -81
- package/dist/test-utils/index.js +2007 -668
- package/dist/types/worker/index.d.ts +3 -2
- package/dist/worker/index.js +1507 -2
- package/package.json +2 -2
- package/reference/claude-config/registries/graph-skills.json +4 -0
- package/reference/claude-config/rules/package-taxonomy.md +33 -0
- package/reference/claude-config/rules/vibe.md +23 -0
- package/reference/claude-config/skills/knowledge/SKILL.md +46 -13
- package/reference/claude-config/skills/project/SKILL.md +21 -0
- package/reference/claude-config/skills/tutorial/SKILL.md +13 -3
- package/reference/claude-config/skills/tutorial/technical.md +6 -8
- package/reference/claude-config/sync-notes/2026-05-05-list-builder.md +42 -0
- package/reference/claude-config/sync-notes/2026-05-06-crm-spine.md +60 -0
- package/reference/claude-config/sync-notes/2026-05-06-sdk-changes-release-train.md +37 -0
- package/reference/scaffold/reference/contracts.md +89 -69
- package/reference/scaffold/reference/feature-registry.md +1 -1
- package/reference/spine/spine-primer.md +99 -0
package/dist/test-utils/index.js
CHANGED
|
@@ -5560,6 +5560,29 @@ function estimateTokens(text) {
|
|
|
5560
5560
|
const chars4 = content.length;
|
|
5561
5561
|
return Math.ceil(chars4 / 3.5);
|
|
5562
5562
|
}
|
|
5563
|
+
var UuidSchema = z.string().uuid();
|
|
5564
|
+
var NonEmptyStringSchema = z.string().trim().min(1).max(1e3);
|
|
5565
|
+
z.enum(["agent", "workflow"]);
|
|
5566
|
+
z.enum(["agent", "workflow", "scheduler", "api"]);
|
|
5567
|
+
z.string().trim().toLowerCase().min(1, "Credential name required").max(100, "Credential name too long (max 100 chars)").regex(
|
|
5568
|
+
/^[a-z0-9]+(-[a-z0-9]+)+$/,
|
|
5569
|
+
"Credential name must be lowercase letters, numbers, and hyphens in format: service-environment (e.g., gmail-prod, attio-dev)"
|
|
5570
|
+
);
|
|
5571
|
+
z.enum(["google-sheets", "google-calendar", "dropbox"]);
|
|
5572
|
+
z.string().min(10, "Authorization code too short").max(1e3, "Authorization code too long");
|
|
5573
|
+
z.string().min(10, "State parameter too short").max(2048, "State parameter too long");
|
|
5574
|
+
z.string().trim().transform((str) => str.replace(/[<>'"]/g, ""));
|
|
5575
|
+
z.string().email();
|
|
5576
|
+
z.string().url();
|
|
5577
|
+
z.object({
|
|
5578
|
+
limit: z.coerce.number().int().min(1).max(100).default(20),
|
|
5579
|
+
offset: z.coerce.number().int().min(0).default(0)
|
|
5580
|
+
});
|
|
5581
|
+
z.string().datetime();
|
|
5582
|
+
z.object({
|
|
5583
|
+
startDate: z.string().datetime(),
|
|
5584
|
+
endDate: z.string().datetime()
|
|
5585
|
+
});
|
|
5563
5586
|
|
|
5564
5587
|
// ../core/src/platform/constants/limits.ts
|
|
5565
5588
|
var MAX_SESSION_MEMORY_KEYS = 25;
|
|
@@ -6488,6 +6511,1301 @@ Fix the errors and generate a valid output.
|
|
|
6488
6511
|
}
|
|
6489
6512
|
}
|
|
6490
6513
|
};
|
|
6514
|
+
var ORGANIZATION_MODEL_ICON_TOKENS = [
|
|
6515
|
+
"nav.dashboard",
|
|
6516
|
+
"nav.calendar",
|
|
6517
|
+
"nav.sales",
|
|
6518
|
+
"nav.crm",
|
|
6519
|
+
"nav.lead-gen",
|
|
6520
|
+
"nav.projects",
|
|
6521
|
+
"nav.operations",
|
|
6522
|
+
"nav.monitoring",
|
|
6523
|
+
"nav.knowledge",
|
|
6524
|
+
"nav.settings",
|
|
6525
|
+
"nav.admin",
|
|
6526
|
+
"nav.archive",
|
|
6527
|
+
"knowledge.playbook",
|
|
6528
|
+
"knowledge.strategy",
|
|
6529
|
+
"knowledge.reference",
|
|
6530
|
+
"feature.dashboard",
|
|
6531
|
+
"feature.calendar",
|
|
6532
|
+
"feature.sales",
|
|
6533
|
+
"feature.crm",
|
|
6534
|
+
"feature.finance",
|
|
6535
|
+
"feature.lead-gen",
|
|
6536
|
+
"feature.platform",
|
|
6537
|
+
"feature.projects",
|
|
6538
|
+
"feature.operations",
|
|
6539
|
+
"feature.knowledge",
|
|
6540
|
+
"feature.monitoring",
|
|
6541
|
+
"feature.settings",
|
|
6542
|
+
"feature.admin",
|
|
6543
|
+
"feature.archive",
|
|
6544
|
+
"feature.seo",
|
|
6545
|
+
"resource.agent",
|
|
6546
|
+
"resource.workflow",
|
|
6547
|
+
"resource.integration",
|
|
6548
|
+
"resource.database",
|
|
6549
|
+
"resource.user",
|
|
6550
|
+
"resource.team",
|
|
6551
|
+
"integration.gmail",
|
|
6552
|
+
"integration.google-sheets",
|
|
6553
|
+
"integration.attio",
|
|
6554
|
+
"surface.dashboard",
|
|
6555
|
+
"surface.calendar",
|
|
6556
|
+
"surface.overview",
|
|
6557
|
+
"surface.command-view",
|
|
6558
|
+
"surface.command-queue",
|
|
6559
|
+
"surface.pipeline",
|
|
6560
|
+
"surface.lists",
|
|
6561
|
+
"surface.resources",
|
|
6562
|
+
"surface.settings",
|
|
6563
|
+
"status.success",
|
|
6564
|
+
"status.error",
|
|
6565
|
+
"status.warning",
|
|
6566
|
+
"status.info",
|
|
6567
|
+
"status.pending",
|
|
6568
|
+
"action.approve",
|
|
6569
|
+
"action.reject",
|
|
6570
|
+
"action.retry",
|
|
6571
|
+
"action.edit",
|
|
6572
|
+
"action.view",
|
|
6573
|
+
"action.launch",
|
|
6574
|
+
"action.message",
|
|
6575
|
+
"action.escalate",
|
|
6576
|
+
"action.promote",
|
|
6577
|
+
"action.submit",
|
|
6578
|
+
"action.email"
|
|
6579
|
+
];
|
|
6580
|
+
var CustomIconTokenSchema = z.string().trim().max(80).regex(/^custom\.[a-z0-9]+(?:[-._][a-z0-9]+)*$/, "Custom icon tokens must start with custom.");
|
|
6581
|
+
var OrganizationModelBuiltinIconTokenSchema = z.enum(ORGANIZATION_MODEL_ICON_TOKENS);
|
|
6582
|
+
var OrganizationModelIconTokenSchema = z.union([
|
|
6583
|
+
OrganizationModelBuiltinIconTokenSchema,
|
|
6584
|
+
CustomIconTokenSchema
|
|
6585
|
+
]);
|
|
6586
|
+
|
|
6587
|
+
// ../core/src/organization-model/domains/shared.ts
|
|
6588
|
+
var ModelIdSchema = z.string().trim().min(1).max(100).regex(/^[a-z0-9]+(?:[-._][a-z0-9]+)*$/, "IDs must be lowercase and use -, _, or . separators");
|
|
6589
|
+
var LabelSchema = z.string().trim().min(1).max(120);
|
|
6590
|
+
var DescriptionSchema = z.string().trim().min(1).max(2e3);
|
|
6591
|
+
var ColorTokenSchema = z.string().trim().min(1).max(50);
|
|
6592
|
+
var IconNameSchema = OrganizationModelIconTokenSchema;
|
|
6593
|
+
z.string().trim().startsWith("/").max(300);
|
|
6594
|
+
var ReferenceIdsSchema = z.array(ModelIdSchema).default([]);
|
|
6595
|
+
var DisplayMetadataSchema = z.object({
|
|
6596
|
+
label: LabelSchema,
|
|
6597
|
+
description: DescriptionSchema.optional(),
|
|
6598
|
+
color: ColorTokenSchema.optional(),
|
|
6599
|
+
icon: IconNameSchema.optional()
|
|
6600
|
+
});
|
|
6601
|
+
var TechStackEntrySchema = z.object({
|
|
6602
|
+
/** Name of the external platform (e.g. "HubSpot", "Stripe", "Notion"). */
|
|
6603
|
+
platform: z.string().trim().min(1).max(200),
|
|
6604
|
+
/** Free-form description of what this integration is used for. */
|
|
6605
|
+
purpose: z.string().trim().min(1).max(500),
|
|
6606
|
+
/**
|
|
6607
|
+
* Health of the credential backing this integration.
|
|
6608
|
+
* - configured: credential present and valid
|
|
6609
|
+
* - pending: not yet set up
|
|
6610
|
+
* - expired: credential existed but has lapsed
|
|
6611
|
+
* - missing: expected but not present
|
|
6612
|
+
*/
|
|
6613
|
+
credentialStatus: z.enum(["configured", "pending", "expired", "missing"]),
|
|
6614
|
+
/**
|
|
6615
|
+
* Whether this integration is the primary system of record for its domain
|
|
6616
|
+
* (e.g. HubSpot is SoR for contacts). Defaults to false.
|
|
6617
|
+
*/
|
|
6618
|
+
isSystemOfRecord: z.boolean().default(false)
|
|
6619
|
+
});
|
|
6620
|
+
DisplayMetadataSchema.extend({
|
|
6621
|
+
id: ModelIdSchema,
|
|
6622
|
+
resourceId: z.string().trim().min(1).max(255),
|
|
6623
|
+
resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
|
|
6624
|
+
featureIds: ReferenceIdsSchema,
|
|
6625
|
+
entityIds: ReferenceIdsSchema,
|
|
6626
|
+
surfaceIds: ReferenceIdsSchema,
|
|
6627
|
+
capabilityIds: ReferenceIdsSchema,
|
|
6628
|
+
/** Optional tech-stack metadata for external-SaaS integrations. */
|
|
6629
|
+
techStack: TechStackEntrySchema.optional()
|
|
6630
|
+
});
|
|
6631
|
+
|
|
6632
|
+
// ../core/src/organization-model/domains/sales.ts
|
|
6633
|
+
var SalesStageSemanticClassSchema = z.enum(["open", "active", "nurturing", "closed_won", "closed_lost"]);
|
|
6634
|
+
var SalesStageSchema = DisplayMetadataSchema.extend({
|
|
6635
|
+
id: ModelIdSchema,
|
|
6636
|
+
order: z.number().int().min(0),
|
|
6637
|
+
semanticClass: SalesStageSemanticClassSchema,
|
|
6638
|
+
surfaceIds: ReferenceIdsSchema,
|
|
6639
|
+
resourceIds: ReferenceIdsSchema
|
|
6640
|
+
});
|
|
6641
|
+
var SalesPipelineSchema = z.object({
|
|
6642
|
+
id: ModelIdSchema,
|
|
6643
|
+
label: z.string().trim().min(1).max(120),
|
|
6644
|
+
description: DescriptionSchema.optional(),
|
|
6645
|
+
entityId: ModelIdSchema,
|
|
6646
|
+
stages: z.array(SalesStageSchema).min(1)
|
|
6647
|
+
});
|
|
6648
|
+
z.object({
|
|
6649
|
+
entityId: ModelIdSchema,
|
|
6650
|
+
defaultPipelineId: ModelIdSchema,
|
|
6651
|
+
pipelines: z.array(SalesPipelineSchema).min(1)
|
|
6652
|
+
});
|
|
6653
|
+
var CRM_DISCOVERY_REPLIED_STATE = {
|
|
6654
|
+
stateKey: "discovery_replied",
|
|
6655
|
+
label: "Discovery Replied"
|
|
6656
|
+
};
|
|
6657
|
+
var CRM_DISCOVERY_LINK_SENT_STATE = {
|
|
6658
|
+
stateKey: "discovery_link_sent",
|
|
6659
|
+
label: "Discovery Link Sent"
|
|
6660
|
+
};
|
|
6661
|
+
var CRM_DISCOVERY_NUDGING_STATE = {
|
|
6662
|
+
stateKey: "discovery_nudging",
|
|
6663
|
+
label: "Discovery Nudging"
|
|
6664
|
+
};
|
|
6665
|
+
var CRM_DISCOVERY_BOOKING_CANCELLED_STATE = {
|
|
6666
|
+
stateKey: "discovery_booking_cancelled",
|
|
6667
|
+
label: "Discovery Booking Cancelled"
|
|
6668
|
+
};
|
|
6669
|
+
var CRM_REPLY_SENT_STATE = {
|
|
6670
|
+
stateKey: "reply_sent",
|
|
6671
|
+
label: "Reply Sent"
|
|
6672
|
+
};
|
|
6673
|
+
var CRM_FOLLOWUP_1_SENT_STATE = {
|
|
6674
|
+
stateKey: "followup_1_sent",
|
|
6675
|
+
label: "Follow-up 1 Sent"
|
|
6676
|
+
};
|
|
6677
|
+
var CRM_FOLLOWUP_2_SENT_STATE = {
|
|
6678
|
+
stateKey: "followup_2_sent",
|
|
6679
|
+
label: "Follow-up 2 Sent"
|
|
6680
|
+
};
|
|
6681
|
+
var CRM_FOLLOWUP_3_SENT_STATE = {
|
|
6682
|
+
stateKey: "followup_3_sent",
|
|
6683
|
+
label: "Follow-up 3 Sent"
|
|
6684
|
+
};
|
|
6685
|
+
var CRM_PIPELINE_DEFINITION = {
|
|
6686
|
+
pipelineKey: "crm",
|
|
6687
|
+
stages: [
|
|
6688
|
+
{
|
|
6689
|
+
stageKey: "interested",
|
|
6690
|
+
label: "Interested",
|
|
6691
|
+
color: "blue",
|
|
6692
|
+
states: [
|
|
6693
|
+
CRM_DISCOVERY_REPLIED_STATE,
|
|
6694
|
+
CRM_DISCOVERY_LINK_SENT_STATE,
|
|
6695
|
+
CRM_DISCOVERY_NUDGING_STATE,
|
|
6696
|
+
CRM_DISCOVERY_BOOKING_CANCELLED_STATE,
|
|
6697
|
+
CRM_REPLY_SENT_STATE,
|
|
6698
|
+
CRM_FOLLOWUP_1_SENT_STATE,
|
|
6699
|
+
CRM_FOLLOWUP_2_SENT_STATE,
|
|
6700
|
+
CRM_FOLLOWUP_3_SENT_STATE
|
|
6701
|
+
]
|
|
6702
|
+
},
|
|
6703
|
+
{ stageKey: "proposal", label: "Proposal", color: "yellow", states: [] },
|
|
6704
|
+
{ stageKey: "closing", label: "Closing", color: "orange", states: [] },
|
|
6705
|
+
{ stageKey: "closed_won", label: "Closed Won", color: "green", states: [] },
|
|
6706
|
+
{ stageKey: "closed_lost", label: "Closed Lost", color: "red", states: [] },
|
|
6707
|
+
{ stageKey: "nurturing", label: "Nurturing", color: "grape", states: [] }
|
|
6708
|
+
]
|
|
6709
|
+
};
|
|
6710
|
+
var LEAD_GEN_STAGE_CATALOG = {
|
|
6711
|
+
// Prospecting — company population
|
|
6712
|
+
scraped: {
|
|
6713
|
+
key: "scraped",
|
|
6714
|
+
label: "Scraped",
|
|
6715
|
+
description: "Company was scraped from a source directory (Apify actor run).",
|
|
6716
|
+
order: 1,
|
|
6717
|
+
entity: "company"
|
|
6718
|
+
},
|
|
6719
|
+
populated: {
|
|
6720
|
+
key: "populated",
|
|
6721
|
+
label: "Companies found",
|
|
6722
|
+
description: "Companies have been found and added to the lead-gen list.",
|
|
6723
|
+
order: 2,
|
|
6724
|
+
entity: "company"
|
|
6725
|
+
},
|
|
6726
|
+
extracted: {
|
|
6727
|
+
key: "extracted",
|
|
6728
|
+
label: "Websites analyzed",
|
|
6729
|
+
description: "Company websites have been analyzed for business signals.",
|
|
6730
|
+
order: 3,
|
|
6731
|
+
entity: "company"
|
|
6732
|
+
},
|
|
6733
|
+
enriched: {
|
|
6734
|
+
key: "enriched",
|
|
6735
|
+
label: "Enriched",
|
|
6736
|
+
description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
|
|
6737
|
+
order: 4,
|
|
6738
|
+
entity: "company"
|
|
6739
|
+
},
|
|
6740
|
+
"decision-makers-enriched": {
|
|
6741
|
+
key: "decision-makers-enriched",
|
|
6742
|
+
label: "Decision-makers found",
|
|
6743
|
+
description: "Decision-maker contacts discovered and attached to a qualified company.",
|
|
6744
|
+
order: 6,
|
|
6745
|
+
entity: "company"
|
|
6746
|
+
},
|
|
6747
|
+
// Prospecting — contact discovery
|
|
6748
|
+
discovered: {
|
|
6749
|
+
key: "discovered",
|
|
6750
|
+
label: "Decision-makers found",
|
|
6751
|
+
description: "Decision-maker contact details have been found.",
|
|
6752
|
+
order: 5,
|
|
6753
|
+
entity: "contact"
|
|
6754
|
+
},
|
|
6755
|
+
verified: {
|
|
6756
|
+
key: "verified",
|
|
6757
|
+
label: "Emails verified",
|
|
6758
|
+
description: "Contact email addresses have been checked for deliverability.",
|
|
6759
|
+
order: 7,
|
|
6760
|
+
entity: "contact"
|
|
6761
|
+
},
|
|
6762
|
+
// Qualification
|
|
6763
|
+
qualified: {
|
|
6764
|
+
key: "qualified",
|
|
6765
|
+
label: "Companies qualified",
|
|
6766
|
+
description: "Companies have been scored against the qualification criteria.",
|
|
6767
|
+
order: 8,
|
|
6768
|
+
entity: "company"
|
|
6769
|
+
},
|
|
6770
|
+
// Outreach
|
|
6771
|
+
personalized: {
|
|
6772
|
+
key: "personalized",
|
|
6773
|
+
label: "Personalized",
|
|
6774
|
+
description: "Outreach message personalized for the contact (Instantly personalization workflow).",
|
|
6775
|
+
order: 9,
|
|
6776
|
+
entity: "contact"
|
|
6777
|
+
},
|
|
6778
|
+
uploaded: {
|
|
6779
|
+
key: "uploaded",
|
|
6780
|
+
label: "Reviewed and exported",
|
|
6781
|
+
description: "Approved records have been reviewed and exported for handoff.",
|
|
6782
|
+
order: 10,
|
|
6783
|
+
entity: "contact"
|
|
6784
|
+
},
|
|
6785
|
+
interested: {
|
|
6786
|
+
key: "interested",
|
|
6787
|
+
label: "Interested",
|
|
6788
|
+
description: "Contact replied with a positive signal (Instantly reply-handler transition).",
|
|
6789
|
+
order: 11,
|
|
6790
|
+
entity: "contact"
|
|
6791
|
+
}
|
|
6792
|
+
};
|
|
6793
|
+
|
|
6794
|
+
// ../core/src/organization-model/domains/prospecting.ts
|
|
6795
|
+
var ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
|
|
6796
|
+
id: ModelIdSchema,
|
|
6797
|
+
order: z.number().int().min(0)
|
|
6798
|
+
});
|
|
6799
|
+
var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
|
|
6800
|
+
id: ModelIdSchema,
|
|
6801
|
+
primaryEntity: z.enum(["company", "contact"]),
|
|
6802
|
+
outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
|
|
6803
|
+
stageKey: ModelIdSchema,
|
|
6804
|
+
dependsOn: z.array(ModelIdSchema).optional(),
|
|
6805
|
+
dependencyMode: z.literal("per-record-eligibility"),
|
|
6806
|
+
capabilityKey: ModelIdSchema,
|
|
6807
|
+
defaultBatchSize: z.number().int().positive(),
|
|
6808
|
+
maxBatchSize: z.number().int().positive()
|
|
6809
|
+
}).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
|
|
6810
|
+
message: "defaultBatchSize must be less than or equal to maxBatchSize",
|
|
6811
|
+
path: ["defaultBatchSize"]
|
|
6812
|
+
});
|
|
6813
|
+
var ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
|
|
6814
|
+
id: ModelIdSchema,
|
|
6815
|
+
steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
|
|
6816
|
+
});
|
|
6817
|
+
z.object({
|
|
6818
|
+
id: ModelIdSchema,
|
|
6819
|
+
label: z.string(),
|
|
6820
|
+
description: z.string(),
|
|
6821
|
+
resourceId: ModelIdSchema
|
|
6822
|
+
});
|
|
6823
|
+
var CAPABILITY_REGISTRY = [
|
|
6824
|
+
{
|
|
6825
|
+
id: "lead-gen.company.source",
|
|
6826
|
+
label: "Source companies",
|
|
6827
|
+
description: "Import source companies from a list provider.",
|
|
6828
|
+
resourceId: "lgn-import-workflow"
|
|
6829
|
+
},
|
|
6830
|
+
{
|
|
6831
|
+
id: "lead-gen.company.apollo-import",
|
|
6832
|
+
label: "Import from Apollo",
|
|
6833
|
+
description: "Pull companies and seed contact data from an Apollo search or list.",
|
|
6834
|
+
resourceId: "lgn-01c-apollo-import-workflow"
|
|
6835
|
+
},
|
|
6836
|
+
{
|
|
6837
|
+
id: "lead-gen.contact.discover",
|
|
6838
|
+
label: "Discover contact emails",
|
|
6839
|
+
description: "Find email addresses for contacts at qualified companies.",
|
|
6840
|
+
resourceId: "lgn-04-email-discovery-workflow"
|
|
6841
|
+
},
|
|
6842
|
+
{
|
|
6843
|
+
id: "lead-gen.contact.verify-email",
|
|
6844
|
+
label: "Verify emails",
|
|
6845
|
+
description: "Check email deliverability before outreach.",
|
|
6846
|
+
resourceId: "lgn-05-email-verification-workflow"
|
|
6847
|
+
},
|
|
6848
|
+
{
|
|
6849
|
+
id: "lead-gen.company.website-extract",
|
|
6850
|
+
label: "Extract website signals",
|
|
6851
|
+
description: "Scrape and analyze company websites for qualification signals.",
|
|
6852
|
+
resourceId: "lgn-02-website-extract-workflow"
|
|
6853
|
+
},
|
|
6854
|
+
{
|
|
6855
|
+
id: "lead-gen.company.qualify",
|
|
6856
|
+
label: "Qualify companies",
|
|
6857
|
+
description: "Score and filter companies against the ICP rubric.",
|
|
6858
|
+
resourceId: "lgn-03-company-qualification-workflow"
|
|
6859
|
+
},
|
|
6860
|
+
{
|
|
6861
|
+
id: "lead-gen.company.dtc-subscription-qualify",
|
|
6862
|
+
label: "Qualify DTC subscription fit",
|
|
6863
|
+
description: "Classify subscription potential and consumable-product fit for DTC brands.",
|
|
6864
|
+
resourceId: "lgn-03b-dtc-subscription-score-workflow"
|
|
6865
|
+
},
|
|
6866
|
+
{
|
|
6867
|
+
id: "lead-gen.contact.apollo-decision-maker-enrich",
|
|
6868
|
+
label: "Enrich decision-makers",
|
|
6869
|
+
description: "Find and enrich qualified contacts at qualified companies via Apollo.",
|
|
6870
|
+
resourceId: "lgn-04b-apollo-decision-maker-enrich-workflow"
|
|
6871
|
+
},
|
|
6872
|
+
{
|
|
6873
|
+
id: "lead-gen.contact.personalize",
|
|
6874
|
+
label: "Personalize outreach",
|
|
6875
|
+
description: "Generate personalized opening lines for each contact.",
|
|
6876
|
+
resourceId: "ist-personalization-workflow"
|
|
6877
|
+
},
|
|
6878
|
+
{
|
|
6879
|
+
id: "lead-gen.review.outreach-ready",
|
|
6880
|
+
label: "Upload to outreach",
|
|
6881
|
+
description: "Upload approved contacts to the outreach sequence after QC review.",
|
|
6882
|
+
resourceId: "ist-upload-contacts-workflow"
|
|
6883
|
+
},
|
|
6884
|
+
{
|
|
6885
|
+
id: "lead-gen.export.list",
|
|
6886
|
+
label: "Export lead list",
|
|
6887
|
+
description: "Export approved leads as a downloadable lead list.",
|
|
6888
|
+
resourceId: "lgn-06-export-list-workflow"
|
|
6889
|
+
},
|
|
6890
|
+
{
|
|
6891
|
+
id: "lead-gen.company.cleanup",
|
|
6892
|
+
label: "Clean up companies",
|
|
6893
|
+
description: "Remove disqualified or duplicate companies from the list.",
|
|
6894
|
+
resourceId: "lgn-company-cleanup-workflow"
|
|
6895
|
+
}
|
|
6896
|
+
];
|
|
6897
|
+
var PROSPECTING_STEPS = {
|
|
6898
|
+
localServices: {
|
|
6899
|
+
sourceCompanies: {
|
|
6900
|
+
id: "source-companies",
|
|
6901
|
+
label: "Companies found",
|
|
6902
|
+
primaryEntity: "company",
|
|
6903
|
+
outputs: ["company"],
|
|
6904
|
+
stageKey: "populated",
|
|
6905
|
+
dependencyMode: "per-record-eligibility",
|
|
6906
|
+
capabilityKey: "lead-gen.company.source",
|
|
6907
|
+
defaultBatchSize: 100,
|
|
6908
|
+
maxBatchSize: 250
|
|
6909
|
+
},
|
|
6910
|
+
analyzeWebsites: {
|
|
6911
|
+
id: "analyze-websites",
|
|
6912
|
+
label: "Websites analyzed",
|
|
6913
|
+
primaryEntity: "company",
|
|
6914
|
+
outputs: ["company"],
|
|
6915
|
+
stageKey: "extracted",
|
|
6916
|
+
dependsOn: ["source-companies"],
|
|
6917
|
+
dependencyMode: "per-record-eligibility",
|
|
6918
|
+
capabilityKey: "lead-gen.company.website-extract",
|
|
6919
|
+
defaultBatchSize: 50,
|
|
6920
|
+
maxBatchSize: 100
|
|
6921
|
+
},
|
|
6922
|
+
qualifyCompanies: {
|
|
6923
|
+
id: "qualify-companies",
|
|
6924
|
+
label: "Companies qualified",
|
|
6925
|
+
primaryEntity: "company",
|
|
6926
|
+
outputs: ["company"],
|
|
6927
|
+
stageKey: "qualified",
|
|
6928
|
+
dependsOn: ["analyze-websites"],
|
|
6929
|
+
dependencyMode: "per-record-eligibility",
|
|
6930
|
+
capabilityKey: "lead-gen.company.qualify",
|
|
6931
|
+
defaultBatchSize: 100,
|
|
6932
|
+
maxBatchSize: 250
|
|
6933
|
+
},
|
|
6934
|
+
findContacts: {
|
|
6935
|
+
id: "find-contacts",
|
|
6936
|
+
label: "Decision-makers found",
|
|
6937
|
+
primaryEntity: "contact",
|
|
6938
|
+
outputs: ["contact"],
|
|
6939
|
+
stageKey: "discovered",
|
|
6940
|
+
dependsOn: ["qualify-companies"],
|
|
6941
|
+
dependencyMode: "per-record-eligibility",
|
|
6942
|
+
capabilityKey: "lead-gen.contact.discover",
|
|
6943
|
+
defaultBatchSize: 50,
|
|
6944
|
+
maxBatchSize: 100
|
|
6945
|
+
},
|
|
6946
|
+
verifyEmails: {
|
|
6947
|
+
id: "verify-emails",
|
|
6948
|
+
label: "Emails verified",
|
|
6949
|
+
primaryEntity: "contact",
|
|
6950
|
+
outputs: ["contact"],
|
|
6951
|
+
stageKey: "verified",
|
|
6952
|
+
dependsOn: ["find-contacts"],
|
|
6953
|
+
dependencyMode: "per-record-eligibility",
|
|
6954
|
+
capabilityKey: "lead-gen.contact.verify-email",
|
|
6955
|
+
defaultBatchSize: 100,
|
|
6956
|
+
maxBatchSize: 500
|
|
6957
|
+
},
|
|
6958
|
+
personalize: {
|
|
6959
|
+
id: "personalize",
|
|
6960
|
+
label: "Personalize",
|
|
6961
|
+
primaryEntity: "contact",
|
|
6962
|
+
outputs: ["contact"],
|
|
6963
|
+
stageKey: "personalized",
|
|
6964
|
+
dependsOn: ["verify-emails"],
|
|
6965
|
+
dependencyMode: "per-record-eligibility",
|
|
6966
|
+
capabilityKey: "lead-gen.contact.personalize",
|
|
6967
|
+
defaultBatchSize: 25,
|
|
6968
|
+
maxBatchSize: 100
|
|
6969
|
+
},
|
|
6970
|
+
review: {
|
|
6971
|
+
id: "review",
|
|
6972
|
+
label: "Reviewed and exported",
|
|
6973
|
+
primaryEntity: "contact",
|
|
6974
|
+
outputs: ["export"],
|
|
6975
|
+
stageKey: "uploaded",
|
|
6976
|
+
dependsOn: ["personalize"],
|
|
6977
|
+
dependencyMode: "per-record-eligibility",
|
|
6978
|
+
capabilityKey: "lead-gen.review.outreach-ready",
|
|
6979
|
+
defaultBatchSize: 25,
|
|
6980
|
+
maxBatchSize: 100
|
|
6981
|
+
}
|
|
6982
|
+
},
|
|
6983
|
+
dtcApolloClickup: {
|
|
6984
|
+
importApolloSearch: {
|
|
6985
|
+
id: "import-apollo-search",
|
|
6986
|
+
label: "Companies found",
|
|
6987
|
+
description: "Pull companies and seed contact data from a predefined Apollo search or list.",
|
|
6988
|
+
primaryEntity: "company",
|
|
6989
|
+
outputs: ["company", "contact"],
|
|
6990
|
+
stageKey: "populated",
|
|
6991
|
+
dependencyMode: "per-record-eligibility",
|
|
6992
|
+
capabilityKey: "lead-gen.company.apollo-import",
|
|
6993
|
+
defaultBatchSize: 250,
|
|
6994
|
+
maxBatchSize: 1e3
|
|
6995
|
+
},
|
|
6996
|
+
analyzeWebsites: {
|
|
6997
|
+
id: "analyze-websites",
|
|
6998
|
+
label: "Websites analyzed",
|
|
6999
|
+
description: "Extract subscription, product, retention, and tech-stack signals from each brand website.",
|
|
7000
|
+
primaryEntity: "company",
|
|
7001
|
+
outputs: ["company"],
|
|
7002
|
+
stageKey: "extracted",
|
|
7003
|
+
dependsOn: ["import-apollo-search"],
|
|
7004
|
+
dependencyMode: "per-record-eligibility",
|
|
7005
|
+
capabilityKey: "lead-gen.company.website-extract",
|
|
7006
|
+
defaultBatchSize: 50,
|
|
7007
|
+
maxBatchSize: 100
|
|
7008
|
+
},
|
|
7009
|
+
scoreDtcFit: {
|
|
7010
|
+
id: "score-dtc-fit",
|
|
7011
|
+
label: "Companies qualified",
|
|
7012
|
+
description: "Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.",
|
|
7013
|
+
primaryEntity: "company",
|
|
7014
|
+
outputs: ["company"],
|
|
7015
|
+
stageKey: "qualified",
|
|
7016
|
+
dependsOn: ["analyze-websites"],
|
|
7017
|
+
dependencyMode: "per-record-eligibility",
|
|
7018
|
+
capabilityKey: "lead-gen.company.dtc-subscription-qualify",
|
|
7019
|
+
defaultBatchSize: 100,
|
|
7020
|
+
maxBatchSize: 250
|
|
7021
|
+
},
|
|
7022
|
+
enrichDecisionMakers: {
|
|
7023
|
+
id: "enrich-decision-makers",
|
|
7024
|
+
label: "Decision-makers found",
|
|
7025
|
+
description: "Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.",
|
|
7026
|
+
primaryEntity: "company",
|
|
7027
|
+
outputs: ["contact"],
|
|
7028
|
+
stageKey: "decision-makers-enriched",
|
|
7029
|
+
dependsOn: ["score-dtc-fit"],
|
|
7030
|
+
dependencyMode: "per-record-eligibility",
|
|
7031
|
+
capabilityKey: "lead-gen.contact.apollo-decision-maker-enrich",
|
|
7032
|
+
defaultBatchSize: 100,
|
|
7033
|
+
maxBatchSize: 250
|
|
7034
|
+
},
|
|
7035
|
+
verifyEmails: {
|
|
7036
|
+
id: "verify-emails",
|
|
7037
|
+
label: "Emails verified",
|
|
7038
|
+
description: "Verify deliverability before the QC and handoff step.",
|
|
7039
|
+
primaryEntity: "contact",
|
|
7040
|
+
outputs: ["contact"],
|
|
7041
|
+
stageKey: "verified",
|
|
7042
|
+
dependsOn: ["enrich-decision-makers"],
|
|
7043
|
+
dependencyMode: "per-record-eligibility",
|
|
7044
|
+
capabilityKey: "lead-gen.contact.verify-email",
|
|
7045
|
+
defaultBatchSize: 250,
|
|
7046
|
+
maxBatchSize: 500
|
|
7047
|
+
},
|
|
7048
|
+
reviewAndExport: {
|
|
7049
|
+
id: "review-and-export",
|
|
7050
|
+
label: "Reviewed and exported",
|
|
7051
|
+
description: "Operator QC approves or rejects leads, then approved records are exported as a lead list.",
|
|
7052
|
+
primaryEntity: "company",
|
|
7053
|
+
outputs: ["export"],
|
|
7054
|
+
stageKey: "uploaded",
|
|
7055
|
+
dependsOn: ["verify-emails"],
|
|
7056
|
+
dependencyMode: "per-record-eligibility",
|
|
7057
|
+
capabilityKey: "lead-gen.export.list",
|
|
7058
|
+
defaultBatchSize: 100,
|
|
7059
|
+
maxBatchSize: 250
|
|
7060
|
+
}
|
|
7061
|
+
}
|
|
7062
|
+
};
|
|
7063
|
+
z.object({
|
|
7064
|
+
listEntityId: ModelIdSchema,
|
|
7065
|
+
companyEntityId: ModelIdSchema,
|
|
7066
|
+
contactEntityId: ModelIdSchema,
|
|
7067
|
+
description: DescriptionSchema.optional(),
|
|
7068
|
+
companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
|
|
7069
|
+
contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
|
|
7070
|
+
defaultBuildTemplateId: ModelIdSchema,
|
|
7071
|
+
buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
|
|
7072
|
+
});
|
|
7073
|
+
function toProspectingLifecycleStage(stage) {
|
|
7074
|
+
return {
|
|
7075
|
+
id: stage.key,
|
|
7076
|
+
label: stage.label,
|
|
7077
|
+
order: stage.order
|
|
7078
|
+
};
|
|
7079
|
+
}
|
|
7080
|
+
function leadGenStagesForEntity(entity) {
|
|
7081
|
+
return Object.values(LEAD_GEN_STAGE_CATALOG).filter((stage) => stage.entity === entity).sort((a3, b2) => a3.order - b2.order).map(toProspectingLifecycleStage);
|
|
7082
|
+
}
|
|
7083
|
+
var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
|
|
7084
|
+
companyStages: leadGenStagesForEntity("company"),
|
|
7085
|
+
contactStages: leadGenStagesForEntity("contact"),
|
|
7086
|
+
buildTemplates: [
|
|
7087
|
+
{
|
|
7088
|
+
id: "local-services",
|
|
7089
|
+
label: "Local Services Prospecting",
|
|
7090
|
+
description: "Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.",
|
|
7091
|
+
steps: [
|
|
7092
|
+
PROSPECTING_STEPS.localServices.sourceCompanies,
|
|
7093
|
+
PROSPECTING_STEPS.localServices.analyzeWebsites,
|
|
7094
|
+
PROSPECTING_STEPS.localServices.qualifyCompanies,
|
|
7095
|
+
PROSPECTING_STEPS.localServices.findContacts,
|
|
7096
|
+
PROSPECTING_STEPS.localServices.verifyEmails,
|
|
7097
|
+
PROSPECTING_STEPS.localServices.personalize,
|
|
7098
|
+
PROSPECTING_STEPS.localServices.review
|
|
7099
|
+
]
|
|
7100
|
+
},
|
|
7101
|
+
{
|
|
7102
|
+
id: "dtc-subscription-apollo-clickup",
|
|
7103
|
+
label: "DTC Subscription Apollo Export",
|
|
7104
|
+
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.",
|
|
7105
|
+
steps: [
|
|
7106
|
+
PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
|
|
7107
|
+
PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
|
|
7108
|
+
PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
|
|
7109
|
+
PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
|
|
7110
|
+
PROSPECTING_STEPS.dtcApolloClickup.verifyEmails,
|
|
7111
|
+
PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
|
|
7112
|
+
]
|
|
7113
|
+
}
|
|
7114
|
+
]
|
|
7115
|
+
};
|
|
7116
|
+
|
|
7117
|
+
// ../core/src/business/acquisition/build-templates.ts
|
|
7118
|
+
var PROSPECTING_BUILD_TEMPLATE_OPTIONS = DEFAULT_ORGANIZATION_MODEL_PROSPECTING.buildTemplates.map(
|
|
7119
|
+
({ id, label, description }) => ({
|
|
7120
|
+
id,
|
|
7121
|
+
label,
|
|
7122
|
+
description
|
|
7123
|
+
})
|
|
7124
|
+
);
|
|
7125
|
+
function isProspectingBuildTemplateId(value) {
|
|
7126
|
+
return PROSPECTING_BUILD_TEMPLATE_OPTIONS.some((template) => template.id === value);
|
|
7127
|
+
}
|
|
7128
|
+
var ProcessingStageStatusSchema = z.enum(["success", "no_result", "skipped", "error"]);
|
|
7129
|
+
var LeadGenStageKeySchema = z.string().refine((value) => Object.prototype.hasOwnProperty.call(LEAD_GEN_STAGE_CATALOG, value), {
|
|
7130
|
+
message: "processing state key must match LEAD_GEN_STAGE_CATALOG"
|
|
7131
|
+
});
|
|
7132
|
+
var LeadGenCapabilityKeySchema = z.string().refine((value) => CAPABILITY_REGISTRY.some((c) => c.id === value), {
|
|
7133
|
+
message: "capabilityKey must match CAPABILITY_REGISTRY"
|
|
7134
|
+
});
|
|
7135
|
+
var crmStageKeys = CRM_PIPELINE_DEFINITION.stages.map((stage) => stage.stageKey);
|
|
7136
|
+
var crmStateKeys = CRM_PIPELINE_DEFINITION.stages.flatMap((stage) => stage.states.map((state) => state.stateKey));
|
|
7137
|
+
var CrmStageKeySchema = z.enum(crmStageKeys);
|
|
7138
|
+
var CrmStateKeySchema = z.enum(crmStateKeys);
|
|
7139
|
+
var ProcessingStateEntrySchema = z.object({
|
|
7140
|
+
status: ProcessingStageStatusSchema,
|
|
7141
|
+
data: z.unknown().optional()
|
|
7142
|
+
}).passthrough();
|
|
7143
|
+
var ProcessingStateSchema = z.record(LeadGenStageKeySchema, ProcessingStateEntrySchema);
|
|
7144
|
+
var CompanyProcessingStateSchema = ProcessingStateSchema;
|
|
7145
|
+
var ContactProcessingStateSchema = ProcessingStateSchema;
|
|
7146
|
+
var DealStageSchema = CrmStageKeySchema;
|
|
7147
|
+
var AcqDealTaskKindSchema = z.enum(["call", "email", "meeting", "other"]);
|
|
7148
|
+
z.object({
|
|
7149
|
+
dealId: UuidSchema
|
|
7150
|
+
});
|
|
7151
|
+
z.object({
|
|
7152
|
+
dealId: UuidSchema,
|
|
7153
|
+
taskId: UuidSchema
|
|
7154
|
+
});
|
|
7155
|
+
z.object({
|
|
7156
|
+
stage: DealStageSchema.optional(),
|
|
7157
|
+
search: z.string().optional(),
|
|
7158
|
+
limit: z.coerce.number().int().positive().default(50),
|
|
7159
|
+
offset: z.coerce.number().int().min(0).default(0)
|
|
7160
|
+
}).strict();
|
|
7161
|
+
z.object({
|
|
7162
|
+
search: z.string().trim().min(1).max(200).optional(),
|
|
7163
|
+
limit: z.coerce.number().int().min(1).max(25).default(10)
|
|
7164
|
+
}).strict();
|
|
7165
|
+
z.object({
|
|
7166
|
+
window: z.enum(["overdue", "today", "today_and_overdue", "upcoming"]).optional(),
|
|
7167
|
+
assigneeUserId: UuidSchema.optional()
|
|
7168
|
+
}).strict();
|
|
7169
|
+
z.object({
|
|
7170
|
+
body: z.string().trim().min(1).max(1e4)
|
|
7171
|
+
}).strict();
|
|
7172
|
+
z.object({
|
|
7173
|
+
title: z.string().trim().min(1).max(255),
|
|
7174
|
+
description: z.string().nullable().optional(),
|
|
7175
|
+
kind: AcqDealTaskKindSchema.optional(),
|
|
7176
|
+
dueAt: z.string().datetime().nullable().optional(),
|
|
7177
|
+
assigneeUserId: UuidSchema.nullable().optional()
|
|
7178
|
+
}).strict();
|
|
7179
|
+
z.object({
|
|
7180
|
+
pipelineKey: z.string().min(1),
|
|
7181
|
+
stageKey: z.string().min(1),
|
|
7182
|
+
stateKey: z.string().min(1).nullable().optional(),
|
|
7183
|
+
reason: z.string().optional(),
|
|
7184
|
+
expectedUpdatedAt: z.string().datetime().optional()
|
|
7185
|
+
}).strict();
|
|
7186
|
+
z.object({
|
|
7187
|
+
pipelineKey: z.literal(CRM_PIPELINE_DEFINITION.pipelineKey),
|
|
7188
|
+
stageKey: CrmStageKeySchema,
|
|
7189
|
+
stateKey: CrmStateKeySchema.nullable().optional(),
|
|
7190
|
+
reason: z.string().optional(),
|
|
7191
|
+
expectedUpdatedAt: z.string().datetime().optional()
|
|
7192
|
+
}).strict();
|
|
7193
|
+
z.object({
|
|
7194
|
+
stateKey: CrmStateKeySchema,
|
|
7195
|
+
reason: z.string().optional(),
|
|
7196
|
+
expectedUpdatedAt: z.string().datetime().optional()
|
|
7197
|
+
}).strict();
|
|
7198
|
+
z.object({
|
|
7199
|
+
dealId: UuidSchema,
|
|
7200
|
+
actionKey: NonEmptyStringSchema
|
|
7201
|
+
}).strict();
|
|
7202
|
+
z.object({
|
|
7203
|
+
payload: z.record(z.string(), z.unknown()).optional()
|
|
7204
|
+
}).strict();
|
|
7205
|
+
var DealContactSummarySchema = z.object({
|
|
7206
|
+
id: z.string(),
|
|
7207
|
+
first_name: z.string().nullable(),
|
|
7208
|
+
last_name: z.string().nullable(),
|
|
7209
|
+
email: z.string(),
|
|
7210
|
+
title: z.string().nullable(),
|
|
7211
|
+
headline: z.string().nullable(),
|
|
7212
|
+
linkedin_url: z.string().nullable(),
|
|
7213
|
+
processing_state: ProcessingStateSchema.nullable(),
|
|
7214
|
+
enrichment_data: z.record(z.string(), z.unknown()).nullable(),
|
|
7215
|
+
company: z.object({
|
|
7216
|
+
id: z.string(),
|
|
7217
|
+
name: z.string(),
|
|
7218
|
+
domain: z.string().nullable(),
|
|
7219
|
+
website: z.string().nullable(),
|
|
7220
|
+
linkedin_url: z.string().nullable(),
|
|
7221
|
+
segment: z.string().nullable(),
|
|
7222
|
+
category: z.string().nullable(),
|
|
7223
|
+
num_employees: z.number().nullable()
|
|
7224
|
+
}).nullable()
|
|
7225
|
+
});
|
|
7226
|
+
var DealPrioritySchema = z.object({
|
|
7227
|
+
bucketKey: z.enum(["needs_response", "follow_up_due", "waiting", "stale", "closed_low"]),
|
|
7228
|
+
rank: z.number().int(),
|
|
7229
|
+
label: z.string(),
|
|
7230
|
+
color: z.string(),
|
|
7231
|
+
reason: z.string(),
|
|
7232
|
+
latestActivityAt: z.string().nullable(),
|
|
7233
|
+
nextActionAt: z.string().nullable()
|
|
7234
|
+
});
|
|
7235
|
+
var DealListItemSchema = z.object({
|
|
7236
|
+
// acq_deals columns
|
|
7237
|
+
id: z.string(),
|
|
7238
|
+
organization_id: z.string(),
|
|
7239
|
+
contact_id: z.string().nullable(),
|
|
7240
|
+
contact_email: z.string(),
|
|
7241
|
+
pipeline_key: z.string(),
|
|
7242
|
+
stage_key: z.string().nullable(),
|
|
7243
|
+
state_key: z.string().nullable(),
|
|
7244
|
+
activity_log: z.unknown(),
|
|
7245
|
+
discovery_data: z.unknown().nullable(),
|
|
7246
|
+
discovery_submitted_at: z.string().nullable(),
|
|
7247
|
+
discovery_submitted_by: z.string().nullable(),
|
|
7248
|
+
proposal_data: z.unknown().nullable(),
|
|
7249
|
+
proposal_sent_at: z.string().nullable(),
|
|
7250
|
+
proposal_pdf_url: z.string().nullable(),
|
|
7251
|
+
signature_envelope_id: z.string().nullable(),
|
|
7252
|
+
source_list_id: z.string().nullable(),
|
|
7253
|
+
source_type: z.string().nullable(),
|
|
7254
|
+
initial_fee: z.number().nullable(),
|
|
7255
|
+
monthly_fee: z.number().nullable(),
|
|
7256
|
+
closed_lost_at: z.string().nullable(),
|
|
7257
|
+
closed_lost_reason: z.string().nullable(),
|
|
7258
|
+
created_at: z.string(),
|
|
7259
|
+
updated_at: z.string(),
|
|
7260
|
+
priority: DealPrioritySchema,
|
|
7261
|
+
ownership: z.enum(["us", "them"]).nullable(),
|
|
7262
|
+
nextAction: z.string().nullable(),
|
|
7263
|
+
// joined relation
|
|
7264
|
+
contact: DealContactSummarySchema.nullable()
|
|
7265
|
+
});
|
|
7266
|
+
z.object({
|
|
7267
|
+
data: z.array(DealListItemSchema),
|
|
7268
|
+
total: z.number().int(),
|
|
7269
|
+
limit: z.number().int(),
|
|
7270
|
+
offset: z.number().int()
|
|
7271
|
+
});
|
|
7272
|
+
var DealStageSummarySchema = z.object({
|
|
7273
|
+
stage: z.string(),
|
|
7274
|
+
count: z.number().int(),
|
|
7275
|
+
totalValue: z.number(),
|
|
7276
|
+
oldestUpdatedAt: z.string().nullable(),
|
|
7277
|
+
newestUpdatedAt: z.string().nullable()
|
|
7278
|
+
});
|
|
7279
|
+
var StaleDealSummarySchema = z.object({
|
|
7280
|
+
id: z.string(),
|
|
7281
|
+
contactEmail: z.string(),
|
|
7282
|
+
stageKey: z.string(),
|
|
7283
|
+
updatedAt: z.string(),
|
|
7284
|
+
daysStale: z.number().int()
|
|
7285
|
+
});
|
|
7286
|
+
z.object({
|
|
7287
|
+
totalDeals: z.number().int(),
|
|
7288
|
+
openDeals: z.number().int(),
|
|
7289
|
+
wonDeals: z.number().int(),
|
|
7290
|
+
lostDeals: z.number().int(),
|
|
7291
|
+
winRate: z.number(),
|
|
7292
|
+
avgDealSize: z.number(),
|
|
7293
|
+
totalPipelineValue: z.number(),
|
|
7294
|
+
stageSummary: z.array(DealStageSummarySchema),
|
|
7295
|
+
staleDeals: z.array(StaleDealSummarySchema)
|
|
7296
|
+
});
|
|
7297
|
+
var DealLookupItemSchema = z.object({
|
|
7298
|
+
id: z.string(),
|
|
7299
|
+
contactEmail: z.string(),
|
|
7300
|
+
stageKey: z.string().nullable(),
|
|
7301
|
+
updatedAt: z.string(),
|
|
7302
|
+
contactName: z.string().nullable(),
|
|
7303
|
+
companyName: z.string().nullable(),
|
|
7304
|
+
displayLabel: z.string()
|
|
7305
|
+
});
|
|
7306
|
+
z.array(DealLookupItemSchema);
|
|
7307
|
+
var ConversationMessageSchema = z.object({
|
|
7308
|
+
id: z.string(),
|
|
7309
|
+
direction: z.enum(["inbound", "outbound"]),
|
|
7310
|
+
fromEmail: z.string(),
|
|
7311
|
+
toEmail: z.string(),
|
|
7312
|
+
subject: z.string().nullable(),
|
|
7313
|
+
body: z.string(),
|
|
7314
|
+
sentAt: z.string().nullable()
|
|
7315
|
+
});
|
|
7316
|
+
var DealConversationSchema = z.object({
|
|
7317
|
+
messages: z.array(ConversationMessageSchema)
|
|
7318
|
+
});
|
|
7319
|
+
DealListItemSchema.extend({
|
|
7320
|
+
conversation: DealConversationSchema
|
|
7321
|
+
});
|
|
7322
|
+
var DealNoteResponseSchema = z.object({
|
|
7323
|
+
id: z.string(),
|
|
7324
|
+
dealId: z.string(),
|
|
7325
|
+
organizationId: z.string(),
|
|
7326
|
+
authorUserId: z.string().nullable(),
|
|
7327
|
+
body: z.string(),
|
|
7328
|
+
createdAt: z.string(),
|
|
7329
|
+
updatedAt: z.string()
|
|
7330
|
+
});
|
|
7331
|
+
z.array(DealNoteResponseSchema);
|
|
7332
|
+
var DealTaskResponseSchema = z.object({
|
|
7333
|
+
id: z.string(),
|
|
7334
|
+
organizationId: z.string(),
|
|
7335
|
+
dealId: z.string(),
|
|
7336
|
+
title: z.string(),
|
|
7337
|
+
description: z.string().nullable(),
|
|
7338
|
+
kind: AcqDealTaskKindSchema,
|
|
7339
|
+
dueAt: z.string().nullable(),
|
|
7340
|
+
assigneeUserId: z.string().nullable(),
|
|
7341
|
+
completedAt: z.string().nullable(),
|
|
7342
|
+
completedByUserId: z.string().nullable(),
|
|
7343
|
+
createdAt: z.string(),
|
|
7344
|
+
updatedAt: z.string(),
|
|
7345
|
+
createdByUserId: z.string().nullable()
|
|
7346
|
+
});
|
|
7347
|
+
z.array(DealTaskResponseSchema);
|
|
7348
|
+
var ListStatusSchema = z.enum(["draft", "enriching", "launched", "closing", "archived"]);
|
|
7349
|
+
var ScrapingConfigSchema = z.object({
|
|
7350
|
+
vertical: z.string().trim().max(255).optional(),
|
|
7351
|
+
geography: z.string().trim().max(500).optional(),
|
|
7352
|
+
size: z.string().trim().max(255).optional(),
|
|
7353
|
+
apifyInput: z.record(z.string(), z.unknown()).optional()
|
|
7354
|
+
});
|
|
7355
|
+
var IcpRubricSchema = z.object({
|
|
7356
|
+
qualificationRubricKey: z.string().trim().max(255).nullish(),
|
|
7357
|
+
targetDescription: z.string().optional(),
|
|
7358
|
+
minReviewCount: z.number().int().min(0).optional(),
|
|
7359
|
+
minRating: z.number().min(0).max(5).optional(),
|
|
7360
|
+
excludeFranchises: z.boolean().optional(),
|
|
7361
|
+
customRules: z.string().optional()
|
|
7362
|
+
});
|
|
7363
|
+
var PipelineStageSchema = z.object({
|
|
7364
|
+
key: z.string().refine((value) => Object.prototype.hasOwnProperty.call(LEAD_GEN_STAGE_CATALOG, value), {
|
|
7365
|
+
message: "pipeline stage key must match LEAD_GEN_STAGE_CATALOG"
|
|
7366
|
+
}),
|
|
7367
|
+
label: z.string().optional(),
|
|
7368
|
+
enabled: z.boolean().optional(),
|
|
7369
|
+
order: z.number().int().optional()
|
|
7370
|
+
});
|
|
7371
|
+
var PipelineConfigSchema = z.object({
|
|
7372
|
+
stages: z.array(PipelineStageSchema).optional()
|
|
7373
|
+
});
|
|
7374
|
+
var BuildPlanSnapshotStepSchema = z.object({
|
|
7375
|
+
id: z.string().trim().min(1).max(100),
|
|
7376
|
+
label: z.string().trim().min(1).max(120),
|
|
7377
|
+
description: z.string().trim().min(1).max(2e3).optional(),
|
|
7378
|
+
primaryEntity: z.enum(["company", "contact"]),
|
|
7379
|
+
outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
|
|
7380
|
+
stageKey: LeadGenStageKeySchema,
|
|
7381
|
+
dependsOn: z.array(z.string().trim().min(1).max(100)).optional(),
|
|
7382
|
+
dependencyMode: z.literal("per-record-eligibility"),
|
|
7383
|
+
capabilityKey: LeadGenCapabilityKeySchema,
|
|
7384
|
+
defaultBatchSize: z.number().int().positive(),
|
|
7385
|
+
maxBatchSize: z.number().int().positive()
|
|
7386
|
+
}).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
|
|
7387
|
+
message: "defaultBatchSize must be less than or equal to maxBatchSize",
|
|
7388
|
+
path: ["defaultBatchSize"]
|
|
7389
|
+
});
|
|
7390
|
+
var BuildPlanSnapshotSchema = z.object({
|
|
7391
|
+
templateId: z.string().trim().min(1).max(100),
|
|
7392
|
+
templateLabel: z.string().trim().min(1).max(120),
|
|
7393
|
+
steps: z.array(BuildPlanSnapshotStepSchema).min(1)
|
|
7394
|
+
}).superRefine((snapshot, ctx) => {
|
|
7395
|
+
const stepIds = /* @__PURE__ */ new Set();
|
|
7396
|
+
snapshot.steps.forEach((step, index2) => {
|
|
7397
|
+
if (stepIds.has(step.id)) {
|
|
7398
|
+
ctx.addIssue({
|
|
7399
|
+
code: z.ZodIssueCode.custom,
|
|
7400
|
+
message: `duplicate build-plan step id "${step.id}"`,
|
|
7401
|
+
path: ["steps", index2, "id"]
|
|
7402
|
+
});
|
|
7403
|
+
}
|
|
7404
|
+
stepIds.add(step.id);
|
|
7405
|
+
});
|
|
7406
|
+
snapshot.steps.forEach((step, index2) => {
|
|
7407
|
+
for (const dependencyId of step.dependsOn ?? []) {
|
|
7408
|
+
if (!stepIds.has(dependencyId)) {
|
|
7409
|
+
ctx.addIssue({
|
|
7410
|
+
code: z.ZodIssueCode.custom,
|
|
7411
|
+
message: `dependsOn references unknown build-plan step "${dependencyId}"`,
|
|
7412
|
+
path: ["steps", index2, "dependsOn"]
|
|
7413
|
+
});
|
|
7414
|
+
}
|
|
7415
|
+
}
|
|
7416
|
+
});
|
|
7417
|
+
});
|
|
7418
|
+
var AcqListMetadataSchema = z.object({
|
|
7419
|
+
buildPlanSnapshot: BuildPlanSnapshotSchema.optional()
|
|
7420
|
+
}).catchall(z.unknown());
|
|
7421
|
+
var ProspectingBuildTemplateIdSchema = z.string().trim().min(1).max(100).refine(isProspectingBuildTemplateId, {
|
|
7422
|
+
message: "buildTemplateId must match a known prospecting build template"
|
|
7423
|
+
});
|
|
7424
|
+
var ListStageCountsSchema = z.object({
|
|
7425
|
+
// Attempted counts by canonical lead-gen stage. The detailed status
|
|
7426
|
+
// distribution lives on ListProgress; telemetry keeps the overview payload small.
|
|
7427
|
+
stageCounts: z.object({
|
|
7428
|
+
populated: z.number().int(),
|
|
7429
|
+
extracted: z.number().int(),
|
|
7430
|
+
qualified: z.number().int(),
|
|
7431
|
+
discovered: z.number().int(),
|
|
7432
|
+
verified: z.number().int(),
|
|
7433
|
+
personalized: z.number().int(),
|
|
7434
|
+
uploaded: z.number().int()
|
|
7435
|
+
}),
|
|
7436
|
+
deliverability: z.object({
|
|
7437
|
+
valid: z.number().int(),
|
|
7438
|
+
risky: z.number().int(),
|
|
7439
|
+
invalid: z.number().int(),
|
|
7440
|
+
unknown: z.number().int(),
|
|
7441
|
+
bounced: z.number().int()
|
|
7442
|
+
})
|
|
7443
|
+
});
|
|
7444
|
+
var ListTelemetrySchema = z.object({
|
|
7445
|
+
listId: UuidSchema,
|
|
7446
|
+
totalCompanies: z.number().int(),
|
|
7447
|
+
totalContacts: z.number().int(),
|
|
7448
|
+
stageCounts: ListStageCountsSchema.shape.stageCounts,
|
|
7449
|
+
deliverability: ListStageCountsSchema.shape.deliverability,
|
|
7450
|
+
activeWorkflows: z.array(z.string()).optional()
|
|
7451
|
+
});
|
|
7452
|
+
z.object({
|
|
7453
|
+
listId: UuidSchema
|
|
7454
|
+
});
|
|
7455
|
+
z.object({
|
|
7456
|
+
name: z.string().trim().min(1).max(255),
|
|
7457
|
+
description: z.string().trim().nullable().optional(),
|
|
7458
|
+
status: ListStatusSchema.optional(),
|
|
7459
|
+
buildTemplateId: ProspectingBuildTemplateIdSchema.optional(),
|
|
7460
|
+
scrapingConfig: ScrapingConfigSchema.optional(),
|
|
7461
|
+
icp: IcpRubricSchema.optional(),
|
|
7462
|
+
pipelineConfig: PipelineConfigSchema.optional()
|
|
7463
|
+
}).strict();
|
|
7464
|
+
z.object({
|
|
7465
|
+
name: z.string().trim().min(1).max(255).optional(),
|
|
7466
|
+
description: z.string().trim().nullable().optional(),
|
|
7467
|
+
batchIds: z.array(z.string()).optional(),
|
|
7468
|
+
buildTemplateId: ProspectingBuildTemplateIdSchema.optional(),
|
|
7469
|
+
confirmBuildTemplateChange: z.literal(true).optional()
|
|
7470
|
+
}).strict().refine(
|
|
7471
|
+
(data) => data.name !== void 0 || data.description !== void 0 || data.batchIds !== void 0 || data.buildTemplateId !== void 0,
|
|
7472
|
+
{
|
|
7473
|
+
message: "At least one field (name, description, batchIds, or buildTemplateId) must be provided"
|
|
7474
|
+
}
|
|
7475
|
+
).refine((data) => data.buildTemplateId === void 0 || data.confirmBuildTemplateChange === true, {
|
|
7476
|
+
message: "confirmBuildTemplateChange must be true when changing buildTemplateId",
|
|
7477
|
+
path: ["confirmBuildTemplateChange"]
|
|
7478
|
+
});
|
|
7479
|
+
z.object({
|
|
7480
|
+
status: ListStatusSchema
|
|
7481
|
+
}).strict();
|
|
7482
|
+
z.object({
|
|
7483
|
+
scrapingConfig: ScrapingConfigSchema.partial().optional(),
|
|
7484
|
+
icp: IcpRubricSchema.partial().optional(),
|
|
7485
|
+
pipelineConfig: PipelineConfigSchema.partial().optional()
|
|
7486
|
+
}).strict().refine((data) => data.scrapingConfig !== void 0 || data.icp !== void 0 || data.pipelineConfig !== void 0, {
|
|
7487
|
+
message: "At least one of scrapingConfig, icp, or pipelineConfig must be provided"
|
|
7488
|
+
});
|
|
7489
|
+
z.object({
|
|
7490
|
+
companyIds: z.array(UuidSchema).min(1).max(1e3)
|
|
7491
|
+
}).strict();
|
|
7492
|
+
z.object({
|
|
7493
|
+
companyIds: z.array(UuidSchema).min(1).max(1e3)
|
|
7494
|
+
}).strict();
|
|
7495
|
+
z.object({
|
|
7496
|
+
contactIds: z.array(UuidSchema).min(1).max(1e3)
|
|
7497
|
+
}).strict();
|
|
7498
|
+
z.object({
|
|
7499
|
+
executionId: UuidSchema,
|
|
7500
|
+
configSnapshot: z.record(z.string(), z.unknown()).optional()
|
|
7501
|
+
}).strict();
|
|
7502
|
+
var AcqListResponseSchema = z.object({
|
|
7503
|
+
id: z.string(),
|
|
7504
|
+
organizationId: z.string(),
|
|
7505
|
+
name: z.string(),
|
|
7506
|
+
description: z.string().nullable(),
|
|
7507
|
+
batchIds: z.array(z.string()),
|
|
7508
|
+
instantlyCampaignId: z.string().nullable(),
|
|
7509
|
+
/** Lifecycle status (draft | enriching | launched | closing | archived). */
|
|
7510
|
+
status: ListStatusSchema,
|
|
7511
|
+
metadata: AcqListMetadataSchema,
|
|
7512
|
+
launchedAt: z.string().nullable(),
|
|
7513
|
+
completedAt: z.string().nullable(),
|
|
7514
|
+
createdAt: z.string(),
|
|
7515
|
+
/** Scraping criteria stored as jsonb on the row. */
|
|
7516
|
+
scrapingConfig: ScrapingConfigSchema,
|
|
7517
|
+
/** ICP / qualification rubric stored as jsonb on the row. */
|
|
7518
|
+
icp: IcpRubricSchema,
|
|
7519
|
+
/** Pipeline presentation contract stored as jsonb on the row. */
|
|
7520
|
+
pipelineConfig: PipelineConfigSchema
|
|
7521
|
+
});
|
|
7522
|
+
z.array(AcqListResponseSchema);
|
|
7523
|
+
z.array(ListTelemetrySchema);
|
|
7524
|
+
var ListStageProgressSchema = z.object({
|
|
7525
|
+
total: z.number().int().min(0),
|
|
7526
|
+
attempted: z.number().int().min(0),
|
|
7527
|
+
success: z.number().int().min(0),
|
|
7528
|
+
noResult: z.number().int().min(0),
|
|
7529
|
+
skipped: z.number().int().min(0),
|
|
7530
|
+
error: z.number().int().min(0),
|
|
7531
|
+
other: z.number().int().min(0),
|
|
7532
|
+
notAttempted: z.number().int().min(0)
|
|
7533
|
+
});
|
|
7534
|
+
z.object({
|
|
7535
|
+
totalMembers: z.number().int().min(0),
|
|
7536
|
+
totalCompanies: z.number().int().min(0),
|
|
7537
|
+
byCompanyStage: z.record(z.string(), ListStageProgressSchema),
|
|
7538
|
+
byContactStage: z.record(z.string(), ListStageProgressSchema)
|
|
7539
|
+
});
|
|
7540
|
+
var ListExecutionSummarySchema = z.object({
|
|
7541
|
+
executionId: z.string(),
|
|
7542
|
+
resourceId: z.string(),
|
|
7543
|
+
status: z.string(),
|
|
7544
|
+
createdAt: z.string(),
|
|
7545
|
+
completedAt: z.string().nullable(),
|
|
7546
|
+
durationMs: z.number().int().nullable(),
|
|
7547
|
+
input: z.unknown().nullable().optional()
|
|
7548
|
+
});
|
|
7549
|
+
z.array(ListExecutionSummarySchema);
|
|
7550
|
+
var QueryBooleanSchema = z.preprocess((value) => {
|
|
7551
|
+
if (value === "true" || value === "1" || value === true) return true;
|
|
7552
|
+
if (value === "false" || value === "0" || value === false) return false;
|
|
7553
|
+
return value;
|
|
7554
|
+
}, z.boolean());
|
|
7555
|
+
var AcqCompanyStatusSchema = z.enum(["active", "invalid"]);
|
|
7556
|
+
var AcqContactStatusSchema = z.enum(["active", "invalid"]);
|
|
7557
|
+
var AcqEmailValidSchema = z.enum(["VALID", "INVALID", "RISKY", "UNKNOWN"]);
|
|
7558
|
+
z.object({
|
|
7559
|
+
companyId: UuidSchema
|
|
7560
|
+
});
|
|
7561
|
+
z.object({
|
|
7562
|
+
contactId: UuidSchema
|
|
7563
|
+
});
|
|
7564
|
+
z.object({
|
|
7565
|
+
search: z.string().trim().min(1).max(200).optional(),
|
|
7566
|
+
listId: UuidSchema.optional(),
|
|
7567
|
+
domain: z.string().trim().min(1).max(255).optional(),
|
|
7568
|
+
website: z.string().trim().min(1).max(2048).optional(),
|
|
7569
|
+
segment: z.string().trim().min(1).max(255).optional(),
|
|
7570
|
+
category: z.string().trim().min(1).max(255).optional(),
|
|
7571
|
+
pipelineStatus: z.unknown().optional(),
|
|
7572
|
+
batchId: z.string().trim().min(1).max(255).optional(),
|
|
7573
|
+
status: AcqCompanyStatusSchema.optional(),
|
|
7574
|
+
includeAll: QueryBooleanSchema.optional(),
|
|
7575
|
+
limit: z.coerce.number().int().min(1).max(5e3).default(50),
|
|
7576
|
+
offset: z.coerce.number().int().min(0).default(0)
|
|
7577
|
+
}).strict();
|
|
7578
|
+
z.object({
|
|
7579
|
+
search: z.string().trim().min(1).max(200).optional(),
|
|
7580
|
+
listId: UuidSchema.optional(),
|
|
7581
|
+
openingLineIsNull: QueryBooleanSchema.optional(),
|
|
7582
|
+
batchId: z.string().trim().min(1).max(255).optional(),
|
|
7583
|
+
contactStatus: AcqContactStatusSchema.optional(),
|
|
7584
|
+
limit: z.coerce.number().int().min(1).max(5e3).default(5e3),
|
|
7585
|
+
offset: z.coerce.number().int().min(0).default(0)
|
|
7586
|
+
}).strict();
|
|
7587
|
+
z.object({
|
|
7588
|
+
name: z.string().trim().min(1).max(255),
|
|
7589
|
+
domain: z.string().trim().min(1).max(255).optional(),
|
|
7590
|
+
linkedinUrl: z.string().trim().url().optional(),
|
|
7591
|
+
website: z.string().trim().url().optional(),
|
|
7592
|
+
numEmployees: z.number().int().min(0).optional(),
|
|
7593
|
+
foundedYear: z.number().int().optional(),
|
|
7594
|
+
locationCity: z.string().trim().min(1).max(255).optional(),
|
|
7595
|
+
locationState: z.string().trim().min(1).max(255).optional(),
|
|
7596
|
+
category: z.string().trim().min(1).max(255).optional(),
|
|
7597
|
+
source: z.string().trim().min(1).max(255).optional(),
|
|
7598
|
+
batchId: z.string().trim().min(1).max(255).optional(),
|
|
7599
|
+
pipelineStatus: z.unknown().optional(),
|
|
7600
|
+
verticalResearch: z.string().trim().min(1).max(5e3).optional()
|
|
7601
|
+
}).strict();
|
|
7602
|
+
z.object({
|
|
7603
|
+
name: z.string().trim().min(1).max(255).optional(),
|
|
7604
|
+
domain: z.string().trim().min(1).max(255).optional(),
|
|
7605
|
+
linkedinUrl: z.string().trim().url().optional(),
|
|
7606
|
+
website: z.string().trim().url().optional(),
|
|
7607
|
+
numEmployees: z.number().int().min(0).optional(),
|
|
7608
|
+
foundedYear: z.number().int().optional(),
|
|
7609
|
+
locationCity: z.string().trim().min(1).max(255).optional(),
|
|
7610
|
+
locationState: z.string().trim().min(1).max(255).optional(),
|
|
7611
|
+
category: z.string().trim().min(1).max(255).optional(),
|
|
7612
|
+
segment: z.string().trim().min(1).max(255).optional(),
|
|
7613
|
+
processingState: CompanyProcessingStateSchema.optional(),
|
|
7614
|
+
pipelineStatus: z.unknown().optional(),
|
|
7615
|
+
enrichmentData: z.record(z.string(), z.unknown()).optional(),
|
|
7616
|
+
source: z.string().trim().min(1).max(255).optional(),
|
|
7617
|
+
batchId: z.string().trim().min(1).max(255).optional(),
|
|
7618
|
+
status: AcqCompanyStatusSchema.optional(),
|
|
7619
|
+
verticalResearch: z.string().trim().min(1).max(5e3).nullable().optional()
|
|
7620
|
+
}).strict().refine(
|
|
7621
|
+
(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,
|
|
7622
|
+
{
|
|
7623
|
+
message: "At least one field must be provided"
|
|
7624
|
+
}
|
|
7625
|
+
);
|
|
7626
|
+
z.object({
|
|
7627
|
+
email: z.string().trim().email(),
|
|
7628
|
+
companyId: UuidSchema.optional(),
|
|
7629
|
+
firstName: z.string().trim().min(1).max(255).optional(),
|
|
7630
|
+
lastName: z.string().trim().min(1).max(255).optional(),
|
|
7631
|
+
linkedinUrl: z.string().trim().url().optional(),
|
|
7632
|
+
title: z.string().trim().min(1).max(255).optional(),
|
|
7633
|
+
source: z.string().trim().min(1).max(255).optional(),
|
|
7634
|
+
sourceId: z.string().trim().min(1).max(255).optional(),
|
|
7635
|
+
batchId: z.string().trim().min(1).max(255).optional(),
|
|
7636
|
+
pipelineStatus: z.unknown().optional()
|
|
7637
|
+
}).strict();
|
|
7638
|
+
z.object({
|
|
7639
|
+
companyId: UuidSchema.optional(),
|
|
7640
|
+
emailValid: AcqEmailValidSchema.optional(),
|
|
7641
|
+
firstName: z.string().trim().min(1).max(255).optional(),
|
|
7642
|
+
lastName: z.string().trim().min(1).max(255).optional(),
|
|
7643
|
+
linkedinUrl: z.string().trim().url().optional(),
|
|
7644
|
+
title: z.string().trim().min(1).max(255).optional(),
|
|
7645
|
+
headline: z.string().trim().min(1).max(5e3).optional(),
|
|
7646
|
+
filterReason: z.string().trim().min(1).max(5e3).optional(),
|
|
7647
|
+
openingLine: z.string().trim().min(1).max(5e3).optional(),
|
|
7648
|
+
processingState: ContactProcessingStateSchema.optional(),
|
|
7649
|
+
pipelineStatus: z.unknown().optional(),
|
|
7650
|
+
enrichmentData: z.record(z.string(), z.unknown()).optional(),
|
|
7651
|
+
status: AcqContactStatusSchema.optional()
|
|
7652
|
+
}).strict().refine(
|
|
7653
|
+
(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,
|
|
7654
|
+
{
|
|
7655
|
+
message: "At least one field must be provided"
|
|
7656
|
+
}
|
|
7657
|
+
);
|
|
7658
|
+
var AcqCompanyResponseSchema = z.object({
|
|
7659
|
+
id: z.string(),
|
|
7660
|
+
organizationId: z.string(),
|
|
7661
|
+
name: z.string(),
|
|
7662
|
+
domain: z.string().nullable(),
|
|
7663
|
+
linkedinUrl: z.string().nullable(),
|
|
7664
|
+
website: z.string().nullable(),
|
|
7665
|
+
numEmployees: z.number().nullable(),
|
|
7666
|
+
foundedYear: z.number().nullable(),
|
|
7667
|
+
locationCity: z.string().nullable(),
|
|
7668
|
+
locationState: z.string().nullable(),
|
|
7669
|
+
category: z.string().nullable(),
|
|
7670
|
+
categoryPain: z.string().nullable(),
|
|
7671
|
+
segment: z.string().nullable(),
|
|
7672
|
+
processingState: CompanyProcessingStateSchema.nullable(),
|
|
7673
|
+
pipelineStatus: z.unknown().nullable().optional(),
|
|
7674
|
+
enrichmentData: z.record(z.string(), z.unknown()).nullable(),
|
|
7675
|
+
source: z.string().nullable(),
|
|
7676
|
+
batchId: z.string().nullable(),
|
|
7677
|
+
status: AcqCompanyStatusSchema,
|
|
7678
|
+
contactCount: z.number().int().min(0),
|
|
7679
|
+
verticalResearch: z.string().nullable(),
|
|
7680
|
+
createdAt: z.string(),
|
|
7681
|
+
updatedAt: z.string()
|
|
7682
|
+
});
|
|
7683
|
+
z.object({
|
|
7684
|
+
data: z.array(AcqCompanyResponseSchema),
|
|
7685
|
+
total: z.number().int(),
|
|
7686
|
+
limit: z.number().int(),
|
|
7687
|
+
offset: z.number().int()
|
|
7688
|
+
});
|
|
7689
|
+
z.object({
|
|
7690
|
+
segments: z.array(z.string()),
|
|
7691
|
+
categories: z.array(z.string()),
|
|
7692
|
+
statuses: z.array(AcqCompanyStatusSchema)
|
|
7693
|
+
});
|
|
7694
|
+
var AcqContactCompanySummarySchema = z.object({
|
|
7695
|
+
id: z.string(),
|
|
7696
|
+
name: z.string(),
|
|
7697
|
+
domain: z.string().nullable(),
|
|
7698
|
+
website: z.string().nullable(),
|
|
7699
|
+
linkedinUrl: z.string().nullable(),
|
|
7700
|
+
segment: z.string().nullable(),
|
|
7701
|
+
category: z.string().nullable(),
|
|
7702
|
+
status: AcqCompanyStatusSchema
|
|
7703
|
+
});
|
|
7704
|
+
var AcqContactResponseSchema = z.object({
|
|
7705
|
+
id: z.string(),
|
|
7706
|
+
organizationId: z.string(),
|
|
7707
|
+
companyId: z.string().nullable(),
|
|
7708
|
+
email: z.string(),
|
|
7709
|
+
emailValid: AcqEmailValidSchema.nullable(),
|
|
7710
|
+
firstName: z.string().nullable(),
|
|
7711
|
+
lastName: z.string().nullable(),
|
|
7712
|
+
linkedinUrl: z.string().nullable(),
|
|
7713
|
+
title: z.string().nullable(),
|
|
7714
|
+
headline: z.string().nullable(),
|
|
7715
|
+
filterReason: z.string().nullable(),
|
|
7716
|
+
openingLine: z.string().nullable(),
|
|
7717
|
+
source: z.string().nullable(),
|
|
7718
|
+
sourceId: z.string().nullable(),
|
|
7719
|
+
processingState: ContactProcessingStateSchema.nullable(),
|
|
7720
|
+
pipelineStatus: z.unknown().nullable().optional(),
|
|
7721
|
+
enrichmentData: z.record(z.string(), z.unknown()).nullable(),
|
|
7722
|
+
attioPersonId: z.string().nullable(),
|
|
7723
|
+
batchId: z.string().nullable(),
|
|
7724
|
+
status: AcqContactStatusSchema,
|
|
7725
|
+
company: AcqContactCompanySummarySchema.nullable().optional(),
|
|
7726
|
+
createdAt: z.string(),
|
|
7727
|
+
updatedAt: z.string()
|
|
7728
|
+
});
|
|
7729
|
+
z.object({
|
|
7730
|
+
data: z.array(AcqContactResponseSchema),
|
|
7731
|
+
total: z.number().int(),
|
|
7732
|
+
limit: z.number().int(),
|
|
7733
|
+
offset: z.number().int()
|
|
7734
|
+
});
|
|
7735
|
+
var AcqArtifactOwnerKindSchema = z.enum(["company", "contact", "deal", "list", "list_member"]);
|
|
7736
|
+
z.object({
|
|
7737
|
+
ownerKind: AcqArtifactOwnerKindSchema,
|
|
7738
|
+
ownerId: UuidSchema
|
|
7739
|
+
}).strict();
|
|
7740
|
+
z.object({
|
|
7741
|
+
ownerKind: AcqArtifactOwnerKindSchema,
|
|
7742
|
+
ownerId: UuidSchema,
|
|
7743
|
+
kind: z.string().trim().min(1).max(255),
|
|
7744
|
+
content: z.record(z.string(), z.unknown()),
|
|
7745
|
+
sourceExecutionId: UuidSchema.optional()
|
|
7746
|
+
}).strict();
|
|
7747
|
+
var AcqArtifactResponseSchema = z.object({
|
|
7748
|
+
id: z.string(),
|
|
7749
|
+
organizationId: z.string(),
|
|
7750
|
+
ownerKind: z.string(),
|
|
7751
|
+
ownerId: z.string(),
|
|
7752
|
+
kind: z.string(),
|
|
7753
|
+
content: z.record(z.string(), z.unknown()),
|
|
7754
|
+
sourceExecutionId: z.string().nullable(),
|
|
7755
|
+
createdBy: z.string().nullable(),
|
|
7756
|
+
createdAt: z.string(),
|
|
7757
|
+
version: z.number().int()
|
|
7758
|
+
});
|
|
7759
|
+
z.object({
|
|
7760
|
+
artifacts: z.array(AcqArtifactResponseSchema)
|
|
7761
|
+
});
|
|
7762
|
+
z.object({
|
|
7763
|
+
limit: z.coerce.number().int().min(1).max(500).default(50),
|
|
7764
|
+
offset: z.coerce.number().int().min(0).default(0)
|
|
7765
|
+
}).strict();
|
|
7766
|
+
z.object({
|
|
7767
|
+
memberId: UuidSchema
|
|
7768
|
+
});
|
|
7769
|
+
var AcqListMemberContactSummarySchema = z.object({
|
|
7770
|
+
id: z.string(),
|
|
7771
|
+
email: z.string(),
|
|
7772
|
+
firstName: z.string().nullable(),
|
|
7773
|
+
lastName: z.string().nullable(),
|
|
7774
|
+
title: z.string().nullable(),
|
|
7775
|
+
linkedinUrl: z.string().nullable(),
|
|
7776
|
+
companyId: z.string().nullable()
|
|
7777
|
+
});
|
|
7778
|
+
var AcqListMemberResponseSchema = z.object({
|
|
7779
|
+
id: z.string(),
|
|
7780
|
+
listId: z.string(),
|
|
7781
|
+
contactId: z.string(),
|
|
7782
|
+
pipelineKey: z.string(),
|
|
7783
|
+
stageKey: z.string(),
|
|
7784
|
+
stateKey: z.string(),
|
|
7785
|
+
activityLog: z.unknown(),
|
|
7786
|
+
addedAt: z.string(),
|
|
7787
|
+
addedBy: z.string().nullable(),
|
|
7788
|
+
sourceExecutionId: z.string().nullable(),
|
|
7789
|
+
contact: AcqListMemberContactSummarySchema.nullable()
|
|
7790
|
+
});
|
|
7791
|
+
z.object({
|
|
7792
|
+
members: z.array(AcqListMemberResponseSchema)
|
|
7793
|
+
});
|
|
7794
|
+
z.object({
|
|
7795
|
+
listCompanyId: UuidSchema
|
|
7796
|
+
});
|
|
7797
|
+
z.object({
|
|
7798
|
+
id: z.string(),
|
|
7799
|
+
listId: z.string(),
|
|
7800
|
+
companyId: z.string(),
|
|
7801
|
+
pipelineKey: z.string(),
|
|
7802
|
+
stageKey: z.string(),
|
|
7803
|
+
stateKey: z.string(),
|
|
7804
|
+
activityLog: z.unknown(),
|
|
7805
|
+
addedAt: z.string(),
|
|
7806
|
+
addedBy: z.string().nullable(),
|
|
7807
|
+
sourceExecutionId: z.string().nullable()
|
|
7808
|
+
});
|
|
6491
7809
|
var RETRYABLE_CODES = /* @__PURE__ */ new Set([
|
|
6492
7810
|
"rate_limit_exceeded",
|
|
6493
7811
|
"network_error",
|
|
@@ -6821,7 +8139,9 @@ createAdapter("list", [
|
|
|
6821
8139
|
"getConfig",
|
|
6822
8140
|
"recordExecution",
|
|
6823
8141
|
"updateCompanyStage",
|
|
6824
|
-
"updateContactStage"
|
|
8142
|
+
"updateContactStage",
|
|
8143
|
+
"listPendingCompanyIds",
|
|
8144
|
+
"listPendingContactIds"
|
|
6825
8145
|
]);
|
|
6826
8146
|
|
|
6827
8147
|
// src/worker/adapters/pdf.ts
|
|
@@ -6836,728 +8156,740 @@ createAdapter("execution", ["trigger", "triggerAsync"]);
|
|
|
6836
8156
|
// src/worker/adapters/email.ts
|
|
6837
8157
|
createAdapter("email", ["send"]);
|
|
6838
8158
|
|
|
6839
|
-
// src/
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
logs.push(entry);
|
|
6848
|
-
parentPort?.postMessage({
|
|
6849
|
-
type: "log",
|
|
6850
|
-
entry: { level, message, timestamp, executionId, context: logContext }
|
|
6851
|
-
});
|
|
6852
|
-
};
|
|
6853
|
-
const capture = (level, orig) => (...args) => {
|
|
6854
|
-
postLog(level, args.map(String).join(" "));
|
|
6855
|
-
orig(...args);
|
|
6856
|
-
};
|
|
6857
|
-
console.log = capture("info", origLog);
|
|
6858
|
-
console.warn = capture("warn", origWarn);
|
|
6859
|
-
console.error = capture("error", origError);
|
|
6860
|
-
return {
|
|
6861
|
-
restore: () => {
|
|
6862
|
-
console.log = origLog;
|
|
6863
|
-
console.warn = origWarn;
|
|
6864
|
-
console.error = origError;
|
|
6865
|
-
},
|
|
6866
|
-
postLog
|
|
6867
|
-
};
|
|
6868
|
-
}
|
|
6869
|
-
var LOG_STRING_TRUNCATE_LIMIT = 200;
|
|
6870
|
-
function truncateForLogging(value) {
|
|
6871
|
-
if (value === null || value === void 0) return value;
|
|
6872
|
-
if (typeof value === "string") {
|
|
6873
|
-
return value.length > LOG_STRING_TRUNCATE_LIMIT ? value.slice(0, LOG_STRING_TRUNCATE_LIMIT) + `\u2026 [${value.length} chars]` : value;
|
|
6874
|
-
}
|
|
6875
|
-
if (Array.isArray(value)) {
|
|
6876
|
-
return value.map(truncateForLogging);
|
|
8159
|
+
// ../core/src/platform/registry/validation.ts
|
|
8160
|
+
var RegistryValidationError = class extends Error {
|
|
8161
|
+
constructor(orgName, resourceId, field, message) {
|
|
8162
|
+
super(message);
|
|
8163
|
+
this.orgName = orgName;
|
|
8164
|
+
this.resourceId = resourceId;
|
|
8165
|
+
this.field = field;
|
|
8166
|
+
this.name = "RegistryValidationError";
|
|
6877
8167
|
}
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
8168
|
+
};
|
|
8169
|
+
function validateDeploymentSpec(orgName, resources) {
|
|
8170
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
8171
|
+
resources.workflows?.forEach((workflow) => {
|
|
8172
|
+
const id = workflow.config.resourceId;
|
|
8173
|
+
if (seenIds.has(id)) {
|
|
8174
|
+
throw new RegistryValidationError(
|
|
8175
|
+
orgName,
|
|
8176
|
+
id,
|
|
8177
|
+
null,
|
|
8178
|
+
`Duplicate resourceId "${id}" in organization "${orgName}". Workflows and agents must have unique IDs within an organization.`
|
|
8179
|
+
);
|
|
6882
8180
|
}
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
}
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
8181
|
+
seenIds.add(id);
|
|
8182
|
+
if ("modelConfig" in workflow && workflow.modelConfig) {
|
|
8183
|
+
validateResourceModelConfig(orgName, id, workflow.modelConfig);
|
|
8184
|
+
}
|
|
8185
|
+
if (workflow.interface) {
|
|
8186
|
+
validateExecutionInterface(orgName, id, workflow.interface, workflow.contract.inputSchema);
|
|
8187
|
+
}
|
|
8188
|
+
});
|
|
8189
|
+
resources.agents?.forEach((agent) => {
|
|
8190
|
+
const id = agent.config.resourceId;
|
|
8191
|
+
if (seenIds.has(id)) {
|
|
8192
|
+
throw new RegistryValidationError(
|
|
8193
|
+
orgName,
|
|
8194
|
+
id,
|
|
8195
|
+
null,
|
|
8196
|
+
`Duplicate resourceId "${id}" in organization "${orgName}". Workflows and agents must have unique IDs within an organization.`
|
|
8197
|
+
);
|
|
8198
|
+
}
|
|
8199
|
+
seenIds.add(id);
|
|
8200
|
+
validateResourceModelConfig(orgName, id, agent.modelConfig);
|
|
8201
|
+
if (agent.interface) {
|
|
8202
|
+
validateExecutionInterface(orgName, id, agent.interface, agent.contract.inputSchema);
|
|
8203
|
+
}
|
|
8204
|
+
});
|
|
6894
8205
|
}
|
|
6895
|
-
function
|
|
6896
|
-
if (!schema || typeof schema !== "object" || !("parse" in schema)) return void 0;
|
|
8206
|
+
function validateResourceModelConfig(orgName, resourceId, modelConfig) {
|
|
6897
8207
|
try {
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
8208
|
+
validateModelConfig(modelConfig);
|
|
8209
|
+
} catch (error) {
|
|
8210
|
+
if (error instanceof ModelConfigError) {
|
|
8211
|
+
throw new RegistryValidationError(
|
|
8212
|
+
orgName,
|
|
8213
|
+
resourceId,
|
|
8214
|
+
error.field,
|
|
8215
|
+
`Invalid model config in ${orgName}/${resourceId}: ${error.message} (field: ${error.field})`
|
|
8216
|
+
);
|
|
6901
8217
|
}
|
|
6902
|
-
|
|
8218
|
+
throw error;
|
|
6903
8219
|
}
|
|
6904
|
-
return void 0;
|
|
6905
|
-
}
|
|
6906
|
-
function serializeNext(next) {
|
|
6907
|
-
if (next === null) return null;
|
|
6908
|
-
if (next.type === "linear") return { type: "linear", target: next.target };
|
|
6909
|
-
return { type: "conditional", routes: next.routes.map((r2) => ({ target: r2.target })), default: next.default };
|
|
6910
8220
|
}
|
|
6911
|
-
|
|
6912
|
-
const
|
|
6913
|
-
const
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
sessionTurnNumber: context.sessionTurnNumber,
|
|
6940
|
-
parentExecutionId: context.parentExecutionId,
|
|
6941
|
-
executionDepth: context.executionDepth,
|
|
6942
|
-
adapters: context.adapters,
|
|
6943
|
-
store: /* @__PURE__ */ new Map(),
|
|
6944
|
-
logger: {
|
|
6945
|
-
debug: (msg) => console.log(`[debug] ${msg}`),
|
|
6946
|
-
info: (msg) => console.log(`[info] ${msg}`),
|
|
6947
|
-
warn: (msg) => console.warn(`[warn] ${msg}`),
|
|
6948
|
-
error: (msg) => console.error(`[error] ${msg}`)
|
|
6949
|
-
}
|
|
6950
|
-
});
|
|
6951
|
-
currentData = step.outputSchema.parse(rawOutput);
|
|
6952
|
-
const stepEndTime = Date.now();
|
|
6953
|
-
const nextStepId = resolveNext(step.next, currentData);
|
|
6954
|
-
postLog("info", `Step '${step.name}' completed (${stepEndTime - stepStartTime}ms)`, {
|
|
6955
|
-
type: "workflow",
|
|
6956
|
-
contextType: "step-completed",
|
|
6957
|
-
stepId: step.id,
|
|
6958
|
-
stepStatus: "completed",
|
|
6959
|
-
output: truncateForLogging(currentData),
|
|
6960
|
-
duration: stepEndTime - stepStartTime,
|
|
6961
|
-
isTerminal: nextStepId === null,
|
|
6962
|
-
startTime: stepStartTime,
|
|
6963
|
-
endTime: stepEndTime
|
|
6964
|
-
});
|
|
6965
|
-
if (step.next?.type === "conditional" && nextStepId !== null) {
|
|
6966
|
-
postLog("info", `Routing from '${step.name}' to '${nextStepId}'`, {
|
|
6967
|
-
type: "workflow",
|
|
6968
|
-
contextType: "conditional-route",
|
|
6969
|
-
stepId: step.id,
|
|
6970
|
-
target: nextStepId
|
|
6971
|
-
});
|
|
8221
|
+
function validateExecutionInterface(orgName, resourceId, executionInterface, inputSchema) {
|
|
8222
|
+
const form = executionInterface.form;
|
|
8223
|
+
const fieldMappings = form.fieldMappings ?? {};
|
|
8224
|
+
const schemaShape = extractZodShape(inputSchema);
|
|
8225
|
+
if (!schemaShape) {
|
|
8226
|
+
return;
|
|
8227
|
+
}
|
|
8228
|
+
const schemaFieldNames = Object.keys(schemaShape);
|
|
8229
|
+
const formToSchemaMap = /* @__PURE__ */ new Map();
|
|
8230
|
+
for (const field of form.fields) {
|
|
8231
|
+
const schemaKey = fieldMappings[field.name] ?? field.name;
|
|
8232
|
+
formToSchemaMap.set(field.name, schemaKey);
|
|
8233
|
+
}
|
|
8234
|
+
for (const schemaFieldName of schemaFieldNames) {
|
|
8235
|
+
const schemaField = schemaShape[schemaFieldName];
|
|
8236
|
+
const isRequired = !isZodOptional(schemaField);
|
|
8237
|
+
let hasFormField = false;
|
|
8238
|
+
for (const [formFieldName, mappedSchemaName] of Array.from(formToSchemaMap.entries())) {
|
|
8239
|
+
if (mappedSchemaName === schemaFieldName) {
|
|
8240
|
+
hasFormField = true;
|
|
8241
|
+
const formField = form.fields.find((f4) => f4.name === formFieldName);
|
|
8242
|
+
if (isRequired && !formField?.required) {
|
|
8243
|
+
throw new RegistryValidationError(
|
|
8244
|
+
orgName,
|
|
8245
|
+
resourceId,
|
|
8246
|
+
`interface.form.fields.${formFieldName}`,
|
|
8247
|
+
`ExecutionInterface field "${formFieldName}" should be required to match inputSchema field "${schemaFieldName}" in ${orgName}/${resourceId}`
|
|
8248
|
+
);
|
|
6972
8249
|
}
|
|
6973
|
-
|
|
6974
|
-
} catch (err) {
|
|
6975
|
-
const stepEndTime = Date.now();
|
|
6976
|
-
postLog("error", `Step '${step.name}' failed: ${String(err)}`, {
|
|
6977
|
-
type: "workflow",
|
|
6978
|
-
contextType: "step-failed",
|
|
6979
|
-
stepId: step.id,
|
|
6980
|
-
stepStatus: "failed",
|
|
6981
|
-
error: String(err),
|
|
6982
|
-
duration: stepEndTime - stepStartTime,
|
|
6983
|
-
startTime: stepStartTime,
|
|
6984
|
-
endTime: stepEndTime
|
|
6985
|
-
});
|
|
6986
|
-
throw err;
|
|
8250
|
+
break;
|
|
6987
8251
|
}
|
|
6988
8252
|
}
|
|
6989
|
-
if (
|
|
6990
|
-
|
|
8253
|
+
if (isRequired && !hasFormField) {
|
|
8254
|
+
throw new RegistryValidationError(
|
|
8255
|
+
orgName,
|
|
8256
|
+
resourceId,
|
|
8257
|
+
"interface.form.fields",
|
|
8258
|
+
`ExecutionInterface missing required field "${schemaFieldName}" from inputSchema in ${orgName}/${resourceId}`
|
|
8259
|
+
);
|
|
8260
|
+
}
|
|
8261
|
+
}
|
|
8262
|
+
for (const [formFieldName, schemaFieldName] of Array.from(formToSchemaMap.entries())) {
|
|
8263
|
+
if (schemaFieldName.includes(".")) {
|
|
8264
|
+
const topLevelField = schemaFieldName.split(".")[0];
|
|
8265
|
+
throw new RegistryValidationError(
|
|
8266
|
+
orgName,
|
|
8267
|
+
resourceId,
|
|
8268
|
+
`interface.form.fields.${formFieldName}`,
|
|
8269
|
+
`ExecutionInterface field "${formFieldName}" uses nested notation. Flatten the inputSchema by moving nested fields to top-level (e.g., "${topLevelField}.x" \u2192 "x") in ${orgName}/${resourceId}`
|
|
8270
|
+
);
|
|
8271
|
+
}
|
|
8272
|
+
if (!schemaFieldNames.includes(schemaFieldName)) {
|
|
8273
|
+
throw new RegistryValidationError(
|
|
8274
|
+
orgName,
|
|
8275
|
+
resourceId,
|
|
8276
|
+
`interface.form.fields.${formFieldName}`,
|
|
8277
|
+
`ExecutionInterface field "${formFieldName}" maps to non-existent schema field "${schemaFieldName}" in ${orgName}/${resourceId}`
|
|
8278
|
+
);
|
|
6991
8279
|
}
|
|
6992
|
-
return { output: currentData, logs };
|
|
6993
|
-
} finally {
|
|
6994
|
-
restore();
|
|
6995
8280
|
}
|
|
6996
8281
|
}
|
|
6997
|
-
function
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
return {
|
|
7006
|
-
executionId: params.executionId,
|
|
7007
|
-
organizationId: params.organizationId,
|
|
7008
|
-
organizationName: params.organizationName,
|
|
7009
|
-
resourceId: params.resourceId,
|
|
7010
|
-
sessionId: params.sessionId,
|
|
7011
|
-
sessionTurnNumber: params.sessionTurnNumber,
|
|
7012
|
-
parentExecutionId: params.parentExecutionId,
|
|
7013
|
-
executionDepth: params.executionDepth,
|
|
7014
|
-
signal: params.signal,
|
|
7015
|
-
store: /* @__PURE__ */ new Map(),
|
|
7016
|
-
logger: {
|
|
7017
|
-
debug: (msg) => {
|
|
7018
|
-
console.log(`[debug] ${msg}`);
|
|
7019
|
-
postLog("info", msg);
|
|
7020
|
-
},
|
|
7021
|
-
info: (msg) => {
|
|
7022
|
-
console.log(`[info] ${msg}`);
|
|
7023
|
-
postLog("info", msg);
|
|
7024
|
-
},
|
|
7025
|
-
warn: (msg) => {
|
|
7026
|
-
console.warn(`[warn] ${msg}`);
|
|
7027
|
-
postLog("warn", msg);
|
|
7028
|
-
},
|
|
7029
|
-
error: (msg) => {
|
|
7030
|
-
console.error(`[error] ${msg}`);
|
|
7031
|
-
postLog("error", msg);
|
|
7032
|
-
}
|
|
7033
|
-
},
|
|
7034
|
-
onMessageEvent: async (event) => {
|
|
7035
|
-
parentPort.postMessage({ type: "message-event", executionId, event });
|
|
8282
|
+
function extractZodShape(schema) {
|
|
8283
|
+
if ("shape" in schema && typeof schema.shape === "object") {
|
|
8284
|
+
return schema.shape;
|
|
8285
|
+
}
|
|
8286
|
+
if ("_def" in schema) {
|
|
8287
|
+
const def = schema._def;
|
|
8288
|
+
if (def.innerType) {
|
|
8289
|
+
return extractZodShape(def.innerType);
|
|
7036
8290
|
}
|
|
7037
|
-
|
|
8291
|
+
if (def.schema) {
|
|
8292
|
+
return extractZodShape(def.schema);
|
|
8293
|
+
}
|
|
8294
|
+
}
|
|
8295
|
+
return null;
|
|
7038
8296
|
}
|
|
7039
|
-
function
|
|
7040
|
-
|
|
7041
|
-
const agents = new Map((org.agents ?? []).map((a3) => [a3.config.resourceId, a3]));
|
|
7042
|
-
let localAbortController = new AbortController();
|
|
7043
|
-
console.log(`[SDK-WORKER] Worker started with ${workflows.size} workflow(s), ${agents.size} agent(s)`);
|
|
7044
|
-
parentPort.on("message", async (msg) => {
|
|
7045
|
-
if (msg.type === "manifest") {
|
|
7046
|
-
parentPort.postMessage({
|
|
7047
|
-
type: "manifest",
|
|
7048
|
-
workflows: (org.workflows ?? []).map((w2) => ({
|
|
7049
|
-
resourceId: w2.config.resourceId,
|
|
7050
|
-
name: w2.config.name,
|
|
7051
|
-
type: w2.config.type,
|
|
7052
|
-
status: w2.config.status,
|
|
7053
|
-
description: w2.config.description,
|
|
7054
|
-
version: w2.config.version,
|
|
7055
|
-
links: w2.config.links,
|
|
7056
|
-
category: w2.config.category,
|
|
7057
|
-
contract: {
|
|
7058
|
-
inputSchema: safeZodToJsonSchema(w2.contract?.inputSchema),
|
|
7059
|
-
outputSchema: safeZodToJsonSchema(w2.contract?.outputSchema)
|
|
7060
|
-
},
|
|
7061
|
-
steps: Object.values(w2.steps).map((step) => ({
|
|
7062
|
-
id: step.id,
|
|
7063
|
-
name: step.name,
|
|
7064
|
-
description: step.description,
|
|
7065
|
-
inputSchema: safeZodToJsonSchema(step.inputSchema),
|
|
7066
|
-
outputSchema: safeZodToJsonSchema(step.outputSchema),
|
|
7067
|
-
next: serializeNext(step.next)
|
|
7068
|
-
})),
|
|
7069
|
-
entryPoint: w2.entryPoint
|
|
7070
|
-
})),
|
|
7071
|
-
agents: (org.agents ?? []).map((a3) => ({
|
|
7072
|
-
resourceId: a3.config.resourceId,
|
|
7073
|
-
name: a3.config.name,
|
|
7074
|
-
type: a3.config.type,
|
|
7075
|
-
status: a3.config.status,
|
|
7076
|
-
description: a3.config.description,
|
|
7077
|
-
version: a3.config.version,
|
|
7078
|
-
links: a3.config.links,
|
|
7079
|
-
category: a3.config.category,
|
|
7080
|
-
contract: {
|
|
7081
|
-
inputSchema: safeZodToJsonSchema(a3.contract?.inputSchema),
|
|
7082
|
-
outputSchema: safeZodToJsonSchema(a3.contract?.outputSchema)
|
|
7083
|
-
}
|
|
7084
|
-
})),
|
|
7085
|
-
triggers: org.triggers ?? [],
|
|
7086
|
-
integrations: org.integrations ?? [],
|
|
7087
|
-
humanCheckpoints: org.humanCheckpoints ?? [],
|
|
7088
|
-
relationships: org.relationships ?? void 0
|
|
7089
|
-
});
|
|
7090
|
-
return;
|
|
7091
|
-
}
|
|
7092
|
-
if (msg.type === "tool-result") {
|
|
7093
|
-
handleToolResult(msg);
|
|
7094
|
-
return;
|
|
7095
|
-
}
|
|
7096
|
-
if (msg.type === "credential-result") {
|
|
7097
|
-
handleCredentialResult(msg);
|
|
7098
|
-
return;
|
|
7099
|
-
}
|
|
7100
|
-
if (msg.type === "abort") {
|
|
7101
|
-
console.log("[SDK-WORKER] Abort requested by parent");
|
|
7102
|
-
localAbortController.abort();
|
|
7103
|
-
return;
|
|
7104
|
-
}
|
|
7105
|
-
if (msg.type === "execute") {
|
|
7106
|
-
const {
|
|
7107
|
-
resourceId,
|
|
7108
|
-
executionId,
|
|
7109
|
-
input,
|
|
7110
|
-
organizationId,
|
|
7111
|
-
organizationName,
|
|
7112
|
-
sessionId,
|
|
7113
|
-
sessionTurnNumber,
|
|
7114
|
-
parentExecutionId,
|
|
7115
|
-
executionDepth
|
|
7116
|
-
} = msg;
|
|
7117
|
-
console.log(`[SDK-WORKER] Execute request: resourceId=${resourceId}, executionId=${executionId}`);
|
|
7118
|
-
localAbortController = new AbortController();
|
|
7119
|
-
const workflow = workflows.get(resourceId);
|
|
7120
|
-
if (workflow) {
|
|
7121
|
-
const startTime = Date.now();
|
|
7122
|
-
try {
|
|
7123
|
-
console.log(`[SDK-WORKER] Running workflow '${resourceId}' (${Object.keys(workflow.steps).length} steps)`);
|
|
7124
|
-
const { output, logs } = await executeWorkflow(workflow, input, {
|
|
7125
|
-
executionId,
|
|
7126
|
-
organizationId: organizationId ?? "",
|
|
7127
|
-
organizationName: organizationName ?? "",
|
|
7128
|
-
sessionId,
|
|
7129
|
-
sessionTurnNumber,
|
|
7130
|
-
parentExecutionId,
|
|
7131
|
-
executionDepth: executionDepth ?? 0
|
|
7132
|
-
});
|
|
7133
|
-
const durationMs = Date.now() - startTime;
|
|
7134
|
-
console.log(`[SDK-WORKER] Workflow '${resourceId}' completed (${durationMs}ms)`);
|
|
7135
|
-
parentPort.postMessage({ type: "result", status: "completed", output, logs, metrics: { durationMs } });
|
|
7136
|
-
} catch (err) {
|
|
7137
|
-
const durationMs = Date.now() - startTime;
|
|
7138
|
-
console.error(`[SDK-WORKER] Workflow '${resourceId}' failed (${durationMs}ms): ${String(err)}`);
|
|
7139
|
-
parentPort.postMessage({
|
|
7140
|
-
type: "result",
|
|
7141
|
-
status: "failed",
|
|
7142
|
-
error: String(err),
|
|
7143
|
-
logs: [],
|
|
7144
|
-
metrics: { durationMs }
|
|
7145
|
-
});
|
|
7146
|
-
}
|
|
7147
|
-
return;
|
|
7148
|
-
}
|
|
7149
|
-
const agentDef = agents.get(resourceId);
|
|
7150
|
-
if (agentDef) {
|
|
7151
|
-
const logs = [];
|
|
7152
|
-
const { restore } = captureConsole(executionId, logs);
|
|
7153
|
-
const startTime = Date.now();
|
|
7154
|
-
try {
|
|
7155
|
-
console.log(`[SDK-WORKER] Running agent '${resourceId}' (${agentDef.tools.length} tools)`);
|
|
7156
|
-
const adapterFactory = createPostMessageAdapterFactory();
|
|
7157
|
-
const agentInstance = new Agent(agentDef, adapterFactory);
|
|
7158
|
-
const context = buildWorkerExecutionContext({
|
|
7159
|
-
executionId,
|
|
7160
|
-
organizationId: organizationId ?? "",
|
|
7161
|
-
organizationName: organizationName ?? "",
|
|
7162
|
-
resourceId,
|
|
7163
|
-
sessionId,
|
|
7164
|
-
sessionTurnNumber,
|
|
7165
|
-
parentExecutionId,
|
|
7166
|
-
executionDepth: executionDepth ?? 0,
|
|
7167
|
-
signal: localAbortController.signal
|
|
7168
|
-
});
|
|
7169
|
-
const output = await agentInstance.execute(input, context);
|
|
7170
|
-
const durationMs = Date.now() - startTime;
|
|
7171
|
-
console.log(`[SDK-WORKER] Agent '${resourceId}' completed (${durationMs}ms)`);
|
|
7172
|
-
parentPort.postMessage({ type: "result", status: "completed", output, logs, metrics: { durationMs } });
|
|
7173
|
-
} catch (err) {
|
|
7174
|
-
const durationMs = Date.now() - startTime;
|
|
7175
|
-
const errorMessage = err?.message ?? String(err);
|
|
7176
|
-
err?.code ?? "unknown";
|
|
7177
|
-
const errorName = err?.name ?? err?.constructor?.name ?? "Error";
|
|
7178
|
-
console.error(`[SDK-WORKER] Agent '${resourceId}' failed (${durationMs}ms): [${errorName}] ${errorMessage}`);
|
|
7179
|
-
parentPort.postMessage({
|
|
7180
|
-
type: "result",
|
|
7181
|
-
status: "failed",
|
|
7182
|
-
error: `${errorName}: ${errorMessage}`,
|
|
7183
|
-
logs,
|
|
7184
|
-
metrics: { durationMs }
|
|
7185
|
-
});
|
|
7186
|
-
} finally {
|
|
7187
|
-
restore();
|
|
7188
|
-
}
|
|
7189
|
-
return;
|
|
7190
|
-
}
|
|
7191
|
-
console.error(`[SDK-WORKER] Resource not found: ${resourceId}`);
|
|
7192
|
-
parentPort.postMessage({
|
|
7193
|
-
type: "result",
|
|
7194
|
-
status: "failed",
|
|
7195
|
-
error: `Resource not found: ${resourceId}`,
|
|
7196
|
-
logs: []
|
|
7197
|
-
});
|
|
7198
|
-
}
|
|
7199
|
-
});
|
|
7200
|
-
}
|
|
7201
|
-
if (workerData != null && workerData.kind === "static") {
|
|
7202
|
-
const { modulePath } = workerData;
|
|
7203
|
-
void (async () => {
|
|
7204
|
-
const mod = await import(modulePath);
|
|
7205
|
-
startWorker(mod.default);
|
|
7206
|
-
})();
|
|
8297
|
+
function isZodOptional(schema) {
|
|
8298
|
+
return schema.isOptional();
|
|
7207
8299
|
}
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
|
|
8300
|
+
function validateRelationships(orgName, resources) {
|
|
8301
|
+
if (!resources.relationships && !resources.triggers && !resources.externalResources && !resources.humanCheckpoints)
|
|
8302
|
+
return;
|
|
8303
|
+
const validAgentIds = new Set(resources.agents?.map((a3) => a3.config.resourceId) ?? []);
|
|
8304
|
+
const validWorkflowIds = new Set(resources.workflows?.map((w2) => w2.config.resourceId) ?? []);
|
|
8305
|
+
const validIntegrationIds = new Set(resources.integrations?.map((i) => i.resourceId) ?? []);
|
|
8306
|
+
const validTriggerIds = new Set(resources.triggers?.map((t) => t.resourceId) ?? []);
|
|
8307
|
+
const allInternalIds = /* @__PURE__ */ new Set([
|
|
8308
|
+
...Array.from(validAgentIds),
|
|
8309
|
+
...Array.from(validWorkflowIds),
|
|
8310
|
+
...Array.from(validTriggerIds),
|
|
8311
|
+
...Array.from(validIntegrationIds)
|
|
8312
|
+
]);
|
|
8313
|
+
validateTriggers(orgName, resources.triggers ?? []);
|
|
8314
|
+
validateResourceRelationships(
|
|
8315
|
+
orgName,
|
|
8316
|
+
resources.relationships ?? {},
|
|
8317
|
+
validAgentIds,
|
|
8318
|
+
validWorkflowIds,
|
|
8319
|
+
validIntegrationIds,
|
|
8320
|
+
validTriggerIds
|
|
8321
|
+
);
|
|
8322
|
+
validateExternalResources(
|
|
8323
|
+
orgName,
|
|
8324
|
+
resources.externalResources ?? [],
|
|
8325
|
+
allInternalIds,
|
|
8326
|
+
validAgentIds,
|
|
8327
|
+
validWorkflowIds,
|
|
8328
|
+
validIntegrationIds
|
|
8329
|
+
);
|
|
8330
|
+
validateHumanCheckpoints(orgName, resources.humanCheckpoints ?? [], allInternalIds, validAgentIds, validWorkflowIds);
|
|
7230
8331
|
}
|
|
7231
|
-
|
|
7232
|
-
const context = options.context ?? {};
|
|
7233
|
-
const { output, logs } = await executeWorkflow(definition, input, {
|
|
7234
|
-
executionId: context.executionId ?? `test-${Date.now()}`,
|
|
7235
|
-
organizationId: context.organizationId ?? "test-org",
|
|
7236
|
-
organizationName: context.organizationName ?? "Test Organization",
|
|
7237
|
-
sessionId: context.sessionId,
|
|
7238
|
-
sessionTurnNumber: context.sessionTurnNumber,
|
|
7239
|
-
parentExecutionId: context.parentExecutionId,
|
|
7240
|
-
executionDepth: context.executionDepth ?? 0,
|
|
7241
|
-
adapters: options.adapters
|
|
7242
|
-
});
|
|
7243
|
-
return {
|
|
7244
|
-
output,
|
|
7245
|
-
logs,
|
|
7246
|
-
stepEvents: extractStepEvents(logs)
|
|
7247
|
-
};
|
|
8332
|
+
function validateTriggers(_orgName, _triggers, _validAgentIds, _validWorkflowIds) {
|
|
7248
8333
|
}
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
super(message);
|
|
7254
|
-
this.orgName = orgName;
|
|
7255
|
-
this.resourceId = resourceId;
|
|
7256
|
-
this.field = field;
|
|
7257
|
-
this.name = "RegistryValidationError";
|
|
7258
|
-
}
|
|
7259
|
-
};
|
|
7260
|
-
function validateDeploymentSpec(orgName, resources) {
|
|
7261
|
-
const seenIds = /* @__PURE__ */ new Set();
|
|
7262
|
-
resources.workflows?.forEach((workflow) => {
|
|
7263
|
-
const id = workflow.config.resourceId;
|
|
7264
|
-
if (seenIds.has(id)) {
|
|
8334
|
+
function validateResourceRelationships(orgName, relationships, validAgentIds, validWorkflowIds, validIntegrationIds, validTriggerIds) {
|
|
8335
|
+
for (const [resourceId, declaration] of Object.entries(relationships)) {
|
|
8336
|
+
const resourceExists = validAgentIds.has(resourceId) || validWorkflowIds.has(resourceId) || validTriggerIds.has(resourceId);
|
|
8337
|
+
if (!resourceExists) {
|
|
7265
8338
|
throw new RegistryValidationError(
|
|
7266
8339
|
orgName,
|
|
7267
|
-
|
|
8340
|
+
resourceId,
|
|
7268
8341
|
null,
|
|
7269
|
-
`
|
|
8342
|
+
`[${orgName}] Relationship declared for non-existent resource: ${resourceId}`
|
|
7270
8343
|
);
|
|
7271
8344
|
}
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
8345
|
+
declaration.triggers?.agents?.forEach((agentId) => {
|
|
8346
|
+
if (!validAgentIds.has(agentId)) {
|
|
8347
|
+
throw new RegistryValidationError(
|
|
8348
|
+
orgName,
|
|
8349
|
+
resourceId,
|
|
8350
|
+
"triggers.agents",
|
|
8351
|
+
`[${orgName}] Resource '${resourceId}' triggers non-existent agent: ${agentId}`
|
|
8352
|
+
);
|
|
8353
|
+
}
|
|
8354
|
+
});
|
|
8355
|
+
declaration.triggers?.workflows?.forEach((workflowId) => {
|
|
8356
|
+
if (!validWorkflowIds.has(workflowId)) {
|
|
8357
|
+
throw new RegistryValidationError(
|
|
8358
|
+
orgName,
|
|
8359
|
+
resourceId,
|
|
8360
|
+
"triggers.workflows",
|
|
8361
|
+
`[${orgName}] Resource '${resourceId}' triggers non-existent workflow: ${workflowId}`
|
|
8362
|
+
);
|
|
8363
|
+
}
|
|
8364
|
+
});
|
|
8365
|
+
declaration.uses?.integrations?.forEach((integrationId) => {
|
|
8366
|
+
if (!validIntegrationIds.has(integrationId)) {
|
|
8367
|
+
throw new RegistryValidationError(
|
|
8368
|
+
orgName,
|
|
8369
|
+
resourceId,
|
|
8370
|
+
"uses.integrations",
|
|
8371
|
+
`[${orgName}] Resource '${resourceId}' uses non-existent integration: ${integrationId}`
|
|
8372
|
+
);
|
|
8373
|
+
}
|
|
8374
|
+
});
|
|
8375
|
+
}
|
|
8376
|
+
}
|
|
8377
|
+
function validateExternalResources(orgName, externalResources, allInternalIds, validAgentIds, validWorkflowIds, validIntegrationIds) {
|
|
8378
|
+
externalResources.forEach((external) => {
|
|
8379
|
+
if (allInternalIds.has(external.resourceId)) {
|
|
7283
8380
|
throw new RegistryValidationError(
|
|
7284
8381
|
orgName,
|
|
7285
|
-
|
|
8382
|
+
external.resourceId,
|
|
7286
8383
|
null,
|
|
7287
|
-
`
|
|
8384
|
+
`[${orgName}] External resource ID '${external.resourceId}' conflicts with internal resource ID`
|
|
7288
8385
|
);
|
|
7289
8386
|
}
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
8387
|
+
external.triggers?.agents?.forEach((agentId) => {
|
|
8388
|
+
if (!validAgentIds.has(agentId)) {
|
|
8389
|
+
throw new RegistryValidationError(
|
|
8390
|
+
orgName,
|
|
8391
|
+
external.resourceId,
|
|
8392
|
+
"triggers.agents",
|
|
8393
|
+
`[${orgName}] External resource '${external.resourceId}' triggers non-existent agent: ${agentId}`
|
|
8394
|
+
);
|
|
8395
|
+
}
|
|
8396
|
+
});
|
|
8397
|
+
external.triggers?.workflows?.forEach((workflowId) => {
|
|
8398
|
+
if (!validWorkflowIds.has(workflowId)) {
|
|
8399
|
+
throw new RegistryValidationError(
|
|
8400
|
+
orgName,
|
|
8401
|
+
external.resourceId,
|
|
8402
|
+
"triggers.workflows",
|
|
8403
|
+
`[${orgName}] External resource '${external.resourceId}' triggers non-existent workflow: ${workflowId}`
|
|
8404
|
+
);
|
|
8405
|
+
}
|
|
8406
|
+
});
|
|
8407
|
+
external.uses?.integrations?.forEach((integrationId) => {
|
|
8408
|
+
if (!validIntegrationIds.has(integrationId)) {
|
|
8409
|
+
throw new RegistryValidationError(
|
|
8410
|
+
orgName,
|
|
8411
|
+
external.resourceId,
|
|
8412
|
+
"uses.integrations",
|
|
8413
|
+
`[${orgName}] External resource '${external.resourceId}' uses non-existent integration: ${integrationId}`
|
|
8414
|
+
);
|
|
8415
|
+
}
|
|
8416
|
+
});
|
|
7295
8417
|
});
|
|
7296
8418
|
}
|
|
7297
|
-
function
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
} catch (error) {
|
|
7301
|
-
if (error instanceof ModelConfigError) {
|
|
8419
|
+
function validateHumanCheckpoints(orgName, humanCheckpoints, allInternalIds, validAgentIds, validWorkflowIds) {
|
|
8420
|
+
humanCheckpoints.forEach((humanCheckpoint) => {
|
|
8421
|
+
if (allInternalIds.has(humanCheckpoint.resourceId)) {
|
|
7302
8422
|
throw new RegistryValidationError(
|
|
7303
8423
|
orgName,
|
|
7304
|
-
resourceId,
|
|
7305
|
-
|
|
7306
|
-
`
|
|
8424
|
+
humanCheckpoint.resourceId,
|
|
8425
|
+
null,
|
|
8426
|
+
`[${orgName}] Human checkpoint ID '${humanCheckpoint.resourceId}' conflicts with internal resource ID`
|
|
7307
8427
|
);
|
|
7308
8428
|
}
|
|
7309
|
-
|
|
8429
|
+
humanCheckpoint.requestedBy?.agents?.forEach((agentId) => {
|
|
8430
|
+
if (!validAgentIds.has(agentId)) {
|
|
8431
|
+
throw new RegistryValidationError(
|
|
8432
|
+
orgName,
|
|
8433
|
+
humanCheckpoint.resourceId,
|
|
8434
|
+
"requestedBy.agents",
|
|
8435
|
+
`[${orgName}] Human checkpoint '${humanCheckpoint.resourceId}' requestedBy non-existent agent: ${agentId}`
|
|
8436
|
+
);
|
|
8437
|
+
}
|
|
8438
|
+
});
|
|
8439
|
+
humanCheckpoint.requestedBy?.workflows?.forEach((workflowId) => {
|
|
8440
|
+
if (!validWorkflowIds.has(workflowId)) {
|
|
8441
|
+
throw new RegistryValidationError(
|
|
8442
|
+
orgName,
|
|
8443
|
+
humanCheckpoint.resourceId,
|
|
8444
|
+
"requestedBy.workflows",
|
|
8445
|
+
`[${orgName}] Human checkpoint '${humanCheckpoint.resourceId}' requestedBy non-existent workflow: ${workflowId}`
|
|
8446
|
+
);
|
|
8447
|
+
}
|
|
8448
|
+
});
|
|
8449
|
+
humanCheckpoint.routesTo?.agents?.forEach((agentId) => {
|
|
8450
|
+
if (!validAgentIds.has(agentId)) {
|
|
8451
|
+
throw new RegistryValidationError(
|
|
8452
|
+
orgName,
|
|
8453
|
+
humanCheckpoint.resourceId,
|
|
8454
|
+
"routesTo.agents",
|
|
8455
|
+
`[${orgName}] Human checkpoint '${humanCheckpoint.resourceId}' routesTo non-existent agent: ${agentId}`
|
|
8456
|
+
);
|
|
8457
|
+
}
|
|
8458
|
+
});
|
|
8459
|
+
humanCheckpoint.routesTo?.workflows?.forEach((workflowId) => {
|
|
8460
|
+
if (!validWorkflowIds.has(workflowId)) {
|
|
8461
|
+
throw new RegistryValidationError(
|
|
8462
|
+
orgName,
|
|
8463
|
+
humanCheckpoint.resourceId,
|
|
8464
|
+
"routesTo.workflows",
|
|
8465
|
+
`[${orgName}] Human checkpoint '${humanCheckpoint.resourceId}' routesTo non-existent workflow: ${workflowId}`
|
|
8466
|
+
);
|
|
8467
|
+
}
|
|
8468
|
+
});
|
|
8469
|
+
});
|
|
8470
|
+
}
|
|
8471
|
+
var listBuilderStageKeys = Object.keys(LEAD_GEN_STAGE_CATALOG);
|
|
8472
|
+
var ListBuilderStageKeySchema = z.enum(listBuilderStageKeys);
|
|
8473
|
+
|
|
8474
|
+
// src/worker/list-builder-workflow.ts
|
|
8475
|
+
var ListBuilderResultSchema = z.object({
|
|
8476
|
+
entity: z.enum(["company", "contact"]),
|
|
8477
|
+
id: z.string().min(1),
|
|
8478
|
+
status: ProcessingStageStatusSchema,
|
|
8479
|
+
stageKey: ListBuilderStageKeySchema.optional(),
|
|
8480
|
+
data: z.unknown().optional()
|
|
8481
|
+
});
|
|
8482
|
+
z.array(ListBuilderResultSchema);
|
|
8483
|
+
|
|
8484
|
+
// src/worker/index.ts
|
|
8485
|
+
function captureConsole(executionId, logs) {
|
|
8486
|
+
const origLog = console.log;
|
|
8487
|
+
const origWarn = console.warn;
|
|
8488
|
+
const origError = console.error;
|
|
8489
|
+
const postLog = (level, message, logContext) => {
|
|
8490
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
8491
|
+
const entry = { level, message, timestamp, context: logContext };
|
|
8492
|
+
logs.push(entry);
|
|
8493
|
+
parentPort?.postMessage({
|
|
8494
|
+
type: "log",
|
|
8495
|
+
entry: { level, message, timestamp, executionId, context: logContext }
|
|
8496
|
+
});
|
|
8497
|
+
};
|
|
8498
|
+
const capture = (level, orig) => (...args) => {
|
|
8499
|
+
postLog(level, args.map(String).join(" "));
|
|
8500
|
+
orig(...args);
|
|
8501
|
+
};
|
|
8502
|
+
console.log = capture("info", origLog);
|
|
8503
|
+
console.warn = capture("warn", origWarn);
|
|
8504
|
+
console.error = capture("error", origError);
|
|
8505
|
+
return {
|
|
8506
|
+
restore: () => {
|
|
8507
|
+
console.log = origLog;
|
|
8508
|
+
console.warn = origWarn;
|
|
8509
|
+
console.error = origError;
|
|
8510
|
+
},
|
|
8511
|
+
postLog
|
|
8512
|
+
};
|
|
8513
|
+
}
|
|
8514
|
+
var LOG_STRING_TRUNCATE_LIMIT = 200;
|
|
8515
|
+
function truncateForLogging(value) {
|
|
8516
|
+
if (value === null || value === void 0) return value;
|
|
8517
|
+
if (typeof value === "string") {
|
|
8518
|
+
return value.length > LOG_STRING_TRUNCATE_LIMIT ? value.slice(0, LOG_STRING_TRUNCATE_LIMIT) + `\u2026 [${value.length} chars]` : value;
|
|
7310
8519
|
}
|
|
8520
|
+
if (Array.isArray(value)) {
|
|
8521
|
+
return value.map(truncateForLogging);
|
|
8522
|
+
}
|
|
8523
|
+
if (typeof value === "object") {
|
|
8524
|
+
const result = {};
|
|
8525
|
+
for (const [k2, v2] of Object.entries(value)) {
|
|
8526
|
+
result[k2] = truncateForLogging(v2);
|
|
8527
|
+
}
|
|
8528
|
+
return result;
|
|
8529
|
+
}
|
|
8530
|
+
return value;
|
|
7311
8531
|
}
|
|
7312
|
-
function
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
const
|
|
7316
|
-
|
|
7317
|
-
return;
|
|
8532
|
+
function resolveNext(next, data) {
|
|
8533
|
+
if (next === null) return null;
|
|
8534
|
+
if (next.type === "linear") return next.target;
|
|
8535
|
+
for (const route of next.routes) {
|
|
8536
|
+
if (route.condition(data)) return route.target;
|
|
7318
8537
|
}
|
|
7319
|
-
|
|
7320
|
-
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
8538
|
+
return next.default;
|
|
8539
|
+
}
|
|
8540
|
+
function safeZodToJsonSchema(schema) {
|
|
8541
|
+
if (!schema || typeof schema !== "object" || !("parse" in schema)) return void 0;
|
|
8542
|
+
try {
|
|
8543
|
+
const result = zodToJsonSchema(schema, { $refStrategy: "none", errorMessages: true });
|
|
8544
|
+
if (result && typeof result === "object" && Object.keys(result).some((k2) => k2 !== "$schema")) {
|
|
8545
|
+
return result;
|
|
8546
|
+
}
|
|
8547
|
+
} catch {
|
|
7324
8548
|
}
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
8549
|
+
return void 0;
|
|
8550
|
+
}
|
|
8551
|
+
function serializeNext(next) {
|
|
8552
|
+
if (next === null) return null;
|
|
8553
|
+
if (next.type === "linear") return { type: "linear", target: next.target };
|
|
8554
|
+
return { type: "conditional", routes: next.routes.map((r2) => ({ target: r2.target })), default: next.default };
|
|
8555
|
+
}
|
|
8556
|
+
async function executeWorkflow(workflow, input, context) {
|
|
8557
|
+
const logs = [];
|
|
8558
|
+
const { restore, postLog } = captureConsole(context.executionId, logs);
|
|
8559
|
+
try {
|
|
8560
|
+
let currentData = workflow.contract.inputSchema ? workflow.contract.inputSchema.parse(input) : input;
|
|
8561
|
+
let stepId = workflow.entryPoint;
|
|
8562
|
+
while (stepId !== null) {
|
|
8563
|
+
const step = workflow.steps[stepId];
|
|
8564
|
+
if (!step) {
|
|
8565
|
+
throw new Error(`Step '${stepId}' not found in workflow '${workflow.config.resourceId}'`);
|
|
8566
|
+
}
|
|
8567
|
+
const stepStartTime = Date.now();
|
|
8568
|
+
const stepInput = step.inputSchema.parse(currentData);
|
|
8569
|
+
postLog("info", `Step '${step.name}' started`, {
|
|
8570
|
+
type: "workflow",
|
|
8571
|
+
contextType: "step-started",
|
|
8572
|
+
stepId: step.id,
|
|
8573
|
+
stepStatus: "started",
|
|
8574
|
+
input: truncateForLogging(stepInput),
|
|
8575
|
+
startTime: stepStartTime
|
|
8576
|
+
});
|
|
8577
|
+
try {
|
|
8578
|
+
const rawOutput = await step.handler(stepInput, {
|
|
8579
|
+
executionId: context.executionId,
|
|
8580
|
+
organizationId: context.organizationId,
|
|
8581
|
+
organizationName: context.organizationName,
|
|
8582
|
+
resourceId: workflow.config.resourceId,
|
|
8583
|
+
sessionId: context.sessionId,
|
|
8584
|
+
sessionTurnNumber: context.sessionTurnNumber,
|
|
8585
|
+
parentExecutionId: context.parentExecutionId,
|
|
8586
|
+
executionDepth: context.executionDepth,
|
|
8587
|
+
adapters: context.adapters,
|
|
8588
|
+
store: /* @__PURE__ */ new Map(),
|
|
8589
|
+
logger: {
|
|
8590
|
+
debug: (msg) => console.log(`[debug] ${msg}`),
|
|
8591
|
+
info: (msg) => console.log(`[info] ${msg}`),
|
|
8592
|
+
warn: (msg) => console.warn(`[warn] ${msg}`),
|
|
8593
|
+
error: (msg) => console.error(`[error] ${msg}`)
|
|
8594
|
+
}
|
|
8595
|
+
});
|
|
8596
|
+
currentData = step.outputSchema.parse(rawOutput);
|
|
8597
|
+
const stepEndTime = Date.now();
|
|
8598
|
+
const nextStepId = resolveNext(step.next, currentData);
|
|
8599
|
+
postLog("info", `Step '${step.name}' completed (${stepEndTime - stepStartTime}ms)`, {
|
|
8600
|
+
type: "workflow",
|
|
8601
|
+
contextType: "step-completed",
|
|
8602
|
+
stepId: step.id,
|
|
8603
|
+
stepStatus: "completed",
|
|
8604
|
+
output: truncateForLogging(currentData),
|
|
8605
|
+
duration: stepEndTime - stepStartTime,
|
|
8606
|
+
isTerminal: nextStepId === null,
|
|
8607
|
+
startTime: stepStartTime,
|
|
8608
|
+
endTime: stepEndTime
|
|
8609
|
+
});
|
|
8610
|
+
if (step.next?.type === "conditional" && nextStepId !== null) {
|
|
8611
|
+
postLog("info", `Routing from '${step.name}' to '${nextStepId}'`, {
|
|
8612
|
+
type: "workflow",
|
|
8613
|
+
contextType: "conditional-route",
|
|
8614
|
+
stepId: step.id,
|
|
8615
|
+
target: nextStepId
|
|
8616
|
+
});
|
|
7340
8617
|
}
|
|
7341
|
-
|
|
8618
|
+
stepId = nextStepId;
|
|
8619
|
+
} catch (err) {
|
|
8620
|
+
const stepEndTime = Date.now();
|
|
8621
|
+
postLog("error", `Step '${step.name}' failed: ${String(err)}`, {
|
|
8622
|
+
type: "workflow",
|
|
8623
|
+
contextType: "step-failed",
|
|
8624
|
+
stepId: step.id,
|
|
8625
|
+
stepStatus: "failed",
|
|
8626
|
+
error: String(err),
|
|
8627
|
+
duration: stepEndTime - stepStartTime,
|
|
8628
|
+
startTime: stepStartTime,
|
|
8629
|
+
endTime: stepEndTime
|
|
8630
|
+
});
|
|
8631
|
+
throw err;
|
|
7342
8632
|
}
|
|
7343
8633
|
}
|
|
7344
|
-
if (
|
|
7345
|
-
|
|
7346
|
-
orgName,
|
|
7347
|
-
resourceId,
|
|
7348
|
-
"interface.form.fields",
|
|
7349
|
-
`ExecutionInterface missing required field "${schemaFieldName}" from inputSchema in ${orgName}/${resourceId}`
|
|
7350
|
-
);
|
|
8634
|
+
if (workflow.contract.outputSchema) {
|
|
8635
|
+
currentData = workflow.contract.outputSchema.parse(currentData);
|
|
7351
8636
|
}
|
|
8637
|
+
return { output: currentData, logs };
|
|
8638
|
+
} finally {
|
|
8639
|
+
restore();
|
|
7352
8640
|
}
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
|
|
7369
|
-
|
|
8641
|
+
}
|
|
8642
|
+
function buildWorkerExecutionContext(params) {
|
|
8643
|
+
const { executionId } = params;
|
|
8644
|
+
const postLog = (level, message) => {
|
|
8645
|
+
parentPort.postMessage({
|
|
8646
|
+
type: "log",
|
|
8647
|
+
entry: { level, message, timestamp: (/* @__PURE__ */ new Date()).toISOString(), executionId }
|
|
8648
|
+
});
|
|
8649
|
+
};
|
|
8650
|
+
return {
|
|
8651
|
+
executionId: params.executionId,
|
|
8652
|
+
organizationId: params.organizationId,
|
|
8653
|
+
organizationName: params.organizationName,
|
|
8654
|
+
resourceId: params.resourceId,
|
|
8655
|
+
sessionId: params.sessionId,
|
|
8656
|
+
sessionTurnNumber: params.sessionTurnNumber,
|
|
8657
|
+
parentExecutionId: params.parentExecutionId,
|
|
8658
|
+
executionDepth: params.executionDepth,
|
|
8659
|
+
signal: params.signal,
|
|
8660
|
+
store: /* @__PURE__ */ new Map(),
|
|
8661
|
+
logger: {
|
|
8662
|
+
debug: (msg) => {
|
|
8663
|
+
console.log(`[debug] ${msg}`);
|
|
8664
|
+
postLog("info", msg);
|
|
8665
|
+
},
|
|
8666
|
+
info: (msg) => {
|
|
8667
|
+
console.log(`[info] ${msg}`);
|
|
8668
|
+
postLog("info", msg);
|
|
8669
|
+
},
|
|
8670
|
+
warn: (msg) => {
|
|
8671
|
+
console.warn(`[warn] ${msg}`);
|
|
8672
|
+
postLog("warn", msg);
|
|
8673
|
+
},
|
|
8674
|
+
error: (msg) => {
|
|
8675
|
+
console.error(`[error] ${msg}`);
|
|
8676
|
+
postLog("error", msg);
|
|
8677
|
+
}
|
|
8678
|
+
},
|
|
8679
|
+
onMessageEvent: async (event) => {
|
|
8680
|
+
parentPort.postMessage({ type: "message-event", executionId, event });
|
|
7370
8681
|
}
|
|
7371
|
-
}
|
|
8682
|
+
};
|
|
7372
8683
|
}
|
|
7373
|
-
function
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
if (
|
|
7380
|
-
|
|
8684
|
+
function startWorker(org) {
|
|
8685
|
+
const workflows = new Map((org.workflows ?? []).map((w2) => [w2.config.resourceId, w2]));
|
|
8686
|
+
const agents = new Map((org.agents ?? []).map((a3) => [a3.config.resourceId, a3]));
|
|
8687
|
+
let localAbortController = new AbortController();
|
|
8688
|
+
console.log(`[SDK-WORKER] Worker started with ${workflows.size} workflow(s), ${agents.size} agent(s)`);
|
|
8689
|
+
parentPort.on("message", async (msg) => {
|
|
8690
|
+
if (msg.type === "manifest") {
|
|
8691
|
+
parentPort.postMessage({
|
|
8692
|
+
type: "manifest",
|
|
8693
|
+
workflows: (org.workflows ?? []).map((w2) => ({
|
|
8694
|
+
resourceId: w2.config.resourceId,
|
|
8695
|
+
name: w2.config.name,
|
|
8696
|
+
type: w2.config.type,
|
|
8697
|
+
status: w2.config.status,
|
|
8698
|
+
description: w2.config.description,
|
|
8699
|
+
version: w2.config.version,
|
|
8700
|
+
links: w2.config.links,
|
|
8701
|
+
category: w2.config.category,
|
|
8702
|
+
contract: {
|
|
8703
|
+
inputSchema: safeZodToJsonSchema(w2.contract?.inputSchema),
|
|
8704
|
+
outputSchema: safeZodToJsonSchema(w2.contract?.outputSchema)
|
|
8705
|
+
},
|
|
8706
|
+
steps: Object.values(w2.steps).map((step) => ({
|
|
8707
|
+
id: step.id,
|
|
8708
|
+
name: step.name,
|
|
8709
|
+
description: step.description,
|
|
8710
|
+
inputSchema: safeZodToJsonSchema(step.inputSchema),
|
|
8711
|
+
outputSchema: safeZodToJsonSchema(step.outputSchema),
|
|
8712
|
+
next: serializeNext(step.next)
|
|
8713
|
+
})),
|
|
8714
|
+
entryPoint: w2.entryPoint
|
|
8715
|
+
})),
|
|
8716
|
+
agents: (org.agents ?? []).map((a3) => ({
|
|
8717
|
+
resourceId: a3.config.resourceId,
|
|
8718
|
+
name: a3.config.name,
|
|
8719
|
+
type: a3.config.type,
|
|
8720
|
+
status: a3.config.status,
|
|
8721
|
+
description: a3.config.description,
|
|
8722
|
+
version: a3.config.version,
|
|
8723
|
+
links: a3.config.links,
|
|
8724
|
+
category: a3.config.category,
|
|
8725
|
+
contract: {
|
|
8726
|
+
inputSchema: safeZodToJsonSchema(a3.contract?.inputSchema),
|
|
8727
|
+
outputSchema: safeZodToJsonSchema(a3.contract?.outputSchema)
|
|
8728
|
+
}
|
|
8729
|
+
})),
|
|
8730
|
+
triggers: org.triggers ?? [],
|
|
8731
|
+
integrations: org.integrations ?? [],
|
|
8732
|
+
humanCheckpoints: org.humanCheckpoints ?? [],
|
|
8733
|
+
relationships: org.relationships ?? void 0
|
|
8734
|
+
});
|
|
8735
|
+
return;
|
|
7381
8736
|
}
|
|
7382
|
-
if (
|
|
7383
|
-
|
|
8737
|
+
if (msg.type === "tool-result") {
|
|
8738
|
+
handleToolResult(msg);
|
|
8739
|
+
return;
|
|
7384
8740
|
}
|
|
7385
|
-
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
return;
|
|
7394
|
-
const validAgentIds = new Set(resources.agents?.map((a3) => a3.config.resourceId) ?? []);
|
|
7395
|
-
const validWorkflowIds = new Set(resources.workflows?.map((w2) => w2.config.resourceId) ?? []);
|
|
7396
|
-
const validIntegrationIds = new Set(resources.integrations?.map((i) => i.resourceId) ?? []);
|
|
7397
|
-
const validTriggerIds = new Set(resources.triggers?.map((t) => t.resourceId) ?? []);
|
|
7398
|
-
const allInternalIds = /* @__PURE__ */ new Set([
|
|
7399
|
-
...Array.from(validAgentIds),
|
|
7400
|
-
...Array.from(validWorkflowIds),
|
|
7401
|
-
...Array.from(validTriggerIds),
|
|
7402
|
-
...Array.from(validIntegrationIds)
|
|
7403
|
-
]);
|
|
7404
|
-
validateTriggers(orgName, resources.triggers ?? []);
|
|
7405
|
-
validateResourceRelationships(
|
|
7406
|
-
orgName,
|
|
7407
|
-
resources.relationships ?? {},
|
|
7408
|
-
validAgentIds,
|
|
7409
|
-
validWorkflowIds,
|
|
7410
|
-
validIntegrationIds,
|
|
7411
|
-
validTriggerIds
|
|
7412
|
-
);
|
|
7413
|
-
validateExternalResources(
|
|
7414
|
-
orgName,
|
|
7415
|
-
resources.externalResources ?? [],
|
|
7416
|
-
allInternalIds,
|
|
7417
|
-
validAgentIds,
|
|
7418
|
-
validWorkflowIds,
|
|
7419
|
-
validIntegrationIds
|
|
7420
|
-
);
|
|
7421
|
-
validateHumanCheckpoints(orgName, resources.humanCheckpoints ?? [], allInternalIds, validAgentIds, validWorkflowIds);
|
|
7422
|
-
}
|
|
7423
|
-
function validateTriggers(_orgName, _triggers, _validAgentIds, _validWorkflowIds) {
|
|
7424
|
-
}
|
|
7425
|
-
function validateResourceRelationships(orgName, relationships, validAgentIds, validWorkflowIds, validIntegrationIds, validTriggerIds) {
|
|
7426
|
-
for (const [resourceId, declaration] of Object.entries(relationships)) {
|
|
7427
|
-
const resourceExists = validAgentIds.has(resourceId) || validWorkflowIds.has(resourceId) || validTriggerIds.has(resourceId);
|
|
7428
|
-
if (!resourceExists) {
|
|
7429
|
-
throw new RegistryValidationError(
|
|
7430
|
-
orgName,
|
|
7431
|
-
resourceId,
|
|
7432
|
-
null,
|
|
7433
|
-
`[${orgName}] Relationship declared for non-existent resource: ${resourceId}`
|
|
7434
|
-
);
|
|
8741
|
+
if (msg.type === "credential-result") {
|
|
8742
|
+
handleCredentialResult(msg);
|
|
8743
|
+
return;
|
|
8744
|
+
}
|
|
8745
|
+
if (msg.type === "abort") {
|
|
8746
|
+
console.log("[SDK-WORKER] Abort requested by parent");
|
|
8747
|
+
localAbortController.abort();
|
|
8748
|
+
return;
|
|
7435
8749
|
}
|
|
7436
|
-
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
8750
|
+
if (msg.type === "execute") {
|
|
8751
|
+
const {
|
|
8752
|
+
resourceId,
|
|
8753
|
+
executionId,
|
|
8754
|
+
input,
|
|
8755
|
+
organizationId,
|
|
8756
|
+
organizationName,
|
|
8757
|
+
sessionId,
|
|
8758
|
+
sessionTurnNumber,
|
|
8759
|
+
parentExecutionId,
|
|
8760
|
+
executionDepth
|
|
8761
|
+
} = msg;
|
|
8762
|
+
console.log(`[SDK-WORKER] Execute request: resourceId=${resourceId}, executionId=${executionId}`);
|
|
8763
|
+
localAbortController = new AbortController();
|
|
8764
|
+
const workflow = workflows.get(resourceId);
|
|
8765
|
+
if (workflow) {
|
|
8766
|
+
const startTime = Date.now();
|
|
8767
|
+
try {
|
|
8768
|
+
console.log(`[SDK-WORKER] Running workflow '${resourceId}' (${Object.keys(workflow.steps).length} steps)`);
|
|
8769
|
+
const { output, logs } = await executeWorkflow(workflow, input, {
|
|
8770
|
+
executionId,
|
|
8771
|
+
organizationId: organizationId ?? "",
|
|
8772
|
+
organizationName: organizationName ?? "",
|
|
8773
|
+
sessionId,
|
|
8774
|
+
sessionTurnNumber,
|
|
8775
|
+
parentExecutionId,
|
|
8776
|
+
executionDepth: executionDepth ?? 0
|
|
8777
|
+
});
|
|
8778
|
+
const durationMs = Date.now() - startTime;
|
|
8779
|
+
console.log(`[SDK-WORKER] Workflow '${resourceId}' completed (${durationMs}ms)`);
|
|
8780
|
+
parentPort.postMessage({ type: "result", status: "completed", output, logs, metrics: { durationMs } });
|
|
8781
|
+
} catch (err) {
|
|
8782
|
+
const durationMs = Date.now() - startTime;
|
|
8783
|
+
console.error(`[SDK-WORKER] Workflow '${resourceId}' failed (${durationMs}ms): ${String(err)}`);
|
|
8784
|
+
parentPort.postMessage({
|
|
8785
|
+
type: "result",
|
|
8786
|
+
status: "failed",
|
|
8787
|
+
error: String(err),
|
|
8788
|
+
logs: [],
|
|
8789
|
+
metrics: { durationMs }
|
|
8790
|
+
});
|
|
8791
|
+
}
|
|
8792
|
+
return;
|
|
7454
8793
|
}
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
8794
|
+
const agentDef = agents.get(resourceId);
|
|
8795
|
+
if (agentDef) {
|
|
8796
|
+
const logs = [];
|
|
8797
|
+
const { restore } = captureConsole(executionId, logs);
|
|
8798
|
+
const startTime = Date.now();
|
|
8799
|
+
try {
|
|
8800
|
+
console.log(`[SDK-WORKER] Running agent '${resourceId}' (${agentDef.tools.length} tools)`);
|
|
8801
|
+
const adapterFactory = createPostMessageAdapterFactory();
|
|
8802
|
+
const agentInstance = new Agent(agentDef, adapterFactory);
|
|
8803
|
+
const context = buildWorkerExecutionContext({
|
|
8804
|
+
executionId,
|
|
8805
|
+
organizationId: organizationId ?? "",
|
|
8806
|
+
organizationName: organizationName ?? "",
|
|
8807
|
+
resourceId,
|
|
8808
|
+
sessionId,
|
|
8809
|
+
sessionTurnNumber,
|
|
8810
|
+
parentExecutionId,
|
|
8811
|
+
executionDepth: executionDepth ?? 0,
|
|
8812
|
+
signal: localAbortController.signal
|
|
8813
|
+
});
|
|
8814
|
+
const output = await agentInstance.execute(input, context);
|
|
8815
|
+
const durationMs = Date.now() - startTime;
|
|
8816
|
+
console.log(`[SDK-WORKER] Agent '${resourceId}' completed (${durationMs}ms)`);
|
|
8817
|
+
parentPort.postMessage({ type: "result", status: "completed", output, logs, metrics: { durationMs } });
|
|
8818
|
+
} catch (err) {
|
|
8819
|
+
const durationMs = Date.now() - startTime;
|
|
8820
|
+
const errorMessage = err?.message ?? String(err);
|
|
8821
|
+
err?.code ?? "unknown";
|
|
8822
|
+
const errorName = err?.name ?? err?.constructor?.name ?? "Error";
|
|
8823
|
+
console.error(`[SDK-WORKER] Agent '${resourceId}' failed (${durationMs}ms): [${errorName}] ${errorMessage}`);
|
|
8824
|
+
parentPort.postMessage({
|
|
8825
|
+
type: "result",
|
|
8826
|
+
status: "failed",
|
|
8827
|
+
error: `${errorName}: ${errorMessage}`,
|
|
8828
|
+
logs,
|
|
8829
|
+
metrics: { durationMs }
|
|
8830
|
+
});
|
|
8831
|
+
} finally {
|
|
8832
|
+
restore();
|
|
8833
|
+
}
|
|
8834
|
+
return;
|
|
7464
8835
|
}
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
orgName,
|
|
7473
|
-
external.resourceId,
|
|
7474
|
-
null,
|
|
7475
|
-
`[${orgName}] External resource ID '${external.resourceId}' conflicts with internal resource ID`
|
|
7476
|
-
);
|
|
8836
|
+
console.error(`[SDK-WORKER] Resource not found: ${resourceId}`);
|
|
8837
|
+
parentPort.postMessage({
|
|
8838
|
+
type: "result",
|
|
8839
|
+
status: "failed",
|
|
8840
|
+
error: `Resource not found: ${resourceId}`,
|
|
8841
|
+
logs: []
|
|
8842
|
+
});
|
|
7477
8843
|
}
|
|
7478
|
-
external.triggers?.agents?.forEach((agentId) => {
|
|
7479
|
-
if (!validAgentIds.has(agentId)) {
|
|
7480
|
-
throw new RegistryValidationError(
|
|
7481
|
-
orgName,
|
|
7482
|
-
external.resourceId,
|
|
7483
|
-
"triggers.agents",
|
|
7484
|
-
`[${orgName}] External resource '${external.resourceId}' triggers non-existent agent: ${agentId}`
|
|
7485
|
-
);
|
|
7486
|
-
}
|
|
7487
|
-
});
|
|
7488
|
-
external.triggers?.workflows?.forEach((workflowId) => {
|
|
7489
|
-
if (!validWorkflowIds.has(workflowId)) {
|
|
7490
|
-
throw new RegistryValidationError(
|
|
7491
|
-
orgName,
|
|
7492
|
-
external.resourceId,
|
|
7493
|
-
"triggers.workflows",
|
|
7494
|
-
`[${orgName}] External resource '${external.resourceId}' triggers non-existent workflow: ${workflowId}`
|
|
7495
|
-
);
|
|
7496
|
-
}
|
|
7497
|
-
});
|
|
7498
|
-
external.uses?.integrations?.forEach((integrationId) => {
|
|
7499
|
-
if (!validIntegrationIds.has(integrationId)) {
|
|
7500
|
-
throw new RegistryValidationError(
|
|
7501
|
-
orgName,
|
|
7502
|
-
external.resourceId,
|
|
7503
|
-
"uses.integrations",
|
|
7504
|
-
`[${orgName}] External resource '${external.resourceId}' uses non-existent integration: ${integrationId}`
|
|
7505
|
-
);
|
|
7506
|
-
}
|
|
7507
|
-
});
|
|
7508
8844
|
});
|
|
7509
8845
|
}
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
|
|
8846
|
+
if (workerData != null && workerData.kind === "static") {
|
|
8847
|
+
const { modulePath } = workerData;
|
|
8848
|
+
void (async () => {
|
|
8849
|
+
const mod = await import(modulePath);
|
|
8850
|
+
startWorker(mod.default);
|
|
8851
|
+
})();
|
|
8852
|
+
}
|
|
8853
|
+
|
|
8854
|
+
// src/test-utils/workflow.ts
|
|
8855
|
+
function extractStepEvents(logs) {
|
|
8856
|
+
return logs.flatMap((log) => {
|
|
8857
|
+
const context = log.context;
|
|
8858
|
+
if (!context || context.type !== "workflow" || typeof context.contextType !== "string") {
|
|
8859
|
+
return [];
|
|
7519
8860
|
}
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
if (!validWorkflowIds.has(workflowId)) {
|
|
7532
|
-
throw new RegistryValidationError(
|
|
7533
|
-
orgName,
|
|
7534
|
-
humanCheckpoint.resourceId,
|
|
7535
|
-
"requestedBy.workflows",
|
|
7536
|
-
`[${orgName}] Human checkpoint '${humanCheckpoint.resourceId}' requestedBy non-existent workflow: ${workflowId}`
|
|
7537
|
-
);
|
|
7538
|
-
}
|
|
7539
|
-
});
|
|
7540
|
-
humanCheckpoint.routesTo?.agents?.forEach((agentId) => {
|
|
7541
|
-
if (!validAgentIds.has(agentId)) {
|
|
7542
|
-
throw new RegistryValidationError(
|
|
7543
|
-
orgName,
|
|
7544
|
-
humanCheckpoint.resourceId,
|
|
7545
|
-
"routesTo.agents",
|
|
7546
|
-
`[${orgName}] Human checkpoint '${humanCheckpoint.resourceId}' routesTo non-existent agent: ${agentId}`
|
|
7547
|
-
);
|
|
7548
|
-
}
|
|
7549
|
-
});
|
|
7550
|
-
humanCheckpoint.routesTo?.workflows?.forEach((workflowId) => {
|
|
7551
|
-
if (!validWorkflowIds.has(workflowId)) {
|
|
7552
|
-
throw new RegistryValidationError(
|
|
7553
|
-
orgName,
|
|
7554
|
-
humanCheckpoint.resourceId,
|
|
7555
|
-
"routesTo.workflows",
|
|
7556
|
-
`[${orgName}] Human checkpoint '${humanCheckpoint.resourceId}' routesTo non-existent workflow: ${workflowId}`
|
|
7557
|
-
);
|
|
8861
|
+
return [
|
|
8862
|
+
{
|
|
8863
|
+
type: context.contextType,
|
|
8864
|
+
stepId: typeof context.stepId === "string" ? context.stepId : void 0,
|
|
8865
|
+
stepStatus: typeof context.stepStatus === "string" ? context.stepStatus : void 0,
|
|
8866
|
+
input: context.input,
|
|
8867
|
+
output: context.output,
|
|
8868
|
+
error: context.error,
|
|
8869
|
+
duration: typeof context.duration === "number" ? context.duration : void 0,
|
|
8870
|
+
target: typeof context.target === "string" ? context.target : void 0,
|
|
8871
|
+
raw: context
|
|
7558
8872
|
}
|
|
7559
|
-
|
|
8873
|
+
];
|
|
8874
|
+
});
|
|
8875
|
+
}
|
|
8876
|
+
async function runWorkflow(definition, input, options = {}) {
|
|
8877
|
+
const context = options.context ?? {};
|
|
8878
|
+
const { output, logs } = await executeWorkflow(definition, input, {
|
|
8879
|
+
executionId: context.executionId ?? `test-${Date.now()}`,
|
|
8880
|
+
organizationId: context.organizationId ?? "test-org",
|
|
8881
|
+
organizationName: context.organizationName ?? "Test Organization",
|
|
8882
|
+
sessionId: context.sessionId,
|
|
8883
|
+
sessionTurnNumber: context.sessionTurnNumber,
|
|
8884
|
+
parentExecutionId: context.parentExecutionId,
|
|
8885
|
+
executionDepth: context.executionDepth ?? 0,
|
|
8886
|
+
adapters: options.adapters
|
|
7560
8887
|
});
|
|
8888
|
+
return {
|
|
8889
|
+
output,
|
|
8890
|
+
logs,
|
|
8891
|
+
stepEvents: extractStepEvents(logs)
|
|
8892
|
+
};
|
|
7561
8893
|
}
|
|
7562
8894
|
|
|
7563
8895
|
// src/test-utils/registry.ts
|
|
@@ -24328,7 +25660,14 @@ var mockCrm = (overrides) => createMockAdapter(
|
|
|
24328
25660
|
overrides
|
|
24329
25661
|
);
|
|
24330
25662
|
var mockList = (overrides) => createMockAdapter(
|
|
24331
|
-
[
|
|
25663
|
+
[
|
|
25664
|
+
"getConfig",
|
|
25665
|
+
"recordExecution",
|
|
25666
|
+
"updateCompanyStage",
|
|
25667
|
+
"updateContactStage",
|
|
25668
|
+
"listPendingCompanyIds",
|
|
25669
|
+
"listPendingContactIds"
|
|
25670
|
+
],
|
|
24332
25671
|
overrides
|
|
24333
25672
|
);
|
|
24334
25673
|
var mockPdf = (overrides) => createMockAdapter(["render", "renderToBuffer"], overrides);
|