@elevasis/core 0.20.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +524 -6
- package/dist/index.js +417 -42
- package/dist/knowledge/index.d.ts +151 -1
- package/dist/organization-model/index.d.ts +524 -6
- package/dist/organization-model/index.js +417 -42
- package/dist/test-utils/index.d.ts +270 -1
- package/dist/test-utils/index.js +407 -41
- package/package.json +5 -5
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +501 -303
- package/src/auth/multi-tenancy/permissions.ts +20 -8
- package/src/business/README.md +2 -2
- package/src/business/acquisition/api-schemas.test.ts +198 -0
- package/src/business/acquisition/api-schemas.ts +250 -9
- package/src/business/acquisition/build-templates.test.ts +28 -0
- package/src/business/acquisition/build-templates.ts +20 -8
- package/src/business/acquisition/index.ts +12 -0
- package/src/business/acquisition/types.ts +6 -1
- package/src/business/clients/api-schemas.test.ts +115 -0
- package/src/business/clients/api-schemas.ts +158 -0
- package/src/business/clients/index.ts +1 -0
- package/src/business/deals/api-schemas.ts +8 -0
- package/src/business/index.ts +5 -2
- package/src/business/projects/types.ts +19 -0
- package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -8
- package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -12
- package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -3
- package/src/execution/engine/agent/core/types.ts +25 -15
- package/src/execution/engine/agent/index.ts +6 -4
- package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -18
- package/src/execution/engine/index.ts +3 -0
- package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.test.ts +55 -0
- package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.ts +107 -41
- package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.test.ts +48 -0
- package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.ts +99 -0
- package/src/execution/engine/tools/integration/server/adapters/apollo/index.ts +1 -0
- package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.test.ts +18 -0
- package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.ts +194 -0
- package/src/execution/engine/tools/integration/server/adapters/clickup/index.ts +7 -0
- package/src/execution/engine/workflow/types.ts +7 -0
- package/src/integrations/credentials/api-schemas.ts +21 -2
- package/src/integrations/credentials/schemas.ts +200 -164
- package/src/organization-model/README.md +10 -3
- package/src/organization-model/__tests__/defaults.test.ts +6 -0
- package/src/organization-model/__tests__/domains/resources.test.ts +188 -0
- package/src/organization-model/__tests__/domains/roles.test.ts +402 -347
- package/src/organization-model/__tests__/domains/systems.test.ts +193 -0
- package/src/organization-model/__tests__/knowledge.test.ts +39 -0
- package/src/organization-model/__tests__/prospecting-ssot.test.ts +7 -4
- package/src/organization-model/__tests__/resolve.test.ts +1 -1
- package/src/organization-model/defaults.ts +24 -3
- package/src/organization-model/domains/knowledge.ts +3 -2
- package/src/organization-model/domains/prospecting.ts +182 -25
- package/src/organization-model/domains/resources.ts +88 -0
- package/src/organization-model/domains/roles.ts +93 -55
- package/src/organization-model/domains/sales.ts +24 -3
- package/src/organization-model/domains/systems.ts +46 -0
- package/src/organization-model/icons.ts +1 -0
- package/src/organization-model/index.ts +2 -0
- package/src/organization-model/organization-model.mdx +33 -14
- package/src/organization-model/published.ts +52 -1
- package/src/organization-model/schema.ts +121 -0
- package/src/organization-model/types.ts +46 -1
- package/src/platform/api/types.ts +38 -35
- package/src/platform/constants/versions.ts +1 -1
- package/src/platform/registry/__tests__/resource-registry.test.ts +2051 -2005
- package/src/platform/registry/__tests__/validation.test.ts +1343 -1086
- package/src/platform/registry/index.ts +14 -0
- package/src/platform/registry/resource-registry.ts +40 -2
- package/src/platform/registry/serialization.ts +241 -202
- package/src/platform/registry/serialized-types.ts +1 -0
- package/src/platform/registry/types.ts +411 -361
- package/src/platform/registry/validation.ts +743 -513
- package/src/projects/api-schemas.ts +290 -267
- package/src/reference/_generated/contracts.md +501 -303
- package/src/reference/glossary.md +8 -3
- package/src/server.ts +2 -0
- package/src/supabase/database.types.ts +121 -0
|
@@ -4,7 +4,36 @@ import { DescriptionSchema, DisplayMetadataSchema, ModelIdSchema } from './share
|
|
|
4
4
|
|
|
5
5
|
export const ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
|
|
6
6
|
id: ModelIdSchema,
|
|
7
|
-
order: z.number().
|
|
7
|
+
order: z.number().min(0)
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
export const RecordColumnConfigSchema = z.object({
|
|
11
|
+
key: ModelIdSchema,
|
|
12
|
+
label: z.string().trim().min(1).max(120),
|
|
13
|
+
path: z.string().trim().min(1).max(500),
|
|
14
|
+
width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
|
|
15
|
+
renderType: z.enum(['text', 'badge', 'datetime', 'count', 'json']).optional(),
|
|
16
|
+
badgeColor: z.string().trim().min(1).max(40).optional()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
export const RecordColumnsConfigSchema = z
|
|
20
|
+
.object({
|
|
21
|
+
company: z.array(RecordColumnConfigSchema).optional(),
|
|
22
|
+
contact: z.array(RecordColumnConfigSchema).optional()
|
|
23
|
+
})
|
|
24
|
+
.refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
|
|
25
|
+
message: 'recordColumns must include at least one entity column set'
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
export const CredentialRequirementSchema = z.object({
|
|
29
|
+
key: ModelIdSchema,
|
|
30
|
+
provider: ModelIdSchema,
|
|
31
|
+
credentialType: z.enum(['api-key', 'api-key-secret', 'oauth', 'webhook-secret']),
|
|
32
|
+
label: z.string().trim().min(1).max(120),
|
|
33
|
+
required: z.boolean(),
|
|
34
|
+
selectionMode: z.enum(['single', 'multiple']).optional(),
|
|
35
|
+
inputPath: z.string().trim().min(1).max(500),
|
|
36
|
+
verifyOnRun: z.boolean().optional()
|
|
8
37
|
})
|
|
9
38
|
|
|
10
39
|
export const ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
|
|
@@ -12,11 +41,16 @@ export const ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
|
|
|
12
41
|
primaryEntity: z.enum(['company', 'contact']),
|
|
13
42
|
outputs: z.array(z.enum(['company', 'contact', 'export'])).min(1),
|
|
14
43
|
stageKey: ModelIdSchema,
|
|
44
|
+
recordEntity: z.enum(['company', 'contact']).optional(),
|
|
45
|
+
recordsStageKey: ModelIdSchema.optional(),
|
|
46
|
+
recordSourceStageKey: ModelIdSchema.optional(),
|
|
15
47
|
dependsOn: z.array(ModelIdSchema).optional(),
|
|
16
48
|
dependencyMode: z.literal('per-record-eligibility'),
|
|
17
49
|
capabilityKey: ModelIdSchema,
|
|
18
50
|
defaultBatchSize: z.number().int().positive(),
|
|
19
|
-
maxBatchSize: z.number().int().positive()
|
|
51
|
+
maxBatchSize: z.number().int().positive(),
|
|
52
|
+
recordColumns: RecordColumnsConfigSchema.optional(),
|
|
53
|
+
credentialRequirements: z.array(CredentialRequirementSchema).optional()
|
|
20
54
|
}).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
|
|
21
55
|
message: 'defaultBatchSize must be less than or equal to maxBatchSize',
|
|
22
56
|
path: ['defaultBatchSize']
|
|
@@ -28,9 +62,68 @@ export const ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
|
|
|
28
62
|
})
|
|
29
63
|
|
|
30
64
|
export type ListBuilderStep = z.infer<typeof ProspectingBuildTemplateStepSchema>
|
|
65
|
+
export type RecordColumnConfig = z.infer<typeof RecordColumnConfigSchema>
|
|
66
|
+
export type CredentialRequirement = z.infer<typeof CredentialRequirementSchema>
|
|
31
67
|
export type TemplateName = 'localServices' | 'dtcApolloClickup'
|
|
32
68
|
export type StepName = string
|
|
33
69
|
|
|
70
|
+
const DTC_RECORD_COLUMNS = {
|
|
71
|
+
populated: {
|
|
72
|
+
company: [
|
|
73
|
+
{ key: 'name', label: 'Company', path: 'company.name' },
|
|
74
|
+
{ key: 'domain', label: 'Domain', path: 'company.domain' },
|
|
75
|
+
{ key: 'employee-count', label: 'Employees', path: 'company.numEmployees', renderType: 'count' },
|
|
76
|
+
{ key: 'apollo-industry', label: 'Apollo industry', path: 'company.category' },
|
|
77
|
+
{ key: 'location', label: 'Location', path: 'company.locationState' }
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
crawled: {
|
|
81
|
+
company: [
|
|
82
|
+
{ key: 'name', label: 'Company', path: 'company.name' },
|
|
83
|
+
{ key: 'domain', label: 'Domain', path: 'company.domain' },
|
|
84
|
+
{ key: 'page-count', label: 'Pages', path: 'company.enrichmentData.websiteCrawl.pageCount', renderType: 'count' },
|
|
85
|
+
{ key: 'crawl-status', label: 'Crawl status', path: 'processingState.crawled.status', renderType: 'badge' }
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
extracted: {
|
|
89
|
+
company: [
|
|
90
|
+
{ key: 'name', label: 'Company', path: 'company.name' },
|
|
91
|
+
{ key: 'domain', label: 'Domain', path: 'company.domain' },
|
|
92
|
+
{ key: 'description', label: 'Description', path: 'company.enrichmentData.websiteCrawl.companyDescription' },
|
|
93
|
+
{ key: 'services', label: 'Services', path: 'company.enrichmentData.websiteCrawl.services', renderType: 'json' },
|
|
94
|
+
{ key: 'automation-gaps', label: 'Automation gaps', path: 'company.enrichmentData.websiteCrawl.automationGaps', renderType: 'json' },
|
|
95
|
+
{ key: 'contact-count', label: 'Contacts', path: 'company.enrichmentData.websiteCrawl.emailCount', renderType: 'count' }
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
qualified: {
|
|
99
|
+
company: [
|
|
100
|
+
{ key: 'name', label: 'Company', path: 'company.name' },
|
|
101
|
+
{ key: 'domain', label: 'Domain', path: 'company.domain' },
|
|
102
|
+
{ key: 'score', label: 'Score', path: 'company.qualificationScore', renderType: 'badge', badgeColor: 'green' },
|
|
103
|
+
{ key: 'signals', label: 'Signals', path: 'company.qualificationSignals', renderType: 'json' },
|
|
104
|
+
{ key: 'disqualified-reason', label: 'Disqualified reason', path: 'processingState.qualified.data.disqualifiedReason' }
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
decisionMakers: {
|
|
108
|
+
contact: [
|
|
109
|
+
{ key: 'name', label: 'Name', path: 'contact.name' },
|
|
110
|
+
{ key: 'title', label: 'Title', path: 'contact.title' },
|
|
111
|
+
{ key: 'email', label: 'Email', path: 'contact.email' },
|
|
112
|
+
{ key: 'linkedin', label: 'LinkedIn', path: 'contact.linkedinUrl' },
|
|
113
|
+
{ key: 'priority-score', label: 'Priority', path: 'contact.enrichmentData.apollo.priorityScore', renderType: 'badge' }
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
uploaded: {
|
|
117
|
+
company: [
|
|
118
|
+
{ key: 'name', label: 'Company', path: 'company.name' },
|
|
119
|
+
{ key: 'domain', label: 'Domain', path: 'company.domain' },
|
|
120
|
+
{ key: 'contacts', label: 'Contacts', path: 'company.enrichmentData.approvedLeadListExport.contacts', renderType: 'json' },
|
|
121
|
+
{ key: 'score', label: 'Score', path: 'company.qualificationScore', renderType: 'badge', badgeColor: 'green' },
|
|
122
|
+
{ key: 'approval', label: 'Approval', path: 'company.enrichmentData.approvedLeadListExport.approvalStatus', renderType: 'badge' }
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
} as const satisfies Record<string, z.infer<typeof RecordColumnsConfigSchema>>
|
|
126
|
+
|
|
34
127
|
export const CapabilitySchema = z.object({
|
|
35
128
|
id: ModelIdSchema,
|
|
36
129
|
label: z.string(),
|
|
@@ -66,6 +159,13 @@ export const CAPABILITY_REGISTRY: CapabilityRegistry = [
|
|
|
66
159
|
description: 'Check email deliverability before outreach.',
|
|
67
160
|
resourceId: 'lgn-05-email-verification-workflow'
|
|
68
161
|
},
|
|
162
|
+
{
|
|
163
|
+
id: 'lead-gen.company.apify-crawl',
|
|
164
|
+
label: 'Crawl websites',
|
|
165
|
+
description:
|
|
166
|
+
'Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis.',
|
|
167
|
+
resourceId: 'lgn-02a-apify-website-crawl-workflow'
|
|
168
|
+
},
|
|
69
169
|
{
|
|
70
170
|
id: 'lead-gen.company.website-extract',
|
|
71
171
|
label: 'Extract website signals',
|
|
@@ -217,7 +317,46 @@ export const PROSPECTING_STEPS = {
|
|
|
217
317
|
dependencyMode: 'per-record-eligibility',
|
|
218
318
|
capabilityKey: 'lead-gen.company.apollo-import',
|
|
219
319
|
defaultBatchSize: 250,
|
|
220
|
-
maxBatchSize: 1000
|
|
320
|
+
maxBatchSize: 1000,
|
|
321
|
+
recordColumns: DTC_RECORD_COLUMNS.populated,
|
|
322
|
+
credentialRequirements: [
|
|
323
|
+
{
|
|
324
|
+
key: 'apollo',
|
|
325
|
+
provider: 'apollo',
|
|
326
|
+
credentialType: 'api-key-secret',
|
|
327
|
+
label: 'Apollo API key',
|
|
328
|
+
required: true,
|
|
329
|
+
selectionMode: 'single',
|
|
330
|
+
inputPath: 'credential'
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
},
|
|
334
|
+
apifyCrawl: {
|
|
335
|
+
id: 'apify-crawl',
|
|
336
|
+
label: 'Websites crawled',
|
|
337
|
+
description:
|
|
338
|
+
'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.',
|
|
339
|
+
primaryEntity: 'company',
|
|
340
|
+
outputs: ['company'],
|
|
341
|
+
stageKey: 'crawled',
|
|
342
|
+
dependsOn: ['import-apollo-search'],
|
|
343
|
+
dependencyMode: 'per-record-eligibility',
|
|
344
|
+
capabilityKey: 'lead-gen.company.apify-crawl',
|
|
345
|
+
defaultBatchSize: 50,
|
|
346
|
+
maxBatchSize: 100,
|
|
347
|
+
recordColumns: DTC_RECORD_COLUMNS.crawled,
|
|
348
|
+
credentialRequirements: [
|
|
349
|
+
{
|
|
350
|
+
key: 'apify',
|
|
351
|
+
provider: 'apify',
|
|
352
|
+
credentialType: 'api-key-secret',
|
|
353
|
+
label: 'Apify API token',
|
|
354
|
+
required: true,
|
|
355
|
+
selectionMode: 'single',
|
|
356
|
+
inputPath: 'credential',
|
|
357
|
+
verifyOnRun: true
|
|
358
|
+
}
|
|
359
|
+
]
|
|
221
360
|
},
|
|
222
361
|
analyzeWebsites: {
|
|
223
362
|
id: 'analyze-websites',
|
|
@@ -226,11 +365,12 @@ export const PROSPECTING_STEPS = {
|
|
|
226
365
|
primaryEntity: 'company',
|
|
227
366
|
outputs: ['company'],
|
|
228
367
|
stageKey: 'extracted',
|
|
229
|
-
dependsOn: ['
|
|
368
|
+
dependsOn: ['apify-crawl'],
|
|
230
369
|
dependencyMode: 'per-record-eligibility',
|
|
231
370
|
capabilityKey: 'lead-gen.company.website-extract',
|
|
232
371
|
defaultBatchSize: 50,
|
|
233
|
-
maxBatchSize: 100
|
|
372
|
+
maxBatchSize: 100,
|
|
373
|
+
recordColumns: DTC_RECORD_COLUMNS.extracted
|
|
234
374
|
},
|
|
235
375
|
scoreDtcFit: {
|
|
236
376
|
id: 'score-dtc-fit',
|
|
@@ -243,7 +383,8 @@ export const PROSPECTING_STEPS = {
|
|
|
243
383
|
dependencyMode: 'per-record-eligibility',
|
|
244
384
|
capabilityKey: 'lead-gen.company.dtc-subscription-qualify',
|
|
245
385
|
defaultBatchSize: 100,
|
|
246
|
-
maxBatchSize: 250
|
|
386
|
+
maxBatchSize: 250,
|
|
387
|
+
recordColumns: DTC_RECORD_COLUMNS.qualified
|
|
247
388
|
},
|
|
248
389
|
enrichDecisionMakers: {
|
|
249
390
|
id: 'enrich-decision-makers',
|
|
@@ -253,37 +394,53 @@ export const PROSPECTING_STEPS = {
|
|
|
253
394
|
primaryEntity: 'company',
|
|
254
395
|
outputs: ['contact'],
|
|
255
396
|
stageKey: 'decision-makers-enriched',
|
|
397
|
+
recordEntity: 'contact',
|
|
256
398
|
dependsOn: ['score-dtc-fit'],
|
|
257
399
|
dependencyMode: 'per-record-eligibility',
|
|
258
400
|
capabilityKey: 'lead-gen.contact.apollo-decision-maker-enrich',
|
|
259
401
|
defaultBatchSize: 100,
|
|
260
|
-
maxBatchSize: 250
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
maxBatchSize: 500
|
|
402
|
+
maxBatchSize: 250,
|
|
403
|
+
recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
|
|
404
|
+
credentialRequirements: [
|
|
405
|
+
{
|
|
406
|
+
key: 'apollo',
|
|
407
|
+
provider: 'apollo',
|
|
408
|
+
credentialType: 'api-key-secret',
|
|
409
|
+
label: 'Apollo API key',
|
|
410
|
+
required: true,
|
|
411
|
+
selectionMode: 'single',
|
|
412
|
+
inputPath: 'credential'
|
|
413
|
+
}
|
|
414
|
+
]
|
|
274
415
|
},
|
|
275
416
|
reviewAndExport: {
|
|
276
417
|
id: 'review-and-export',
|
|
277
418
|
label: 'Reviewed and exported',
|
|
278
|
-
description:
|
|
419
|
+
description:
|
|
420
|
+
'Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.',
|
|
279
421
|
primaryEntity: 'company',
|
|
280
422
|
outputs: ['export'],
|
|
281
423
|
stageKey: 'uploaded',
|
|
282
|
-
|
|
424
|
+
recordsStageKey: 'uploaded',
|
|
425
|
+
recordSourceStageKey: 'qualified',
|
|
426
|
+
dependsOn: ['enrich-decision-makers'],
|
|
283
427
|
dependencyMode: 'per-record-eligibility',
|
|
284
428
|
capabilityKey: 'lead-gen.export.list',
|
|
285
429
|
defaultBatchSize: 100,
|
|
286
|
-
maxBatchSize: 250
|
|
430
|
+
maxBatchSize: 250,
|
|
431
|
+
recordColumns: DTC_RECORD_COLUMNS.uploaded,
|
|
432
|
+
credentialRequirements: [
|
|
433
|
+
{
|
|
434
|
+
key: 'clickup',
|
|
435
|
+
provider: 'clickup',
|
|
436
|
+
credentialType: 'api-key-secret',
|
|
437
|
+
label: 'ClickUp API token',
|
|
438
|
+
required: true,
|
|
439
|
+
selectionMode: 'single',
|
|
440
|
+
inputPath: 'clickupCredential',
|
|
441
|
+
verifyOnRun: true
|
|
442
|
+
}
|
|
443
|
+
]
|
|
287
444
|
}
|
|
288
445
|
}
|
|
289
446
|
} as const satisfies Record<TemplateName, Record<StepName, ListBuilderStep>>
|
|
@@ -311,7 +468,7 @@ function leadGenStagesForEntity(
|
|
|
311
468
|
entity: LeadGenStageCatalogEntry['entity']
|
|
312
469
|
): z.infer<typeof ProspectingLifecycleStageSchema>[] {
|
|
313
470
|
return Object.values(LEAD_GEN_STAGE_CATALOG)
|
|
314
|
-
.filter((stage) => stage.entity === entity)
|
|
471
|
+
.filter((stage) => stage.entity === entity || stage.additionalEntities?.includes(entity))
|
|
315
472
|
.sort((a, b) => a.order - b.order)
|
|
316
473
|
.map(toProspectingLifecycleStage)
|
|
317
474
|
}
|
|
@@ -346,10 +503,10 @@ export const DEFAULT_ORGANIZATION_MODEL_PROSPECTING: z.infer<typeof Organization
|
|
|
346
503
|
'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.',
|
|
347
504
|
steps: [
|
|
348
505
|
PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
|
|
506
|
+
PROSPECTING_STEPS.dtcApolloClickup.apifyCrawl,
|
|
349
507
|
PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
|
|
350
508
|
PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
|
|
351
509
|
PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
|
|
352
|
-
PROSPECTING_STEPS.dtcApolloClickup.verifyEmails,
|
|
353
510
|
PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
|
|
354
511
|
]
|
|
355
512
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { ModelIdSchema } from './shared'
|
|
3
|
+
import { SystemIdSchema } from './systems'
|
|
4
|
+
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Resources domain
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
//
|
|
9
|
+
// Resources are governance-only OM descriptors. Runtime code imports these
|
|
10
|
+
// descriptors and attaches executable behavior; it does not re-author identity.
|
|
11
|
+
|
|
12
|
+
export const ResourceKindSchema = z.enum(['workflow', 'agent', 'integration'])
|
|
13
|
+
export const ResourceGovernanceStatusSchema = z.enum(['active', 'deprecated', 'archived'])
|
|
14
|
+
export const AgentKindSchema = z.enum(['orchestrator', 'specialist', 'utility', 'system'])
|
|
15
|
+
|
|
16
|
+
export const ResourceIdSchema = z
|
|
17
|
+
.string()
|
|
18
|
+
.trim()
|
|
19
|
+
.min(1)
|
|
20
|
+
.max(255)
|
|
21
|
+
.regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, 'Resource IDs must use letters, numbers, -, _, or . separators')
|
|
22
|
+
|
|
23
|
+
const ResourceEntryBaseSchema = z.object({
|
|
24
|
+
/** Canonical resource id; runtime resourceId derives from this value. */
|
|
25
|
+
id: ResourceIdSchema,
|
|
26
|
+
/** Required single System membership. */
|
|
27
|
+
systemId: SystemIdSchema,
|
|
28
|
+
/** Optional role responsible for maintaining this resource. */
|
|
29
|
+
ownerRoleId: ModelIdSchema.optional(),
|
|
30
|
+
status: ResourceGovernanceStatusSchema
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
export const WorkflowResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
34
|
+
kind: z.literal('workflow'),
|
|
35
|
+
/** Mirrors WorkflowConfig.capabilityKey when the runtime workflow has one. */
|
|
36
|
+
capabilityKey: z.string().trim().min(1).max(255).optional()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
export const AgentResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
40
|
+
kind: z.literal('agent'),
|
|
41
|
+
/** Mirrors code-side AgentConfig.kind. */
|
|
42
|
+
agentKind: AgentKindSchema,
|
|
43
|
+
/** Role this agent embodies, if any. */
|
|
44
|
+
actsAsRoleId: ModelIdSchema.optional(),
|
|
45
|
+
/** Mirrors AgentConfig.sessionCapable. */
|
|
46
|
+
sessionCapable: z.boolean()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
export const IntegrationResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
50
|
+
kind: z.literal('integration'),
|
|
51
|
+
provider: z.string().trim().min(1).max(100)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
export const ResourceEntrySchema = z.discriminatedUnion('kind', [
|
|
55
|
+
WorkflowResourceEntrySchema,
|
|
56
|
+
AgentResourceEntrySchema,
|
|
57
|
+
IntegrationResourceEntrySchema
|
|
58
|
+
])
|
|
59
|
+
|
|
60
|
+
export const ResourcesDomainSchema = z.object({
|
|
61
|
+
entries: z.array(ResourceEntrySchema).default([])
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
export const DEFAULT_ORGANIZATION_MODEL_RESOURCES: z.infer<typeof ResourcesDomainSchema> = {
|
|
65
|
+
entries: []
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function defineResource<const TResource extends ResourceEntry>(resource: TResource): TResource {
|
|
69
|
+
return ResourceEntrySchema.parse(resource) as TResource
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function defineResources<const TResources extends Record<string, ResourceEntry>>(resources: TResources): TResources {
|
|
73
|
+
for (const resource of Object.values(resources)) {
|
|
74
|
+
ResourceEntrySchema.parse(resource)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return resources
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type ResourceId = z.infer<typeof ResourceIdSchema>
|
|
81
|
+
export type ResourceKind = z.infer<typeof ResourceKindSchema>
|
|
82
|
+
export type ResourceGovernanceStatus = z.infer<typeof ResourceGovernanceStatusSchema>
|
|
83
|
+
export type ResourceAgentKind = z.infer<typeof AgentKindSchema>
|
|
84
|
+
export type WorkflowResourceEntry = z.infer<typeof WorkflowResourceEntrySchema>
|
|
85
|
+
export type AgentResourceEntry = z.infer<typeof AgentResourceEntrySchema>
|
|
86
|
+
export type IntegrationResourceEntry = z.infer<typeof IntegrationResourceEntrySchema>
|
|
87
|
+
export type ResourceEntry = z.infer<typeof ResourceEntrySchema>
|
|
88
|
+
export type ResourcesDomain = z.infer<typeof ResourcesDomainSchema>
|
|
@@ -1,55 +1,93 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { ResourceIdSchema } from './resources'
|
|
3
|
+
import { ModelIdSchema } from './shared'
|
|
4
|
+
import { SystemIdSchema } from './systems'
|
|
5
|
+
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Role schema - one entry per distinct role in the organization's chart.
|
|
8
|
+
// Inspired by the EOS Accountability Chart but uses plain-language field names
|
|
9
|
+
// throughout. No EOS jargon: "title" (not seatTitle), "responsibilities"
|
|
10
|
+
// (not accountabilities), "reportsToId", "heldBy".
|
|
11
|
+
//
|
|
12
|
+
// Cross-reference enforcement lives in `OrganizationModelSchema.superRefine()`:
|
|
13
|
+
// `reportsToId` must resolve to another Role, `responsibleFor` entries must
|
|
14
|
+
// resolve to Systems, and agent holders must resolve to Agent Resources.
|
|
15
|
+
// Cycle detection is NOT enforced (known limitation; document if needed).
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
export const RoleIdSchema = ModelIdSchema
|
|
19
|
+
|
|
20
|
+
export const HumanRoleHolderSchema = z.object({
|
|
21
|
+
kind: z.literal('human'),
|
|
22
|
+
userId: z.string().trim().min(1).max(200)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
export const AgentRoleHolderSchema = z.object({
|
|
26
|
+
kind: z.literal('agent'),
|
|
27
|
+
agentId: ResourceIdSchema
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
export const TeamRoleHolderSchema = z.object({
|
|
31
|
+
kind: z.literal('team'),
|
|
32
|
+
memberIds: z.array(z.string().trim().min(1).max(200)).min(1)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
export const RoleHolderSchema = z.discriminatedUnion('kind', [
|
|
36
|
+
HumanRoleHolderSchema,
|
|
37
|
+
AgentRoleHolderSchema,
|
|
38
|
+
TeamRoleHolderSchema
|
|
39
|
+
])
|
|
40
|
+
|
|
41
|
+
export const RoleHoldersSchema = z.union([RoleHolderSchema, z.array(RoleHolderSchema).min(1)])
|
|
42
|
+
|
|
43
|
+
export const RoleSchema = z.object({
|
|
44
|
+
/** Stable unique identifier for the role (e.g. "role-ceo", "role-head-of-sales"). */
|
|
45
|
+
id: RoleIdSchema,
|
|
46
|
+
/** Human-readable title shown to agents and in UI (e.g. "CEO", "Head of Sales"). */
|
|
47
|
+
title: z.string().trim().min(1).max(200),
|
|
48
|
+
/**
|
|
49
|
+
* List of responsibilities this role owns - plain-language descriptions of
|
|
50
|
+
* what the person in this role is accountable for delivering.
|
|
51
|
+
* Defaults to empty array so minimal role definitions stay concise.
|
|
52
|
+
*/
|
|
53
|
+
responsibilities: z.array(z.string().trim().max(500)).default([]),
|
|
54
|
+
/**
|
|
55
|
+
* Optional: ID of another role this role reports to.
|
|
56
|
+
* When present, must reference another `roles[].id` in the same organization.
|
|
57
|
+
*/
|
|
58
|
+
reportsToId: RoleIdSchema.optional(),
|
|
59
|
+
/**
|
|
60
|
+
* Optional: human, agent, or team holder currently filling this role.
|
|
61
|
+
* Agent holders reference OM Resource IDs and are validated at the model level.
|
|
62
|
+
*/
|
|
63
|
+
heldBy: RoleHoldersSchema.optional(),
|
|
64
|
+
/**
|
|
65
|
+
* Optional Systems this role is accountable for.
|
|
66
|
+
* Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
|
|
67
|
+
*/
|
|
68
|
+
responsibleFor: z.array(SystemIdSchema).optional()
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// Roles domain schema - a collection of roles.
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
export const RolesDomainSchema = z.object({
|
|
76
|
+
roles: z.array(RoleSchema).default([])
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Seed - empty by default; adapters populate with real role definitions.
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
export const DEFAULT_ORGANIZATION_MODEL_ROLES: z.infer<typeof RolesDomainSchema> = {
|
|
84
|
+
roles: []
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type RoleId = z.infer<typeof RoleIdSchema>
|
|
88
|
+
export type HumanRoleHolder = z.infer<typeof HumanRoleHolderSchema>
|
|
89
|
+
export type AgentRoleHolder = z.infer<typeof AgentRoleHolderSchema>
|
|
90
|
+
export type TeamRoleHolder = z.infer<typeof TeamRoleHolderSchema>
|
|
91
|
+
export type RoleHolder = z.infer<typeof RoleHolderSchema>
|
|
92
|
+
export type Role = z.infer<typeof RoleSchema>
|
|
93
|
+
export type RolesDomain = z.infer<typeof RolesDomainSchema>
|
|
@@ -113,6 +113,7 @@ export const DEFAULT_ORGANIZATION_MODEL_SALES: z.infer<typeof OrganizationModelS
|
|
|
113
113
|
// - interested (instantly-reply-handler.ts → contacts, initial reply transition)
|
|
114
114
|
// prospecting/:
|
|
115
115
|
// - populated (apify-acquire.ts, apify-scrape.ts → companies)
|
|
116
|
+
// - crawled (apify-website-crawl.ts → companies)
|
|
116
117
|
// - extracted (website-extract.ts → companies)
|
|
117
118
|
// - discovered (email-discovery.ts, anymailfinder-enrich.ts → contacts)
|
|
118
119
|
// - verified (email-verification.ts → contacts)
|
|
@@ -414,7 +415,7 @@ export const ACQ_LIST_COMPANIES_LEAD_GEN_PIPELINE: StatefulPipelineDefinition =
|
|
|
414
415
|
{
|
|
415
416
|
stageKey: 'outreach',
|
|
416
417
|
label: 'Outreach',
|
|
417
|
-
states: [PENDING_STATE]
|
|
418
|
+
states: [PENDING_STATE, { stateKey: 'uploaded', label: 'Uploaded' }]
|
|
418
419
|
},
|
|
419
420
|
{
|
|
420
421
|
stageKey: 'prospecting',
|
|
@@ -472,6 +473,15 @@ export interface LeadGenStageCatalogEntry {
|
|
|
472
473
|
order: number
|
|
473
474
|
/** Which entity's processing_state jsonb carries this stage status. */
|
|
474
475
|
entity: 'company' | 'contact'
|
|
476
|
+
/** Additional entities allowed to write/read this processing_state key. */
|
|
477
|
+
additionalEntities?: Array<'company' | 'contact'>
|
|
478
|
+
/**
|
|
479
|
+
* Optional read-side override for Records views when a company-scoped step
|
|
480
|
+
* produces records on a different entity.
|
|
481
|
+
*/
|
|
482
|
+
recordEntity?: 'company' | 'contact'
|
|
483
|
+
/** Stage key to read from recordEntity.processing_state for Records views. */
|
|
484
|
+
recordStageKey?: string
|
|
475
485
|
}
|
|
476
486
|
|
|
477
487
|
/**
|
|
@@ -496,6 +506,14 @@ export const LEAD_GEN_STAGE_CATALOG: Record<string, LeadGenStageCatalogEntry> =
|
|
|
496
506
|
order: 2,
|
|
497
507
|
entity: 'company'
|
|
498
508
|
},
|
|
509
|
+
crawled: {
|
|
510
|
+
key: 'crawled',
|
|
511
|
+
label: 'Websites crawled',
|
|
512
|
+
description:
|
|
513
|
+
'Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.',
|
|
514
|
+
order: 2.5,
|
|
515
|
+
entity: 'company'
|
|
516
|
+
},
|
|
499
517
|
extracted: {
|
|
500
518
|
key: 'extracted',
|
|
501
519
|
label: 'Websites analyzed',
|
|
@@ -515,7 +533,9 @@ export const LEAD_GEN_STAGE_CATALOG: Record<string, LeadGenStageCatalogEntry> =
|
|
|
515
533
|
label: 'Decision-makers found',
|
|
516
534
|
description: 'Decision-maker contacts discovered and attached to a qualified company.',
|
|
517
535
|
order: 6,
|
|
518
|
-
entity: 'company'
|
|
536
|
+
entity: 'company',
|
|
537
|
+
recordEntity: 'contact',
|
|
538
|
+
recordStageKey: 'discovered'
|
|
519
539
|
},
|
|
520
540
|
|
|
521
541
|
// Prospecting — contact discovery
|
|
@@ -556,7 +576,8 @@ export const LEAD_GEN_STAGE_CATALOG: Record<string, LeadGenStageCatalogEntry> =
|
|
|
556
576
|
label: 'Reviewed and exported',
|
|
557
577
|
description: 'Approved records have been reviewed and exported for handoff.',
|
|
558
578
|
order: 10,
|
|
559
|
-
entity: '
|
|
579
|
+
entity: 'company',
|
|
580
|
+
additionalEntities: ['contact']
|
|
560
581
|
},
|
|
561
582
|
interested: {
|
|
562
583
|
key: 'interested',
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { DescriptionSchema, LabelSchema, ModelIdSchema, ReferenceIdsSchema } from './shared'
|
|
3
|
+
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Systems domain
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
//
|
|
8
|
+
// A System is a tenant-defined bounded context that groups operational
|
|
9
|
+
// resources and carries governance metadata. The shared schema validates the
|
|
10
|
+
// shape and references; each tenant supplies its own catalog.
|
|
11
|
+
|
|
12
|
+
export const SystemKindSchema = z.enum(['product', 'operational', 'platform', 'diagnostic'])
|
|
13
|
+
export const SystemStatusSchema = z.enum(['active', 'deprecated', 'archived'])
|
|
14
|
+
export const SystemIdSchema = ModelIdSchema
|
|
15
|
+
|
|
16
|
+
export const SystemEntrySchema = z.object({
|
|
17
|
+
/** Stable tenant-defined system id (e.g. "sys.lead-gen"). */
|
|
18
|
+
id: SystemIdSchema,
|
|
19
|
+
/** Human-readable system title shown in governance and operations UI. */
|
|
20
|
+
title: LabelSchema,
|
|
21
|
+
/** One-paragraph purpose statement for the bounded context. */
|
|
22
|
+
description: DescriptionSchema,
|
|
23
|
+
/** Closed system shape enum; catalog values remain tenant-defined. */
|
|
24
|
+
kind: SystemKindSchema,
|
|
25
|
+
/** Optional role responsible for this system. */
|
|
26
|
+
responsibleRoleId: ModelIdSchema.optional(),
|
|
27
|
+
/** Optional knowledge nodes that govern this system. */
|
|
28
|
+
governedByKnowledge: ReferenceIdsSchema,
|
|
29
|
+
/** Optional goals this system contributes to. */
|
|
30
|
+
drivesGoals: ReferenceIdsSchema,
|
|
31
|
+
status: SystemStatusSchema
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
export const SystemsDomainSchema = z.object({
|
|
35
|
+
systems: z.array(SystemEntrySchema).default([])
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
export const DEFAULT_ORGANIZATION_MODEL_SYSTEMS: z.infer<typeof SystemsDomainSchema> = {
|
|
39
|
+
systems: []
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type SystemId = z.infer<typeof SystemIdSchema>
|
|
43
|
+
export type SystemKind = z.infer<typeof SystemKindSchema>
|
|
44
|
+
export type SystemStatus = z.infer<typeof SystemStatusSchema>
|
|
45
|
+
export type SystemEntry = z.infer<typeof SystemEntrySchema>
|
|
46
|
+
export type SystemsDomain = z.infer<typeof SystemsDomainSchema>
|