@elevasis/sdk 1.20.2 → 1.21.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 +3386 -1529
- package/dist/index.d.ts +412 -149
- package/dist/index.js +955 -721
- package/dist/node/index.d.ts +0 -3
- package/dist/node/index.js +21 -48
- package/dist/test-utils/index.d.ts +395 -128
- package/dist/test-utils/index.js +599 -368
- package/dist/worker/index.js +536 -323
- package/package.json +2 -2
- package/reference/_navigation.md +9 -7
- package/reference/_reference-manifest.json +1 -1
- package/reference/claude-config/rules/agent-start-here.md +4 -0
- package/reference/claude-config/rules/frontend.md +2 -2
- package/reference/claude-config/rules/organization-model.md +44 -2
- package/reference/claude-config/rules/organization-os.md +12 -12
- package/reference/claude-config/rules/ui.md +14 -14
- package/reference/claude-config/rules/vibe.md +37 -33
- package/reference/claude-config/skills/explore/SKILL.md +6 -6
- package/reference/claude-config/skills/knowledge/SKILL.md +73 -29
- package/reference/claude-config/skills/knowledge/operations/codify-level-a.md +1 -1
- package/reference/claude-config/skills/knowledge/operations/codify-level-b.md +25 -24
- package/reference/claude-config/skills/knowledge/operations/features.md +56 -93
- package/reference/claude-config/skills/knowledge/operations/labels.md +19 -14
- package/reference/claude-config/skills/knowledge/operations/offerings.md +6 -6
- package/reference/claude-config/skills/save/SKILL.md +2 -2
- package/reference/claude-config/skills/setup/SKILL.md +1 -1
- package/reference/claude-config/skills/tutorial/technical.md +23 -26
- package/reference/claude-config/skills/tutorial/vibe-coder.md +9 -9
- package/reference/claude-config/sync-notes/2026-05-12-sdk-ready-release-train.md +30 -0
- package/reference/cli.mdx +140 -0
- package/reference/deployment/provided-features.mdx +29 -15
- package/reference/examples/organization-model.ts +1 -1
- package/reference/packages/core/src/knowledge/README.md +8 -7
- package/reference/packages/core/src/organization-model/README.md +66 -26
- package/reference/packages/ui/src/provider/README.md +5 -5
- package/reference/scaffold/core/organization-graph.mdx +16 -15
- package/reference/scaffold/core/organization-model.mdx +89 -41
- package/reference/scaffold/index.mdx +9 -9
- package/reference/scaffold/operations/propagation-pipeline.md +3 -3
- package/reference/scaffold/operations/scaffold-maintenance.md +11 -11
- package/reference/scaffold/recipes/add-a-feature.md +26 -24
- package/reference/scaffold/recipes/add-a-resource.md +10 -14
- package/reference/scaffold/recipes/customize-crm-actions.md +439 -439
- package/reference/scaffold/recipes/customize-knowledge-browser.md +384 -0
- package/reference/scaffold/recipes/customize-organization-model.md +72 -44
- package/reference/scaffold/recipes/extend-crm.md +40 -39
- package/reference/scaffold/recipes/extend-lead-gen.md +15 -16
- package/reference/scaffold/recipes/gate-by-feature-or-admin.md +34 -30
- package/reference/scaffold/recipes/index.md +13 -12
- package/reference/scaffold/recipes/query-the-knowledge-graph.md +200 -0
- package/reference/scaffold/reference/contracts.md +362 -99
- package/reference/scaffold/reference/feature-registry.md +9 -20
- package/reference/scaffold/reference/glossary.md +18 -18
- package/reference/scaffold/ui/composition-extensibility.mdx +23 -23
- package/reference/scaffold/ui/customization.md +11 -11
- package/reference/scaffold/ui/feature-flags-and-gating.md +8 -8
- package/reference/scaffold/ui/feature-shell.mdx +19 -19
- package/reference/scaffold/ui/recipes.md +29 -28
package/dist/index.js
CHANGED
|
@@ -171,776 +171,464 @@ DisplayMetadataSchema.extend({
|
|
|
171
171
|
id: ModelIdSchema,
|
|
172
172
|
resourceId: z.string().trim().min(1).max(255),
|
|
173
173
|
resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
|
|
174
|
-
|
|
174
|
+
systemIds: ReferenceIdsSchema,
|
|
175
175
|
entityIds: ReferenceIdsSchema,
|
|
176
176
|
surfaceIds: ReferenceIdsSchema,
|
|
177
|
-
|
|
177
|
+
actionIds: ReferenceIdsSchema,
|
|
178
178
|
/** Optional tech-stack metadata for external-SaaS integrations. */
|
|
179
179
|
techStack: TechStackEntrySchema.optional()
|
|
180
180
|
});
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
181
|
+
|
|
182
|
+
// ../core/src/organization-model/domains/entities.ts
|
|
183
|
+
var EntityIdSchema = ModelIdSchema;
|
|
184
|
+
var EntityLinkKindSchema = z.enum(["belongs-to", "has-many", "has-one", "many-to-many"]).meta({ label: "Link kind" });
|
|
185
|
+
var EntityLinkSchema = z.object({
|
|
186
|
+
toEntity: EntityIdSchema.meta({ ref: "entity" }),
|
|
187
|
+
kind: EntityLinkKindSchema,
|
|
188
|
+
via: z.string().trim().min(1).max(255).optional(),
|
|
189
|
+
label: LabelSchema.optional()
|
|
188
190
|
});
|
|
189
|
-
var
|
|
190
|
-
id:
|
|
191
|
-
|
|
191
|
+
var EntitySchema = z.object({
|
|
192
|
+
id: EntityIdSchema,
|
|
193
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
194
|
+
order: z.number(),
|
|
195
|
+
label: LabelSchema,
|
|
192
196
|
description: DescriptionSchema.optional(),
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
defaultPipelineId: ModelIdSchema,
|
|
199
|
-
pipelines: z.array(SalesPipelineSchema).min(1)
|
|
197
|
+
ownedBySystemId: ModelIdSchema.meta({ ref: "system" }),
|
|
198
|
+
table: z.string().trim().min(1).max(255).optional(),
|
|
199
|
+
rowSchema: ModelIdSchema.optional(),
|
|
200
|
+
stateCatalogId: ModelIdSchema.optional(),
|
|
201
|
+
links: z.array(EntityLinkSchema).optional()
|
|
200
202
|
});
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
stateKey: "discovery_booking_cancelled",
|
|
215
|
-
label: "Discovery Booking Cancelled"
|
|
216
|
-
};
|
|
217
|
-
var CRM_REPLY_SENT_STATE = {
|
|
218
|
-
stateKey: "reply_sent",
|
|
219
|
-
label: "Reply Sent"
|
|
220
|
-
};
|
|
221
|
-
var CRM_FOLLOWUP_1_SENT_STATE = {
|
|
222
|
-
stateKey: "followup_1_sent",
|
|
223
|
-
label: "Follow-up 1 Sent"
|
|
224
|
-
};
|
|
225
|
-
var CRM_FOLLOWUP_2_SENT_STATE = {
|
|
226
|
-
stateKey: "followup_2_sent",
|
|
227
|
-
label: "Follow-up 2 Sent"
|
|
228
|
-
};
|
|
229
|
-
var CRM_FOLLOWUP_3_SENT_STATE = {
|
|
230
|
-
stateKey: "followup_3_sent",
|
|
231
|
-
label: "Follow-up 3 Sent"
|
|
232
|
-
};
|
|
233
|
-
var CRM_PIPELINE_DEFINITION = {
|
|
234
|
-
pipelineKey: "crm",
|
|
235
|
-
label: "CRM",
|
|
236
|
-
entityKey: "crm.deal",
|
|
237
|
-
stages: [
|
|
238
|
-
{
|
|
239
|
-
stageKey: "interested",
|
|
240
|
-
label: "Interested",
|
|
241
|
-
color: "blue",
|
|
242
|
-
states: [
|
|
243
|
-
CRM_DISCOVERY_REPLIED_STATE,
|
|
244
|
-
CRM_DISCOVERY_LINK_SENT_STATE,
|
|
245
|
-
CRM_DISCOVERY_NUDGING_STATE,
|
|
246
|
-
CRM_DISCOVERY_BOOKING_CANCELLED_STATE,
|
|
247
|
-
CRM_REPLY_SENT_STATE,
|
|
248
|
-
CRM_FOLLOWUP_1_SENT_STATE,
|
|
249
|
-
CRM_FOLLOWUP_2_SENT_STATE,
|
|
250
|
-
CRM_FOLLOWUP_3_SENT_STATE
|
|
251
|
-
]
|
|
252
|
-
},
|
|
253
|
-
{ stageKey: "proposal", label: "Proposal", color: "yellow", states: [] },
|
|
254
|
-
{ stageKey: "closing", label: "Closing", color: "orange", states: [] },
|
|
255
|
-
{ stageKey: "closed_won", label: "Closed Won", color: "green", states: [] },
|
|
256
|
-
{ stageKey: "closed_lost", label: "Closed Lost", color: "red", states: [] },
|
|
257
|
-
{ stageKey: "nurturing", label: "Nurturing", color: "grape", states: [] }
|
|
258
|
-
]
|
|
259
|
-
};
|
|
260
|
-
var LEAD_GEN_STAGE_CATALOG = {
|
|
261
|
-
// Prospecting — company population
|
|
262
|
-
scraped: {
|
|
263
|
-
key: "scraped",
|
|
264
|
-
label: "Scraped",
|
|
265
|
-
description: "Company was scraped from a source directory (Apify actor run).",
|
|
266
|
-
order: 1,
|
|
267
|
-
entity: "company"
|
|
268
|
-
},
|
|
269
|
-
populated: {
|
|
270
|
-
key: "populated",
|
|
271
|
-
label: "Companies found",
|
|
272
|
-
description: "Companies have been found and added to the lead-gen list.",
|
|
273
|
-
order: 2,
|
|
274
|
-
entity: "company"
|
|
275
|
-
},
|
|
276
|
-
crawled: {
|
|
277
|
-
key: "crawled",
|
|
278
|
-
label: "Websites crawled",
|
|
279
|
-
description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
|
|
280
|
-
order: 2.5,
|
|
281
|
-
entity: "company"
|
|
282
|
-
},
|
|
283
|
-
extracted: {
|
|
284
|
-
key: "extracted",
|
|
285
|
-
label: "Websites analyzed",
|
|
286
|
-
description: "Company websites have been analyzed for business signals.",
|
|
287
|
-
order: 3,
|
|
288
|
-
entity: "company"
|
|
289
|
-
},
|
|
290
|
-
enriched: {
|
|
291
|
-
key: "enriched",
|
|
292
|
-
label: "Enriched",
|
|
293
|
-
description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
|
|
294
|
-
order: 4,
|
|
295
|
-
entity: "company"
|
|
203
|
+
z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
204
|
+
message: "Each entity entry id must match its map key"
|
|
205
|
+
}).default({});
|
|
206
|
+
var ENTITY_ENTRY_INPUTS = [
|
|
207
|
+
{
|
|
208
|
+
id: "crm.deal",
|
|
209
|
+
order: 10,
|
|
210
|
+
label: "Deal",
|
|
211
|
+
description: "A CRM opportunity or sales pipeline record.",
|
|
212
|
+
ownedBySystemId: "sales.crm",
|
|
213
|
+
table: "crm_deals",
|
|
214
|
+
stateCatalogId: "crm.pipeline",
|
|
215
|
+
links: [{ toEntity: "crm.contact", kind: "has-many", via: "deal_contacts", label: "contacts" }]
|
|
296
216
|
},
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
recordStageKey: "discovered"
|
|
217
|
+
{
|
|
218
|
+
id: "crm.contact",
|
|
219
|
+
order: 20,
|
|
220
|
+
label: "CRM Contact",
|
|
221
|
+
description: "A person associated with a CRM relationship or deal.",
|
|
222
|
+
ownedBySystemId: "sales.crm",
|
|
223
|
+
table: "crm_contacts"
|
|
305
224
|
},
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
label: "
|
|
310
|
-
description: "
|
|
311
|
-
|
|
312
|
-
|
|
225
|
+
{
|
|
226
|
+
id: "leadgen.list",
|
|
227
|
+
order: 30,
|
|
228
|
+
label: "Lead List",
|
|
229
|
+
description: "A prospecting list that groups companies and contacts for acquisition workflows.",
|
|
230
|
+
ownedBySystemId: "sales.lead-gen",
|
|
231
|
+
table: "acq_lists",
|
|
232
|
+
links: [
|
|
233
|
+
{ toEntity: "leadgen.company", kind: "has-many", via: "acq_list_companies", label: "companies" },
|
|
234
|
+
{ toEntity: "leadgen.contact", kind: "has-many", via: "acq_list_members", label: "contacts" }
|
|
235
|
+
]
|
|
313
236
|
},
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
237
|
+
{
|
|
238
|
+
id: "leadgen.company",
|
|
239
|
+
order: 40,
|
|
240
|
+
label: "Lead Company",
|
|
241
|
+
description: "A company record sourced, enriched, and qualified during prospecting.",
|
|
242
|
+
ownedBySystemId: "sales.lead-gen",
|
|
243
|
+
table: "acq_list_companies",
|
|
244
|
+
stateCatalogId: "lead-gen.company",
|
|
245
|
+
links: [
|
|
246
|
+
{ toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
|
|
247
|
+
{ toEntity: "leadgen.contact", kind: "has-many", via: "company_id", label: "contacts" }
|
|
248
|
+
]
|
|
320
249
|
},
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
label: "
|
|
325
|
-
description: "
|
|
326
|
-
|
|
327
|
-
|
|
250
|
+
{
|
|
251
|
+
id: "leadgen.contact",
|
|
252
|
+
order: 50,
|
|
253
|
+
label: "Lead Contact",
|
|
254
|
+
description: "A prospect contact discovered or enriched during lead generation.",
|
|
255
|
+
ownedBySystemId: "sales.lead-gen",
|
|
256
|
+
table: "acq_list_members",
|
|
257
|
+
stateCatalogId: "lead-gen.contact",
|
|
258
|
+
links: [
|
|
259
|
+
{ toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
|
|
260
|
+
{ toEntity: "leadgen.company", kind: "belongs-to", via: "company_id", label: "company" }
|
|
261
|
+
]
|
|
328
262
|
},
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
label: "
|
|
333
|
-
description: "
|
|
334
|
-
|
|
335
|
-
|
|
263
|
+
{
|
|
264
|
+
id: "delivery.project",
|
|
265
|
+
order: 60,
|
|
266
|
+
label: "Project",
|
|
267
|
+
description: "A client delivery project.",
|
|
268
|
+
ownedBySystemId: "projects",
|
|
269
|
+
table: "projects",
|
|
270
|
+
links: [
|
|
271
|
+
{ toEntity: "delivery.milestone", kind: "has-many", via: "project_id", label: "milestones" },
|
|
272
|
+
{ toEntity: "delivery.task", kind: "has-many", via: "project_id", label: "tasks" }
|
|
273
|
+
]
|
|
336
274
|
},
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
275
|
+
{
|
|
276
|
+
id: "delivery.milestone",
|
|
277
|
+
order: 70,
|
|
278
|
+
label: "Milestone",
|
|
279
|
+
description: "A delivery checkpoint within a project.",
|
|
280
|
+
ownedBySystemId: "projects",
|
|
281
|
+
table: "project_milestones",
|
|
282
|
+
links: [
|
|
283
|
+
{ toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
|
|
284
|
+
{ toEntity: "delivery.task", kind: "has-many", via: "milestone_id", label: "tasks" }
|
|
285
|
+
]
|
|
344
286
|
},
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
287
|
+
{
|
|
288
|
+
id: "delivery.task",
|
|
289
|
+
order: 80,
|
|
290
|
+
label: "Task",
|
|
291
|
+
description: "A delivery task that can move through the task status catalog.",
|
|
292
|
+
ownedBySystemId: "projects",
|
|
293
|
+
table: "project_tasks",
|
|
294
|
+
stateCatalogId: "delivery.task",
|
|
295
|
+
links: [
|
|
296
|
+
{ toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
|
|
297
|
+
{ toEntity: "delivery.milestone", kind: "belongs-to", via: "milestone_id", label: "milestone" }
|
|
298
|
+
]
|
|
351
299
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
300
|
+
];
|
|
301
|
+
Object.fromEntries(
|
|
302
|
+
ENTITY_ENTRY_INPUTS.map((entity) => {
|
|
303
|
+
const parsed = EntitySchema.parse(entity);
|
|
304
|
+
return [parsed.id, parsed];
|
|
305
|
+
})
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
// ../core/src/organization-model/domains/actions.ts
|
|
309
|
+
var ActionResourceIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
|
|
310
|
+
z.enum(["slash-command", "mcp-tool", "api-endpoint", "script-execution"]).meta({ label: "Invocation kind" });
|
|
311
|
+
var ActionIdSchema = ModelIdSchema;
|
|
312
|
+
var ActionScopeSchema = z.union([
|
|
313
|
+
z.literal("global"),
|
|
314
|
+
z.object({
|
|
315
|
+
domain: ModelIdSchema
|
|
316
|
+
})
|
|
317
|
+
]);
|
|
318
|
+
z.object({
|
|
319
|
+
actionId: ActionIdSchema.meta({ ref: "action" }),
|
|
320
|
+
intent: z.enum(["exposes", "consumes"]).meta({ label: "Intent" })
|
|
356
321
|
});
|
|
357
|
-
var
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
|
|
362
|
-
renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
|
|
363
|
-
badgeColor: z.string().trim().min(1).max(40).optional()
|
|
322
|
+
var SlashCommandInvocationSchema = z.object({
|
|
323
|
+
kind: z.literal("slash-command"),
|
|
324
|
+
command: z.string().trim().min(1).max(200).regex(/^\/[^\s].*$/, "Slash commands must start with /"),
|
|
325
|
+
toolFactory: ModelIdSchema.optional()
|
|
364
326
|
});
|
|
365
|
-
var
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
message: "recordColumns must include at least one entity column set"
|
|
327
|
+
var McpToolInvocationSchema = z.object({
|
|
328
|
+
kind: z.literal("mcp-tool"),
|
|
329
|
+
server: ModelIdSchema,
|
|
330
|
+
name: ModelIdSchema
|
|
370
331
|
});
|
|
371
|
-
var
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
selectionMode: z.enum(["single", "multiple"]).optional(),
|
|
378
|
-
inputPath: z.string().trim().min(1).max(500),
|
|
379
|
-
verifyOnRun: z.boolean().optional()
|
|
332
|
+
var ApiEndpointInvocationSchema = z.object({
|
|
333
|
+
kind: z.literal("api-endpoint"),
|
|
334
|
+
method: z.enum(["GET", "POST", "PATCH", "DELETE"]).meta({ label: "HTTP method" }),
|
|
335
|
+
path: z.string().trim().startsWith("/").max(500),
|
|
336
|
+
requestSchema: ModelIdSchema.optional(),
|
|
337
|
+
responseSchema: ModelIdSchema.optional()
|
|
380
338
|
});
|
|
381
|
-
var
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
|
|
385
|
-
stageKey: ModelIdSchema,
|
|
386
|
-
recordEntity: z.enum(["company", "contact"]).optional(),
|
|
387
|
-
recordsStageKey: ModelIdSchema.optional(),
|
|
388
|
-
recordSourceStageKey: ModelIdSchema.optional(),
|
|
389
|
-
dependsOn: z.array(ModelIdSchema).optional(),
|
|
390
|
-
dependencyMode: z.literal("per-record-eligibility"),
|
|
391
|
-
capabilityKey: ModelIdSchema,
|
|
392
|
-
defaultBatchSize: z.number().int().positive(),
|
|
393
|
-
maxBatchSize: z.number().int().positive(),
|
|
394
|
-
recordColumns: RecordColumnsConfigSchema.optional(),
|
|
395
|
-
credentialRequirements: z.array(CredentialRequirementSchema).optional()
|
|
396
|
-
}).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
|
|
397
|
-
message: "defaultBatchSize must be less than or equal to maxBatchSize",
|
|
398
|
-
path: ["defaultBatchSize"]
|
|
339
|
+
var ScriptExecutionInvocationSchema = z.object({
|
|
340
|
+
kind: z.literal("script-execution"),
|
|
341
|
+
resourceId: ActionResourceIdSchema
|
|
399
342
|
});
|
|
400
|
-
var
|
|
401
|
-
|
|
402
|
-
|
|
343
|
+
var ActionInvocationSchema = z.discriminatedUnion("kind", [
|
|
344
|
+
SlashCommandInvocationSchema,
|
|
345
|
+
McpToolInvocationSchema,
|
|
346
|
+
ApiEndpointInvocationSchema,
|
|
347
|
+
ScriptExecutionInvocationSchema
|
|
348
|
+
]);
|
|
349
|
+
var ActionSchema = z.object({
|
|
350
|
+
id: ActionIdSchema,
|
|
351
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
352
|
+
order: z.number(),
|
|
353
|
+
label: LabelSchema,
|
|
354
|
+
description: DescriptionSchema.optional(),
|
|
355
|
+
scope: ActionScopeSchema.default("global"),
|
|
356
|
+
resourceId: ActionResourceIdSchema.optional(),
|
|
357
|
+
affects: z.array(EntityIdSchema.meta({ ref: "entity" })).optional(),
|
|
358
|
+
invocations: z.array(ActionInvocationSchema).default([]),
|
|
359
|
+
knowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
|
|
360
|
+
lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
|
|
403
361
|
});
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
362
|
+
z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
363
|
+
message: "Each action entry id must match its map key"
|
|
364
|
+
}).default({});
|
|
365
|
+
var LEAD_GEN_ACTION_ENTRY_INPUTS = [
|
|
366
|
+
{
|
|
367
|
+
id: "lead-gen.company.source",
|
|
368
|
+
order: 10,
|
|
369
|
+
label: "Source companies",
|
|
370
|
+
description: "Import source companies from a list provider.",
|
|
371
|
+
scope: { domain: "sales" },
|
|
372
|
+
resourceId: "lgn-import-workflow",
|
|
373
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/source" }]
|
|
413
374
|
},
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
extracted: {
|
|
423
|
-
company: [
|
|
424
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
425
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
426
|
-
{ key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
|
|
427
|
-
{ key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
|
|
428
|
-
{ key: "automation-gaps", label: "Automation gaps", path: "company.enrichmentData.websiteCrawl.automationGaps", renderType: "json" },
|
|
429
|
-
{ key: "contact-count", label: "Contacts", path: "company.enrichmentData.websiteCrawl.emailCount", renderType: "count" }
|
|
430
|
-
]
|
|
431
|
-
},
|
|
432
|
-
qualified: {
|
|
433
|
-
company: [
|
|
434
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
435
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
436
|
-
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
437
|
-
{ key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
|
|
438
|
-
{ key: "disqualified-reason", label: "Disqualified reason", path: "processingState.qualified.data.disqualifiedReason" }
|
|
439
|
-
]
|
|
440
|
-
},
|
|
441
|
-
decisionMakers: {
|
|
442
|
-
contact: [
|
|
443
|
-
{ key: "name", label: "Name", path: "contact.name" },
|
|
444
|
-
{ key: "title", label: "Title", path: "contact.title" },
|
|
445
|
-
{ key: "email", label: "Email", path: "contact.email" },
|
|
446
|
-
{ key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
|
|
447
|
-
{ key: "priority-score", label: "Priority", path: "contact.enrichmentData.apollo.priorityScore", renderType: "badge" }
|
|
448
|
-
]
|
|
449
|
-
},
|
|
450
|
-
uploaded: {
|
|
451
|
-
company: [
|
|
452
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
453
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
454
|
-
{ key: "contacts", label: "Contacts", path: "company.enrichmentData.approvedLeadListExport.contacts", renderType: "json" },
|
|
455
|
-
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
456
|
-
{ key: "approval", label: "Approval", path: "company.enrichmentData.approvedLeadListExport.approvalStatus", renderType: "badge" }
|
|
457
|
-
]
|
|
458
|
-
}
|
|
459
|
-
};
|
|
460
|
-
z.object({
|
|
461
|
-
id: ModelIdSchema,
|
|
462
|
-
label: z.string(),
|
|
463
|
-
description: z.string(),
|
|
464
|
-
resourceId: ModelIdSchema
|
|
465
|
-
});
|
|
466
|
-
var CAPABILITY_REGISTRY = [
|
|
467
|
-
{
|
|
468
|
-
id: "lead-gen.company.source",
|
|
469
|
-
label: "Source companies",
|
|
470
|
-
description: "Import source companies from a list provider.",
|
|
471
|
-
resourceId: "lgn-import-workflow"
|
|
472
|
-
},
|
|
473
|
-
{
|
|
474
|
-
id: "lead-gen.company.apollo-import",
|
|
475
|
-
label: "Import from Apollo",
|
|
476
|
-
description: "Pull companies and seed contact data from an Apollo search or list.",
|
|
477
|
-
resourceId: "lgn-01c-apollo-import-workflow"
|
|
375
|
+
{
|
|
376
|
+
id: "lead-gen.company.apollo-import",
|
|
377
|
+
order: 20,
|
|
378
|
+
label: "Import from Apollo",
|
|
379
|
+
description: "Pull companies and seed contact data from an Apollo search or list.",
|
|
380
|
+
scope: { domain: "sales" },
|
|
381
|
+
resourceId: "lgn-01c-apollo-import-workflow",
|
|
382
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/apollo-import" }]
|
|
478
383
|
},
|
|
479
384
|
{
|
|
480
385
|
id: "lead-gen.contact.discover",
|
|
386
|
+
order: 30,
|
|
481
387
|
label: "Discover contact emails",
|
|
482
388
|
description: "Find email addresses for contacts at qualified companies.",
|
|
483
|
-
|
|
389
|
+
scope: { domain: "sales" },
|
|
390
|
+
resourceId: "lgn-04-email-discovery-workflow",
|
|
391
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/discover" }]
|
|
484
392
|
},
|
|
485
393
|
{
|
|
486
394
|
id: "lead-gen.contact.verify-email",
|
|
395
|
+
order: 40,
|
|
487
396
|
label: "Verify emails",
|
|
488
397
|
description: "Check email deliverability before outreach.",
|
|
489
|
-
|
|
398
|
+
scope: { domain: "sales" },
|
|
399
|
+
resourceId: "lgn-05-email-verification-workflow",
|
|
400
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/verify-email" }]
|
|
490
401
|
},
|
|
491
402
|
{
|
|
492
403
|
id: "lead-gen.company.apify-crawl",
|
|
404
|
+
order: 50,
|
|
493
405
|
label: "Crawl websites",
|
|
494
406
|
description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis.",
|
|
495
|
-
|
|
407
|
+
scope: { domain: "sales" },
|
|
408
|
+
resourceId: "lgn-02a-apify-website-crawl-workflow",
|
|
409
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/apify-crawl" }]
|
|
496
410
|
},
|
|
497
411
|
{
|
|
498
412
|
id: "lead-gen.company.website-extract",
|
|
413
|
+
order: 60,
|
|
499
414
|
label: "Extract website signals",
|
|
500
415
|
description: "Scrape and analyze company websites for qualification signals.",
|
|
501
|
-
|
|
416
|
+
scope: { domain: "sales" },
|
|
417
|
+
resourceId: "lgn-02-website-extract-workflow",
|
|
418
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/website-extract" }]
|
|
502
419
|
},
|
|
503
420
|
{
|
|
504
421
|
id: "lead-gen.company.qualify",
|
|
422
|
+
order: 70,
|
|
505
423
|
label: "Qualify companies",
|
|
506
424
|
description: "Score and filter companies against the ICP rubric.",
|
|
507
|
-
|
|
425
|
+
scope: { domain: "sales" },
|
|
426
|
+
resourceId: "lgn-03-company-qualification-workflow",
|
|
427
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/qualify" }]
|
|
508
428
|
},
|
|
509
429
|
{
|
|
510
430
|
id: "lead-gen.company.dtc-subscription-qualify",
|
|
431
|
+
order: 80,
|
|
511
432
|
label: "Qualify DTC subscription fit",
|
|
512
433
|
description: "Classify subscription potential and consumable-product fit for DTC brands.",
|
|
513
|
-
|
|
434
|
+
scope: { domain: "sales" },
|
|
435
|
+
resourceId: "lgn-03b-dtc-subscription-score-workflow",
|
|
436
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/dtc-subscription-qualify" }]
|
|
514
437
|
},
|
|
515
438
|
{
|
|
516
439
|
id: "lead-gen.contact.apollo-decision-maker-enrich",
|
|
440
|
+
order: 90,
|
|
517
441
|
label: "Enrich decision-makers",
|
|
518
442
|
description: "Find and enrich qualified contacts at qualified companies via Apollo.",
|
|
519
|
-
|
|
443
|
+
scope: { domain: "sales" },
|
|
444
|
+
resourceId: "lgn-04b-apollo-decision-maker-enrich-workflow",
|
|
445
|
+
invocations: [
|
|
446
|
+
{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/apollo-decision-maker-enrich" }
|
|
447
|
+
]
|
|
520
448
|
},
|
|
521
449
|
{
|
|
522
450
|
id: "lead-gen.contact.personalize",
|
|
451
|
+
order: 100,
|
|
523
452
|
label: "Personalize outreach",
|
|
524
453
|
description: "Generate personalized opening lines for each contact.",
|
|
525
|
-
|
|
454
|
+
scope: { domain: "sales" },
|
|
455
|
+
resourceId: "ist-personalization-workflow",
|
|
456
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/personalize" }]
|
|
526
457
|
},
|
|
527
458
|
{
|
|
528
459
|
id: "lead-gen.review.outreach-ready",
|
|
460
|
+
order: 110,
|
|
529
461
|
label: "Upload to outreach",
|
|
530
462
|
description: "Upload approved contacts to the outreach sequence after QC review.",
|
|
531
|
-
|
|
463
|
+
scope: { domain: "sales" },
|
|
464
|
+
resourceId: "ist-upload-contacts-workflow",
|
|
465
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/review/outreach-ready" }]
|
|
532
466
|
},
|
|
533
467
|
{
|
|
534
468
|
id: "lead-gen.export.list",
|
|
469
|
+
order: 120,
|
|
535
470
|
label: "Export lead list",
|
|
536
471
|
description: "Export approved leads as a downloadable lead list.",
|
|
537
|
-
|
|
472
|
+
scope: { domain: "sales" },
|
|
473
|
+
resourceId: "lgn-06-export-list-workflow",
|
|
474
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/export/list" }]
|
|
538
475
|
},
|
|
539
476
|
{
|
|
540
477
|
id: "lead-gen.company.cleanup",
|
|
478
|
+
order: 130,
|
|
541
479
|
label: "Clean up companies",
|
|
542
480
|
description: "Remove disqualified or duplicate companies from the list.",
|
|
543
|
-
|
|
481
|
+
scope: { domain: "sales" },
|
|
482
|
+
resourceId: "lgn-company-cleanup-workflow",
|
|
483
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/cleanup" }]
|
|
544
484
|
}
|
|
545
485
|
];
|
|
546
|
-
var
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
maxBatchSize: 100
|
|
594
|
-
},
|
|
595
|
-
verifyEmails: {
|
|
596
|
-
id: "verify-emails",
|
|
597
|
-
label: "Emails verified",
|
|
598
|
-
primaryEntity: "contact",
|
|
599
|
-
outputs: ["contact"],
|
|
600
|
-
stageKey: "verified",
|
|
601
|
-
dependsOn: ["find-contacts"],
|
|
602
|
-
dependencyMode: "per-record-eligibility",
|
|
603
|
-
capabilityKey: "lead-gen.contact.verify-email",
|
|
604
|
-
defaultBatchSize: 100,
|
|
605
|
-
maxBatchSize: 500
|
|
606
|
-
},
|
|
607
|
-
personalize: {
|
|
608
|
-
id: "personalize",
|
|
609
|
-
label: "Personalize",
|
|
610
|
-
primaryEntity: "contact",
|
|
611
|
-
outputs: ["contact"],
|
|
612
|
-
stageKey: "personalized",
|
|
613
|
-
dependsOn: ["verify-emails"],
|
|
614
|
-
dependencyMode: "per-record-eligibility",
|
|
615
|
-
capabilityKey: "lead-gen.contact.personalize",
|
|
616
|
-
defaultBatchSize: 25,
|
|
617
|
-
maxBatchSize: 100
|
|
618
|
-
},
|
|
619
|
-
review: {
|
|
620
|
-
id: "review",
|
|
621
|
-
label: "Reviewed and exported",
|
|
622
|
-
primaryEntity: "contact",
|
|
623
|
-
outputs: ["export"],
|
|
624
|
-
stageKey: "uploaded",
|
|
625
|
-
dependsOn: ["personalize"],
|
|
626
|
-
dependencyMode: "per-record-eligibility",
|
|
627
|
-
capabilityKey: "lead-gen.review.outreach-ready",
|
|
628
|
-
defaultBatchSize: 25,
|
|
629
|
-
maxBatchSize: 100
|
|
486
|
+
var LEAD_GEN_ACTION_ENTRIES = Object.fromEntries(
|
|
487
|
+
LEAD_GEN_ACTION_ENTRY_INPUTS.map((action) => {
|
|
488
|
+
const parsed = ActionSchema.parse(action);
|
|
489
|
+
return [parsed.id, parsed];
|
|
490
|
+
})
|
|
491
|
+
);
|
|
492
|
+
|
|
493
|
+
// ../core/src/platform/registry/reserved.ts
|
|
494
|
+
var RESERVED_RESOURCE_IDS = /* @__PURE__ */ new Set(["command-center-assistant"]);
|
|
495
|
+
Array.from(RESERVED_RESOURCE_IDS);
|
|
496
|
+
function isReservedResourceId(resourceId) {
|
|
497
|
+
return RESERVED_RESOURCE_IDS.has(resourceId);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// ../core/src/organization-model/helpers.ts
|
|
501
|
+
function listAllSystems(model) {
|
|
502
|
+
const results = [];
|
|
503
|
+
function walk(map, prefix) {
|
|
504
|
+
for (const [localId, system] of Object.entries(map)) {
|
|
505
|
+
const fullPath = prefix ? `${prefix}.${localId}` : localId;
|
|
506
|
+
results.push({ path: fullPath, system });
|
|
507
|
+
if (system.subsystems) {
|
|
508
|
+
walk(system.subsystems, fullPath);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
walk(model.systems, "");
|
|
513
|
+
return results;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// ../core/src/execution/engine/base/errors.ts
|
|
517
|
+
var ExecutionError2 = class extends Error {
|
|
518
|
+
/**
|
|
519
|
+
* Additional context/metadata for the error.
|
|
520
|
+
* Stored in execution_errors.metadata JSONB column.
|
|
521
|
+
*/
|
|
522
|
+
context;
|
|
523
|
+
/**
|
|
524
|
+
* @param message - Human-readable error message
|
|
525
|
+
* @param context - Additional context/metadata for observability
|
|
526
|
+
*/
|
|
527
|
+
constructor(message, context) {
|
|
528
|
+
super(message);
|
|
529
|
+
this.name = this.constructor.name;
|
|
530
|
+
this.context = context;
|
|
531
|
+
if (Error.captureStackTrace) {
|
|
532
|
+
Error.captureStackTrace(this, this.constructor);
|
|
630
533
|
}
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
credentialType: "api-key-secret",
|
|
730
|
-
label: "Apollo API key",
|
|
731
|
-
required: true,
|
|
732
|
-
selectionMode: "single",
|
|
733
|
-
inputPath: "credential"
|
|
734
|
-
}
|
|
735
|
-
]
|
|
736
|
-
},
|
|
737
|
-
reviewAndExport: {
|
|
738
|
-
id: "review-and-export",
|
|
739
|
-
label: "Reviewed and exported",
|
|
740
|
-
description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
|
|
741
|
-
primaryEntity: "company",
|
|
742
|
-
outputs: ["export"],
|
|
743
|
-
stageKey: "uploaded",
|
|
744
|
-
recordsStageKey: "uploaded",
|
|
745
|
-
recordSourceStageKey: "qualified",
|
|
746
|
-
dependsOn: ["enrich-decision-makers"],
|
|
747
|
-
dependencyMode: "per-record-eligibility",
|
|
748
|
-
capabilityKey: "lead-gen.export.list",
|
|
749
|
-
defaultBatchSize: 100,
|
|
750
|
-
maxBatchSize: 250,
|
|
751
|
-
recordColumns: DTC_RECORD_COLUMNS.uploaded,
|
|
752
|
-
credentialRequirements: [
|
|
753
|
-
{
|
|
754
|
-
key: "clickup",
|
|
755
|
-
provider: "clickup",
|
|
756
|
-
credentialType: "api-key-secret",
|
|
757
|
-
label: "ClickUp API token",
|
|
758
|
-
required: true,
|
|
759
|
-
selectionMode: "single",
|
|
760
|
-
inputPath: "clickupCredential",
|
|
761
|
-
verifyOnRun: true
|
|
762
|
-
}
|
|
763
|
-
]
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
};
|
|
767
|
-
z.object({
|
|
768
|
-
listEntityId: ModelIdSchema,
|
|
769
|
-
companyEntityId: ModelIdSchema,
|
|
770
|
-
contactEntityId: ModelIdSchema,
|
|
771
|
-
description: DescriptionSchema.optional(),
|
|
772
|
-
companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
|
|
773
|
-
contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
|
|
774
|
-
defaultBuildTemplateId: ModelIdSchema,
|
|
775
|
-
buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
|
|
776
|
-
});
|
|
777
|
-
function toProspectingLifecycleStage(stage) {
|
|
778
|
-
return {
|
|
779
|
-
id: stage.key,
|
|
780
|
-
label: stage.label,
|
|
781
|
-
order: stage.order
|
|
782
|
-
};
|
|
783
|
-
}
|
|
784
|
-
function leadGenStagesForEntity(entity) {
|
|
785
|
-
return Object.values(LEAD_GEN_STAGE_CATALOG).filter((stage) => stage.entity === entity || stage.additionalEntities?.includes(entity)).sort((a, b) => a.order - b.order).map(toProspectingLifecycleStage);
|
|
786
|
-
}
|
|
787
|
-
var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
|
|
788
|
-
companyStages: leadGenStagesForEntity("company"),
|
|
789
|
-
contactStages: leadGenStagesForEntity("contact"),
|
|
790
|
-
buildTemplates: [
|
|
791
|
-
{
|
|
792
|
-
id: "local-services",
|
|
793
|
-
label: "Local Services Prospecting",
|
|
794
|
-
description: "Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.",
|
|
795
|
-
steps: [
|
|
796
|
-
PROSPECTING_STEPS.localServices.sourceCompanies,
|
|
797
|
-
PROSPECTING_STEPS.localServices.analyzeWebsites,
|
|
798
|
-
PROSPECTING_STEPS.localServices.qualifyCompanies,
|
|
799
|
-
PROSPECTING_STEPS.localServices.findContacts,
|
|
800
|
-
PROSPECTING_STEPS.localServices.verifyEmails,
|
|
801
|
-
PROSPECTING_STEPS.localServices.personalize,
|
|
802
|
-
PROSPECTING_STEPS.localServices.review
|
|
803
|
-
]
|
|
804
|
-
},
|
|
805
|
-
{
|
|
806
|
-
id: "dtc-subscription-apollo-clickup",
|
|
807
|
-
label: "DTC Subscription Apollo Export",
|
|
808
|
-
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.",
|
|
809
|
-
steps: [
|
|
810
|
-
PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
|
|
811
|
-
PROSPECTING_STEPS.dtcApolloClickup.apifyCrawl,
|
|
812
|
-
PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
|
|
813
|
-
PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
|
|
814
|
-
PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
|
|
815
|
-
PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
|
|
816
|
-
]
|
|
817
|
-
}
|
|
818
|
-
]
|
|
819
|
-
};
|
|
820
|
-
|
|
821
|
-
// ../core/src/platform/registry/reserved.ts
|
|
822
|
-
var RESERVED_RESOURCE_IDS = /* @__PURE__ */ new Set(["command-center-assistant"]);
|
|
823
|
-
Array.from(RESERVED_RESOURCE_IDS);
|
|
824
|
-
function isReservedResourceId(resourceId) {
|
|
825
|
-
return RESERVED_RESOURCE_IDS.has(resourceId);
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
// ../core/src/execution/engine/base/errors.ts
|
|
829
|
-
var ExecutionError2 = class extends Error {
|
|
830
|
-
/**
|
|
831
|
-
* Additional context/metadata for the error.
|
|
832
|
-
* Stored in execution_errors.metadata JSONB column.
|
|
833
|
-
*/
|
|
834
|
-
context;
|
|
835
|
-
/**
|
|
836
|
-
* @param message - Human-readable error message
|
|
837
|
-
* @param context - Additional context/metadata for observability
|
|
838
|
-
*/
|
|
839
|
-
constructor(message, context) {
|
|
840
|
-
super(message);
|
|
841
|
-
this.name = this.constructor.name;
|
|
842
|
-
this.context = context;
|
|
843
|
-
if (Error.captureStackTrace) {
|
|
844
|
-
Error.captureStackTrace(this, this.constructor);
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
/**
|
|
848
|
-
* Indicates whether this error type is retryable.
|
|
849
|
-
* Default: false (safe default - only retry when explicitly safe to do so)
|
|
850
|
-
*
|
|
851
|
-
* Subclasses should override to return true for retryable scenarios:
|
|
852
|
-
* - Network/infrastructure errors (exponential backoff)
|
|
853
|
-
* - Rate limiting (linear backoff)
|
|
854
|
-
* - Service availability (exponential backoff)
|
|
855
|
-
* - Circuit breaker (circuit breaker's own delay)
|
|
856
|
-
*
|
|
857
|
-
* DO NOT retry:
|
|
858
|
-
* - Authentication/authorization errors
|
|
859
|
-
* - Validation errors
|
|
860
|
-
* - Configuration errors
|
|
861
|
-
* - Resource exhaustion errors
|
|
862
|
-
*/
|
|
863
|
-
isRetryable() {
|
|
864
|
-
return false;
|
|
865
|
-
}
|
|
866
|
-
};
|
|
867
|
-
var GPT5OptionsSchema = z.object({
|
|
868
|
-
reasoning_effort: z.enum(["minimal", "low", "medium", "high"]).optional(),
|
|
869
|
-
verbosity: z.enum(["low", "medium", "high"]).optional()
|
|
870
|
-
});
|
|
871
|
-
var GPT5ConfigSchema = z.object({
|
|
872
|
-
model: z.enum(["gpt-5", "gpt-5.4-mini", "gpt-5.4-nano"]),
|
|
873
|
-
provider: z.enum(["openai"]),
|
|
874
|
-
apiKey: z.string(),
|
|
875
|
-
temperature: z.literal(1),
|
|
876
|
-
// Required to be exactly 1
|
|
877
|
-
maxOutputTokens: z.number().min(4e3).optional(),
|
|
878
|
-
topP: z.number().min(0).max(1).optional(),
|
|
879
|
-
modelOptions: GPT5OptionsSchema.optional()
|
|
880
|
-
});
|
|
881
|
-
var MockConfigSchema = z.object({
|
|
882
|
-
model: z.enum(["mock"]),
|
|
883
|
-
provider: z.enum(["mock"]),
|
|
884
|
-
apiKey: z.string(),
|
|
885
|
-
temperature: z.number().min(0).max(2).optional(),
|
|
886
|
-
maxOutputTokens: z.number().min(500).optional(),
|
|
887
|
-
topP: z.number().min(0).max(1).optional(),
|
|
888
|
-
modelOptions: z.object({}).strict().optional()
|
|
889
|
-
// No options supported
|
|
890
|
-
});
|
|
891
|
-
var OpenRouterOptionsSchema = z.object({
|
|
892
|
-
/** Optional transforms to apply (e.g., 'middle-out' for long context) */
|
|
893
|
-
transforms: z.array(z.string()).optional(),
|
|
894
|
-
/** Routing strategy (e.g., 'fallback' for automatic provider failover) */
|
|
895
|
-
route: z.enum(["fallback"]).optional()
|
|
896
|
-
});
|
|
897
|
-
var OpenRouterConfigSchema = z.object({
|
|
898
|
-
model: z.enum(["openrouter/z-ai/glm-5"]),
|
|
899
|
-
provider: z.literal("openrouter"),
|
|
900
|
-
apiKey: z.string(),
|
|
901
|
-
temperature: z.number().min(0).max(2).optional(),
|
|
902
|
-
maxOutputTokens: z.number().min(500).optional(),
|
|
903
|
-
topP: z.number().min(0).max(1).optional(),
|
|
904
|
-
modelOptions: OpenRouterOptionsSchema.optional()
|
|
905
|
-
});
|
|
906
|
-
var GoogleOptionsSchema = z.object({
|
|
907
|
-
/** Thinking level for Gemini 3 models (controls reasoning depth) */
|
|
908
|
-
thinkingLevel: z.enum(["minimal", "low", "medium", "high"]).optional()
|
|
909
|
-
});
|
|
910
|
-
var GoogleConfigSchema = z.object({
|
|
911
|
-
model: z.enum(["gemini-3-flash-preview", "gemini-3.1-flash-lite-preview"]),
|
|
912
|
-
provider: z.literal("google"),
|
|
913
|
-
apiKey: z.string(),
|
|
914
|
-
temperature: z.number().min(0).max(2).optional(),
|
|
915
|
-
maxOutputTokens: z.number().min(500).optional(),
|
|
916
|
-
topP: z.number().min(0).max(1).optional(),
|
|
917
|
-
modelOptions: GoogleOptionsSchema.optional()
|
|
918
|
-
});
|
|
919
|
-
var AnthropicOptionsSchema = z.object({});
|
|
920
|
-
var AnthropicConfigSchema = z.object({
|
|
921
|
-
model: z.enum(["claude-sonnet-4-5"]),
|
|
922
|
-
provider: z.literal("anthropic"),
|
|
923
|
-
apiKey: z.string(),
|
|
924
|
-
temperature: z.number().min(0).max(1).optional(),
|
|
925
|
-
maxOutputTokens: z.number().min(1e3).optional(),
|
|
926
|
-
// Anthropic requires max_tokens
|
|
927
|
-
topP: z.number().min(0).max(1).optional(),
|
|
928
|
-
modelOptions: AnthropicOptionsSchema.optional()
|
|
929
|
-
});
|
|
930
|
-
var MODEL_INFO = {
|
|
931
|
-
// OpenAI GPT-5 (Reasoning Models)
|
|
932
|
-
"gpt-5": {
|
|
933
|
-
inputCostPer1M: 125,
|
|
934
|
-
// $1.25 per 1M tokens
|
|
935
|
-
outputCostPer1M: 1e3,
|
|
936
|
-
// $10.00 per 1M tokens
|
|
937
|
-
minTokens: 4e3,
|
|
938
|
-
// Reasoning models need more
|
|
939
|
-
recommendedTokens: 8e3,
|
|
940
|
-
maxTokens: 4e5,
|
|
941
|
-
// 400k context window
|
|
942
|
-
category: "reasoning",
|
|
943
|
-
configSchema: GPT5ConfigSchema
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Indicates whether this error type is retryable.
|
|
537
|
+
* Default: false (safe default - only retry when explicitly safe to do so)
|
|
538
|
+
*
|
|
539
|
+
* Subclasses should override to return true for retryable scenarios:
|
|
540
|
+
* - Network/infrastructure errors (exponential backoff)
|
|
541
|
+
* - Rate limiting (linear backoff)
|
|
542
|
+
* - Service availability (exponential backoff)
|
|
543
|
+
* - Circuit breaker (circuit breaker's own delay)
|
|
544
|
+
*
|
|
545
|
+
* DO NOT retry:
|
|
546
|
+
* - Authentication/authorization errors
|
|
547
|
+
* - Validation errors
|
|
548
|
+
* - Configuration errors
|
|
549
|
+
* - Resource exhaustion errors
|
|
550
|
+
*/
|
|
551
|
+
isRetryable() {
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
var GPT5OptionsSchema = z.object({
|
|
556
|
+
reasoning_effort: z.enum(["minimal", "low", "medium", "high"]).optional(),
|
|
557
|
+
verbosity: z.enum(["low", "medium", "high"]).optional()
|
|
558
|
+
});
|
|
559
|
+
var GPT5ConfigSchema = z.object({
|
|
560
|
+
model: z.enum(["gpt-5", "gpt-5.4-mini", "gpt-5.4-nano"]),
|
|
561
|
+
provider: z.enum(["openai"]),
|
|
562
|
+
apiKey: z.string(),
|
|
563
|
+
temperature: z.literal(1),
|
|
564
|
+
// Required to be exactly 1
|
|
565
|
+
maxOutputTokens: z.number().min(4e3).optional(),
|
|
566
|
+
topP: z.number().min(0).max(1).optional(),
|
|
567
|
+
modelOptions: GPT5OptionsSchema.optional()
|
|
568
|
+
});
|
|
569
|
+
var MockConfigSchema = z.object({
|
|
570
|
+
model: z.enum(["mock"]),
|
|
571
|
+
provider: z.enum(["mock"]),
|
|
572
|
+
apiKey: z.string(),
|
|
573
|
+
temperature: z.number().min(0).max(2).optional(),
|
|
574
|
+
maxOutputTokens: z.number().min(500).optional(),
|
|
575
|
+
topP: z.number().min(0).max(1).optional(),
|
|
576
|
+
modelOptions: z.object({}).strict().optional()
|
|
577
|
+
// No options supported
|
|
578
|
+
});
|
|
579
|
+
var OpenRouterOptionsSchema = z.object({
|
|
580
|
+
/** Optional transforms to apply (e.g., 'middle-out' for long context) */
|
|
581
|
+
transforms: z.array(z.string()).optional(),
|
|
582
|
+
/** Routing strategy (e.g., 'fallback' for automatic provider failover) */
|
|
583
|
+
route: z.enum(["fallback"]).optional()
|
|
584
|
+
});
|
|
585
|
+
var OpenRouterConfigSchema = z.object({
|
|
586
|
+
model: z.enum(["openrouter/z-ai/glm-5"]),
|
|
587
|
+
provider: z.literal("openrouter"),
|
|
588
|
+
apiKey: z.string(),
|
|
589
|
+
temperature: z.number().min(0).max(2).optional(),
|
|
590
|
+
maxOutputTokens: z.number().min(500).optional(),
|
|
591
|
+
topP: z.number().min(0).max(1).optional(),
|
|
592
|
+
modelOptions: OpenRouterOptionsSchema.optional()
|
|
593
|
+
});
|
|
594
|
+
var GoogleOptionsSchema = z.object({
|
|
595
|
+
/** Thinking level for Gemini 3 models (controls reasoning depth) */
|
|
596
|
+
thinkingLevel: z.enum(["minimal", "low", "medium", "high"]).optional()
|
|
597
|
+
});
|
|
598
|
+
var GoogleConfigSchema = z.object({
|
|
599
|
+
model: z.enum(["gemini-3-flash-preview", "gemini-3.1-flash-lite-preview"]),
|
|
600
|
+
provider: z.literal("google"),
|
|
601
|
+
apiKey: z.string(),
|
|
602
|
+
temperature: z.number().min(0).max(2).optional(),
|
|
603
|
+
maxOutputTokens: z.number().min(500).optional(),
|
|
604
|
+
topP: z.number().min(0).max(1).optional(),
|
|
605
|
+
modelOptions: GoogleOptionsSchema.optional()
|
|
606
|
+
});
|
|
607
|
+
var AnthropicOptionsSchema = z.object({});
|
|
608
|
+
var AnthropicConfigSchema = z.object({
|
|
609
|
+
model: z.enum(["claude-sonnet-4-5"]),
|
|
610
|
+
provider: z.literal("anthropic"),
|
|
611
|
+
apiKey: z.string(),
|
|
612
|
+
temperature: z.number().min(0).max(1).optional(),
|
|
613
|
+
maxOutputTokens: z.number().min(1e3).optional(),
|
|
614
|
+
// Anthropic requires max_tokens
|
|
615
|
+
topP: z.number().min(0).max(1).optional(),
|
|
616
|
+
modelOptions: AnthropicOptionsSchema.optional()
|
|
617
|
+
});
|
|
618
|
+
var MODEL_INFO = {
|
|
619
|
+
// OpenAI GPT-5 (Reasoning Models)
|
|
620
|
+
"gpt-5": {
|
|
621
|
+
inputCostPer1M: 125,
|
|
622
|
+
// $1.25 per 1M tokens
|
|
623
|
+
outputCostPer1M: 1e3,
|
|
624
|
+
// $10.00 per 1M tokens
|
|
625
|
+
minTokens: 4e3,
|
|
626
|
+
// Reasoning models need more
|
|
627
|
+
recommendedTokens: 8e3,
|
|
628
|
+
maxTokens: 4e5,
|
|
629
|
+
// 400k context window
|
|
630
|
+
category: "reasoning",
|
|
631
|
+
configSchema: GPT5ConfigSchema
|
|
944
632
|
},
|
|
945
633
|
"gpt-5.4-mini": {
|
|
946
634
|
inputCostPer1M: 75,
|
|
@@ -1131,25 +819,27 @@ function getRuntimeResources(resources) {
|
|
|
1131
819
|
}
|
|
1132
820
|
function validateResourceGovernance(orgName, deployment, organizationModel = deployment.organizationModel, options = {}) {
|
|
1133
821
|
const mode = getResourceValidatorMode(options.mode);
|
|
1134
|
-
const
|
|
1135
|
-
const
|
|
822
|
+
const omResourcesMap = organizationModel?.resources;
|
|
823
|
+
const omSystemsMap = organizationModel?.systems;
|
|
1136
824
|
const issues = [];
|
|
1137
|
-
if (!
|
|
825
|
+
if (!omResourcesMap || !omSystemsMap) {
|
|
1138
826
|
return { valid: true, mode, issues };
|
|
1139
827
|
}
|
|
1140
|
-
const systemsById = new Map(
|
|
1141
|
-
|
|
828
|
+
const systemsById = new Map(
|
|
829
|
+
listAllSystems({ systems: omSystemsMap }).map(({ path, system }) => [path, system])
|
|
830
|
+
);
|
|
831
|
+
const activeOmResources = Object.values(omResourcesMap).filter((resource) => resource.status === "active");
|
|
1142
832
|
const omResourcesById = new Map(activeOmResources.map((resource) => [resource.id, resource]));
|
|
1143
833
|
const runtimeResources = getRuntimeResources(deployment);
|
|
1144
834
|
const runtimeResourcesById = new Map(runtimeResources.map((resource) => [resource.resourceId, resource]));
|
|
1145
835
|
for (const resource of activeOmResources) {
|
|
1146
|
-
if (!systemsById.has(resource.
|
|
836
|
+
if (!systemsById.has(resource.systemPath)) {
|
|
1147
837
|
addGovernanceIssue(
|
|
1148
838
|
issues,
|
|
1149
839
|
"missing-om-system",
|
|
1150
840
|
orgName,
|
|
1151
841
|
resource.id,
|
|
1152
|
-
`[${orgName}] OM resource '${resource.id}' references missing
|
|
842
|
+
`[${orgName}] OM resource '${resource.id}' references missing system path '${resource.systemPath}'.`
|
|
1153
843
|
);
|
|
1154
844
|
}
|
|
1155
845
|
const runtimeResource = runtimeResourcesById.get(resource.id);
|
|
@@ -1172,13 +862,13 @@ function validateResourceGovernance(orgName, deployment, organizationModel = dep
|
|
|
1172
862
|
`[${orgName}] Resource '${resource.id}' type mismatch: code has '${runtimeResource.type}', OM has '${resource.kind}'.`
|
|
1173
863
|
);
|
|
1174
864
|
}
|
|
1175
|
-
if (runtimeResource.descriptor && runtimeResource.descriptor.
|
|
865
|
+
if (runtimeResource.descriptor && runtimeResource.descriptor.systemPath !== resource.systemPath) {
|
|
1176
866
|
addGovernanceIssue(
|
|
1177
867
|
issues,
|
|
1178
868
|
"system-mismatch",
|
|
1179
869
|
orgName,
|
|
1180
870
|
resource.id,
|
|
1181
|
-
`[${orgName}] Resource '${resource.id}' system mismatch: code descriptor has '${runtimeResource.descriptor.
|
|
871
|
+
`[${orgName}] Resource '${resource.id}' system mismatch: code descriptor has '${runtimeResource.descriptor.systemPath}', OM has '${resource.systemPath}'.`
|
|
1182
872
|
);
|
|
1183
873
|
}
|
|
1184
874
|
}
|
|
@@ -3753,21 +3443,21 @@ function summarizeSystem(system) {
|
|
|
3753
3443
|
if (!system) return void 0;
|
|
3754
3444
|
return {
|
|
3755
3445
|
id: system.id,
|
|
3756
|
-
title: system.title,
|
|
3446
|
+
title: system.label ?? system.title,
|
|
3757
3447
|
description: system.description,
|
|
3758
3448
|
kind: system.kind,
|
|
3759
|
-
|
|
3449
|
+
lifecycle: system.lifecycle
|
|
3760
3450
|
};
|
|
3761
3451
|
}
|
|
3762
3452
|
function createGovernanceMetadataResolver(resources) {
|
|
3763
|
-
const resourcesById = new Map((resources.organizationModel?.resources
|
|
3764
|
-
const systemsById = new Map((resources.organizationModel?.systems
|
|
3453
|
+
const resourcesById = new Map(Object.values(resources.organizationModel?.resources ?? {}).map((r) => [r.id, r]));
|
|
3454
|
+
const systemsById = new Map(Object.values(resources.organizationModel?.systems ?? {}).map((s) => [s.id, s]));
|
|
3765
3455
|
return (resourceId, descriptor) => {
|
|
3766
3456
|
const resource = descriptor ?? resourcesById.get(resourceId);
|
|
3767
3457
|
if (!resource) return {};
|
|
3768
3458
|
return {
|
|
3769
|
-
|
|
3770
|
-
system: summarizeSystem(systemsById.get(resource.
|
|
3459
|
+
systemPath: resource.systemPath,
|
|
3460
|
+
system: summarizeSystem(systemsById.get(resource.systemPath)),
|
|
3771
3461
|
governanceStatus: resource.status
|
|
3772
3462
|
};
|
|
3773
3463
|
};
|
|
@@ -3989,10 +3679,10 @@ function summarizeSystem2(system) {
|
|
|
3989
3679
|
if (!system) return void 0;
|
|
3990
3680
|
return {
|
|
3991
3681
|
id: system.id,
|
|
3992
|
-
title: system.title,
|
|
3682
|
+
title: system.label ?? system.title,
|
|
3993
3683
|
description: system.description,
|
|
3994
3684
|
kind: system.kind,
|
|
3995
|
-
|
|
3685
|
+
lifecycle: system.lifecycle
|
|
3996
3686
|
};
|
|
3997
3687
|
}
|
|
3998
3688
|
var ResourceRegistry = class {
|
|
@@ -4141,14 +3831,17 @@ var ResourceRegistry = class {
|
|
|
4141
3831
|
environment
|
|
4142
3832
|
};
|
|
4143
3833
|
}
|
|
4144
|
-
const resourcesById = new Map((orgResources.organizationModel?.resources
|
|
4145
|
-
const
|
|
3834
|
+
const resourcesById = new Map(Object.values(orgResources.organizationModel?.resources ?? {}).map((r) => [r.id, r]));
|
|
3835
|
+
const omSystems = orgResources.organizationModel?.systems;
|
|
3836
|
+
const systemsByPath = new Map(
|
|
3837
|
+
omSystems ? listAllSystems({ systems: omSystems }).map(({ path, system }) => [path, system]) : []
|
|
3838
|
+
);
|
|
4146
3839
|
const getGovernanceMetadata = (resourceId, descriptor) => {
|
|
4147
3840
|
const resource = descriptor ?? resourcesById.get(resourceId);
|
|
4148
3841
|
if (!resource) return {};
|
|
4149
3842
|
return {
|
|
4150
|
-
|
|
4151
|
-
system: summarizeSystem2(
|
|
3843
|
+
systemPath: resource.systemPath,
|
|
3844
|
+
system: summarizeSystem2(systemsByPath.get(resource.systemPath)),
|
|
4152
3845
|
governanceStatus: resource.status
|
|
4153
3846
|
};
|
|
4154
3847
|
};
|
|
@@ -4596,22 +4289,563 @@ var ResourceRegistry = class {
|
|
|
4596
4289
|
edges: []
|
|
4597
4290
|
};
|
|
4598
4291
|
}
|
|
4599
|
-
return cache.commandView;
|
|
4292
|
+
return cache.commandView;
|
|
4293
|
+
}
|
|
4294
|
+
};
|
|
4295
|
+
DisplayMetadataSchema.extend({
|
|
4296
|
+
id: ModelIdSchema,
|
|
4297
|
+
order: z.number().min(0)
|
|
4298
|
+
});
|
|
4299
|
+
var RecordColumnConfigSchema = z.object({
|
|
4300
|
+
key: ModelIdSchema,
|
|
4301
|
+
label: z.string().trim().min(1).max(120),
|
|
4302
|
+
path: z.string().trim().min(1).max(500),
|
|
4303
|
+
width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
|
|
4304
|
+
renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
|
|
4305
|
+
badgeColor: z.string().trim().min(1).max(40).optional()
|
|
4306
|
+
});
|
|
4307
|
+
var RecordColumnsConfigSchema = z.object({
|
|
4308
|
+
company: z.array(RecordColumnConfigSchema).optional(),
|
|
4309
|
+
contact: z.array(RecordColumnConfigSchema).optional()
|
|
4310
|
+
}).refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
|
|
4311
|
+
message: "recordColumns must include at least one entity column set"
|
|
4312
|
+
});
|
|
4313
|
+
var CredentialRequirementSchema = z.object({
|
|
4314
|
+
key: ModelIdSchema,
|
|
4315
|
+
provider: ModelIdSchema,
|
|
4316
|
+
credentialType: z.enum(["api-key", "api-key-secret", "oauth", "webhook-secret"]),
|
|
4317
|
+
label: z.string().trim().min(1).max(120),
|
|
4318
|
+
required: z.boolean(),
|
|
4319
|
+
selectionMode: z.enum(["single", "multiple"]).optional(),
|
|
4320
|
+
inputPath: z.string().trim().min(1).max(500),
|
|
4321
|
+
verifyOnRun: z.boolean().optional()
|
|
4322
|
+
});
|
|
4323
|
+
var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
|
|
4324
|
+
id: ModelIdSchema,
|
|
4325
|
+
primaryEntity: z.enum(["company", "contact"]),
|
|
4326
|
+
outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
|
|
4327
|
+
stageKey: ModelIdSchema,
|
|
4328
|
+
recordEntity: z.enum(["company", "contact"]).optional(),
|
|
4329
|
+
recordsStageKey: ModelIdSchema.optional(),
|
|
4330
|
+
recordSourceStageKey: ModelIdSchema.optional(),
|
|
4331
|
+
dependsOn: z.array(ModelIdSchema).optional(),
|
|
4332
|
+
dependencyMode: z.literal("per-record-eligibility"),
|
|
4333
|
+
actionKey: ModelIdSchema,
|
|
4334
|
+
defaultBatchSize: z.number().int().positive(),
|
|
4335
|
+
maxBatchSize: z.number().int().positive(),
|
|
4336
|
+
recordColumns: RecordColumnsConfigSchema.optional(),
|
|
4337
|
+
credentialRequirements: z.array(CredentialRequirementSchema).optional()
|
|
4338
|
+
}).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
|
|
4339
|
+
message: "defaultBatchSize must be less than or equal to maxBatchSize",
|
|
4340
|
+
path: ["defaultBatchSize"]
|
|
4341
|
+
});
|
|
4342
|
+
var ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
|
|
4343
|
+
id: ModelIdSchema,
|
|
4344
|
+
steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
|
|
4345
|
+
});
|
|
4346
|
+
var DTC_RECORD_COLUMNS = {
|
|
4347
|
+
populated: {
|
|
4348
|
+
company: [
|
|
4349
|
+
{ key: "name", label: "Company", path: "company.name" },
|
|
4350
|
+
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
4351
|
+
{ key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
|
|
4352
|
+
{ key: "apollo-industry", label: "Apollo industry", path: "company.category" },
|
|
4353
|
+
{ key: "location", label: "Location", path: "company.locationState" }
|
|
4354
|
+
]
|
|
4355
|
+
},
|
|
4356
|
+
crawled: {
|
|
4357
|
+
company: [
|
|
4358
|
+
{ key: "name", label: "Company", path: "company.name" },
|
|
4359
|
+
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
4360
|
+
{ key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
|
|
4361
|
+
{ key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
|
|
4362
|
+
]
|
|
4363
|
+
},
|
|
4364
|
+
extracted: {
|
|
4365
|
+
company: [
|
|
4366
|
+
{ key: "name", label: "Company", path: "company.name" },
|
|
4367
|
+
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
4368
|
+
{ key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
|
|
4369
|
+
{ key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
|
|
4370
|
+
{
|
|
4371
|
+
key: "automation-gaps",
|
|
4372
|
+
label: "Automation gaps",
|
|
4373
|
+
path: "company.enrichmentData.websiteCrawl.automationGaps",
|
|
4374
|
+
renderType: "json"
|
|
4375
|
+
},
|
|
4376
|
+
{
|
|
4377
|
+
key: "contact-count",
|
|
4378
|
+
label: "Contacts",
|
|
4379
|
+
path: "company.enrichmentData.websiteCrawl.emailCount",
|
|
4380
|
+
renderType: "count"
|
|
4381
|
+
}
|
|
4382
|
+
]
|
|
4383
|
+
},
|
|
4384
|
+
qualified: {
|
|
4385
|
+
company: [
|
|
4386
|
+
{ key: "name", label: "Company", path: "company.name" },
|
|
4387
|
+
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
4388
|
+
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
4389
|
+
{ key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
|
|
4390
|
+
{
|
|
4391
|
+
key: "disqualified-reason",
|
|
4392
|
+
label: "Disqualified reason",
|
|
4393
|
+
path: "processingState.qualified.data.disqualifiedReason"
|
|
4394
|
+
}
|
|
4395
|
+
]
|
|
4396
|
+
},
|
|
4397
|
+
decisionMakers: {
|
|
4398
|
+
contact: [
|
|
4399
|
+
{ key: "name", label: "Name", path: "contact.name" },
|
|
4400
|
+
{ key: "title", label: "Title", path: "contact.title" },
|
|
4401
|
+
{ key: "email", label: "Email", path: "contact.email" },
|
|
4402
|
+
{ key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
|
|
4403
|
+
{
|
|
4404
|
+
key: "priority-score",
|
|
4405
|
+
label: "Priority",
|
|
4406
|
+
path: "contact.enrichmentData.apollo.priorityScore",
|
|
4407
|
+
renderType: "badge"
|
|
4408
|
+
}
|
|
4409
|
+
]
|
|
4410
|
+
},
|
|
4411
|
+
uploaded: {
|
|
4412
|
+
company: [
|
|
4413
|
+
{ key: "name", label: "Company", path: "company.name" },
|
|
4414
|
+
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
4415
|
+
{
|
|
4416
|
+
key: "contacts",
|
|
4417
|
+
label: "Contacts",
|
|
4418
|
+
path: "company.enrichmentData.approvedLeadListExport.contacts",
|
|
4419
|
+
renderType: "json"
|
|
4420
|
+
},
|
|
4421
|
+
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
4422
|
+
{
|
|
4423
|
+
key: "approval",
|
|
4424
|
+
label: "Approval",
|
|
4425
|
+
path: "company.enrichmentData.approvedLeadListExport.approvalStatus",
|
|
4426
|
+
renderType: "badge"
|
|
4427
|
+
}
|
|
4428
|
+
]
|
|
4429
|
+
}
|
|
4430
|
+
};
|
|
4431
|
+
var ACTION_REGISTRY = Object.values(LEAD_GEN_ACTION_ENTRIES);
|
|
4432
|
+
var PROSPECTING_STEPS = {
|
|
4433
|
+
localServices: {
|
|
4434
|
+
sourceCompanies: {
|
|
4435
|
+
id: "source-companies",
|
|
4436
|
+
label: "Companies found",
|
|
4437
|
+
primaryEntity: "company",
|
|
4438
|
+
outputs: ["company"],
|
|
4439
|
+
stageKey: "populated",
|
|
4440
|
+
dependencyMode: "per-record-eligibility",
|
|
4441
|
+
actionKey: "lead-gen.company.source",
|
|
4442
|
+
defaultBatchSize: 100,
|
|
4443
|
+
maxBatchSize: 250
|
|
4444
|
+
},
|
|
4445
|
+
analyzeWebsites: {
|
|
4446
|
+
id: "analyze-websites",
|
|
4447
|
+
label: "Websites analyzed",
|
|
4448
|
+
primaryEntity: "company",
|
|
4449
|
+
outputs: ["company"],
|
|
4450
|
+
stageKey: "extracted",
|
|
4451
|
+
dependsOn: ["source-companies"],
|
|
4452
|
+
dependencyMode: "per-record-eligibility",
|
|
4453
|
+
actionKey: "lead-gen.company.website-extract",
|
|
4454
|
+
defaultBatchSize: 50,
|
|
4455
|
+
maxBatchSize: 100
|
|
4456
|
+
},
|
|
4457
|
+
qualifyCompanies: {
|
|
4458
|
+
id: "qualify-companies",
|
|
4459
|
+
label: "Companies qualified",
|
|
4460
|
+
primaryEntity: "company",
|
|
4461
|
+
outputs: ["company"],
|
|
4462
|
+
stageKey: "qualified",
|
|
4463
|
+
dependsOn: ["analyze-websites"],
|
|
4464
|
+
dependencyMode: "per-record-eligibility",
|
|
4465
|
+
actionKey: "lead-gen.company.qualify",
|
|
4466
|
+
defaultBatchSize: 100,
|
|
4467
|
+
maxBatchSize: 250
|
|
4468
|
+
},
|
|
4469
|
+
findContacts: {
|
|
4470
|
+
id: "find-contacts",
|
|
4471
|
+
label: "Decision-makers found",
|
|
4472
|
+
primaryEntity: "contact",
|
|
4473
|
+
outputs: ["contact"],
|
|
4474
|
+
stageKey: "discovered",
|
|
4475
|
+
dependsOn: ["qualify-companies"],
|
|
4476
|
+
dependencyMode: "per-record-eligibility",
|
|
4477
|
+
actionKey: "lead-gen.contact.discover",
|
|
4478
|
+
defaultBatchSize: 50,
|
|
4479
|
+
maxBatchSize: 100
|
|
4480
|
+
},
|
|
4481
|
+
verifyEmails: {
|
|
4482
|
+
id: "verify-emails",
|
|
4483
|
+
label: "Emails verified",
|
|
4484
|
+
primaryEntity: "contact",
|
|
4485
|
+
outputs: ["contact"],
|
|
4486
|
+
stageKey: "verified",
|
|
4487
|
+
dependsOn: ["find-contacts"],
|
|
4488
|
+
dependencyMode: "per-record-eligibility",
|
|
4489
|
+
actionKey: "lead-gen.contact.verify-email",
|
|
4490
|
+
defaultBatchSize: 100,
|
|
4491
|
+
maxBatchSize: 500
|
|
4492
|
+
},
|
|
4493
|
+
personalize: {
|
|
4494
|
+
id: "personalize",
|
|
4495
|
+
label: "Personalize",
|
|
4496
|
+
primaryEntity: "contact",
|
|
4497
|
+
outputs: ["contact"],
|
|
4498
|
+
stageKey: "personalized",
|
|
4499
|
+
dependsOn: ["verify-emails"],
|
|
4500
|
+
dependencyMode: "per-record-eligibility",
|
|
4501
|
+
actionKey: "lead-gen.contact.personalize",
|
|
4502
|
+
defaultBatchSize: 25,
|
|
4503
|
+
maxBatchSize: 100
|
|
4504
|
+
},
|
|
4505
|
+
review: {
|
|
4506
|
+
id: "review",
|
|
4507
|
+
label: "Reviewed and exported",
|
|
4508
|
+
primaryEntity: "contact",
|
|
4509
|
+
outputs: ["export"],
|
|
4510
|
+
stageKey: "uploaded",
|
|
4511
|
+
dependsOn: ["personalize"],
|
|
4512
|
+
dependencyMode: "per-record-eligibility",
|
|
4513
|
+
actionKey: "lead-gen.review.outreach-ready",
|
|
4514
|
+
defaultBatchSize: 25,
|
|
4515
|
+
maxBatchSize: 100
|
|
4516
|
+
}
|
|
4517
|
+
},
|
|
4518
|
+
dtcApolloClickup: {
|
|
4519
|
+
importApolloSearch: {
|
|
4520
|
+
id: "import-apollo-search",
|
|
4521
|
+
label: "Companies found",
|
|
4522
|
+
description: "Pull companies and seed contact data from a predefined Apollo search or list.",
|
|
4523
|
+
primaryEntity: "company",
|
|
4524
|
+
outputs: ["company", "contact"],
|
|
4525
|
+
stageKey: "populated",
|
|
4526
|
+
dependencyMode: "per-record-eligibility",
|
|
4527
|
+
actionKey: "lead-gen.company.apollo-import",
|
|
4528
|
+
defaultBatchSize: 250,
|
|
4529
|
+
maxBatchSize: 1e3,
|
|
4530
|
+
recordColumns: DTC_RECORD_COLUMNS.populated,
|
|
4531
|
+
credentialRequirements: [
|
|
4532
|
+
{
|
|
4533
|
+
key: "apollo",
|
|
4534
|
+
provider: "apollo",
|
|
4535
|
+
credentialType: "api-key-secret",
|
|
4536
|
+
label: "Apollo API key",
|
|
4537
|
+
required: true,
|
|
4538
|
+
selectionMode: "single",
|
|
4539
|
+
inputPath: "credential"
|
|
4540
|
+
}
|
|
4541
|
+
]
|
|
4542
|
+
},
|
|
4543
|
+
apifyCrawl: {
|
|
4544
|
+
id: "apify-crawl",
|
|
4545
|
+
label: "Websites crawled",
|
|
4546
|
+
description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis. Overwrites the synthetic seed Apollo Import wrote with real page content.",
|
|
4547
|
+
primaryEntity: "company",
|
|
4548
|
+
outputs: ["company"],
|
|
4549
|
+
stageKey: "crawled",
|
|
4550
|
+
dependsOn: ["import-apollo-search"],
|
|
4551
|
+
dependencyMode: "per-record-eligibility",
|
|
4552
|
+
actionKey: "lead-gen.company.apify-crawl",
|
|
4553
|
+
defaultBatchSize: 50,
|
|
4554
|
+
maxBatchSize: 100,
|
|
4555
|
+
recordColumns: DTC_RECORD_COLUMNS.crawled,
|
|
4556
|
+
credentialRequirements: [
|
|
4557
|
+
{
|
|
4558
|
+
key: "apify",
|
|
4559
|
+
provider: "apify",
|
|
4560
|
+
credentialType: "api-key-secret",
|
|
4561
|
+
label: "Apify API token",
|
|
4562
|
+
required: true,
|
|
4563
|
+
selectionMode: "single",
|
|
4564
|
+
inputPath: "credential",
|
|
4565
|
+
verifyOnRun: true
|
|
4566
|
+
}
|
|
4567
|
+
]
|
|
4568
|
+
},
|
|
4569
|
+
analyzeWebsites: {
|
|
4570
|
+
id: "analyze-websites",
|
|
4571
|
+
label: "Websites analyzed",
|
|
4572
|
+
description: "Extract subscription, product, retention, and tech-stack signals from each brand website.",
|
|
4573
|
+
primaryEntity: "company",
|
|
4574
|
+
outputs: ["company"],
|
|
4575
|
+
stageKey: "extracted",
|
|
4576
|
+
dependsOn: ["apify-crawl"],
|
|
4577
|
+
dependencyMode: "per-record-eligibility",
|
|
4578
|
+
actionKey: "lead-gen.company.website-extract",
|
|
4579
|
+
defaultBatchSize: 50,
|
|
4580
|
+
maxBatchSize: 100,
|
|
4581
|
+
recordColumns: DTC_RECORD_COLUMNS.extracted
|
|
4582
|
+
},
|
|
4583
|
+
scoreDtcFit: {
|
|
4584
|
+
id: "score-dtc-fit",
|
|
4585
|
+
label: "Companies qualified",
|
|
4586
|
+
description: "Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.",
|
|
4587
|
+
primaryEntity: "company",
|
|
4588
|
+
outputs: ["company"],
|
|
4589
|
+
stageKey: "qualified",
|
|
4590
|
+
dependsOn: ["analyze-websites"],
|
|
4591
|
+
dependencyMode: "per-record-eligibility",
|
|
4592
|
+
actionKey: "lead-gen.company.dtc-subscription-qualify",
|
|
4593
|
+
defaultBatchSize: 100,
|
|
4594
|
+
maxBatchSize: 250,
|
|
4595
|
+
recordColumns: DTC_RECORD_COLUMNS.qualified
|
|
4596
|
+
},
|
|
4597
|
+
enrichDecisionMakers: {
|
|
4598
|
+
id: "enrich-decision-makers",
|
|
4599
|
+
label: "Decision-makers found",
|
|
4600
|
+
description: "Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.",
|
|
4601
|
+
primaryEntity: "company",
|
|
4602
|
+
outputs: ["contact"],
|
|
4603
|
+
stageKey: "decision-makers-enriched",
|
|
4604
|
+
recordEntity: "contact",
|
|
4605
|
+
dependsOn: ["score-dtc-fit"],
|
|
4606
|
+
dependencyMode: "per-record-eligibility",
|
|
4607
|
+
actionKey: "lead-gen.contact.apollo-decision-maker-enrich",
|
|
4608
|
+
defaultBatchSize: 100,
|
|
4609
|
+
maxBatchSize: 250,
|
|
4610
|
+
recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
|
|
4611
|
+
credentialRequirements: [
|
|
4612
|
+
{
|
|
4613
|
+
key: "apollo",
|
|
4614
|
+
provider: "apollo",
|
|
4615
|
+
credentialType: "api-key-secret",
|
|
4616
|
+
label: "Apollo API key",
|
|
4617
|
+
required: true,
|
|
4618
|
+
selectionMode: "single",
|
|
4619
|
+
inputPath: "credential"
|
|
4620
|
+
}
|
|
4621
|
+
]
|
|
4622
|
+
},
|
|
4623
|
+
reviewAndExport: {
|
|
4624
|
+
id: "review-and-export",
|
|
4625
|
+
label: "Reviewed and exported",
|
|
4626
|
+
description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
|
|
4627
|
+
primaryEntity: "company",
|
|
4628
|
+
outputs: ["export"],
|
|
4629
|
+
stageKey: "uploaded",
|
|
4630
|
+
recordsStageKey: "uploaded",
|
|
4631
|
+
recordSourceStageKey: "qualified",
|
|
4632
|
+
dependsOn: ["enrich-decision-makers"],
|
|
4633
|
+
dependencyMode: "per-record-eligibility",
|
|
4634
|
+
actionKey: "lead-gen.export.list",
|
|
4635
|
+
defaultBatchSize: 100,
|
|
4636
|
+
maxBatchSize: 250,
|
|
4637
|
+
recordColumns: DTC_RECORD_COLUMNS.uploaded,
|
|
4638
|
+
credentialRequirements: [
|
|
4639
|
+
{
|
|
4640
|
+
key: "clickup",
|
|
4641
|
+
provider: "clickup",
|
|
4642
|
+
credentialType: "api-key-secret",
|
|
4643
|
+
label: "ClickUp API token",
|
|
4644
|
+
required: true,
|
|
4645
|
+
selectionMode: "single",
|
|
4646
|
+
inputPath: "clickupCredential",
|
|
4647
|
+
verifyOnRun: true
|
|
4648
|
+
}
|
|
4649
|
+
]
|
|
4650
|
+
}
|
|
4600
4651
|
}
|
|
4601
4652
|
};
|
|
4602
4653
|
|
|
4603
4654
|
// ../core/src/business/acquisition/build-templates.ts
|
|
4604
|
-
var
|
|
4605
|
-
|
|
4606
|
-
id,
|
|
4607
|
-
label,
|
|
4608
|
-
description
|
|
4609
|
-
|
|
4610
|
-
|
|
4655
|
+
var BUILD_TEMPLATE_CATALOG = [
|
|
4656
|
+
{
|
|
4657
|
+
id: "local-services",
|
|
4658
|
+
label: "Local Services",
|
|
4659
|
+
description: "Source, analyze, qualify, and personalize local service businesses for outreach.",
|
|
4660
|
+
steps: Object.values(PROSPECTING_STEPS.localServices)
|
|
4661
|
+
},
|
|
4662
|
+
{
|
|
4663
|
+
id: "dtc-subscription-apollo-clickup",
|
|
4664
|
+
label: "DTC Subscription (Apollo + ClickUp)",
|
|
4665
|
+
description: "Import DTC brand leads from Apollo, crawl their websites, score fit, enrich contacts, and export via ClickUp.",
|
|
4666
|
+
steps: Object.values(PROSPECTING_STEPS.dtcApolloClickup)
|
|
4667
|
+
}
|
|
4668
|
+
];
|
|
4669
|
+
var PROSPECTING_BUILD_TEMPLATE_OPTIONS = BUILD_TEMPLATE_CATALOG.map(({ id, label, description }) => ({
|
|
4670
|
+
id,
|
|
4671
|
+
label,
|
|
4672
|
+
description
|
|
4673
|
+
}));
|
|
4611
4674
|
function isProspectingBuildTemplateId(value) {
|
|
4612
4675
|
return PROSPECTING_BUILD_TEMPLATE_OPTIONS.some((template) => template.id === value);
|
|
4613
4676
|
}
|
|
4614
4677
|
|
|
4678
|
+
// ../core/src/organization-model/catalogs/lead-gen.ts
|
|
4679
|
+
var LEAD_GEN_STAGE_CATALOG = {
|
|
4680
|
+
// Prospecting - company population
|
|
4681
|
+
scraped: {
|
|
4682
|
+
key: "scraped",
|
|
4683
|
+
label: "Scraped",
|
|
4684
|
+
description: "Company was scraped from a source directory (Apify actor run).",
|
|
4685
|
+
order: 1,
|
|
4686
|
+
entity: "company"
|
|
4687
|
+
},
|
|
4688
|
+
populated: {
|
|
4689
|
+
key: "populated",
|
|
4690
|
+
label: "Companies found",
|
|
4691
|
+
description: "Companies have been found and added to the lead-gen list.",
|
|
4692
|
+
order: 2,
|
|
4693
|
+
entity: "company"
|
|
4694
|
+
},
|
|
4695
|
+
crawled: {
|
|
4696
|
+
key: "crawled",
|
|
4697
|
+
label: "Websites crawled",
|
|
4698
|
+
description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
|
|
4699
|
+
order: 2.5,
|
|
4700
|
+
entity: "company"
|
|
4701
|
+
},
|
|
4702
|
+
extracted: {
|
|
4703
|
+
key: "extracted",
|
|
4704
|
+
label: "Websites analyzed",
|
|
4705
|
+
description: "Company websites have been analyzed for business signals.",
|
|
4706
|
+
order: 3,
|
|
4707
|
+
entity: "company"
|
|
4708
|
+
},
|
|
4709
|
+
enriched: {
|
|
4710
|
+
key: "enriched",
|
|
4711
|
+
label: "Enriched",
|
|
4712
|
+
description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
|
|
4713
|
+
order: 4,
|
|
4714
|
+
entity: "company"
|
|
4715
|
+
},
|
|
4716
|
+
"decision-makers-enriched": {
|
|
4717
|
+
key: "decision-makers-enriched",
|
|
4718
|
+
label: "Decision-makers found",
|
|
4719
|
+
description: "Decision-maker contacts discovered and attached to a qualified company.",
|
|
4720
|
+
order: 6,
|
|
4721
|
+
entity: "company",
|
|
4722
|
+
recordEntity: "contact",
|
|
4723
|
+
recordStageKey: "discovered"
|
|
4724
|
+
},
|
|
4725
|
+
// Prospecting - contact discovery
|
|
4726
|
+
discovered: {
|
|
4727
|
+
key: "discovered",
|
|
4728
|
+
label: "Decision-makers found",
|
|
4729
|
+
description: "Decision-maker contact details have been found.",
|
|
4730
|
+
order: 5,
|
|
4731
|
+
entity: "contact"
|
|
4732
|
+
},
|
|
4733
|
+
verified: {
|
|
4734
|
+
key: "verified",
|
|
4735
|
+
label: "Emails verified",
|
|
4736
|
+
description: "Contact email addresses have been checked for deliverability.",
|
|
4737
|
+
order: 7,
|
|
4738
|
+
entity: "contact"
|
|
4739
|
+
},
|
|
4740
|
+
// Qualification
|
|
4741
|
+
qualified: {
|
|
4742
|
+
key: "qualified",
|
|
4743
|
+
label: "Companies qualified",
|
|
4744
|
+
description: "Companies have been scored against the qualification criteria.",
|
|
4745
|
+
order: 8,
|
|
4746
|
+
entity: "company"
|
|
4747
|
+
},
|
|
4748
|
+
// Outreach
|
|
4749
|
+
personalized: {
|
|
4750
|
+
key: "personalized",
|
|
4751
|
+
label: "Personalized",
|
|
4752
|
+
description: "Outreach message personalized for the contact (Instantly personalization workflow).",
|
|
4753
|
+
order: 9,
|
|
4754
|
+
entity: "contact"
|
|
4755
|
+
},
|
|
4756
|
+
uploaded: {
|
|
4757
|
+
key: "uploaded",
|
|
4758
|
+
label: "Reviewed and exported",
|
|
4759
|
+
description: "Approved records have been reviewed and exported for handoff.",
|
|
4760
|
+
order: 10,
|
|
4761
|
+
entity: "company",
|
|
4762
|
+
additionalEntities: ["contact"]
|
|
4763
|
+
},
|
|
4764
|
+
interested: {
|
|
4765
|
+
key: "interested",
|
|
4766
|
+
label: "Interested",
|
|
4767
|
+
description: "Contact replied with a positive signal (Instantly reply-handler transition).",
|
|
4768
|
+
order: 11,
|
|
4769
|
+
entity: "contact"
|
|
4770
|
+
}
|
|
4771
|
+
};
|
|
4772
|
+
|
|
4773
|
+
// ../core/src/organization-model/domains/sales.ts
|
|
4774
|
+
var SalesStageSemanticClassSchema = z.enum(["open", "active", "nurturing", "closed_won", "closed_lost"]);
|
|
4775
|
+
var SalesStageSchema = DisplayMetadataSchema.extend({
|
|
4776
|
+
id: ModelIdSchema,
|
|
4777
|
+
order: z.number().int().min(0),
|
|
4778
|
+
semanticClass: SalesStageSemanticClassSchema,
|
|
4779
|
+
surfaceIds: ReferenceIdsSchema,
|
|
4780
|
+
resourceIds: ReferenceIdsSchema
|
|
4781
|
+
});
|
|
4782
|
+
z.object({
|
|
4783
|
+
id: ModelIdSchema,
|
|
4784
|
+
label: z.string().trim().min(1).max(120),
|
|
4785
|
+
description: DescriptionSchema.optional(),
|
|
4786
|
+
entityId: ModelIdSchema,
|
|
4787
|
+
stages: z.array(SalesStageSchema).min(1)
|
|
4788
|
+
});
|
|
4789
|
+
var CRM_DISCOVERY_REPLIED_STATE = {
|
|
4790
|
+
stateKey: "discovery_replied",
|
|
4791
|
+
label: "Discovery Replied"
|
|
4792
|
+
};
|
|
4793
|
+
var CRM_DISCOVERY_LINK_SENT_STATE = {
|
|
4794
|
+
stateKey: "discovery_link_sent",
|
|
4795
|
+
label: "Discovery Link Sent"
|
|
4796
|
+
};
|
|
4797
|
+
var CRM_DISCOVERY_NUDGING_STATE = {
|
|
4798
|
+
stateKey: "discovery_nudging",
|
|
4799
|
+
label: "Discovery Nudging"
|
|
4800
|
+
};
|
|
4801
|
+
var CRM_DISCOVERY_BOOKING_CANCELLED_STATE = {
|
|
4802
|
+
stateKey: "discovery_booking_cancelled",
|
|
4803
|
+
label: "Discovery Booking Cancelled"
|
|
4804
|
+
};
|
|
4805
|
+
var CRM_REPLY_SENT_STATE = {
|
|
4806
|
+
stateKey: "reply_sent",
|
|
4807
|
+
label: "Reply Sent"
|
|
4808
|
+
};
|
|
4809
|
+
var CRM_FOLLOWUP_1_SENT_STATE = {
|
|
4810
|
+
stateKey: "followup_1_sent",
|
|
4811
|
+
label: "Follow-up 1 Sent"
|
|
4812
|
+
};
|
|
4813
|
+
var CRM_FOLLOWUP_2_SENT_STATE = {
|
|
4814
|
+
stateKey: "followup_2_sent",
|
|
4815
|
+
label: "Follow-up 2 Sent"
|
|
4816
|
+
};
|
|
4817
|
+
var CRM_FOLLOWUP_3_SENT_STATE = {
|
|
4818
|
+
stateKey: "followup_3_sent",
|
|
4819
|
+
label: "Follow-up 3 Sent"
|
|
4820
|
+
};
|
|
4821
|
+
var CRM_PIPELINE_DEFINITION = {
|
|
4822
|
+
pipelineKey: "crm",
|
|
4823
|
+
label: "CRM",
|
|
4824
|
+
entityKey: "crm.deal",
|
|
4825
|
+
stages: [
|
|
4826
|
+
{
|
|
4827
|
+
stageKey: "interested",
|
|
4828
|
+
label: "Interested",
|
|
4829
|
+
color: "blue",
|
|
4830
|
+
states: [
|
|
4831
|
+
CRM_DISCOVERY_REPLIED_STATE,
|
|
4832
|
+
CRM_DISCOVERY_LINK_SENT_STATE,
|
|
4833
|
+
CRM_DISCOVERY_NUDGING_STATE,
|
|
4834
|
+
CRM_DISCOVERY_BOOKING_CANCELLED_STATE,
|
|
4835
|
+
CRM_REPLY_SENT_STATE,
|
|
4836
|
+
CRM_FOLLOWUP_1_SENT_STATE,
|
|
4837
|
+
CRM_FOLLOWUP_2_SENT_STATE,
|
|
4838
|
+
CRM_FOLLOWUP_3_SENT_STATE
|
|
4839
|
+
]
|
|
4840
|
+
},
|
|
4841
|
+
{ stageKey: "proposal", label: "Proposal", color: "yellow", states: [] },
|
|
4842
|
+
{ stageKey: "closing", label: "Closing", color: "orange", states: [] },
|
|
4843
|
+
{ stageKey: "closed_won", label: "Closed Won", color: "green", states: [] },
|
|
4844
|
+
{ stageKey: "closed_lost", label: "Closed Lost", color: "red", states: [] },
|
|
4845
|
+
{ stageKey: "nurturing", label: "Nurturing", color: "grape", states: [] }
|
|
4846
|
+
]
|
|
4847
|
+
};
|
|
4848
|
+
|
|
4615
4849
|
// ../core/src/business/acquisition/deal-ownership.ts
|
|
4616
4850
|
var INBOUND_EVENT_TYPES = ["reply_received"];
|
|
4617
4851
|
var OUTBOUND_EVENT_TYPES = [
|
|
@@ -4673,8 +4907,8 @@ var ProcessingStageStatusSchema = z.enum(["success", "no_result", "skipped", "er
|
|
|
4673
4907
|
var LeadGenStageKeySchema = z.string().refine((value) => Object.prototype.hasOwnProperty.call(LEAD_GEN_STAGE_CATALOG, value), {
|
|
4674
4908
|
message: "processing state key must match LEAD_GEN_STAGE_CATALOG"
|
|
4675
4909
|
});
|
|
4676
|
-
var
|
|
4677
|
-
message: "
|
|
4910
|
+
var LeadGenActionKeySchema = z.string().refine((value) => ACTION_REGISTRY.some((c) => c.id === value), {
|
|
4911
|
+
message: "actionKey must match ACTION_REGISTRY"
|
|
4678
4912
|
});
|
|
4679
4913
|
var crmStageKeys = CRM_PIPELINE_DEFINITION.stages.map((stage) => stage.stageKey);
|
|
4680
4914
|
var crmStateKeys = CRM_PIPELINE_DEFINITION.stages.flatMap((stage) => stage.states.map((state) => state.stateKey));
|
|
@@ -4954,7 +5188,7 @@ var BuildPlanSnapshotStepSchema = z.object({
|
|
|
4954
5188
|
recordSourceStageKey: LeadGenStageKeySchema.optional(),
|
|
4955
5189
|
dependsOn: z.array(z.string().trim().min(1).max(100)).optional(),
|
|
4956
5190
|
dependencyMode: z.literal("per-record-eligibility"),
|
|
4957
|
-
|
|
5191
|
+
actionKey: LeadGenActionKeySchema,
|
|
4958
5192
|
defaultBatchSize: z.number().int().positive(),
|
|
4959
5193
|
maxBatchSize: z.number().int().positive(),
|
|
4960
5194
|
recordColumns: z.object({
|