@elevasis/core 0.21.0 → 0.23.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 +2518 -2169
- package/dist/index.js +2495 -1095
- package/dist/knowledge/index.d.ts +706 -1044
- package/dist/knowledge/index.js +9 -9
- package/dist/organization-model/index.d.ts +2518 -2169
- package/dist/organization-model/index.js +2495 -1095
- package/dist/test-utils/index.d.ts +826 -1014
- package/dist/test-utils/index.js +1894 -1032
- package/package.json +3 -3
- package/src/__tests__/template-core-compatibility.test.ts +11 -79
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +852 -397
- package/src/auth/multi-tenancy/permissions.ts +20 -8
- package/src/business/README.md +2 -2
- package/src/business/acquisition/api-schemas.test.ts +175 -2
- package/src/business/acquisition/api-schemas.ts +132 -16
- package/src/business/acquisition/build-templates.test.ts +4 -4
- package/src/business/acquisition/build-templates.ts +72 -30
- package/src/business/acquisition/crm-state-actions.test.ts +13 -11
- package/src/business/acquisition/index.ts +12 -0
- package/src/business/acquisition/types.ts +7 -3
- 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/workflow/types.ts +9 -2
- package/src/knowledge/README.md +8 -7
- package/src/knowledge/__tests__/queries.test.ts +74 -73
- package/src/knowledge/format.ts +10 -9
- package/src/knowledge/index.ts +1 -1
- package/src/knowledge/published.ts +1 -1
- package/src/knowledge/queries.ts +26 -25
- package/src/organization-model/README.md +73 -26
- package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
- package/src/organization-model/__tests__/defaults.test.ts +76 -96
- package/src/organization-model/__tests__/domains/actions.test.ts +56 -0
- package/src/organization-model/__tests__/domains/customers.test.ts +299 -295
- package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
- package/src/organization-model/__tests__/domains/goals.test.ts +493 -479
- package/src/organization-model/__tests__/domains/identity.test.ts +280 -279
- package/src/organization-model/__tests__/domains/navigation.test.ts +268 -212
- package/src/organization-model/__tests__/domains/offerings.test.ts +414 -419
- package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
- package/src/organization-model/__tests__/domains/resource-mappings.test.ts +271 -271
- package/src/organization-model/__tests__/domains/resources.test.ts +310 -0
- package/src/organization-model/__tests__/domains/roles.test.ts +463 -347
- package/src/organization-model/__tests__/domains/statuses.test.ts +246 -243
- package/src/organization-model/__tests__/domains/systems.test.ts +209 -0
- package/src/organization-model/__tests__/flatten-additive-merge.test.ts +361 -0
- package/src/organization-model/__tests__/foundation.test.ts +74 -102
- package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
- package/src/organization-model/__tests__/graph.test.ts +899 -71
- package/src/organization-model/__tests__/knowledge.test.ts +209 -49
- package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
- package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
- package/src/organization-model/__tests__/prospecting-ssot.test.ts +36 -27
- package/src/organization-model/__tests__/recursive-system-schema.test.ts +520 -0
- package/src/organization-model/__tests__/resolve.test.ts +174 -23
- package/src/organization-model/__tests__/schema.test.ts +291 -114
- package/src/organization-model/__tests__/surface-projection.test.ts +207 -97
- package/src/organization-model/catalogs/lead-gen.ts +144 -0
- package/src/organization-model/content-kinds/config.ts +36 -0
- package/src/organization-model/content-kinds/index.ts +74 -0
- package/src/organization-model/content-kinds/pipeline.ts +68 -0
- package/src/organization-model/content-kinds/registry.ts +44 -0
- package/src/organization-model/content-kinds/status.ts +71 -0
- package/src/organization-model/content-kinds/template.ts +83 -0
- package/src/organization-model/content-kinds/types.ts +117 -0
- package/src/organization-model/contracts.ts +13 -3
- package/src/organization-model/defaults.ts +499 -86
- package/src/organization-model/domains/actions.ts +239 -0
- package/src/organization-model/domains/customers.ts +78 -75
- package/src/organization-model/domains/entities.ts +144 -0
- package/src/organization-model/domains/goals.ts +83 -80
- package/src/organization-model/domains/knowledge.ts +76 -17
- package/src/organization-model/domains/navigation.ts +107 -384
- package/src/organization-model/domains/offerings.ts +71 -66
- package/src/organization-model/domains/policies.ts +102 -0
- package/src/organization-model/domains/projects.ts +14 -48
- package/src/organization-model/domains/prospecting.ts +62 -181
- package/src/organization-model/domains/resources.ts +145 -0
- package/src/organization-model/domains/roles.ts +96 -55
- package/src/organization-model/domains/sales.ts +10 -219
- package/src/organization-model/domains/shared.ts +57 -57
- package/src/organization-model/domains/statuses.ts +339 -130
- package/src/organization-model/domains/systems.ts +203 -0
- package/src/organization-model/foundation.ts +54 -67
- package/src/organization-model/graph/build.ts +682 -54
- package/src/organization-model/graph/link.ts +1 -1
- package/src/organization-model/graph/schema.ts +24 -9
- package/src/organization-model/graph/types.ts +20 -7
- package/src/organization-model/helpers.ts +231 -26
- package/src/organization-model/icons.ts +1 -0
- package/src/organization-model/index.ts +118 -5
- package/src/organization-model/migration-helpers.ts +249 -0
- package/src/organization-model/organization-graph.mdx +16 -15
- package/src/organization-model/organization-model.mdx +111 -44
- package/src/organization-model/published.ts +172 -19
- package/src/organization-model/resolve.ts +117 -54
- package/src/organization-model/schema.ts +654 -112
- package/src/organization-model/surface-projection.ts +116 -122
- package/src/organization-model/types.ts +146 -20
- package/src/platform/api/types.ts +38 -35
- package/src/platform/constants/versions.ts +1 -1
- package/src/platform/registry/__tests__/command-view.test.ts +6 -8
- package/src/platform/registry/__tests__/resource-link.test.ts +13 -8
- package/src/platform/registry/__tests__/resource-registry.integration.test.ts +16 -31
- package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
- package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2005
- package/src/platform/registry/__tests__/validation.test.ts +1347 -1086
- package/src/platform/registry/index.ts +14 -0
- package/src/platform/registry/resource-registry.ts +52 -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 +745 -513
- package/src/projects/api-schemas.ts +290 -267
- package/src/reference/_generated/contracts.md +853 -397
- package/src/reference/glossary.md +23 -18
- package/src/supabase/database.types.ts +181 -0
- package/src/test-utils/test-utils.test.ts +1 -6
- package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
- package/src/organization-model/domains/features.ts +0 -31
- package/src/organization-model/domains/operations.ts +0 -85
|
@@ -1,28 +1,60 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
// Phase 4: DEFAULT_ORGANIZATION_MODEL_PROSPECTING was deleted (compound domain removed per D8).
|
|
2
|
+
// Build-template definitions are now sourced inline from PROSPECTING_STEPS, which retains
|
|
3
|
+
// the step catalog. The template catalog (id, label, description, steps[]) is declared here
|
|
4
|
+
// as a local constant — Wave 2 will author these as system.content entries on the canonical OM.
|
|
5
|
+
import {
|
|
6
|
+
PROSPECTING_STEPS,
|
|
7
|
+
type CredentialRequirement,
|
|
8
|
+
type ListBuilderStep,
|
|
9
|
+
type RecordColumnConfig
|
|
10
|
+
} from '../../organization-model/domains/prospecting'
|
|
11
|
+
import type { BuildPlanSnapshot, BuildPlanSnapshotStep } from './types'
|
|
12
|
+
|
|
13
|
+
interface BuildTemplateCatalogEntry {
|
|
14
|
+
id: string
|
|
15
|
+
label: string
|
|
16
|
+
description?: string
|
|
17
|
+
steps: ListBuilderStep[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Template catalog — mirrors the data that lived in DEFAULT_ORGANIZATION_MODEL_PROSPECTING.buildTemplates.
|
|
21
|
+
// Wave 2 canonical OM will author these as (kind:'schema', type:'template') content nodes.
|
|
22
|
+
const BUILD_TEMPLATE_CATALOG: BuildTemplateCatalogEntry[] = [
|
|
23
|
+
{
|
|
24
|
+
id: 'local-services',
|
|
25
|
+
label: 'Local Services',
|
|
26
|
+
description: 'Source, analyze, qualify, and personalize local service businesses for outreach.',
|
|
27
|
+
steps: Object.values(PROSPECTING_STEPS.localServices)
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: 'dtc-subscription-apollo-clickup',
|
|
31
|
+
label: 'DTC Subscription (Apollo + ClickUp)',
|
|
32
|
+
description:
|
|
33
|
+
'Import DTC brand leads from Apollo, crawl their websites, score fit, enrich contacts, and export via ClickUp.',
|
|
34
|
+
steps: Object.values(PROSPECTING_STEPS.dtcApolloClickup)
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
export const DEFAULT_PROSPECTING_BUILD_TEMPLATE_ID = 'local-services'
|
|
39
|
+
|
|
40
|
+
export const PROSPECTING_BUILD_TEMPLATE_OPTIONS = BUILD_TEMPLATE_CATALOG.map(({ id, label, description }) => ({
|
|
41
|
+
id,
|
|
42
|
+
label,
|
|
43
|
+
description
|
|
44
|
+
}))
|
|
45
|
+
|
|
46
|
+
export function isProspectingBuildTemplateId(value: string): boolean {
|
|
47
|
+
return PROSPECTING_BUILD_TEMPLATE_OPTIONS.some((template) => template.id === value)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function createBuildPlanSnapshotFromTemplateId(templateId: string): BuildPlanSnapshot | null {
|
|
51
|
+
const template = BUILD_TEMPLATE_CATALOG.find((item: BuildTemplateCatalogEntry) => item.id === templateId)
|
|
52
|
+
if (!template) return null
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
templateId: template.id,
|
|
56
|
+
templateLabel: template.label,
|
|
57
|
+
steps: template.steps.map((step: ListBuilderStep): BuildPlanSnapshotStep => {
|
|
26
58
|
const snapshotStep: BuildPlanSnapshotStep = {
|
|
27
59
|
id: step.id,
|
|
28
60
|
label: step.label,
|
|
@@ -32,7 +64,7 @@ export function createBuildPlanSnapshotFromTemplateId(templateId: string): Build
|
|
|
32
64
|
recordsStageKey: step.recordsStageKey ?? step.stageKey,
|
|
33
65
|
recordSourceStageKey: step.recordSourceStageKey ?? step.recordsStageKey ?? step.stageKey,
|
|
34
66
|
dependencyMode: step.dependencyMode,
|
|
35
|
-
|
|
67
|
+
actionKey: step.actionKey,
|
|
36
68
|
defaultBatchSize: step.defaultBatchSize,
|
|
37
69
|
maxBatchSize: step.maxBatchSize
|
|
38
70
|
}
|
|
@@ -41,16 +73,26 @@ export function createBuildPlanSnapshotFromTemplateId(templateId: string): Build
|
|
|
41
73
|
if (step.recordEntity) snapshotStep.recordEntity = step.recordEntity
|
|
42
74
|
if (step.dependsOn?.length) snapshotStep.dependsOn = [...step.dependsOn]
|
|
43
75
|
if (step.credentialRequirements?.length) {
|
|
44
|
-
snapshotStep.credentialRequirements = step.credentialRequirements.map((requirement) => ({
|
|
76
|
+
snapshotStep.credentialRequirements = step.credentialRequirements.map((requirement: CredentialRequirement) => ({
|
|
77
|
+
...requirement
|
|
78
|
+
}))
|
|
45
79
|
}
|
|
46
80
|
if (step.recordColumns) {
|
|
47
81
|
snapshotStep.recordColumns = {
|
|
48
|
-
...(step.recordColumns.company
|
|
49
|
-
|
|
82
|
+
...(step.recordColumns.company
|
|
83
|
+
? {
|
|
84
|
+
company: step.recordColumns.company.map((column: RecordColumnConfig) => ({ ...column }))
|
|
85
|
+
}
|
|
86
|
+
: {}),
|
|
87
|
+
...(step.recordColumns.contact
|
|
88
|
+
? {
|
|
89
|
+
contact: step.recordColumns.contact.map((column: RecordColumnConfig) => ({ ...column }))
|
|
90
|
+
}
|
|
91
|
+
: {})
|
|
50
92
|
}
|
|
51
93
|
}
|
|
52
94
|
|
|
53
95
|
return snapshotStep
|
|
54
96
|
})
|
|
55
97
|
}
|
|
56
|
-
}
|
|
98
|
+
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
-
|
|
2
|
+
// Phase 4 (D8): DEFAULT_ORGANIZATION_MODEL_SALES no longer exported — pipeline data moved to
|
|
3
|
+
// system.content. CRM_PIPELINE_DEFINITION is retained as the Stateful pipeline shape
|
|
4
|
+
// for CRM business logic (separate from the OM content nodes).
|
|
5
|
+
import { CRM_PIPELINE_DEFINITION, LEAD_GEN_PIPELINE_DEFINITIONS } from '../../organization-model/domains/sales'
|
|
3
6
|
import { ActivityEventSchema } from './activity-events'
|
|
4
7
|
import { DealStageSchema, TransitionItemRequestSchema } from './api-schemas'
|
|
5
8
|
import { deriveActions } from './derive-actions'
|
|
@@ -106,15 +109,14 @@ describe('ActivityEventSchema', () => {
|
|
|
106
109
|
})
|
|
107
110
|
|
|
108
111
|
describe('CRM stage and transition vocabulary contracts', () => {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
expect(defaultSalesStages).toEqual([...DEAL_STAGES])
|
|
112
|
+
// Phase 4 (D8): DEFAULT_ORGANIZATION_MODEL_SALES.pipelines removed.
|
|
113
|
+
// CRM_PIPELINE_DEFINITION (StatefulPipelineDefinition) is the retained Stateful-trait
|
|
114
|
+
// pipeline shape used by CRM business logic. stageKey → DealStageSchema alignment
|
|
115
|
+
// is now verified against CRM_PIPELINE_DEFINITION.stages[*].stageKey.
|
|
116
|
+
it('keeps DealStage, DealStageSchema, and CRM_PIPELINE_DEFINITION stages aligned', () => {
|
|
117
|
+
const crmStageKeys = CRM_PIPELINE_DEFINITION.stages.map((stage) => stage.stageKey)
|
|
118
|
+
|
|
119
|
+
expect(crmStageKeys).toEqual([...DEAL_STAGES])
|
|
118
120
|
expect(DealStageSchema.options).toEqual([...DEAL_STAGES])
|
|
119
121
|
})
|
|
120
122
|
|
|
@@ -122,7 +124,7 @@ describe('CRM stage and transition vocabulary contracts', () => {
|
|
|
122
124
|
for (const stageKey of DEAL_STAGES) {
|
|
123
125
|
expect(
|
|
124
126
|
TransitionItemRequestSchema.safeParse({
|
|
125
|
-
pipelineKey:
|
|
127
|
+
pipelineKey: CRM_PIPELINE_DEFINITION.pipelineKey,
|
|
126
128
|
stageKey,
|
|
127
129
|
stateKey: null,
|
|
128
130
|
expectedUpdatedAt: '2026-04-27T12:34:56.000Z'
|
|
@@ -61,6 +61,8 @@ export {
|
|
|
61
61
|
ListStageCountsSchema,
|
|
62
62
|
ListTelemetrySchema,
|
|
63
63
|
ListIdParamsSchema,
|
|
64
|
+
ListReadQuerySchema,
|
|
65
|
+
GetListQuerySchema,
|
|
64
66
|
CreateListRequestSchema,
|
|
65
67
|
UpdateListRequestSchema,
|
|
66
68
|
UpdateListStatusRequestSchema,
|
|
@@ -70,7 +72,11 @@ export {
|
|
|
70
72
|
AddContactsToListRequestSchema,
|
|
71
73
|
RecordListExecutionRequestSchema,
|
|
72
74
|
AcqListResponseSchema,
|
|
75
|
+
AcqListDetailResponseSchema,
|
|
73
76
|
AcqListListResponseSchema,
|
|
77
|
+
AcqListDealRefSchema,
|
|
78
|
+
AcqListLineageSchema,
|
|
79
|
+
AcqListStatusResponseSchema,
|
|
74
80
|
ListTelemetryResponseSchema,
|
|
75
81
|
ListTelemetryListResponseSchema,
|
|
76
82
|
ListExecutionSummarySchema,
|
|
@@ -144,6 +150,8 @@ export {
|
|
|
144
150
|
type ListStageCountsInput,
|
|
145
151
|
type ListTelemetryInput,
|
|
146
152
|
type ListIdParams,
|
|
153
|
+
type ListReadQuery,
|
|
154
|
+
type GetListQuery,
|
|
147
155
|
type CreateListRequest,
|
|
148
156
|
type UpdateListRequest,
|
|
149
157
|
type UpdateListStatusRequest,
|
|
@@ -153,7 +161,11 @@ export {
|
|
|
153
161
|
type AddContactsToListRequest,
|
|
154
162
|
type RecordListExecutionRequest,
|
|
155
163
|
type AcqListResponse,
|
|
164
|
+
type AcqListDetailResponse,
|
|
156
165
|
type AcqListListResponse,
|
|
166
|
+
type AcqListDealRef,
|
|
167
|
+
type AcqListLineage,
|
|
168
|
+
type AcqListStatusResponse,
|
|
157
169
|
type ListTelemetryResponse,
|
|
158
170
|
type ListTelemetryListResponse,
|
|
159
171
|
type ListExecutionSummaryInput,
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { Database } from '../../supabase/database.types'
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
ActionRegistry,
|
|
4
|
+
CredentialRequirement,
|
|
5
|
+
RecordColumnConfig
|
|
6
|
+
} from '../../organization-model/domains/prospecting'
|
|
3
7
|
import type { LEAD_GEN_STAGE_CATALOG } from '../../organization-model/domains/sales'
|
|
4
8
|
import type { PipelineStage, ProcessingStageStatus } from './api-schemas'
|
|
5
9
|
|
|
@@ -52,7 +56,7 @@ export interface WebPost {
|
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
export type LeadGenStageKey = (typeof LEAD_GEN_STAGE_CATALOG)[keyof typeof LEAD_GEN_STAGE_CATALOG]['key']
|
|
55
|
-
export type
|
|
59
|
+
export type LeadGenActionKey = ActionRegistry[number]['id']
|
|
56
60
|
|
|
57
61
|
export interface ProcessingStateEntry {
|
|
58
62
|
status: ProcessingStageStatus
|
|
@@ -172,7 +176,7 @@ export interface BuildPlanSnapshotStep {
|
|
|
172
176
|
recordSourceStageKey?: string
|
|
173
177
|
dependsOn?: string[]
|
|
174
178
|
dependencyMode: BuildPlanSnapshotDependencyMode
|
|
175
|
-
|
|
179
|
+
actionKey: string
|
|
176
180
|
defaultBatchSize: number
|
|
177
181
|
maxBatchSize: number
|
|
178
182
|
recordColumns?: Partial<Record<BuildPlanSnapshotPrimaryEntity, RecordColumnConfig[]>>
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import {
|
|
3
|
+
ClientDetailResponseSchema,
|
|
4
|
+
ClientListResponseSchema,
|
|
5
|
+
ClientStatusResponseSchema,
|
|
6
|
+
ListClientsQuerySchema
|
|
7
|
+
} from './api-schemas'
|
|
8
|
+
|
|
9
|
+
const VALID_UUID = '00000000-0000-4000-8000-000000000001'
|
|
10
|
+
const ISO_TS = '2026-05-08T00:00:00.000Z'
|
|
11
|
+
|
|
12
|
+
describe('client API schemas', () => {
|
|
13
|
+
it('coerces list pagination and accepts status/search filters', () => {
|
|
14
|
+
const result = ListClientsQuerySchema.safeParse({
|
|
15
|
+
status: 'active',
|
|
16
|
+
search: 'Acme',
|
|
17
|
+
limit: '10',
|
|
18
|
+
offset: '20'
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
expect(result.success).toBe(true)
|
|
22
|
+
if (result.success) {
|
|
23
|
+
expect(result.data).toEqual({
|
|
24
|
+
status: 'active',
|
|
25
|
+
search: 'Acme',
|
|
26
|
+
limit: 10,
|
|
27
|
+
offset: 20
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('rejects unknown list query fields', () => {
|
|
33
|
+
expect(ListClientsQuerySchema.safeParse({ includeDeals: true }).success).toBe(false)
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('accepts client list responses', () => {
|
|
37
|
+
expect(
|
|
38
|
+
ClientListResponseSchema.safeParse({
|
|
39
|
+
data: [
|
|
40
|
+
{
|
|
41
|
+
id: VALID_UUID,
|
|
42
|
+
organizationId: VALID_UUID,
|
|
43
|
+
name: 'Acme',
|
|
44
|
+
status: 'active',
|
|
45
|
+
sourceDealId: null,
|
|
46
|
+
primaryCompanyId: null,
|
|
47
|
+
primaryContactId: null,
|
|
48
|
+
convertedAt: null,
|
|
49
|
+
metadata: {},
|
|
50
|
+
createdAt: ISO_TS,
|
|
51
|
+
updatedAt: ISO_TS
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
total: 1,
|
|
55
|
+
limit: 50,
|
|
56
|
+
offset: 0
|
|
57
|
+
}).success
|
|
58
|
+
).toBe(true)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('accepts client detail lineage refs', () => {
|
|
62
|
+
expect(
|
|
63
|
+
ClientDetailResponseSchema.safeParse({
|
|
64
|
+
id: VALID_UUID,
|
|
65
|
+
organizationId: VALID_UUID,
|
|
66
|
+
name: 'Acme',
|
|
67
|
+
status: 'onboarding',
|
|
68
|
+
sourceDealId: VALID_UUID,
|
|
69
|
+
primaryCompanyId: VALID_UUID,
|
|
70
|
+
primaryContactId: VALID_UUID,
|
|
71
|
+
convertedAt: ISO_TS,
|
|
72
|
+
metadata: { source: 'closed_won' },
|
|
73
|
+
createdAt: ISO_TS,
|
|
74
|
+
updatedAt: ISO_TS,
|
|
75
|
+
lineage: {
|
|
76
|
+
deals: [
|
|
77
|
+
{
|
|
78
|
+
id: VALID_UUID,
|
|
79
|
+
contactEmail: 'lead@example.com',
|
|
80
|
+
stageKey: 'closed_won',
|
|
81
|
+
stateKey: null,
|
|
82
|
+
updatedAt: ISO_TS
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
projects: [{ id: VALID_UUID, name: 'Delivery', kind: 'client_engagement', status: 'active', updatedAt: ISO_TS }],
|
|
86
|
+
companies: [{ id: VALID_UUID, name: 'Acme Co', domain: 'acme.test', status: 'active' }],
|
|
87
|
+
contacts: [
|
|
88
|
+
{
|
|
89
|
+
id: VALID_UUID,
|
|
90
|
+
email: 'lead@example.com',
|
|
91
|
+
firstName: 'Ada',
|
|
92
|
+
lastName: null,
|
|
93
|
+
title: 'CEO',
|
|
94
|
+
companyId: VALID_UUID,
|
|
95
|
+
status: 'active'
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
}).success
|
|
100
|
+
).toBe(true)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('accepts client portfolio status responses', () => {
|
|
104
|
+
expect(
|
|
105
|
+
ClientStatusResponseSchema.safeParse({
|
|
106
|
+
totalClients: 1,
|
|
107
|
+
byStatus: { active: 1, onboarding: 0, paused: 0, completed: 0, churned: 0 },
|
|
108
|
+
linkedDeals: 1,
|
|
109
|
+
linkedProjects: 1,
|
|
110
|
+
linkedCompanies: 1,
|
|
111
|
+
linkedContacts: 1
|
|
112
|
+
}).success
|
|
113
|
+
).toBe(true)
|
|
114
|
+
})
|
|
115
|
+
})
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { UuidSchema } from '../../platform/utils/validation'
|
|
3
|
+
|
|
4
|
+
export const ClientStatusSchema = z.enum(['active', 'onboarding', 'paused', 'completed', 'churned'])
|
|
5
|
+
|
|
6
|
+
export const ClientIdParamsSchema = z
|
|
7
|
+
.object({
|
|
8
|
+
clientId: UuidSchema
|
|
9
|
+
})
|
|
10
|
+
.strict()
|
|
11
|
+
|
|
12
|
+
export const ListClientsQuerySchema = z
|
|
13
|
+
.object({
|
|
14
|
+
status: ClientStatusSchema.optional(),
|
|
15
|
+
search: z.string().trim().min(1).max(255).optional(),
|
|
16
|
+
limit: z.coerce.number().int().min(1).max(100).default(50),
|
|
17
|
+
offset: z.coerce.number().int().min(0).default(0)
|
|
18
|
+
})
|
|
19
|
+
.strict()
|
|
20
|
+
|
|
21
|
+
export const ClientRefSchema = z.object({
|
|
22
|
+
id: z.string(),
|
|
23
|
+
name: z.string(),
|
|
24
|
+
status: ClientStatusSchema
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
export const ClientResponseSchema = z.object({
|
|
28
|
+
id: z.string(),
|
|
29
|
+
organizationId: z.string(),
|
|
30
|
+
name: z.string(),
|
|
31
|
+
status: ClientStatusSchema,
|
|
32
|
+
sourceDealId: z.string().nullable(),
|
|
33
|
+
primaryCompanyId: z.string().nullable(),
|
|
34
|
+
primaryContactId: z.string().nullable(),
|
|
35
|
+
convertedAt: z.string().nullable(),
|
|
36
|
+
metadata: z.record(z.string(), z.unknown()),
|
|
37
|
+
createdAt: z.string(),
|
|
38
|
+
updatedAt: z.string()
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
export const ClientDealRefSchema = z.object({
|
|
42
|
+
id: z.string(),
|
|
43
|
+
contactEmail: z.string(),
|
|
44
|
+
stageKey: z.string().nullable(),
|
|
45
|
+
stateKey: z.string().nullable(),
|
|
46
|
+
updatedAt: z.string()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
export const ClientProjectRefSchema = z.object({
|
|
50
|
+
id: z.string(),
|
|
51
|
+
name: z.string(),
|
|
52
|
+
kind: z.string(),
|
|
53
|
+
status: z.string(),
|
|
54
|
+
updatedAt: z.string()
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
export const ClientCompanyRefSchema = z.object({
|
|
58
|
+
id: z.string(),
|
|
59
|
+
name: z.string(),
|
|
60
|
+
domain: z.string().nullable(),
|
|
61
|
+
status: z.string()
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
export const ClientContactRefSchema = z.object({
|
|
65
|
+
id: z.string(),
|
|
66
|
+
email: z.string(),
|
|
67
|
+
firstName: z.string().nullable(),
|
|
68
|
+
lastName: z.string().nullable(),
|
|
69
|
+
title: z.string().nullable(),
|
|
70
|
+
companyId: z.string().nullable(),
|
|
71
|
+
status: z.string()
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
export const ClientLineageSchema = z.object({
|
|
75
|
+
deals: z.array(ClientDealRefSchema),
|
|
76
|
+
projects: z.array(ClientProjectRefSchema),
|
|
77
|
+
companies: z.array(ClientCompanyRefSchema),
|
|
78
|
+
contacts: z.array(ClientContactRefSchema)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
export const ClientDetailResponseSchema = ClientResponseSchema.extend({
|
|
82
|
+
lineage: ClientLineageSchema
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
export const ClientListResponseSchema = z.object({
|
|
86
|
+
data: z.array(ClientResponseSchema),
|
|
87
|
+
total: z.number().int().min(0),
|
|
88
|
+
limit: z.number().int().min(1),
|
|
89
|
+
offset: z.number().int().min(0)
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
export const ClientStatusResponseSchema = z.object({
|
|
93
|
+
totalClients: z.number().int().min(0),
|
|
94
|
+
byStatus: z.record(ClientStatusSchema, z.number().int().min(0)),
|
|
95
|
+
linkedDeals: z.number().int().min(0),
|
|
96
|
+
linkedProjects: z.number().int().min(0),
|
|
97
|
+
linkedCompanies: z.number().int().min(0),
|
|
98
|
+
linkedContacts: z.number().int().min(0)
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
export const CreateClientRequestSchema = z
|
|
102
|
+
.object({
|
|
103
|
+
name: z.string().trim().min(1).max(255),
|
|
104
|
+
status: ClientStatusSchema.optional(),
|
|
105
|
+
sourceDealId: UuidSchema.nullable().optional(),
|
|
106
|
+
primaryCompanyId: UuidSchema.nullable().optional(),
|
|
107
|
+
primaryContactId: UuidSchema.nullable().optional(),
|
|
108
|
+
metadata: z.record(z.string(), z.unknown()).nullable().optional()
|
|
109
|
+
})
|
|
110
|
+
.strict()
|
|
111
|
+
|
|
112
|
+
export const UpdateClientRequestSchema = z
|
|
113
|
+
.object({
|
|
114
|
+
name: z.string().trim().min(1).max(255).optional(),
|
|
115
|
+
status: ClientStatusSchema.optional(),
|
|
116
|
+
sourceDealId: UuidSchema.nullable().optional(),
|
|
117
|
+
primaryCompanyId: UuidSchema.nullable().optional(),
|
|
118
|
+
primaryContactId: UuidSchema.nullable().optional(),
|
|
119
|
+
metadata: z.record(z.string(), z.unknown()).nullable().optional()
|
|
120
|
+
})
|
|
121
|
+
.strict()
|
|
122
|
+
.refine((data) => Object.keys(data).length > 0, {
|
|
123
|
+
message: 'At least one field must be provided'
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
export const ClientSchemas = {
|
|
127
|
+
ClientStatus: ClientStatusSchema,
|
|
128
|
+
ClientIdParams: ClientIdParamsSchema,
|
|
129
|
+
ListClientsQuery: ListClientsQuerySchema,
|
|
130
|
+
ClientRef: ClientRefSchema,
|
|
131
|
+
ClientResponse: ClientResponseSchema,
|
|
132
|
+
ClientDealRef: ClientDealRefSchema,
|
|
133
|
+
ClientProjectRef: ClientProjectRefSchema,
|
|
134
|
+
ClientCompanyRef: ClientCompanyRefSchema,
|
|
135
|
+
ClientContactRef: ClientContactRefSchema,
|
|
136
|
+
ClientLineage: ClientLineageSchema,
|
|
137
|
+
ClientDetailResponse: ClientDetailResponseSchema,
|
|
138
|
+
ClientListResponse: ClientListResponseSchema,
|
|
139
|
+
ClientStatusResponse: ClientStatusResponseSchema,
|
|
140
|
+
CreateClientRequest: CreateClientRequestSchema,
|
|
141
|
+
UpdateClientRequest: UpdateClientRequestSchema
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export type ClientStatus = z.infer<typeof ClientStatusSchema>
|
|
145
|
+
export type ClientIdParams = z.infer<typeof ClientIdParamsSchema>
|
|
146
|
+
export type ListClientsQuery = z.infer<typeof ListClientsQuerySchema>
|
|
147
|
+
export type ClientRef = z.infer<typeof ClientRefSchema>
|
|
148
|
+
export type ClientResponse = z.infer<typeof ClientResponseSchema>
|
|
149
|
+
export type ClientDealRef = z.infer<typeof ClientDealRefSchema>
|
|
150
|
+
export type ClientProjectRef = z.infer<typeof ClientProjectRefSchema>
|
|
151
|
+
export type ClientCompanyRef = z.infer<typeof ClientCompanyRefSchema>
|
|
152
|
+
export type ClientContactRef = z.infer<typeof ClientContactRefSchema>
|
|
153
|
+
export type ClientLineage = z.infer<typeof ClientLineageSchema>
|
|
154
|
+
export type ClientDetailResponse = z.infer<typeof ClientDetailResponseSchema>
|
|
155
|
+
export type ClientListResponse = z.infer<typeof ClientListResponseSchema>
|
|
156
|
+
export type ClientStatusResponse = z.infer<typeof ClientStatusResponseSchema>
|
|
157
|
+
export type CreateClientRequest = z.infer<typeof CreateClientRequestSchema>
|
|
158
|
+
export type UpdateClientRequest = z.infer<typeof UpdateClientRequestSchema>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './api-schemas'
|
|
@@ -42,6 +42,10 @@ export {
|
|
|
42
42
|
DealLookupResponseSchema,
|
|
43
43
|
ConversationMessageSchema,
|
|
44
44
|
DealConversationSchema,
|
|
45
|
+
DealLineageListRefSchema,
|
|
46
|
+
DealLineageProjectRefSchema,
|
|
47
|
+
DealLineageClientRefSchema,
|
|
48
|
+
DealLineageSchema,
|
|
45
49
|
DealDetailResponseSchema,
|
|
46
50
|
DealNoteResponseSchema,
|
|
47
51
|
DealNoteListResponseSchema,
|
|
@@ -71,6 +75,10 @@ export {
|
|
|
71
75
|
type DealLookupItem,
|
|
72
76
|
type DealLookupResponse,
|
|
73
77
|
type ConversationMessage,
|
|
78
|
+
type DealLineageListRef,
|
|
79
|
+
type DealLineageProjectRef,
|
|
80
|
+
type DealLineageClientRef,
|
|
81
|
+
type DealLineage,
|
|
74
82
|
type DealDetailResponse,
|
|
75
83
|
type DealNoteResponse,
|
|
76
84
|
type DealNoteListResponse,
|
package/src/business/index.ts
CHANGED
|
@@ -5,8 +5,11 @@
|
|
|
5
5
|
* Note: PDF has its own subpath exports (./pdf, ./pdf/browser, ./pdf/server, ./pdf/sections)
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
// Acquisition types (lead database domain types)
|
|
9
|
-
export * from './acquisition/index'
|
|
8
|
+
// Acquisition types (lead database domain types)
|
|
9
|
+
export * from './acquisition/index'
|
|
10
|
+
|
|
11
|
+
// Client hub schemas
|
|
12
|
+
export * from './clients/index'
|
|
10
13
|
|
|
11
14
|
// SEO types (seo_pages, seo_metrics, chart types)
|
|
12
15
|
export * from './seo/index'
|
|
@@ -75,6 +75,24 @@ export interface ProjectDetail extends ProjectRow {
|
|
|
75
75
|
milestones: MilestoneRow[]
|
|
76
76
|
tasks: TaskRow[]
|
|
77
77
|
company: { id: string; name: string; domain: string | null } | null
|
|
78
|
+
deal: ProjectSourceDealRef | null
|
|
79
|
+
client: ProjectClientRef | null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface ProjectSourceDealRef {
|
|
83
|
+
id: string
|
|
84
|
+
clientId?: string | null
|
|
85
|
+
contactEmail: string
|
|
86
|
+
stageKey: string | null
|
|
87
|
+
stateKey: string | null
|
|
88
|
+
sourceListId: string | null
|
|
89
|
+
updatedAt: string
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface ProjectClientRef {
|
|
93
|
+
id: string
|
|
94
|
+
name: string
|
|
95
|
+
status: string
|
|
78
96
|
}
|
|
79
97
|
|
|
80
98
|
export interface MilestoneWithTasks extends MilestoneRow {
|
|
@@ -104,6 +122,7 @@ export interface Project {
|
|
|
104
122
|
status: ProjectStatus
|
|
105
123
|
description: string | null
|
|
106
124
|
dealId: string | null
|
|
125
|
+
clientId: string | null
|
|
107
126
|
clientCompanyId: string | null
|
|
108
127
|
startDate: string | null
|
|
109
128
|
targetEndDate: string | null
|
|
@@ -11,10 +11,11 @@ export function createPlatformToolAgent(): AgentDefinition {
|
|
|
11
11
|
config: {
|
|
12
12
|
resourceId: 'platform-tool-agent',
|
|
13
13
|
name: 'Platform Tool Agent',
|
|
14
|
-
description: 'Test agent with platform tools for approval workflows',
|
|
15
|
-
systemPrompt: 'You help with approvals and notifications',
|
|
16
|
-
type: 'agent',
|
|
17
|
-
|
|
14
|
+
description: 'Test agent with platform tools for approval workflows',
|
|
15
|
+
systemPrompt: 'You help with approvals and notifications',
|
|
16
|
+
type: 'agent',
|
|
17
|
+
kind: 'utility',
|
|
18
|
+
status: 'dev',
|
|
18
19
|
version: '1.0.0'
|
|
19
20
|
},
|
|
20
21
|
contract: {
|
|
@@ -68,10 +69,11 @@ export function createKnowledgeMapAgent(): AgentDefinition {
|
|
|
68
69
|
config: {
|
|
69
70
|
resourceId: 'knowledge-agent',
|
|
70
71
|
name: 'Knowledge Map Agent',
|
|
71
|
-
description: 'Test agent with knowledge map for dynamic capability loading',
|
|
72
|
-
systemPrompt: 'You can load knowledge nodes as needed',
|
|
73
|
-
type: 'agent',
|
|
74
|
-
|
|
72
|
+
description: 'Test agent with knowledge map for dynamic capability loading',
|
|
73
|
+
systemPrompt: 'You can load knowledge nodes as needed',
|
|
74
|
+
type: 'agent',
|
|
75
|
+
kind: 'utility',
|
|
76
|
+
status: 'dev',
|
|
75
77
|
version: '1.0.0'
|
|
76
78
|
},
|
|
77
79
|
contract: {
|
|
@@ -19,9 +19,10 @@ describe('Agent Execution', () => {
|
|
|
19
19
|
|
|
20
20
|
// Helper: Create minimal agent definition with mock provider
|
|
21
21
|
const createAgentDefinition = (overrides?: Partial<AgentDefinition>): AgentDefinition => {
|
|
22
|
-
const config: AgentConfig = {
|
|
23
|
-
type: 'agent',
|
|
24
|
-
|
|
22
|
+
const config: AgentConfig = {
|
|
23
|
+
type: 'agent',
|
|
24
|
+
kind: 'utility',
|
|
25
|
+
resourceId: 'test-agent',
|
|
25
26
|
name: 'Test Agent',
|
|
26
27
|
description: 'Agent for testing',
|
|
27
28
|
environment: 'dev',
|
|
@@ -165,9 +166,10 @@ describe('Agent Execution', () => {
|
|
|
165
166
|
|
|
166
167
|
it('respects maxIterations constraint', async () => {
|
|
167
168
|
const definition = createAgentDefinition({
|
|
168
|
-
config: {
|
|
169
|
-
type: 'agent',
|
|
170
|
-
|
|
169
|
+
config: {
|
|
170
|
+
type: 'agent',
|
|
171
|
+
kind: 'utility',
|
|
172
|
+
resourceId: 'test-agent',
|
|
171
173
|
name: 'Test Agent',
|
|
172
174
|
description: 'Agent for testing',
|
|
173
175
|
environment: 'dev',
|
|
@@ -418,9 +420,10 @@ describe('Agent Execution', () => {
|
|
|
418
420
|
|
|
419
421
|
it('handles maxIterations edge case (zero iterations)', async () => {
|
|
420
422
|
const definition = createAgentDefinition({
|
|
421
|
-
config: {
|
|
422
|
-
type: 'agent',
|
|
423
|
-
|
|
423
|
+
config: {
|
|
424
|
+
type: 'agent',
|
|
425
|
+
kind: 'utility',
|
|
426
|
+
resourceId: 'test-agent',
|
|
424
427
|
name: 'Test Agent',
|
|
425
428
|
description: 'Agent for testing',
|
|
426
429
|
environment: 'dev',
|
|
@@ -442,9 +445,10 @@ describe('Agent Execution', () => {
|
|
|
442
445
|
|
|
443
446
|
it('handles negative maxIterations', async () => {
|
|
444
447
|
const definition = createAgentDefinition({
|
|
445
|
-
config: {
|
|
446
|
-
type: 'agent',
|
|
447
|
-
|
|
448
|
+
config: {
|
|
449
|
+
type: 'agent',
|
|
450
|
+
kind: 'utility',
|
|
451
|
+
resourceId: 'test-agent',
|
|
448
452
|
name: 'Test Agent',
|
|
449
453
|
description: 'Agent for testing',
|
|
450
454
|
environment: 'dev',
|