@ecodrix/erix-api 1.4.3 → 1.5.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.js +8 -8
- package/dist/ts/cjs/index.cjs +1 -1
- package/dist/ts/esm/index.d.ts +2424 -8
- package/dist/ts/esm/index.js +1 -1
- package/package.json +1 -1
package/dist/ts/esm/index.d.ts
CHANGED
|
@@ -61,6 +61,1485 @@ declare class Agency extends APIResource {
|
|
|
61
61
|
createStaff<T = any>(payload: any): Promise<T>;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Adaptive Onboarding type definitions.
|
|
66
|
+
*
|
|
67
|
+
* These types mirror the Postgres data shapes from the
|
|
68
|
+
* `adaptive-onboarding-ai-persona` spec — see
|
|
69
|
+
* `.kiro/specs/adaptive-onboarding-ai-persona/design.md` §"Data Models" and
|
|
70
|
+
* §"Onboarding engine".
|
|
71
|
+
*
|
|
72
|
+
* NO RUNTIME CODE. Types only. Both saas (Next.js) and server (Express)
|
|
73
|
+
* import from here so the wire shape stays in lockstep.
|
|
74
|
+
*/
|
|
75
|
+
/**
|
|
76
|
+
* Renderable step kinds. The saas selects the appropriate React component
|
|
77
|
+
* from `components/onboarding/steps/*` based on this discriminator.
|
|
78
|
+
*/
|
|
79
|
+
type OnboardingStepType = "single_choice" | "multi_choice" | "text_input" | "ai_summary_confirm" | "feature_preview" | "completion";
|
|
80
|
+
/**
|
|
81
|
+
* One selectable answer option in a `single_choice` / `multi_choice` step.
|
|
82
|
+
*/
|
|
83
|
+
interface OnboardingOption {
|
|
84
|
+
/** Internal value persisted in `session.answers[stepId]`. */
|
|
85
|
+
value: string;
|
|
86
|
+
/** Human-readable label shown to the user. */
|
|
87
|
+
label: string;
|
|
88
|
+
/** Optional short description rendered under the label. */
|
|
89
|
+
description?: string;
|
|
90
|
+
/** Optional icon identifier (Lucide name, image URL, or emoji). */
|
|
91
|
+
icon?: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Declares which persona field a step's answer writes to.
|
|
95
|
+
*
|
|
96
|
+
* Engine flow: when the step is answered, the value is written to
|
|
97
|
+
* `session.draftPersona.<targetField>`, optionally passed through a named
|
|
98
|
+
* transformation. On `complete()` the draft persona is upserted to
|
|
99
|
+
* `ecodrix_ai_personas`.
|
|
100
|
+
*/
|
|
101
|
+
interface OnboardingMemoryMapping {
|
|
102
|
+
/**
|
|
103
|
+
* Dot-path into the persona document, e.g.
|
|
104
|
+
* `"identity.nicheSubtype"` or `"behaviorRules.outreachTone"`.
|
|
105
|
+
*/
|
|
106
|
+
targetField: string;
|
|
107
|
+
/**
|
|
108
|
+
* Optional named transformation applied to the raw answer before write.
|
|
109
|
+
* Engine-defined (`"map_to_niche_config"`, `"lowercase"`, `"split_csv"`,
|
|
110
|
+
* etc.).
|
|
111
|
+
*/
|
|
112
|
+
transformation?: string;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* A single step in an `OnboardingConfig`.
|
|
116
|
+
*
|
|
117
|
+
* Branching is via `showIf` / `skipIf` JsonLogic expressions evaluated
|
|
118
|
+
* against `session.answers`. The engine never reaches an undefined step —
|
|
119
|
+
* a missing `nextStepId` terminates the flow.
|
|
120
|
+
*/
|
|
121
|
+
interface OnboardingStep {
|
|
122
|
+
/** Stable identifier referenced by branch expressions and analytics. */
|
|
123
|
+
stepId: string;
|
|
124
|
+
/** Title rendered above the question. */
|
|
125
|
+
title: string;
|
|
126
|
+
/** Optional secondary line under the title. */
|
|
127
|
+
subtitle?: string;
|
|
128
|
+
/** Discriminator — drives which renderer the saas picks. */
|
|
129
|
+
type: OnboardingStepType;
|
|
130
|
+
/**
|
|
131
|
+
* JsonLogic expression. When present and false, the engine skips this
|
|
132
|
+
* step (does not render). Evaluated against `session.answers`.
|
|
133
|
+
*/
|
|
134
|
+
showIf?: unknown;
|
|
135
|
+
/**
|
|
136
|
+
* JsonLogic expression. When present and true, the engine skips this
|
|
137
|
+
* step. Evaluated alongside / after `showIf`.
|
|
138
|
+
*/
|
|
139
|
+
skipIf?: unknown;
|
|
140
|
+
/** The actual question text shown to the user. */
|
|
141
|
+
question: string;
|
|
142
|
+
/** Optional helper / "Why we ask" tooltip text (REQ-018). */
|
|
143
|
+
helperText?: string;
|
|
144
|
+
/** Selectable options for `single_choice` / `multi_choice` types. */
|
|
145
|
+
options?: OnboardingOption[];
|
|
146
|
+
/** Where the answer lands in the persona draft. */
|
|
147
|
+
memoryMapping: OnboardingMemoryMapping;
|
|
148
|
+
/**
|
|
149
|
+
* Workspace module keys that this step's completion makes visible
|
|
150
|
+
* (drives `WorkspaceProfile.modules.<key>.locked = false`).
|
|
151
|
+
*/
|
|
152
|
+
unlocks?: string[];
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* A versioned onboarding flow for one product. Stored as a row in
|
|
156
|
+
* `ecodrix_onboarding_configs` and as `niche_pack.onboarding_config`.
|
|
157
|
+
*/
|
|
158
|
+
interface OnboardingConfig {
|
|
159
|
+
/** `"crm" | "laie" | "flow"` (string for forward-compat). */
|
|
160
|
+
productId: string;
|
|
161
|
+
/** Monotonic version string, e.g. `"crm-v1"`, `"crm-v2"`. */
|
|
162
|
+
version: string;
|
|
163
|
+
/** Ordered list of steps; engine walks these honoring branch logic. */
|
|
164
|
+
steps: OnboardingStep[];
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Lifecycle status of an onboarding session row.
|
|
168
|
+
*/
|
|
169
|
+
type OnboardingSessionStatus = "active" | "completed" | "abandoned" | "archived";
|
|
170
|
+
/**
|
|
171
|
+
* Persisted onboarding session — one per `(userId, productId)` until
|
|
172
|
+
* completed or abandoned. ISO strings for timestamps so the shape is
|
|
173
|
+
* JSON-safe over the wire.
|
|
174
|
+
*/
|
|
175
|
+
interface OnboardingSession {
|
|
176
|
+
id: string;
|
|
177
|
+
orgId: string;
|
|
178
|
+
userId: string;
|
|
179
|
+
productId: string;
|
|
180
|
+
/** `<top_level>__<leaf>` slug, e.g. `"healthcare__clinic"`. May be null
|
|
181
|
+
* before the niche pick step. */
|
|
182
|
+
nichePackSlug: string | null;
|
|
183
|
+
/** Version of the `OnboardingConfig` driving this session. */
|
|
184
|
+
configVersion: string;
|
|
185
|
+
/** ID of the step the user is currently on, or null when finished. */
|
|
186
|
+
currentStepId: string | null;
|
|
187
|
+
/** `{ [stepId]: answerValue }` map persisted on every PATCH. */
|
|
188
|
+
answers: Record<string, unknown>;
|
|
189
|
+
/** Persona-shaped draft built incrementally from `answers` via memoryMapping. */
|
|
190
|
+
draftPersona: Record<string, unknown>;
|
|
191
|
+
status: OnboardingSessionStatus;
|
|
192
|
+
/** Optional A/B cohort, e.g. `"A"` / `"B"`. */
|
|
193
|
+
cohort: string | null;
|
|
194
|
+
/**
|
|
195
|
+
* Slug of the running experiment that drove the session's config
|
|
196
|
+
* resolution at start-time, or `null` when no experiment was active.
|
|
197
|
+
* Stamped by `POST /:productId/start` from the engine's
|
|
198
|
+
* `resolveSessionConfig` result so analytics can correlate sessions
|
|
199
|
+
* to experiments without re-resolving the cohort routing.
|
|
200
|
+
*/
|
|
201
|
+
experimentSlug?: string | null;
|
|
202
|
+
/**
|
|
203
|
+
* `OnboardingConfig` version the session was rendered against — the
|
|
204
|
+
* concrete version chosen by the variant resolver (when an
|
|
205
|
+
* experiment ran) or the latest-published path. May differ from
|
|
206
|
+
* `configVersion` when the resolver picked a variant that maps to a
|
|
207
|
+
* different version than the latest published config.
|
|
208
|
+
*/
|
|
209
|
+
variantConfigVersion?: string | null;
|
|
210
|
+
startedAt: string;
|
|
211
|
+
completedAt: string | null;
|
|
212
|
+
lastActiveAt: string;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Visibility + cosmetic configuration for one sidebar/workspace module.
|
|
216
|
+
*/
|
|
217
|
+
interface WorkspaceModuleConfig {
|
|
218
|
+
/** Whether the module renders at all in the sidebar. */
|
|
219
|
+
enabled: boolean;
|
|
220
|
+
/** Niche-tuned label, e.g. `"Patients"` instead of `"Contacts"`. */
|
|
221
|
+
label: string;
|
|
222
|
+
/** When true, module renders with a lock icon + tooltip. */
|
|
223
|
+
locked: boolean;
|
|
224
|
+
/** Sort order within the sidebar (ascending). */
|
|
225
|
+
sortOrder: number;
|
|
226
|
+
/**
|
|
227
|
+
* Optional gate name; the saas calls a Server Action that returns
|
|
228
|
+
* whether the gate currently passes given persona state.
|
|
229
|
+
*/
|
|
230
|
+
onboardingGate?: string;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Default pipeline produced by the workspace shaper. Mirrors the existing
|
|
234
|
+
* `erix_pipelines` / `erix_pipeline_stages` rows that are materialized.
|
|
235
|
+
*/
|
|
236
|
+
interface WorkspaceDefaultPipeline {
|
|
237
|
+
name: string;
|
|
238
|
+
isDefault?: boolean;
|
|
239
|
+
stages: Array<{
|
|
240
|
+
name: string;
|
|
241
|
+
color?: string;
|
|
242
|
+
probability?: number;
|
|
243
|
+
isWon?: boolean;
|
|
244
|
+
isLost?: boolean;
|
|
245
|
+
order: number;
|
|
246
|
+
}>;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Default custom-field definition produced by the workspace shaper.
|
|
250
|
+
* Mirrors `erix_custom_fields` rows.
|
|
251
|
+
*/
|
|
252
|
+
interface WorkspaceDefaultField {
|
|
253
|
+
key: string;
|
|
254
|
+
label: string;
|
|
255
|
+
type: string;
|
|
256
|
+
required?: boolean;
|
|
257
|
+
options?: string[] | Array<{
|
|
258
|
+
label: string;
|
|
259
|
+
value: string;
|
|
260
|
+
}>;
|
|
261
|
+
group?: string;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Default automation produced by the workspace shaper. Mirrors
|
|
265
|
+
* `erix_automation_rules` rows.
|
|
266
|
+
*/
|
|
267
|
+
interface WorkspaceDefaultAutomation {
|
|
268
|
+
name: string;
|
|
269
|
+
trigger: string;
|
|
270
|
+
/** Free-form condition payload understood by the automation engine. */
|
|
271
|
+
conditions?: Record<string, unknown>;
|
|
272
|
+
/** Ordered list of action descriptors. */
|
|
273
|
+
actions: Array<Record<string, unknown>>;
|
|
274
|
+
enabled?: boolean;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Default dashboard layout — opaque grid descriptor consumed by the
|
|
278
|
+
* dashboard renderer.
|
|
279
|
+
*/
|
|
280
|
+
interface WorkspaceDashboardLayout {
|
|
281
|
+
widgets: Array<Record<string, unknown>>;
|
|
282
|
+
[extra: string]: unknown;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* The full per-product workspace shape produced by
|
|
286
|
+
* `workspaceShaper.produce(persona, nichePack)` and persisted at
|
|
287
|
+
* `ecodrix_organizations.service_config -> '<productId>' -> 'workspace'`.
|
|
288
|
+
*/
|
|
289
|
+
interface WorkspaceProfile {
|
|
290
|
+
workspaceId: string;
|
|
291
|
+
productId: string;
|
|
292
|
+
/** Niche slug this profile was shaped for, e.g. `"agency__digital_marketing"`. */
|
|
293
|
+
niche: string;
|
|
294
|
+
modules: Record<string, WorkspaceModuleConfig>;
|
|
295
|
+
defaultPipelines: WorkspaceDefaultPipeline[];
|
|
296
|
+
defaultFields: WorkspaceDefaultField[];
|
|
297
|
+
defaultAutomations: WorkspaceDefaultAutomation[];
|
|
298
|
+
defaultDashboardLayout: WorkspaceDashboardLayout;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Org-wide onboarding flags under `service_config.global`.
|
|
302
|
+
*/
|
|
303
|
+
interface ServiceConfigGlobal {
|
|
304
|
+
/** Product the user picked at signup. */
|
|
305
|
+
primaryProduct: "crm" | "laie" | "flow" | "not_sure";
|
|
306
|
+
/** Feature flag — when false, legacy 4-step wizard is used. */
|
|
307
|
+
useAdaptiveOnboarding: boolean;
|
|
308
|
+
/**
|
|
309
|
+
* A/B-test cohort assigned by `ensureOnboardingCohort` — a stable
|
|
310
|
+
* deterministic bucket in `[0, 99]` derived from `hash(userId)`.
|
|
311
|
+
* Once written, it is never reassigned.
|
|
312
|
+
*/
|
|
313
|
+
onboardingCohort?: number;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Per-product onboarding state under `service_config.<productId>`.
|
|
317
|
+
*
|
|
318
|
+
* Drives the dashboard CTA logic (REQ-002):
|
|
319
|
+
* `onboardingComplete=true && enabledAt!=null` → "Open {Product}"
|
|
320
|
+
* `enabledAt!=null && onboardingComplete=false` → "Open {Product}" + banner
|
|
321
|
+
* `enabledAt==null` → "Enable {Product}"
|
|
322
|
+
*/
|
|
323
|
+
interface ServiceConfigPerProduct {
|
|
324
|
+
onboardingComplete: boolean;
|
|
325
|
+
/** Last persisted step the user was on (for resumability). */
|
|
326
|
+
onboardingStep?: number | string;
|
|
327
|
+
/** Version of the `OnboardingConfig` that produced the persona. */
|
|
328
|
+
onboardingVersion?: string;
|
|
329
|
+
/** Niche slug, e.g. `"healthcare__clinic"`. */
|
|
330
|
+
niche?: string;
|
|
331
|
+
/** Mirrored from `ecodrix_ai_personas.confidence_score`. */
|
|
332
|
+
personaConfidence?: number;
|
|
333
|
+
/** Opt-in for confidence ≥ 70 auto-pilot features. */
|
|
334
|
+
autoPilotEnabled?: boolean;
|
|
335
|
+
/** ISO timestamp the user clicked "Enable {Product}" (REQ-002). */
|
|
336
|
+
enabledAt?: string;
|
|
337
|
+
/** Materialized workspace shape from the shaper. */
|
|
338
|
+
workspace?: WorkspaceProfile;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Full org-level `service_config` JSONB shape.
|
|
342
|
+
*
|
|
343
|
+
* The shape is open (it lives in JSONB), but every consumer should treat
|
|
344
|
+
* it as if it conforms to this interface and prefer named keys over
|
|
345
|
+
* arbitrary top-level extensions.
|
|
346
|
+
*/
|
|
347
|
+
interface ServiceConfig {
|
|
348
|
+
global: ServiceConfigGlobal;
|
|
349
|
+
crm?: ServiceConfigPerProduct;
|
|
350
|
+
laie?: ServiceConfigPerProduct;
|
|
351
|
+
flow?: ServiceConfigPerProduct;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Status lifecycle for a niche pack version. Only `published` rows are
|
|
355
|
+
* served by the runtime engine; `draft` is admin-authoring only and
|
|
356
|
+
* `archived` keeps history accessible to already-bootstrapped personas.
|
|
357
|
+
*/
|
|
358
|
+
type NichePackStatus = "draft" | "published" | "archived";
|
|
359
|
+
/**
|
|
360
|
+
* Loose shape of `researchConfig` — the LAIE-side blob that drives lead
|
|
361
|
+
* validation, outreach style, and (now, task 3.1.5) reinforcement
|
|
362
|
+
* signal enrichment.
|
|
363
|
+
*
|
|
364
|
+
* The shape stays open (`[extra: string]: unknown`) because seeded
|
|
365
|
+
* packs and admin-edited packs can carry additional product-specific
|
|
366
|
+
* fields the platform doesn't model strictly.
|
|
367
|
+
*
|
|
368
|
+
* Two naming conventions are supported for the same arrays:
|
|
369
|
+
*
|
|
370
|
+
* - `validation` / `disqualification` — the literal
|
|
371
|
+
* shape the seeded LAIE niche packs ship today.
|
|
372
|
+
* - `validationSignals` / `disqualificationSignals` — the spec's
|
|
373
|
+
* forward-looking name (used by the persona derivation layer).
|
|
374
|
+
*
|
|
375
|
+
* Consumers should accept either, prefer the explicit `*Signals` form
|
|
376
|
+
* when both are present, and fall back to the legacy short name.
|
|
377
|
+
*/
|
|
378
|
+
interface NichePackResearchConfig {
|
|
379
|
+
validation?: string[];
|
|
380
|
+
disqualification?: string[];
|
|
381
|
+
validationSignals?: string[];
|
|
382
|
+
disqualificationSignals?: string[];
|
|
383
|
+
/**
|
|
384
|
+
* Per-niche follow-up question templates the persona self-review
|
|
385
|
+
* Loop 1 (REQ-016, confidence-gap detection) fires when a given
|
|
386
|
+
* persona subfield is judged the weakest signal.
|
|
387
|
+
*
|
|
388
|
+
* Keys are persona dot-paths (e.g. `"icp.industryTargets"`,
|
|
389
|
+
* `"behaviorRules.outreachTone"`); values are free-form question
|
|
390
|
+
* strings. The placeholder `{niche}` is interpolated with
|
|
391
|
+
* `persona.identity.nicheSubtype` at fire time (falls back to
|
|
392
|
+
* `"your niche"` when the persona has no niche set).
|
|
393
|
+
*
|
|
394
|
+
* When a key is missing the loop falls back to the platform-wide
|
|
395
|
+
* default in `defaultFollowupTemplate(targetField)`.
|
|
396
|
+
*/
|
|
397
|
+
followupTemplates?: Record<string, string>;
|
|
398
|
+
[extra: string]: unknown;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Lifecycle status for an `OnboardingExperiment`. Only `running`
|
|
402
|
+
* experiments influence the runtime engine's variant routing
|
|
403
|
+
* (task 4.2.3) — `paused` keeps the row visible without affecting
|
|
404
|
+
* cohort assignment, and `completed` is a terminal state.
|
|
405
|
+
*/
|
|
406
|
+
type OnboardingExperimentStatus = "draft" | "running" | "paused" | "completed";
|
|
407
|
+
/**
|
|
408
|
+
* Half-open cohort bucket range. `from` is INCLUSIVE, `to` is
|
|
409
|
+
* EXCLUSIVE. Both endpoints must satisfy `0 <= from < to <= 100` and
|
|
410
|
+
* align with the bucket assignment in
|
|
411
|
+
* `service_config.global.onboardingCohort` (a stable integer in
|
|
412
|
+
* `[0, 99]`).
|
|
413
|
+
*/
|
|
414
|
+
interface OnboardingCohortRange {
|
|
415
|
+
/** Inclusive lower bound. */
|
|
416
|
+
from: number;
|
|
417
|
+
/** Exclusive upper bound. */
|
|
418
|
+
to: number;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* One variant in an `OnboardingExperiment`.
|
|
422
|
+
*
|
|
423
|
+
* Variant ranges may not overlap (the admin-side validator rejects
|
|
424
|
+
* such payloads); when a user's cohort falls in a gap (or no variant
|
|
425
|
+
* is defined), the engine serves `controlConfigVersion` instead.
|
|
426
|
+
*/
|
|
427
|
+
interface OnboardingExperimentVariant {
|
|
428
|
+
/** Cohort range claimed by this variant — see `OnboardingCohortRange`. */
|
|
429
|
+
cohortRange: OnboardingCohortRange;
|
|
430
|
+
/**
|
|
431
|
+
* Versioned `OnboardingConfig` slug, e.g. `"crm@1.0.0"` or any
|
|
432
|
+
* value the engine's config loader resolves.
|
|
433
|
+
*/
|
|
434
|
+
configVersion: string;
|
|
435
|
+
/** Optional sampling weight for analytics; defaults to 1. */
|
|
436
|
+
weight?: number;
|
|
437
|
+
/** Optional human-readable label, e.g. `"treatment"`. */
|
|
438
|
+
label?: string;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Full experiment row. Mirrors the Postgres
|
|
442
|
+
* `ecodrix_onboarding_experiments` table (see
|
|
443
|
+
* `server/src/shared/db/schema/platform/onboarding-experiments.ts`).
|
|
444
|
+
*/
|
|
445
|
+
interface OnboardingExperiment {
|
|
446
|
+
/** UUID primary key — opaque to SDK callers. */
|
|
447
|
+
id: string;
|
|
448
|
+
/** Admin-facing handle, unique platform-wide. */
|
|
449
|
+
slug: string;
|
|
450
|
+
/** Product family this experiment targets. */
|
|
451
|
+
productId: "crm" | "laie" | "flow" | string;
|
|
452
|
+
/** Display name for admin surfaces. */
|
|
453
|
+
name: string;
|
|
454
|
+
/** Optional long-form description. */
|
|
455
|
+
description?: string | null;
|
|
456
|
+
status: OnboardingExperimentStatus;
|
|
457
|
+
/** Cohort routing table — empty array for fresh drafts. */
|
|
458
|
+
variants: OnboardingExperimentVariant[];
|
|
459
|
+
/**
|
|
460
|
+
* Fallback config version served when no variant matches. Null
|
|
461
|
+
* defers to the product's latest published `OnboardingConfig` row.
|
|
462
|
+
*/
|
|
463
|
+
controlConfigVersion?: string | null;
|
|
464
|
+
/** ISO 8601 timestamps — server clock. */
|
|
465
|
+
createdAt: string;
|
|
466
|
+
updatedAt: string;
|
|
467
|
+
startedAt?: string | null;
|
|
468
|
+
endedAt?: string | null;
|
|
469
|
+
/** Admin staff id (UUID) of the authoring user, when known. */
|
|
470
|
+
createdBy?: string | null;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Versioned bundle of `OnboardingConfig` + `WorkspaceProfile` +
|
|
474
|
+
* `ResearchConfig` for a single niche slug. One row per `(slug,
|
|
475
|
+
* version)` in `ecodrix_niche_packs`.
|
|
476
|
+
*
|
|
477
|
+
* Niche packs are PLATFORM-WIDE reference data — they are NOT
|
|
478
|
+
* tenant-scoped. Per-tenant assignment lives at
|
|
479
|
+
* `ecodrix_organizations.service_config -> '<productId>' -> 'niche'`.
|
|
480
|
+
*/
|
|
481
|
+
interface NichePack {
|
|
482
|
+
/** Niche slug, e.g. `"healthcare__clinic"`, `"designer__ui_ux"`. */
|
|
483
|
+
slug: string;
|
|
484
|
+
/** Product family this pack targets. */
|
|
485
|
+
productId: "crm" | "laie" | "flow" | string;
|
|
486
|
+
/** Semantic version, e.g. `"1.0.0"`. */
|
|
487
|
+
version: string;
|
|
488
|
+
/** Lifecycle status. Only `"published"` is served at runtime. */
|
|
489
|
+
status: NichePackStatus;
|
|
490
|
+
/** Optional — full branching onboarding flow. */
|
|
491
|
+
onboardingConfig?: OnboardingConfig;
|
|
492
|
+
/** Optional — default workspace shape. */
|
|
493
|
+
workspaceProfile?: WorkspaceProfile;
|
|
494
|
+
/** Optional — research / validation config (LAIE only today). */
|
|
495
|
+
researchConfig?: NichePackResearchConfig;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Identity block — who the user is, what they sell, where they operate.
|
|
500
|
+
* Stored at `ecodrix_ai_personas.identity` (JSONB).
|
|
501
|
+
*/
|
|
502
|
+
interface PersonaIdentity {
|
|
503
|
+
/** Top-level taxonomy slug, e.g. `"designer"`, `"healthcare"`. */
|
|
504
|
+
niche?: string;
|
|
505
|
+
/** Leaf slug, e.g. `"designer__ui_ux"`. Partition key for niche packs. */
|
|
506
|
+
nicheSubtype?: string;
|
|
507
|
+
/** Free-form business model descriptor, e.g. `"freelancer"`, `"agency"`. */
|
|
508
|
+
businessModel?: string;
|
|
509
|
+
/** `"solo" | "2-5" | "6-20" | "20+"` (string for forward-compat). */
|
|
510
|
+
teamSize?: string;
|
|
511
|
+
/** Revenue stage, e.g. `"pre-revenue"`, `"<10k_mrr"`, `">100k_mrr"`. */
|
|
512
|
+
revenueStage?: string;
|
|
513
|
+
/** Geographies the user serves, ISO-2 country codes or freeform region names. */
|
|
514
|
+
geographyFocus?: string[];
|
|
515
|
+
/** Preferred operating language(s). */
|
|
516
|
+
languages?: string[];
|
|
517
|
+
[extra: string]: unknown;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Behavior rules — how the AI should act on the user's behalf.
|
|
521
|
+
* Stored at `ecodrix_ai_personas.behavior_rules` (JSONB).
|
|
522
|
+
*/
|
|
523
|
+
interface BehaviorRules {
|
|
524
|
+
/** Tone, e.g. `"warm"`, `"direct"`, `"playful"`. */
|
|
525
|
+
outreachTone?: string;
|
|
526
|
+
/** Style, e.g. `"audit_first"`, `"value_first"`, `"roi_data_first"`. */
|
|
527
|
+
outreachStyle?: string;
|
|
528
|
+
/** Cadence preset name or descriptor. */
|
|
529
|
+
outreachCadence?: string;
|
|
530
|
+
/** Hard rules — strings/phrases the AI must never use. */
|
|
531
|
+
avoidPatterns?: string[];
|
|
532
|
+
/** Signals that should immediately validate a lead. */
|
|
533
|
+
validationSignals?: string[];
|
|
534
|
+
/** Signals that should immediately disqualify a lead. */
|
|
535
|
+
disqualificationSignals?: string[];
|
|
536
|
+
/**
|
|
537
|
+
* Auto-derived rules from the pattern-generalisation loop (REQ-016 §3),
|
|
538
|
+
* each carrying a `confidence` weight.
|
|
539
|
+
*/
|
|
540
|
+
derivedRules?: Array<{
|
|
541
|
+
expression: string;
|
|
542
|
+
confidence: number;
|
|
543
|
+
derivedAt?: string;
|
|
544
|
+
}>;
|
|
545
|
+
/**
|
|
546
|
+
* Bookkeeping for the pattern-generalisation loop (REQ-016 §3,
|
|
547
|
+
* Task 3.5.3.1). The worker uses `lastClusterAt` to short-circuit
|
|
548
|
+
* Loop 3 until the persona's `totalReinforcement` crosses a new
|
|
549
|
+
* 50-event boundary since the previous derived-rule write.
|
|
550
|
+
*/
|
|
551
|
+
derivedRulesMeta?: {
|
|
552
|
+
/** `learningMemory.totalReinforcement` at the time of the last
|
|
553
|
+
* derived-rule write. */
|
|
554
|
+
lastClusterAt?: number;
|
|
555
|
+
};
|
|
556
|
+
[extra: string]: unknown;
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Vocabulary — phrases the AI should reuse for resonance.
|
|
560
|
+
* Stored at `ecodrix_ai_personas.vocabulary` (JSONB).
|
|
561
|
+
*/
|
|
562
|
+
interface Vocabulary {
|
|
563
|
+
clientPainPoints?: string[];
|
|
564
|
+
serviceValueProps?: string[];
|
|
565
|
+
proofStatements?: string[];
|
|
566
|
+
signaturePhrases?: string[];
|
|
567
|
+
[extra: string]: unknown;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Ideal Customer Profile. Stored at `ecodrix_ai_personas.icp` (JSONB).
|
|
571
|
+
*/
|
|
572
|
+
interface ICP {
|
|
573
|
+
industryTargets?: string[];
|
|
574
|
+
decisionMakerRole?: string[];
|
|
575
|
+
budgetRange?: {
|
|
576
|
+
min?: number;
|
|
577
|
+
max?: number;
|
|
578
|
+
currency?: string;
|
|
579
|
+
};
|
|
580
|
+
geographyTargets?: string[];
|
|
581
|
+
techStack?: string[];
|
|
582
|
+
fundingStages?: string[];
|
|
583
|
+
companySize?: string[];
|
|
584
|
+
[extra: string]: unknown;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* One observed lead pattern — recorded on approve / reject so the
|
|
588
|
+
* confidence and pattern-generalisation loops can converge over time.
|
|
589
|
+
*/
|
|
590
|
+
interface LeadPattern {
|
|
591
|
+
/** UUID of the originating reinforcement event (for idempotency). */
|
|
592
|
+
eventId: string;
|
|
593
|
+
/** Signal name, e.g. `"funding_stage"`, `"company_size"`. */
|
|
594
|
+
signal: string;
|
|
595
|
+
/** Observed value, e.g. `"series_a"`, `"1-10"`. */
|
|
596
|
+
value: string;
|
|
597
|
+
/** Soft weight in [0, 1]; older patterns decay. */
|
|
598
|
+
weight: number;
|
|
599
|
+
createdAt: string;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* One captured edit of an AI-generated outreach message — feeds the
|
|
603
|
+
* outreach-style-drift detection loop (REQ-016 §4).
|
|
604
|
+
*/
|
|
605
|
+
interface OutreachEdit {
|
|
606
|
+
eventId: string;
|
|
607
|
+
outreachId: string;
|
|
608
|
+
/** RFC 6902 JSON Patch describing the user's edit. */
|
|
609
|
+
diff: Array<Record<string, unknown>>;
|
|
610
|
+
/** Optional categorisation supplied by the user. */
|
|
611
|
+
reason?: string;
|
|
612
|
+
createdAt: string;
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* One user-issued correction of an AI assumption (REQ-007). Surfaced via
|
|
616
|
+
* the inline "Not quite" buttons on persona-displayed assumptions.
|
|
617
|
+
*/
|
|
618
|
+
interface Correction {
|
|
619
|
+
eventId: string;
|
|
620
|
+
/** Dot-path to the corrected persona field, e.g. `"icp.industryTargets"`. */
|
|
621
|
+
field: string;
|
|
622
|
+
oldValue: unknown;
|
|
623
|
+
newValue: unknown;
|
|
624
|
+
createdAt: string;
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* One captured user-action against an AI suggestion surface — the
|
|
628
|
+
* granular audit trail that powers REQ-007 reinforcement learning AND
|
|
629
|
+
* REQ-012 audit-grade memory for every accept / reject the user
|
|
630
|
+
* issues at any AI suggestion site (CRM follow-up, LAIE outreach
|
|
631
|
+
* accept/regenerate, lead-score narrative thumbs, dashboard
|
|
632
|
+
* next-action, …).
|
|
633
|
+
*
|
|
634
|
+
* Stored as `learningMemory.acceptedSuggestionEvents[]` /
|
|
635
|
+
* `learningMemory.rejectedSuggestionEvents[]` (Task 3.1.4). The
|
|
636
|
+
* counters `acceptedSuggestions` / `rejectedSuggestions` continue to
|
|
637
|
+
* carry the cumulative totals so existing confidence math stays
|
|
638
|
+
* untouched; the per-event arrays are the new audit log.
|
|
639
|
+
*/
|
|
640
|
+
interface SuggestionEvent {
|
|
641
|
+
/** Idempotency key — the worker dedupes on this. */
|
|
642
|
+
eventId: string;
|
|
643
|
+
/** Stable id of the suggestion the user acted on. */
|
|
644
|
+
suggestionId: string;
|
|
645
|
+
/**
|
|
646
|
+
* Suggestion taxonomy slug, e.g. `"follow_up_message"`,
|
|
647
|
+
* `"lead_score_narrative"`, `"outreach_subject"`, `"next_action"`,
|
|
648
|
+
* `"inbox_reply"`. Used by the pattern-generalisation loop to bucket
|
|
649
|
+
* accept/reject ratios per suggestion type.
|
|
650
|
+
*/
|
|
651
|
+
suggestionType: string;
|
|
652
|
+
/**
|
|
653
|
+
* UI surface the user acted from, e.g. `"crm.deal.followup"`,
|
|
654
|
+
* `"saas.inbox.reply"`, `"laie.lead.score"`. Free-form but
|
|
655
|
+
* conventionally a dot-path under `<product>.<area>.<surface>`.
|
|
656
|
+
*/
|
|
657
|
+
surface: string;
|
|
658
|
+
/**
|
|
659
|
+
* Surface-specific extra context (`dealId`, `leadId`, `conversationId`,
|
|
660
|
+
* etc) so the audit trail can correlate the action back to the
|
|
661
|
+
* originating row without bloating the top-level shape. Optional.
|
|
662
|
+
*/
|
|
663
|
+
productContext?: Record<string, unknown>;
|
|
664
|
+
/** Optional rejection reason (`rejected` arrays only). */
|
|
665
|
+
rejectionReason?: string;
|
|
666
|
+
createdAt: string;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* One captured `ai_outreach_sent` event — a row recorded every time
|
|
670
|
+
* an AI-generated outreach actually goes out. Pairs with
|
|
671
|
+
* {@link OutreachEdit} as the denominator side of the rolling
|
|
672
|
+
* edit-ratio that drives REQ-016 §4 (outreach style drift).
|
|
673
|
+
*
|
|
674
|
+
* Stored at `learningMemory.aiOutreachSent[]`. The writer caps the
|
|
675
|
+
* array at 500 entries (oldest rolled off) — same blast-radius
|
|
676
|
+
* pattern as `outreachEditHistory` to keep the JSONB blob bounded.
|
|
677
|
+
*/
|
|
678
|
+
interface OutreachSent {
|
|
679
|
+
/** ISO 8601. The detector's window predicate runs on this. */
|
|
680
|
+
createdAt: string;
|
|
681
|
+
/** Optional id of the outreach row this corresponds to. */
|
|
682
|
+
outreachId?: string;
|
|
683
|
+
/**
|
|
684
|
+
* Originating product. Optional — recorded for telemetry / future
|
|
685
|
+
* per-product drift breakdowns. Free-form so non-`crm | laie | flow`
|
|
686
|
+
* surfaces can also log here without a discriminated-union update.
|
|
687
|
+
*/
|
|
688
|
+
productId?: string;
|
|
689
|
+
/** Optional channel descriptor, e.g. `"email"`, `"linkedin"`. */
|
|
690
|
+
channel?: string;
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Learning memory — append-only signals derived from reinforcement
|
|
694
|
+
* events. Trimmed by the workers; rotated to history on overflow.
|
|
695
|
+
*
|
|
696
|
+
* Stored at `ecodrix_ai_personas.learning_memory` (JSONB).
|
|
697
|
+
*/
|
|
698
|
+
interface LearningMemory {
|
|
699
|
+
approvedLeadPatterns: LeadPattern[];
|
|
700
|
+
rejectedLeadPatterns: LeadPattern[];
|
|
701
|
+
wonDealSignals: LeadPattern[];
|
|
702
|
+
lostDealSignals: LeadPattern[];
|
|
703
|
+
outreachEditHistory: OutreachEdit[];
|
|
704
|
+
corrections: Correction[];
|
|
705
|
+
/**
|
|
706
|
+
* Audit log of every `ai_suggestion_accepted` event applied to this
|
|
707
|
+
* persona. Counters below carry the rolling totals; this array is
|
|
708
|
+
* the per-event trail required by REQ-012. Trimmed by the worker
|
|
709
|
+
* when growth becomes a token-budget concern.
|
|
710
|
+
*/
|
|
711
|
+
acceptedSuggestionEvents: SuggestionEvent[];
|
|
712
|
+
/** Audit log of every `ai_suggestion_rejected` event. See above. */
|
|
713
|
+
rejectedSuggestionEvents: SuggestionEvent[];
|
|
714
|
+
/** Cumulative count, used by the confidence math (REQ-008). */
|
|
715
|
+
acceptedSuggestions: number;
|
|
716
|
+
/** Cumulative count, used by the confidence math (REQ-008). */
|
|
717
|
+
rejectedSuggestions: number;
|
|
718
|
+
/** Sum of all reinforcement events ever applied to this persona. */
|
|
719
|
+
totalReinforcement: number;
|
|
720
|
+
/**
|
|
721
|
+
* Append-only log of AI-generated outreach that was actually sent.
|
|
722
|
+
* Powers the denominator of the 7-day rolling edit-ratio (REQ-016
|
|
723
|
+
* §4 / Task 3.5.4.1). Optional because pre-Loop 4 personas don't
|
|
724
|
+
* carry the field; the writer initialises it to `[]` on every new
|
|
725
|
+
* row written after Phase 3.5. Capped at 500 entries by the writer
|
|
726
|
+
* (oldest rolled off) — same pattern as `outreachEditHistory`.
|
|
727
|
+
*/
|
|
728
|
+
aiOutreachSent?: OutreachSent[];
|
|
729
|
+
/**
|
|
730
|
+
* Cooldown gate for the outreach style drift loop (REQ-016 §4 /
|
|
731
|
+
* Task 3.5.4.2). When the worker emits a `style_drift` warning it
|
|
732
|
+
* stamps this field; subsequent loop runs skip the persona until
|
|
733
|
+
* the configured cooldown elapses (default 7 days). Absent on
|
|
734
|
+
* personas that have never tripped a drift warning.
|
|
735
|
+
*/
|
|
736
|
+
lastStyleDriftWarningAt?: string;
|
|
737
|
+
[extra: string]: unknown;
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Full AI persona — one row per `(userId, orgId, productId)` in
|
|
741
|
+
* `ecodrix_ai_personas`. Returned by `GET /api/persona/:productId`.
|
|
742
|
+
*/
|
|
743
|
+
interface AIPersona {
|
|
744
|
+
id: string;
|
|
745
|
+
orgId: string;
|
|
746
|
+
userId: string;
|
|
747
|
+
productId: "crm" | "laie" | "flow";
|
|
748
|
+
identity: PersonaIdentity;
|
|
749
|
+
behaviorRules: BehaviorRules;
|
|
750
|
+
vocabulary: Vocabulary;
|
|
751
|
+
icp: ICP;
|
|
752
|
+
learningMemory: LearningMemory;
|
|
753
|
+
/** Version string of the `OnboardingConfig` that bootstrapped this row. */
|
|
754
|
+
onboardingVersion: string | null;
|
|
755
|
+
onboardingCompletedAt: string | null;
|
|
756
|
+
lastReinforced: string | null;
|
|
757
|
+
/** Monotonically increasing per persona; bumped on every write. */
|
|
758
|
+
memoryVersion: number;
|
|
759
|
+
/** True only after onboarding completes; false on the generic baseline. */
|
|
760
|
+
isBootstrapped: boolean;
|
|
761
|
+
/** 0–100 — see REQ-008 for the formula. */
|
|
762
|
+
confidenceScore: number;
|
|
763
|
+
createdAt: string;
|
|
764
|
+
updatedAt: string;
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Common envelope fields shared by every reinforcement event.
|
|
768
|
+
* `eventId` enables worker-side idempotency (Property 5 in design.md).
|
|
769
|
+
*/
|
|
770
|
+
interface ReinforcementEventBase {
|
|
771
|
+
/** Unique id (uuid) for idempotent re-delivery. */
|
|
772
|
+
eventId: string;
|
|
773
|
+
productId: "crm" | "laie" | "flow";
|
|
774
|
+
/** Wall-clock at the originating UI surface. ISO 8601 string. */
|
|
775
|
+
occurredAt?: string;
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* REQ-007 — discriminated union of every reinforcement event the
|
|
779
|
+
* platform emits. Workers fan these into `learning_memory` mutations.
|
|
780
|
+
*/
|
|
781
|
+
type ReinforcementEvent = (ReinforcementEventBase & {
|
|
782
|
+
kind: "lead_approved";
|
|
783
|
+
leadId: string;
|
|
784
|
+
/**
|
|
785
|
+
* Optional `(signal, value, weight?)` tuples. Weight defaults to
|
|
786
|
+
* `1.0` on the writer and is bounded `[0, 1]`. The reinforcement
|
|
787
|
+
* worker enriches this list via the signal-derivation layer
|
|
788
|
+
* (task 3.1.5) before the writer persists it.
|
|
789
|
+
*/
|
|
790
|
+
signals?: Array<{
|
|
791
|
+
signal: string;
|
|
792
|
+
value: string;
|
|
793
|
+
weight?: number;
|
|
794
|
+
}>;
|
|
795
|
+
}) | (ReinforcementEventBase & {
|
|
796
|
+
kind: "lead_rejected";
|
|
797
|
+
leadId: string;
|
|
798
|
+
signals?: Array<{
|
|
799
|
+
signal: string;
|
|
800
|
+
value: string;
|
|
801
|
+
weight?: number;
|
|
802
|
+
}>;
|
|
803
|
+
reason?: string;
|
|
804
|
+
}) | (ReinforcementEventBase & {
|
|
805
|
+
kind: "deal_won";
|
|
806
|
+
leadId: string;
|
|
807
|
+
dealValue?: number;
|
|
808
|
+
signals?: Array<{
|
|
809
|
+
signal: string;
|
|
810
|
+
value: string;
|
|
811
|
+
weight?: number;
|
|
812
|
+
}>;
|
|
813
|
+
}) | (ReinforcementEventBase & {
|
|
814
|
+
kind: "deal_lost";
|
|
815
|
+
leadId: string;
|
|
816
|
+
reason?: string;
|
|
817
|
+
signals?: Array<{
|
|
818
|
+
signal: string;
|
|
819
|
+
value: string;
|
|
820
|
+
weight?: number;
|
|
821
|
+
}>;
|
|
822
|
+
}) | (ReinforcementEventBase & {
|
|
823
|
+
kind: "outreach_edited";
|
|
824
|
+
outreachId: string;
|
|
825
|
+
diff: Array<Record<string, unknown>>;
|
|
826
|
+
reason?: string;
|
|
827
|
+
}) | (ReinforcementEventBase & {
|
|
828
|
+
/**
|
|
829
|
+
* Recorded every time an AI-generated outreach actually goes
|
|
830
|
+
* out. Feeds the denominator of the 7-day rolling edit-ratio
|
|
831
|
+
* that drives REQ-016 §4 (outreach style drift detection,
|
|
832
|
+
* Task 3.5.4). The writer appends one
|
|
833
|
+
* {@link OutreachSent} entry to
|
|
834
|
+
* `learningMemory.aiOutreachSent` and caps the array at 500
|
|
835
|
+
* entries (oldest rolled off).
|
|
836
|
+
*/
|
|
837
|
+
kind: "outreach_sent";
|
|
838
|
+
/** Optional id of the originating outreach row. */
|
|
839
|
+
outreachId?: string;
|
|
840
|
+
/** Optional channel descriptor, e.g. `"email"`, `"linkedin"`. */
|
|
841
|
+
channel?: string;
|
|
842
|
+
}) | (ReinforcementEventBase & {
|
|
843
|
+
kind: "ai_suggestion_accepted";
|
|
844
|
+
/** Stable id of the AI suggestion the user accepted. */
|
|
845
|
+
suggestionId: string;
|
|
846
|
+
/**
|
|
847
|
+
* Suggestion taxonomy slug, e.g. `"follow_up_message"`,
|
|
848
|
+
* `"lead_score_narrative"`, `"outreach_subject"`, `"next_action"`,
|
|
849
|
+
* `"inbox_reply"`.
|
|
850
|
+
*/
|
|
851
|
+
suggestionType: string;
|
|
852
|
+
/**
|
|
853
|
+
* UI surface the user acted from, e.g. `"crm.deal.followup"`,
|
|
854
|
+
* `"saas.inbox.reply"`, `"laie.lead.score"`.
|
|
855
|
+
*/
|
|
856
|
+
surface: string;
|
|
857
|
+
/**
|
|
858
|
+
* Surface-specific extra context (`dealId`, `leadId`,
|
|
859
|
+
* `conversationId`, etc).
|
|
860
|
+
*/
|
|
861
|
+
productContext?: Record<string, unknown>;
|
|
862
|
+
/**
|
|
863
|
+
* Persona memory version that produced the AI generation.
|
|
864
|
+
* Threaded through history for attribution.
|
|
865
|
+
*/
|
|
866
|
+
personaVersion?: number | null;
|
|
867
|
+
}) | (ReinforcementEventBase & {
|
|
868
|
+
kind: "ai_suggestion_rejected";
|
|
869
|
+
suggestionId: string;
|
|
870
|
+
suggestionType: string;
|
|
871
|
+
surface: string;
|
|
872
|
+
/** Optional user-supplied rejection reason. */
|
|
873
|
+
rejectionReason?: string;
|
|
874
|
+
productContext?: Record<string, unknown>;
|
|
875
|
+
personaVersion?: number | null;
|
|
876
|
+
}) | (ReinforcementEventBase & {
|
|
877
|
+
kind: "ai_assumption_corrected";
|
|
878
|
+
field: string;
|
|
879
|
+
oldValue: unknown;
|
|
880
|
+
newValue: unknown;
|
|
881
|
+
}) | (ReinforcementEventBase & {
|
|
882
|
+
kind: "followup_answer";
|
|
883
|
+
questionId: string;
|
|
884
|
+
targetField: string;
|
|
885
|
+
answer: unknown;
|
|
886
|
+
});
|
|
887
|
+
/**
|
|
888
|
+
* Response of `POST /api/persona/reinforce`.
|
|
889
|
+
*/
|
|
890
|
+
interface ReinforceResponse {
|
|
891
|
+
ok: true;
|
|
892
|
+
/** Persona memory version after this event was applied. */
|
|
893
|
+
version: number;
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Response of `GET /api/persona/confidence`.
|
|
897
|
+
*/
|
|
898
|
+
interface ConfidenceResponse {
|
|
899
|
+
/** 0–100 score per REQ-008. */
|
|
900
|
+
score: number;
|
|
901
|
+
/** Same breakdown the saas pill exposes on click. */
|
|
902
|
+
breakdown: {
|
|
903
|
+
acceptRatioContribution: number;
|
|
904
|
+
reinforcementContribution: number;
|
|
905
|
+
bootstrapContribution: number;
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* One row of a persona's version history. Mirrors the wire shape of
|
|
910
|
+
* `GET /api/persona/:productId/timeline` produced by
|
|
911
|
+
* `personaHistory.listTimeline` on the server.
|
|
912
|
+
*
|
|
913
|
+
* The DB stores 50 of these per persona (`personaHistory.appendAndPrune`
|
|
914
|
+
* caps retention); the saas timeline page renders the diff for each
|
|
915
|
+
* row inline via the `diff` array of RFC 6902 ops.
|
|
916
|
+
*/
|
|
917
|
+
interface PersonaTimelineEntry {
|
|
918
|
+
id: string;
|
|
919
|
+
personaId: string;
|
|
920
|
+
/** Monotonically increasing per persona; matches `AIPersona.memoryVersion`
|
|
921
|
+
* at the time of write. */
|
|
922
|
+
memoryVersion: number;
|
|
923
|
+
/** One of `onboarding_edit | reinforcement | admin_override | self_review`,
|
|
924
|
+
* but typed loosely so a new server reason doesn't break SDK consumers. */
|
|
925
|
+
changeReason: string;
|
|
926
|
+
/** User id, `system`, or `worker:<name>`. */
|
|
927
|
+
changedBy: string;
|
|
928
|
+
/** RFC 6902 JSON Patch ops applied by this version. */
|
|
929
|
+
diff: Array<Record<string, unknown>>;
|
|
930
|
+
/** Snapshot of the persona BEFORE this change. */
|
|
931
|
+
prevSnapshot: Record<string, unknown>;
|
|
932
|
+
/** ISO 8601 wall-clock at the time of write. */
|
|
933
|
+
createdAt: string;
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Response shape of `GET /api/persona/:productId/timeline`.
|
|
937
|
+
*
|
|
938
|
+
* `hasMore` is a soft "did we hit the page size?" hint — the server
|
|
939
|
+
* doesn't run a second COUNT(*) to compute an exact total. The saas
|
|
940
|
+
* treats it as a CTA gate: render "Load older" when true.
|
|
941
|
+
*/
|
|
942
|
+
interface PersonaTimelineResponse {
|
|
943
|
+
entries: PersonaTimelineEntry[];
|
|
944
|
+
hasMore: boolean;
|
|
945
|
+
}
|
|
946
|
+
/** Optional query parameters for `Persona.timeline(...)`. */
|
|
947
|
+
interface PersonaTimelineOptions {
|
|
948
|
+
/** Page size — clamped server-side to `[1, 50]`. Default `50`. */
|
|
949
|
+
limit?: number;
|
|
950
|
+
/** Cursor — return entries with `memoryVersion < before`. */
|
|
951
|
+
before?: number;
|
|
952
|
+
}
|
|
953
|
+
/**
|
|
954
|
+
* One pending followup question synthesised by the
|
|
955
|
+
* confidence-gap-detection loop (REQ-016 Loop 1). The saas
|
|
956
|
+
* `<FollowupQuestionCard>` renders the newest pending entry inline
|
|
957
|
+
* on the relevant product page; the user's answer routes through
|
|
958
|
+
* `POST /api/persona/:productId/followups/:id/answer` (which flips
|
|
959
|
+
* `answeredAt` on the row) and additionally fires a
|
|
960
|
+
* `kind: "followup_answer"` reinforcement event so the persona's
|
|
961
|
+
* `corrections[]` audit slot is updated.
|
|
962
|
+
*
|
|
963
|
+
* Mirrors the wire shape returned by
|
|
964
|
+
* `GET /api/persona/:productId/followups`. The DB row carries
|
|
965
|
+
* `answeredAt` and `answer` columns; we deliberately omit them here
|
|
966
|
+
* because the reader only ever returns pending rows (both columns
|
|
967
|
+
* are NULL until the user answers).
|
|
968
|
+
*/
|
|
969
|
+
interface PersonaFollowupQuestion {
|
|
970
|
+
id: string;
|
|
971
|
+
personaId: string;
|
|
972
|
+
question: string;
|
|
973
|
+
/** Persona JSONB dot-path the answer maps to,
|
|
974
|
+
* e.g. `"icp.industryTargets"` or `"behaviorRules.outreachTone"`. */
|
|
975
|
+
targetField: string;
|
|
976
|
+
/** ISO 8601 — when the worker generated the question. */
|
|
977
|
+
askedAt: string;
|
|
978
|
+
/**
|
|
979
|
+
* Open structured payload for advanced followup kinds (REQ-016
|
|
980
|
+
* §4 / Task 3.5.4.2 — outreach style drift recalibration).
|
|
981
|
+
*
|
|
982
|
+
* Loop 4 fills this with `{ kind: "style_recalibration", ratio,
|
|
983
|
+
* options: [{ id, label }, ...] }` so the saas
|
|
984
|
+
* `<FollowupQuestionCard>` can render a multi-choice toggle
|
|
985
|
+
* instead of the simpler free-text textarea. Absent / `null` on
|
|
986
|
+
* rows created by the Loop 1 confidence-gap path.
|
|
987
|
+
*
|
|
988
|
+
* Free-form by design — workers can extend the payload without an
|
|
989
|
+
* SDK rebuild and saas surfaces ignore unknown keys gracefully.
|
|
990
|
+
*/
|
|
991
|
+
metadata?: {
|
|
992
|
+
kind?: string;
|
|
993
|
+
options?: Array<{
|
|
994
|
+
id: string;
|
|
995
|
+
label: string;
|
|
996
|
+
}>;
|
|
997
|
+
ratio?: number;
|
|
998
|
+
[k: string]: unknown;
|
|
999
|
+
} | null;
|
|
1000
|
+
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Body shape of `POST /api/persona/:productId/followups/:id/answer`.
|
|
1003
|
+
*
|
|
1004
|
+
* Two acceptable forms:
|
|
1005
|
+
* - Plain string answer — the legacy path used by Loop 1
|
|
1006
|
+
* confidence-gap followups. The string is stored verbatim on the
|
|
1007
|
+
* row and forwarded to the persona as a `kind: "followup_answer"`
|
|
1008
|
+
* reinforcement event.
|
|
1009
|
+
* - Structured `{ dimension, detail? }` answer — the Loop 4
|
|
1010
|
+
* style-recalibration path. The route validates `dimension`
|
|
1011
|
+
* against the five recognised ids (`tone | length |
|
|
1012
|
+
* personalization | cta | structure`), forwards the answer to
|
|
1013
|
+
* `personaWriter.applyStyleRecalibration`, AND additionally fires
|
|
1014
|
+
* the standard reinforcement event for the audit trail.
|
|
1015
|
+
*/
|
|
1016
|
+
type AnswerFollowupBody = {
|
|
1017
|
+
answer: string;
|
|
1018
|
+
} | {
|
|
1019
|
+
answer: {
|
|
1020
|
+
dimension: "tone" | "length" | "personalization" | "cta" | "structure";
|
|
1021
|
+
detail?: string;
|
|
1022
|
+
};
|
|
1023
|
+
};
|
|
1024
|
+
/**
|
|
1025
|
+
* Response shape of `GET /api/persona/:productId/followups`.
|
|
1026
|
+
*
|
|
1027
|
+
* The list is ordered newest-first by `askedAt` and capped at 5
|
|
1028
|
+
* server-side. The saas card only ever renders the first entry.
|
|
1029
|
+
*/
|
|
1030
|
+
interface PersonaFollowupsResponse {
|
|
1031
|
+
entries: PersonaFollowupQuestion[];
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* AI persona resource.
|
|
1035
|
+
*
|
|
1036
|
+
* Mounted on the main client as `ecod.persona`. Reads the persona row,
|
|
1037
|
+
* accepts reinforcement events, and exposes the live confidence score.
|
|
1038
|
+
*
|
|
1039
|
+
* @example
|
|
1040
|
+
* ```typescript
|
|
1041
|
+
* const persona = await ecod.persona.get("crm");
|
|
1042
|
+
*
|
|
1043
|
+
* await ecod.persona.reinforce({
|
|
1044
|
+
* eventId: crypto.randomUUID(),
|
|
1045
|
+
* productId: "laie",
|
|
1046
|
+
* kind: "lead_approved",
|
|
1047
|
+
* leadId: "lead_123",
|
|
1048
|
+
* signals: [{ signal: "funding_stage", value: "series_a" }],
|
|
1049
|
+
* });
|
|
1050
|
+
*
|
|
1051
|
+
* const { score } = await ecod.persona.confidence("laie");
|
|
1052
|
+
* ```
|
|
1053
|
+
*/
|
|
1054
|
+
declare class Persona extends APIResource {
|
|
1055
|
+
/**
|
|
1056
|
+
* Read the persona for the calling user + given product. Returns the
|
|
1057
|
+
* generic baseline shape when the user hasn't bootstrapped yet
|
|
1058
|
+
* (`isBootstrapped === false`).
|
|
1059
|
+
*
|
|
1060
|
+
* Note: this method shadows `APIResource.get` (which is `protected`).
|
|
1061
|
+
* The override widens visibility to public and narrows the return type
|
|
1062
|
+
* to `AIPersona`, which TypeScript flags as a structural override
|
|
1063
|
+
* mismatch — that mismatch is intentional and benign here, hence the
|
|
1064
|
+
* directive below. Implementation delegates to `super.get(...)`.
|
|
1065
|
+
*/
|
|
1066
|
+
get(productId: "crm" | "laie" | "flow"): Promise<AIPersona>;
|
|
1067
|
+
/**
|
|
1068
|
+
* Submit a reinforcement event. The server enqueues it onto the
|
|
1069
|
+
* `persona-reinforcement` queue and returns the post-apply memory
|
|
1070
|
+
* version. Idempotent on `eventId`.
|
|
1071
|
+
*/
|
|
1072
|
+
reinforce(event: ReinforcementEvent): Promise<ReinforceResponse>;
|
|
1073
|
+
/**
|
|
1074
|
+
* Read the live confidence score + the per-component breakdown.
|
|
1075
|
+
*/
|
|
1076
|
+
confidence(productId: "crm" | "laie" | "flow"): Promise<ConfidenceResponse>;
|
|
1077
|
+
/**
|
|
1078
|
+
* Read the persona's version history — one entry per `personaWriter`
|
|
1079
|
+
* mutation, with the RFC 6902 patch + previous snapshot.
|
|
1080
|
+
*
|
|
1081
|
+
* Returns at most 50 rows per call (matches the per-persona
|
|
1082
|
+
* retention cap enforced server-side by
|
|
1083
|
+
* `personaHistory.appendAndPrune`). When `hasMore === true`, page
|
|
1084
|
+
* back with `{ before: entries[entries.length - 1].memoryVersion }`.
|
|
1085
|
+
*
|
|
1086
|
+
* Note: this method shadows `APIResource.get` (which is `protected`)
|
|
1087
|
+
* via the public override above on `get(...)`. The same caveat
|
|
1088
|
+
* applies here — we intentionally widen visibility and narrow the
|
|
1089
|
+
* return type to the timeline envelope. Implementation delegates
|
|
1090
|
+
* to `super.get(...)`.
|
|
1091
|
+
*/
|
|
1092
|
+
timeline(productId: "crm" | "laie" | "flow", options?: PersonaTimelineOptions): Promise<PersonaTimelineResponse>;
|
|
1093
|
+
/**
|
|
1094
|
+
* Read the persona's pending followup questions — the
|
|
1095
|
+
* confidence-gap-detection loop (REQ-016 Loop 1) writes one row
|
|
1096
|
+
* per `(persona, weakest subfield)` pair when
|
|
1097
|
+
* `confidenceScore < 50` AND `learningMemory.totalReinforcement
|
|
1098
|
+
* >= 20`. The saas `<FollowupQuestionCard>` mounts on the
|
|
1099
|
+
* relevant product page and renders the newest pending entry
|
|
1100
|
+
* inline.
|
|
1101
|
+
*
|
|
1102
|
+
* Returns the unwrapped `entries` array (no surrounding `{ success,
|
|
1103
|
+
* data }` envelope) — matches the project's preference of having
|
|
1104
|
+
* the SDK do the unwrap so call sites stay slim. An empty list
|
|
1105
|
+
* means there's nothing pending; the card opts itself out and
|
|
1106
|
+
* returns `null` in that case.
|
|
1107
|
+
*
|
|
1108
|
+
* Note: this method shadows `APIResource.get` (which is `protected`)
|
|
1109
|
+
* — see the note above {@link Persona.get} / {@link Persona.timeline}.
|
|
1110
|
+
*/
|
|
1111
|
+
followups(productId: "crm" | "laie" | "flow"): Promise<PersonaFollowupQuestion[]>;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
/**
|
|
1115
|
+
* Admin-side onboarding resource.
|
|
1116
|
+
*
|
|
1117
|
+
* Mounted on the main client as `ecod.adminOnboarding`. Mirrors the
|
|
1118
|
+
* platform-admin endpoints under `/api/admin/onboarding/*` documented
|
|
1119
|
+
* in `server/src/platform/routes/admin/onboarding.routes.ts`.
|
|
1120
|
+
*
|
|
1121
|
+
* Auth: every method requires the elevated platform `coreApiKey`. The
|
|
1122
|
+
* SDK forwards it as `x-core-api-key`; admin server-side callers should
|
|
1123
|
+
* always construct a client with `coreApiKey` set (see
|
|
1124
|
+
* `admin/src/lib/client/erix-admin.ts`).
|
|
1125
|
+
*
|
|
1126
|
+
* Endpoints covered in this build (task 4.1.1 — list page):
|
|
1127
|
+
*
|
|
1128
|
+
* - GET /api/admin/onboarding/niche-packs list
|
|
1129
|
+
* - GET /api/admin/onboarding/niche-packs/:slug fetch one
|
|
1130
|
+
* - POST /api/admin/onboarding/niche-packs create
|
|
1131
|
+
* - PATCH /api/admin/onboarding/niche-packs/:slug update
|
|
1132
|
+
* - POST /api/admin/onboarding/niche-packs/:slug/publish publish
|
|
1133
|
+
* - POST /api/admin/onboarding/niche-packs/:slug/unpublish back to draft
|
|
1134
|
+
* - POST /api/admin/onboarding/niche-packs/:slug/fork new draft copy
|
|
1135
|
+
* - GET /api/admin/onboarding/configs list configs
|
|
1136
|
+
* - POST /api/admin/onboarding/configs create config
|
|
1137
|
+
* - PATCH /api/admin/onboarding/configs/:productId/:version update
|
|
1138
|
+
* - POST /api/admin/onboarding/configs/:productId/:version/publish publish
|
|
1139
|
+
*
|
|
1140
|
+
* Endpoints for A/B onboarding experiments (task 4.2.2):
|
|
1141
|
+
*
|
|
1142
|
+
* - GET /api/admin/onboarding/experiments list
|
|
1143
|
+
* - GET /api/admin/onboarding/experiments/:slug fetch one
|
|
1144
|
+
* - POST /api/admin/onboarding/experiments create draft
|
|
1145
|
+
* - PATCH /api/admin/onboarding/experiments/:slug partial update
|
|
1146
|
+
* - DELETE /api/admin/onboarding/experiments/:slug hard-delete
|
|
1147
|
+
*
|
|
1148
|
+
* Successive admin tasks (4.1.2–4.1.5) layer richer editor / fork /
|
|
1149
|
+
* publish flows on top of these primitives.
|
|
1150
|
+
*/
|
|
1151
|
+
|
|
1152
|
+
/** Niche pack row as returned by the admin list endpoint. */
|
|
1153
|
+
interface NichePackSummary {
|
|
1154
|
+
id: string;
|
|
1155
|
+
slug: string;
|
|
1156
|
+
productId: NichePack["productId"];
|
|
1157
|
+
version: string;
|
|
1158
|
+
status: NichePackStatus;
|
|
1159
|
+
/** ISO 8601 — creation timestamp (server clock). */
|
|
1160
|
+
createdAt: string;
|
|
1161
|
+
/** ISO 8601 — last edit timestamp. */
|
|
1162
|
+
updatedAt: string;
|
|
1163
|
+
/** ISO 8601 — first time `status` flipped to `published`. */
|
|
1164
|
+
publishedAt?: string | null;
|
|
1165
|
+
/** Admin staff id who created this version. */
|
|
1166
|
+
createdBy?: string | null;
|
|
1167
|
+
}
|
|
1168
|
+
/** Filters accepted by `adminOnboarding.listNichePacks`. */
|
|
1169
|
+
interface ListNichePacksParams {
|
|
1170
|
+
/** Restrict to a single product family. */
|
|
1171
|
+
productId?: NichePack["productId"];
|
|
1172
|
+
/** Restrict to one lifecycle status. */
|
|
1173
|
+
status?: NichePackStatus;
|
|
1174
|
+
/**
|
|
1175
|
+
* Free-form fuzzy search. Matched (case-insensitive) against `slug`
|
|
1176
|
+
* and `productId`. Whitespace is trimmed.
|
|
1177
|
+
*/
|
|
1178
|
+
search?: string;
|
|
1179
|
+
/** Page size — server clamps to 1..100, default 25. */
|
|
1180
|
+
limit?: number;
|
|
1181
|
+
/** Pagination offset, default 0. */
|
|
1182
|
+
offset?: number;
|
|
1183
|
+
}
|
|
1184
|
+
/** Body accepted by the create-pack endpoint. */
|
|
1185
|
+
interface CreateNichePackPayload {
|
|
1186
|
+
slug: string;
|
|
1187
|
+
productId: NichePack["productId"];
|
|
1188
|
+
/** Defaults to `"1.0.0"` server-side. */
|
|
1189
|
+
version?: string;
|
|
1190
|
+
onboardingConfig?: Record<string, unknown>;
|
|
1191
|
+
workspaceProfile?: Record<string, unknown>;
|
|
1192
|
+
researchConfig?: Record<string, unknown>;
|
|
1193
|
+
}
|
|
1194
|
+
/** Body accepted by the update-pack endpoint. At least one field required. */
|
|
1195
|
+
interface UpdateNichePackPayload {
|
|
1196
|
+
status?: NichePackStatus;
|
|
1197
|
+
onboardingConfig?: Record<string, unknown>;
|
|
1198
|
+
workspaceProfile?: Record<string, unknown>;
|
|
1199
|
+
researchConfig?: Record<string, unknown>;
|
|
1200
|
+
}
|
|
1201
|
+
/** Body accepted by the fork-pack endpoint. */
|
|
1202
|
+
interface ForkNichePackPayload {
|
|
1203
|
+
/** Source version to clone; defaults to the latest row for the slug. */
|
|
1204
|
+
fromVersion?: string;
|
|
1205
|
+
/** Target version for the new draft; defaults to a server-side bump. */
|
|
1206
|
+
version?: string;
|
|
1207
|
+
}
|
|
1208
|
+
/**
|
|
1209
|
+
* Body accepted by `adminOnboarding.smokeTestNichePack` (task 4.1.5).
|
|
1210
|
+
*
|
|
1211
|
+
* Both fields are optional:
|
|
1212
|
+
*
|
|
1213
|
+
* - `fromVersion` pins a specific row for the slug; without it the
|
|
1214
|
+
* server picks the most recent (typically the latest draft).
|
|
1215
|
+
* - `answers` is a `{ stepId: value }` map. When omitted (or missing
|
|
1216
|
+
* keys for some steps) the in-memory runner auto-picks the first
|
|
1217
|
+
* option of `single_choice` / `multi_choice` steps and uses a
|
|
1218
|
+
* placeholder for `text_input`.
|
|
1219
|
+
*/
|
|
1220
|
+
interface SmokeTestNichePackPayload {
|
|
1221
|
+
fromVersion?: string;
|
|
1222
|
+
answers?: Record<string, unknown>;
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* One materializer action the live `workspaceShaper.materialize` call
|
|
1226
|
+
* WOULD perform if the smoke-tested pack were used in a real
|
|
1227
|
+
* onboarding-complete flow. The summary string is what the admin
|
|
1228
|
+
* panel renders verbatim ("Would create pipeline 'Patient Journey'
|
|
1229
|
+
* with 5 stages").
|
|
1230
|
+
*/
|
|
1231
|
+
type SmokeTestMaterializerAction = {
|
|
1232
|
+
kind: "pipeline";
|
|
1233
|
+
name: string;
|
|
1234
|
+
stageCount: number;
|
|
1235
|
+
isDefault: boolean;
|
|
1236
|
+
summary: string;
|
|
1237
|
+
} | {
|
|
1238
|
+
kind: "field";
|
|
1239
|
+
key: string;
|
|
1240
|
+
label: string;
|
|
1241
|
+
type: string;
|
|
1242
|
+
required: boolean;
|
|
1243
|
+
summary: string;
|
|
1244
|
+
} | {
|
|
1245
|
+
kind: "automation";
|
|
1246
|
+
name: string;
|
|
1247
|
+
trigger: string;
|
|
1248
|
+
enabled: boolean;
|
|
1249
|
+
summary: string;
|
|
1250
|
+
};
|
|
1251
|
+
/**
|
|
1252
|
+
* Result envelope returned by `adminOnboarding.smokeTestNichePack`.
|
|
1253
|
+
*
|
|
1254
|
+
* Mirrors `SmokeTestResult` in
|
|
1255
|
+
* `server/src/erix/services/onboarding/smokeTestRunner.ts`.
|
|
1256
|
+
*/
|
|
1257
|
+
interface SmokeTestResult {
|
|
1258
|
+
/** In-memory `OnboardingSession` produced by the simulator. */
|
|
1259
|
+
session: OnboardingSession;
|
|
1260
|
+
/** Persona shaped from the answers + memory mappings. */
|
|
1261
|
+
persona: AIPersona;
|
|
1262
|
+
/** Workspace profile produced by `workspaceShaper.produce`. */
|
|
1263
|
+
workspaceProfile: WorkspaceProfile;
|
|
1264
|
+
/** Actions the live materializer would perform. */
|
|
1265
|
+
materializerActions: SmokeTestMaterializerAction[];
|
|
1266
|
+
/** Wall-clock duration (millis) of the simulation. */
|
|
1267
|
+
durationMs: number;
|
|
1268
|
+
/** Step ids the engine visited (in order). */
|
|
1269
|
+
visitedStepIds: string[];
|
|
1270
|
+
/** Step ids the engine skipped via branching predicates. */
|
|
1271
|
+
skippedStepIds: string[];
|
|
1272
|
+
/** Whether the runner had to auto-pick at least one answer. */
|
|
1273
|
+
autoPicked: boolean;
|
|
1274
|
+
}
|
|
1275
|
+
/** Standard `{ success, data }` envelope used by every admin endpoint. */
|
|
1276
|
+
interface ApiEnvelope<T> {
|
|
1277
|
+
success: boolean;
|
|
1278
|
+
data: T;
|
|
1279
|
+
}
|
|
1280
|
+
/** Envelope returned by `GET /admin/onboarding/niche-packs`. */
|
|
1281
|
+
interface ListNichePacksResponse extends ApiEnvelope<NichePackSummary[]> {
|
|
1282
|
+
/**
|
|
1283
|
+
* Total niche-pack rows matching the current filter set, ignoring
|
|
1284
|
+
* the page window. Drives the saas-side paginator. Falls back to
|
|
1285
|
+
* `data.length` when the server can't compute a true count.
|
|
1286
|
+
*/
|
|
1287
|
+
total: number;
|
|
1288
|
+
}
|
|
1289
|
+
/** Envelope returned by single-pack endpoints (get / create / update / fork). */
|
|
1290
|
+
type NichePackResponse = ApiEnvelope<NichePack & NichePackSummary>;
|
|
1291
|
+
/** Filters accepted by `adminOnboarding.listOnboardingConfigs`. */
|
|
1292
|
+
interface ListOnboardingConfigsParams {
|
|
1293
|
+
productId?: OnboardingConfig["productId"];
|
|
1294
|
+
status?: NichePackStatus;
|
|
1295
|
+
}
|
|
1296
|
+
/** Body accepted by the create-config endpoint. */
|
|
1297
|
+
interface CreateOnboardingConfigPayload {
|
|
1298
|
+
productId: OnboardingConfig["productId"];
|
|
1299
|
+
version?: string;
|
|
1300
|
+
config?: Record<string, unknown>;
|
|
1301
|
+
}
|
|
1302
|
+
/** Body accepted by the update-config endpoint. */
|
|
1303
|
+
interface UpdateOnboardingConfigPayload {
|
|
1304
|
+
status?: NichePackStatus;
|
|
1305
|
+
config?: Record<string, unknown>;
|
|
1306
|
+
}
|
|
1307
|
+
/** Filters accepted by `adminOnboarding.listOnboardingExperiments`. */
|
|
1308
|
+
interface ListOnboardingExperimentsParams {
|
|
1309
|
+
productId?: OnboardingExperiment["productId"];
|
|
1310
|
+
status?: OnboardingExperimentStatus;
|
|
1311
|
+
/** Page size — server clamps to 1..100, default 25. */
|
|
1312
|
+
limit?: number;
|
|
1313
|
+
/** Pagination offset, default 0. */
|
|
1314
|
+
offset?: number;
|
|
1315
|
+
} /** Body accepted by the create-experiment endpoint. */
|
|
1316
|
+
interface CreateOnboardingExperimentPayload {
|
|
1317
|
+
/** Admin-facing handle; unique platform-wide. */
|
|
1318
|
+
slug: string;
|
|
1319
|
+
productId: OnboardingExperiment["productId"];
|
|
1320
|
+
/** Display name shown in the admin panel. */
|
|
1321
|
+
name: string;
|
|
1322
|
+
description?: string;
|
|
1323
|
+
/** Defaults to `"draft"` server-side. */
|
|
1324
|
+
status?: OnboardingExperimentStatus;
|
|
1325
|
+
/**
|
|
1326
|
+
* Variant routing table — may be empty for a freshly created
|
|
1327
|
+
* draft. Variants whose `cohortRange` overlaps are rejected with
|
|
1328
|
+
* `OVERLAPPING_VARIANTS`.
|
|
1329
|
+
*/
|
|
1330
|
+
variants?: OnboardingExperimentVariant[];
|
|
1331
|
+
/** Fallback config version when no variant matches the user's bucket. */
|
|
1332
|
+
controlConfigVersion?: string | null;
|
|
1333
|
+
}
|
|
1334
|
+
/** Body accepted by the patch-experiment endpoint. */
|
|
1335
|
+
interface UpdateOnboardingExperimentPayload {
|
|
1336
|
+
name?: string;
|
|
1337
|
+
description?: string | null;
|
|
1338
|
+
status?: OnboardingExperimentStatus;
|
|
1339
|
+
variants?: OnboardingExperimentVariant[];
|
|
1340
|
+
controlConfigVersion?: string | null;
|
|
1341
|
+
}
|
|
1342
|
+
/** Envelope returned by `GET /admin/onboarding/experiments`. */
|
|
1343
|
+
interface ListOnboardingExperimentsResponse extends ApiEnvelope<OnboardingExperiment[]> {
|
|
1344
|
+
/**
|
|
1345
|
+
* Total experiments matching the current filter set, ignoring the
|
|
1346
|
+
* page window. Drives the saas-side paginator. Falls back to
|
|
1347
|
+
* `data.length` when the server can't compute a true count.
|
|
1348
|
+
*/
|
|
1349
|
+
total: number;
|
|
1350
|
+
}
|
|
1351
|
+
/** Envelope returned by single-experiment endpoints. */
|
|
1352
|
+
type OnboardingExperimentResponse = ApiEnvelope<OnboardingExperiment>;
|
|
1353
|
+
/**
|
|
1354
|
+
* Filters accepted by every analytics endpoint
|
|
1355
|
+
* (`getOnboardingFunnel`, `getOnboardingTimeOnStep`,
|
|
1356
|
+
* `getOnboardingAbandonment`).
|
|
1357
|
+
*
|
|
1358
|
+
* `productId` constrains by product family, `nicheSubtype` by the
|
|
1359
|
+
* `nichePackSlug` recorded on the originating session row. `fromDate`
|
|
1360
|
+
* / `toDate` are wire-side ISO 8601 strings (the server coerces them
|
|
1361
|
+
* via Zod's `z.coerce.date()`); when omitted, the server defaults to
|
|
1362
|
+
* the trailing 30 days. The server hard-caps the requested window at
|
|
1363
|
+
* 180 days and rejects `fromDate >= toDate` with 400 INVALID_FIELD.
|
|
1364
|
+
*/
|
|
1365
|
+
interface OnboardingAnalyticsFiltersParams {
|
|
1366
|
+
productId?: "crm" | "laie" | "flow" | string;
|
|
1367
|
+
nicheSubtype?: string;
|
|
1368
|
+
/** ISO 8601 datetime, e.g. `"2025-01-01T00:00:00.000Z"`. */
|
|
1369
|
+
fromDate?: string;
|
|
1370
|
+
/** ISO 8601 datetime. */
|
|
1371
|
+
toDate?: string;
|
|
1372
|
+
}
|
|
1373
|
+
/** One funnel row — distinct sessions that reached `stepId`. */
|
|
1374
|
+
interface OnboardingFunnelStep {
|
|
1375
|
+
productId: string;
|
|
1376
|
+
nichePackSlug: string | null;
|
|
1377
|
+
stepId: string;
|
|
1378
|
+
/** Distinct sessions that emitted at least one event for this step. */
|
|
1379
|
+
sessions: number;
|
|
1380
|
+
/**
|
|
1381
|
+
* Fraction `[0, 1]` of sessions that reached this step relative to
|
|
1382
|
+
* the first step in the same `(productId, nichePackSlug)` flow.
|
|
1383
|
+
* The first step always has `conversionRate = 1`.
|
|
1384
|
+
*/
|
|
1385
|
+
conversionRate: number;
|
|
1386
|
+
}
|
|
1387
|
+
/** Result envelope for `getOnboardingFunnel`. */
|
|
1388
|
+
interface OnboardingFunnelResult {
|
|
1389
|
+
/** Flat list, ordered by `(productId, nichePackSlug, sessions DESC)`. */
|
|
1390
|
+
funnel: OnboardingFunnelStep[];
|
|
1391
|
+
/** Distinct sessions across all rows in the window. */
|
|
1392
|
+
totalSessions: number;
|
|
1393
|
+
}
|
|
1394
|
+
/** One time-on-step row — per `(productId, nichePackSlug, stepId)`. */
|
|
1395
|
+
interface OnboardingTimeOnStepRow {
|
|
1396
|
+
productId: string;
|
|
1397
|
+
nichePackSlug: string | null;
|
|
1398
|
+
stepId: string;
|
|
1399
|
+
/** Median (p50) milliseconds from `stepId` first event → next step. */
|
|
1400
|
+
medianMs: number;
|
|
1401
|
+
/** p95 milliseconds. */
|
|
1402
|
+
p95Ms: number;
|
|
1403
|
+
/** Number of (session, step) pairs that contributed a delta. */
|
|
1404
|
+
sampleSize: number;
|
|
1405
|
+
}
|
|
1406
|
+
/** Result envelope for `getOnboardingTimeOnStep`. */
|
|
1407
|
+
interface OnboardingTimeOnStepResult {
|
|
1408
|
+
rows: OnboardingTimeOnStepRow[];
|
|
1409
|
+
}
|
|
1410
|
+
/** One abandonment bucket — abandoned sessions whose last seen step was `stepId`. */
|
|
1411
|
+
interface OnboardingAbandonmentRow {
|
|
1412
|
+
productId: string;
|
|
1413
|
+
nichePackSlug: string | null;
|
|
1414
|
+
stepId: string;
|
|
1415
|
+
abandonedSessions: number;
|
|
1416
|
+
}
|
|
1417
|
+
/** Result envelope for `getOnboardingAbandonment`. */
|
|
1418
|
+
interface OnboardingAbandonmentResult {
|
|
1419
|
+
rows: OnboardingAbandonmentRow[];
|
|
1420
|
+
totalAbandoned: number;
|
|
1421
|
+
}
|
|
1422
|
+
/** `{ success, data: OnboardingFunnelResult }`. */
|
|
1423
|
+
type OnboardingFunnelResponse = ApiEnvelope<OnboardingFunnelResult>;
|
|
1424
|
+
/** `{ success, data: OnboardingTimeOnStepResult }`. */
|
|
1425
|
+
type OnboardingTimeOnStepResponse = ApiEnvelope<OnboardingTimeOnStepResult>;
|
|
1426
|
+
/** `{ success, data: OnboardingAbandonmentResult }`. */
|
|
1427
|
+
type OnboardingAbandonmentResponse = ApiEnvelope<OnboardingAbandonmentResult>;
|
|
1428
|
+
/**
|
|
1429
|
+
* Admin-side onboarding control plane.
|
|
1430
|
+
*
|
|
1431
|
+
* @example
|
|
1432
|
+
* ```typescript
|
|
1433
|
+
* const { data, total } = await ecod.adminOnboarding.listNichePacks({
|
|
1434
|
+
* productId: "crm",
|
|
1435
|
+
* status: "published",
|
|
1436
|
+
* search: "clinic",
|
|
1437
|
+
* limit: 25,
|
|
1438
|
+
* offset: 0,
|
|
1439
|
+
* });
|
|
1440
|
+
* ```
|
|
1441
|
+
*/
|
|
1442
|
+
declare class AdminOnboarding extends APIResource {
|
|
1443
|
+
/**
|
|
1444
|
+
* List niche packs with optional filtering, search, and pagination.
|
|
1445
|
+
* Server response shape: `{ success, data, total }`.
|
|
1446
|
+
*/
|
|
1447
|
+
listNichePacks(params?: ListNichePacksParams): Promise<ListNichePacksResponse>;
|
|
1448
|
+
/** Fetch a single niche pack by slug. Without `version` returns the latest. */
|
|
1449
|
+
getNichePack(slug: string, version?: string): Promise<NichePackResponse>;
|
|
1450
|
+
/** Create a new niche pack draft. */
|
|
1451
|
+
createNichePack(payload: CreateNichePackPayload): Promise<NichePackResponse>;
|
|
1452
|
+
/** Patch a draft niche pack. Server enforces "at least one field". */
|
|
1453
|
+
updateNichePack(slug: string, payload: UpdateNichePackPayload, version?: string): Promise<NichePackResponse>;
|
|
1454
|
+
/** Flip a niche pack to `published`. */
|
|
1455
|
+
publishNichePack(slug: string, version?: string): Promise<NichePackResponse>;
|
|
1456
|
+
/** Flip a niche pack back to `draft`. */
|
|
1457
|
+
unpublishNichePack(slug: string, version?: string): Promise<NichePackResponse>;
|
|
1458
|
+
/** Fork an existing niche pack into a new draft version. */
|
|
1459
|
+
forkNichePack(slug: string, payload?: ForkNichePackPayload): Promise<NichePackResponse>;
|
|
1460
|
+
/**
|
|
1461
|
+
* Run an in-memory smoke test against a niche pack (task 4.1.5).
|
|
1462
|
+
*
|
|
1463
|
+
* The server resolves the pack row, walks its `onboardingConfig`
|
|
1464
|
+
* with the supplied (or auto-picked) answers, shapes a persona
|
|
1465
|
+
* + workspace profile, and returns the result without writing
|
|
1466
|
+
* anything. Useful for admins to validate a draft pack before
|
|
1467
|
+
* publishing.
|
|
1468
|
+
*
|
|
1469
|
+
* @param slug - Niche pack slug.
|
|
1470
|
+
* @param payload - Optional `{ fromVersion?, answers? }`. Both
|
|
1471
|
+
* fields are independently optional; `version` (the legacy
|
|
1472
|
+
* query-string equivalent) is also supported as a third
|
|
1473
|
+
* argument for parity with the other slug-keyed methods.
|
|
1474
|
+
* @param version - Optional version override applied as a
|
|
1475
|
+
* `?version=` query param (kept for callers that already
|
|
1476
|
+
* thread version through the URL).
|
|
1477
|
+
*/
|
|
1478
|
+
smokeTestNichePack(slug: string, payload?: SmokeTestNichePackPayload, version?: string): Promise<ApiEnvelope<SmokeTestResult>>;
|
|
1479
|
+
listOnboardingConfigs(params?: ListOnboardingConfigsParams): Promise<ApiEnvelope<unknown[]>>;
|
|
1480
|
+
createOnboardingConfig(payload: CreateOnboardingConfigPayload): Promise<ApiEnvelope<unknown>>;
|
|
1481
|
+
updateOnboardingConfig(productId: OnboardingConfig["productId"], version: string, payload: UpdateOnboardingConfigPayload): Promise<ApiEnvelope<unknown>>;
|
|
1482
|
+
publishOnboardingConfig(productId: OnboardingConfig["productId"], version: string): Promise<ApiEnvelope<unknown>>;
|
|
1483
|
+
/**
|
|
1484
|
+
* List onboarding A/B experiments with optional filters and
|
|
1485
|
+
* pagination. Server response shape: `{ success, data, total }`.
|
|
1486
|
+
*/
|
|
1487
|
+
listOnboardingExperiments(params?: ListOnboardingExperimentsParams): Promise<ListOnboardingExperimentsResponse>;
|
|
1488
|
+
/** Fetch a single experiment by its slug. 404 when absent. */
|
|
1489
|
+
getOnboardingExperiment(slug: string): Promise<OnboardingExperimentResponse>;
|
|
1490
|
+
/**
|
|
1491
|
+
* Create a draft experiment. The server enforces:
|
|
1492
|
+
*
|
|
1493
|
+
* - `slug` non-empty + globally unique.
|
|
1494
|
+
* - `productId ∈ {crm, laie, flow}`.
|
|
1495
|
+
* - `variants` is an array (may be empty for a draft).
|
|
1496
|
+
* - Each variant's `cohortRange.from < cohortRange.to`, both in
|
|
1497
|
+
* `[0, 100]`.
|
|
1498
|
+
* - Variants don't overlap (returns 400 `OVERLAPPING_VARIANTS`).
|
|
1499
|
+
*/
|
|
1500
|
+
createOnboardingExperiment(payload: CreateOnboardingExperimentPayload): Promise<OnboardingExperimentResponse>;
|
|
1501
|
+
/**
|
|
1502
|
+
* Patch an experiment. At least one of `name | description |
|
|
1503
|
+
* status | variants | controlConfigVersion` must be supplied —
|
|
1504
|
+
* the server returns 400 `NO_UPDATES` for an empty body. When
|
|
1505
|
+
* `variants` is supplied the overlap validator re-runs.
|
|
1506
|
+
*/
|
|
1507
|
+
updateOnboardingExperiment(slug: string, payload: UpdateOnboardingExperimentPayload): Promise<OnboardingExperimentResponse>;
|
|
1508
|
+
/**
|
|
1509
|
+
* Hard-delete an experiment. Returns the deleted row in `data` for
|
|
1510
|
+
* audit-log convenience. Admin-only — no soft-delete column.
|
|
1511
|
+
*/
|
|
1512
|
+
deleteOnboardingExperiment(slug: string): Promise<OnboardingExperimentResponse>;
|
|
1513
|
+
/**
|
|
1514
|
+
* Funnel-by-step counts for `(productId, nichePackSlug)`, plus
|
|
1515
|
+
* conversion rates relative to each flow's first step.
|
|
1516
|
+
*
|
|
1517
|
+
* Server-side filters: `productId`, `nicheSubtype` (the niche pack
|
|
1518
|
+
* slug — UI-friendly alias of the column name), `fromDate`,
|
|
1519
|
+
* `toDate`. Both date bounds default to the trailing 30 days. The
|
|
1520
|
+
* server clamps the window at 180 days and rejects
|
|
1521
|
+
* `fromDate >= toDate` with 400 INVALID_FIELD.
|
|
1522
|
+
*
|
|
1523
|
+
* Powers the admin Sankey + per-step bar chart in Task 4.3.2.
|
|
1524
|
+
*/
|
|
1525
|
+
getOnboardingFunnel(params?: OnboardingAnalyticsFiltersParams): Promise<OnboardingFunnelResponse>;
|
|
1526
|
+
/**
|
|
1527
|
+
* Median + p95 milliseconds spent on each step (per
|
|
1528
|
+
* `(productId, nichePackSlug, stepId)`), computed via
|
|
1529
|
+
* `LEAD(created_at) OVER (PARTITION BY session_id …)` on the event
|
|
1530
|
+
* stream. Sample size accompanies each row so the saas can
|
|
1531
|
+
* grey-out under-sampled buckets.
|
|
1532
|
+
*/
|
|
1533
|
+
getOnboardingTimeOnStep(params?: OnboardingAnalyticsFiltersParams): Promise<OnboardingTimeOnStepResponse>;
|
|
1534
|
+
/**
|
|
1535
|
+
* Histogram of `stepId` values where sessions went inactive — i.e.
|
|
1536
|
+
* `status = 'abandoned'` OR (active for >24h with no further
|
|
1537
|
+
* events). The server also tallies a `totalAbandoned` aggregate so
|
|
1538
|
+
* the saas can render a percentage column without re-summing.
|
|
1539
|
+
*/
|
|
1540
|
+
getOnboardingAbandonment(params?: OnboardingAnalyticsFiltersParams): Promise<OnboardingAbandonmentResponse>;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
64
1543
|
interface CheckoutProduct {
|
|
65
1544
|
externalId: string;
|
|
66
1545
|
name: string;
|
|
@@ -628,9 +2107,15 @@ declare class Automations extends APIResource {
|
|
|
628
2107
|
}
|
|
629
2108
|
|
|
630
2109
|
/**
|
|
631
|
-
* The specific UI control type suggested for a field
|
|
2110
|
+
* The specific UI control type suggested for a field on a `ResourceManifest`.
|
|
2111
|
+
*
|
|
2112
|
+
* NOTE: this is the UI-hint vocabulary used by `ResourceManifest`. It is
|
|
2113
|
+
* intentionally distinct from the custom-fields `FieldType` (16 storage
|
|
2114
|
+
* types) exported from `./custom-fields`. Use `ManifestFieldType` when
|
|
2115
|
+
* declaring auto-generated form fields, and `FieldType` (custom-fields)
|
|
2116
|
+
* when declaring tenant-owned custom fields stored in `dynamic_fields`.
|
|
632
2117
|
*/
|
|
633
|
-
type
|
|
2118
|
+
type ManifestFieldType = "string" | "number" | "boolean" | "date" | "datetime" | "select" | "multi-select" | "phone" | "email" | "currency" | "json" | "textarea" | "richtext" | "file" | "image";
|
|
634
2119
|
/**
|
|
635
2120
|
* Metadata defining a single field within a resource.
|
|
636
2121
|
* Used by UI kits to automatically generate forms and validation logic.
|
|
@@ -641,7 +2126,7 @@ interface FieldManifest {
|
|
|
641
2126
|
/** Human-readable label (localized if possible). */
|
|
642
2127
|
label: string;
|
|
643
2128
|
/** Suggested UI type. */
|
|
644
|
-
type:
|
|
2129
|
+
type: ManifestFieldType;
|
|
645
2130
|
/** Short hint/placeholder text. */
|
|
646
2131
|
description?: string;
|
|
647
2132
|
/** Whether the field is required for creation. */
|
|
@@ -689,13 +2174,70 @@ interface ResourceManifest {
|
|
|
689
2174
|
}
|
|
690
2175
|
|
|
691
2176
|
/**
|
|
692
|
-
*
|
|
2177
|
+
* Org-wide lifecycle status of a CRM Lead. Matches the `erix_leads.status`
|
|
2178
|
+
* column in Postgres and the legacy Mongoose `Lead.status` enum.
|
|
2179
|
+
*
|
|
2180
|
+
* open — active in any pipeline (default for new leads)
|
|
2181
|
+
* won — closed positively (set when stage.isWon = true)
|
|
2182
|
+
* lost — closed negatively (set when stage.isLost = true)
|
|
2183
|
+
* archived — soft-deleted / parked
|
|
2184
|
+
*
|
|
2185
|
+
* NOTE: the Kanban columns visible in the UI ("New", "Contacted",
|
|
2186
|
+
* "Qualified", etc.) are *pipeline stages* (`Lead.stageId` →
|
|
2187
|
+
* `PipelineStage`), NOT statuses. To move a lead between Kanban columns,
|
|
2188
|
+
* call `leads.move(leadId, stageId)`. Use `leads.update(leadId, { status })`
|
|
2189
|
+
* only to flip the lifecycle to one of the four values above.
|
|
693
2190
|
*/
|
|
694
|
-
type LeadStatus = "
|
|
2191
|
+
type LeadStatus = "open" | "won" | "lost" | "archived";
|
|
2192
|
+
/**
|
|
2193
|
+
* Runtime list of every valid LeadStatus value. Use this when validating
|
|
2194
|
+
* input or rendering selectors so the array stays in sync with the type.
|
|
2195
|
+
*/
|
|
2196
|
+
declare const LEAD_STATUS_VALUES: readonly ["open", "won", "lost", "archived"];
|
|
695
2197
|
/**
|
|
696
2198
|
* Common lead acquisition sources. Additional string values are allowed.
|
|
697
2199
|
*/
|
|
698
2200
|
type LeadSource = "website" | "whatsapp" | "direct" | "referral" | string;
|
|
2201
|
+
/**
|
|
2202
|
+
* Lead entity as returned by the API. Mongo-shaped (`_id`).
|
|
2203
|
+
*
|
|
2204
|
+
* `pipelineId` and `stageId` may be either an ID string or a populated
|
|
2205
|
+
* sub-document depending on whether the endpoint expanded them.
|
|
2206
|
+
*/
|
|
2207
|
+
interface Lead {
|
|
2208
|
+
_id: string;
|
|
2209
|
+
firstName: string;
|
|
2210
|
+
lastName?: string;
|
|
2211
|
+
phone: string;
|
|
2212
|
+
email?: string;
|
|
2213
|
+
company?: string;
|
|
2214
|
+
status: LeadStatus;
|
|
2215
|
+
value?: number;
|
|
2216
|
+
source?: string;
|
|
2217
|
+
assignedTo?: string;
|
|
2218
|
+
tags?: string[];
|
|
2219
|
+
pipelineId?: string | {
|
|
2220
|
+
_id: string;
|
|
2221
|
+
name: string;
|
|
2222
|
+
isDefault?: boolean;
|
|
2223
|
+
};
|
|
2224
|
+
stageId?: string | {
|
|
2225
|
+
_id: string;
|
|
2226
|
+
name: string;
|
|
2227
|
+
color: string;
|
|
2228
|
+
probability?: number;
|
|
2229
|
+
isWon?: boolean;
|
|
2230
|
+
isLost?: boolean;
|
|
2231
|
+
order?: number;
|
|
2232
|
+
};
|
|
2233
|
+
score?: number;
|
|
2234
|
+
lastContactedAt?: string;
|
|
2235
|
+
createdAt: string;
|
|
2236
|
+
updatedAt: string;
|
|
2237
|
+
metadata?: Record<string, unknown>;
|
|
2238
|
+
/** Custom fields dictionary keyed by FieldDefinition.id. */
|
|
2239
|
+
dynamic_fields?: Record<string, unknown>;
|
|
2240
|
+
}
|
|
699
2241
|
/**
|
|
700
2242
|
* Parameters for creating a new CRM Lead.
|
|
701
2243
|
*/
|
|
@@ -1051,6 +2593,32 @@ declare class Payments extends APIResource {
|
|
|
1051
2593
|
}): Promise<T>;
|
|
1052
2594
|
}
|
|
1053
2595
|
|
|
2596
|
+
/**
|
|
2597
|
+
* A single stage inside a CRM pipeline (Mongo-shaped `_id`).
|
|
2598
|
+
*/
|
|
2599
|
+
interface PipelineStage {
|
|
2600
|
+
_id: string;
|
|
2601
|
+
name: string;
|
|
2602
|
+
color: string;
|
|
2603
|
+
probability?: number;
|
|
2604
|
+
isWon?: boolean;
|
|
2605
|
+
isLost?: boolean;
|
|
2606
|
+
order: number;
|
|
2607
|
+
}
|
|
2608
|
+
/**
|
|
2609
|
+
* A CRM pipeline returned by the API. Stages are embedded.
|
|
2610
|
+
*/
|
|
2611
|
+
interface Pipeline {
|
|
2612
|
+
_id: string;
|
|
2613
|
+
name: string;
|
|
2614
|
+
isDefault: boolean;
|
|
2615
|
+
stages: PipelineStage[];
|
|
2616
|
+
}
|
|
2617
|
+
interface CreatePipelineParams {
|
|
2618
|
+
name: string;
|
|
2619
|
+
isDefault?: boolean;
|
|
2620
|
+
stages?: any[];
|
|
2621
|
+
}
|
|
1054
2622
|
interface PipelineStageParams {
|
|
1055
2623
|
name: string;
|
|
1056
2624
|
color?: string;
|
|
@@ -1669,6 +3237,118 @@ declare class EventsResource extends APIResource {
|
|
|
1669
3237
|
}): Promise<T>;
|
|
1670
3238
|
}
|
|
1671
3239
|
|
|
3240
|
+
/**
|
|
3241
|
+
* ERIX-Flow — no-code visual workflow orchestration.
|
|
3242
|
+
*
|
|
3243
|
+
* Create, manage, and trigger flow-based automations with a visual canvas.
|
|
3244
|
+
* Mounted at `/api/flow/v1`.
|
|
3245
|
+
*
|
|
3246
|
+
* @example
|
|
3247
|
+
* ```typescript
|
|
3248
|
+
* const workflows = await ecod.flow.list();
|
|
3249
|
+
* const run = await ecod.flow.run(workflowId, { seed: { person: { phone: "+91..." } } });
|
|
3250
|
+
* const status = await ecod.flow.getRun(run.runId);
|
|
3251
|
+
* ```
|
|
3252
|
+
*/
|
|
3253
|
+
declare class Flow extends APIResource {
|
|
3254
|
+
/**
|
|
3255
|
+
* List flow definitions for the tenant.
|
|
3256
|
+
*/
|
|
3257
|
+
list<T = any>(params?: {
|
|
3258
|
+
page?: number;
|
|
3259
|
+
limit?: number;
|
|
3260
|
+
status?: string;
|
|
3261
|
+
}): Promise<T>;
|
|
3262
|
+
/**
|
|
3263
|
+
* Create a new flow definition.
|
|
3264
|
+
*/
|
|
3265
|
+
create<T = any>(payload: {
|
|
3266
|
+
name: string;
|
|
3267
|
+
description?: string;
|
|
3268
|
+
graph: {
|
|
3269
|
+
nodes: unknown[];
|
|
3270
|
+
edges: unknown[];
|
|
3271
|
+
};
|
|
3272
|
+
status?: string;
|
|
3273
|
+
triggerType?: string;
|
|
3274
|
+
triggerConfig?: unknown;
|
|
3275
|
+
}): Promise<T>;
|
|
3276
|
+
/**
|
|
3277
|
+
* Get a single flow definition by ID.
|
|
3278
|
+
*/
|
|
3279
|
+
getWorkflow<T = any>(id: string): Promise<T>;
|
|
3280
|
+
/**
|
|
3281
|
+
* Update a flow definition.
|
|
3282
|
+
*/
|
|
3283
|
+
update<T = any>(id: string, payload: {
|
|
3284
|
+
name?: string;
|
|
3285
|
+
description?: string;
|
|
3286
|
+
graph?: {
|
|
3287
|
+
nodes: unknown[];
|
|
3288
|
+
edges: unknown[];
|
|
3289
|
+
};
|
|
3290
|
+
status?: string;
|
|
3291
|
+
}): Promise<T>;
|
|
3292
|
+
/**
|
|
3293
|
+
* Trigger a flow run. Returns the runId for tracking.
|
|
3294
|
+
*/
|
|
3295
|
+
run<T = any>(workflowId: string, payload?: {
|
|
3296
|
+
triggerType?: string;
|
|
3297
|
+
seed?: {
|
|
3298
|
+
recordId?: string;
|
|
3299
|
+
person?: {
|
|
3300
|
+
fullName?: string;
|
|
3301
|
+
email?: string;
|
|
3302
|
+
phone?: string;
|
|
3303
|
+
};
|
|
3304
|
+
company?: {
|
|
3305
|
+
name?: string;
|
|
3306
|
+
domain?: string;
|
|
3307
|
+
};
|
|
3308
|
+
crm?: {
|
|
3309
|
+
contactRef?: string;
|
|
3310
|
+
stage?: string;
|
|
3311
|
+
};
|
|
3312
|
+
};
|
|
3313
|
+
}): Promise<T>;
|
|
3314
|
+
/**
|
|
3315
|
+
* Get a run's summary + node statuses.
|
|
3316
|
+
*/
|
|
3317
|
+
getRun<T = any>(runId: string): Promise<T>;
|
|
3318
|
+
/**
|
|
3319
|
+
* Get run records (review surface, PII-redacted).
|
|
3320
|
+
*/
|
|
3321
|
+
getRunRecords<T = any>(runId: string): Promise<T>;
|
|
3322
|
+
/**
|
|
3323
|
+
* Retry a failed run from the failed node.
|
|
3324
|
+
*/
|
|
3325
|
+
retry<T = any>(runId: string): Promise<T>;
|
|
3326
|
+
/**
|
|
3327
|
+
* Approve/reject/edit at an approval checkpoint.
|
|
3328
|
+
*/
|
|
3329
|
+
approve<T = any>(runId: string, payload: {
|
|
3330
|
+
decision: "approve" | "reject" | "edit";
|
|
3331
|
+
record?: Record<string, unknown>;
|
|
3332
|
+
nodeId?: string;
|
|
3333
|
+
}): Promise<T>;
|
|
3334
|
+
/**
|
|
3335
|
+
* Get run execution logs.
|
|
3336
|
+
*/
|
|
3337
|
+
getRunLogs<T = any>(runId: string): Promise<T>;
|
|
3338
|
+
/**
|
|
3339
|
+
* List installable flow templates.
|
|
3340
|
+
*/
|
|
3341
|
+
templates<T = any>(params?: {
|
|
3342
|
+
category?: string;
|
|
3343
|
+
}): Promise<T>;
|
|
3344
|
+
/**
|
|
3345
|
+
* Install a template into the tenant's workspace.
|
|
3346
|
+
*/
|
|
3347
|
+
installTemplate<T = any>(templateId: string, payload?: {
|
|
3348
|
+
name?: string;
|
|
3349
|
+
}): Promise<T>;
|
|
3350
|
+
}
|
|
3351
|
+
|
|
1672
3352
|
interface SystemHealth {
|
|
1673
3353
|
status: string;
|
|
1674
3354
|
version: string;
|
|
@@ -1733,6 +3413,58 @@ declare class Health extends APIResource {
|
|
|
1733
3413
|
jobStatus(jobId: string): Promise<JobStatus>;
|
|
1734
3414
|
}
|
|
1735
3415
|
|
|
3416
|
+
/**
|
|
3417
|
+
* Invoices — CRM invoice management.
|
|
3418
|
+
*
|
|
3419
|
+
* Create, send, and track invoices for CRM deals.
|
|
3420
|
+
* Mounted at `/api/saas/invoices`.
|
|
3421
|
+
*
|
|
3422
|
+
* @example
|
|
3423
|
+
* ```typescript
|
|
3424
|
+
* const invoices = await ecod.invoices.list();
|
|
3425
|
+
* const inv = await ecod.invoices.create({ leadId, items, currency: "INR" });
|
|
3426
|
+
* await ecod.invoices.sendViaWhatsApp(inv.id);
|
|
3427
|
+
* ```
|
|
3428
|
+
*/
|
|
3429
|
+
declare class Invoices extends APIResource {
|
|
3430
|
+
/**
|
|
3431
|
+
* List invoices for the tenant.
|
|
3432
|
+
*/
|
|
3433
|
+
list<T = any>(params?: {
|
|
3434
|
+
page?: number;
|
|
3435
|
+
limit?: number;
|
|
3436
|
+
status?: string;
|
|
3437
|
+
}): Promise<T>;
|
|
3438
|
+
/**
|
|
3439
|
+
* Get a single invoice by ID.
|
|
3440
|
+
*/
|
|
3441
|
+
getInvoice<T = any>(id: string): Promise<T>;
|
|
3442
|
+
/**
|
|
3443
|
+
* Create a new invoice.
|
|
3444
|
+
*/
|
|
3445
|
+
create<T = any>(payload: Record<string, unknown>): Promise<T>;
|
|
3446
|
+
/**
|
|
3447
|
+
* Update an invoice.
|
|
3448
|
+
*/
|
|
3449
|
+
update<T = any>(id: string, payload: Record<string, unknown>): Promise<T>;
|
|
3450
|
+
/**
|
|
3451
|
+
* Delete an invoice.
|
|
3452
|
+
*/
|
|
3453
|
+
delete<T = any>(id: string): Promise<T>;
|
|
3454
|
+
/**
|
|
3455
|
+
* Send an invoice via WhatsApp to the linked lead.
|
|
3456
|
+
*/
|
|
3457
|
+
sendViaWhatsApp<T = any>(id: string): Promise<T>;
|
|
3458
|
+
/**
|
|
3459
|
+
* Get invoice settings for the tenant.
|
|
3460
|
+
*/
|
|
3461
|
+
getSettings<T = any>(): Promise<T>;
|
|
3462
|
+
/**
|
|
3463
|
+
* Update invoice settings.
|
|
3464
|
+
*/
|
|
3465
|
+
updateSettings<T = any>(payload: Record<string, unknown>): Promise<T>;
|
|
3466
|
+
}
|
|
3467
|
+
|
|
1736
3468
|
interface LogPaginationQuery {
|
|
1737
3469
|
page?: number;
|
|
1738
3470
|
limit?: number;
|
|
@@ -2420,6 +4152,270 @@ declare class Notifications extends APIResource {
|
|
|
2420
4152
|
retryAction<T = any>(notificationId: string): Promise<T>;
|
|
2421
4153
|
}
|
|
2422
4154
|
|
|
4155
|
+
/**
|
|
4156
|
+
* Body of `POST /api/onboarding/global` — the four-question signup form.
|
|
4157
|
+
*
|
|
4158
|
+
* Fields land directly on `ecodrix_organizations.*` columns (workspace
|
|
4159
|
+
* name, timezone) and `service_config -> 'global'` (primary product,
|
|
4160
|
+
* adaptive flag). See REQ-001.
|
|
4161
|
+
*/
|
|
4162
|
+
interface GlobalOnboardingPayload {
|
|
4163
|
+
/** Workspace / org display name. Persisted to `ecodrix_organizations.name`. */
|
|
4164
|
+
workspaceName: string;
|
|
4165
|
+
/** Personal display name of the signing-up user. */
|
|
4166
|
+
displayName: string;
|
|
4167
|
+
/** IANA timezone, e.g. `"Asia/Kolkata"`. Persisted to `organizations.timezone`. */
|
|
4168
|
+
timezone: string;
|
|
4169
|
+
/**
|
|
4170
|
+
* The product the user wants to start with. `"not_sure"` defers
|
|
4171
|
+
* per-product onboarding to first product open.
|
|
4172
|
+
*/
|
|
4173
|
+
primaryProduct: "crm" | "laie" | "flow" | "not_sure";
|
|
4174
|
+
}
|
|
4175
|
+
/**
|
|
4176
|
+
* Body of `POST /api/onboarding/start` — opens a per-product onboarding
|
|
4177
|
+
* session. Triggered by the explicit "Enable {Product}" click on
|
|
4178
|
+
* `/products/<productId>` (REQ-002).
|
|
4179
|
+
*/
|
|
4180
|
+
interface StartOnboardingPayload {
|
|
4181
|
+
productId: "crm" | "laie" | "flow";
|
|
4182
|
+
}
|
|
4183
|
+
/**
|
|
4184
|
+
* Body of `POST /api/onboarding/answer` — records one step's answer and
|
|
4185
|
+
* advances the engine. The saas calls this on every step submit (and as
|
|
4186
|
+
* a debounced PATCH for resumability).
|
|
4187
|
+
*/
|
|
4188
|
+
interface AnswerOnboardingPayload {
|
|
4189
|
+
sessionId: string;
|
|
4190
|
+
stepId: string;
|
|
4191
|
+
/** Shape depends on the step type — string, string[], boolean, etc. */
|
|
4192
|
+
answer: unknown;
|
|
4193
|
+
}
|
|
4194
|
+
/**
|
|
4195
|
+
* Body of `POST /api/onboarding/complete` — terminates the session,
|
|
4196
|
+
* upserts the persona, and materializes the workspace defaults.
|
|
4197
|
+
*/
|
|
4198
|
+
interface CompleteOnboardingPayload {
|
|
4199
|
+
sessionId: string;
|
|
4200
|
+
}
|
|
4201
|
+
/**
|
|
4202
|
+
* Body of `POST /api/onboarding/edit` — post-completion edit of a single
|
|
4203
|
+
* answer from `/settings/onboarding`. Triggers a `persona_recomputed`
|
|
4204
|
+
* event (REQ-010).
|
|
4205
|
+
*/
|
|
4206
|
+
interface EditOnboardingPayload {
|
|
4207
|
+
stepId: string;
|
|
4208
|
+
answer: unknown;
|
|
4209
|
+
}
|
|
4210
|
+
/**
|
|
4211
|
+
* Result of `POST /api/onboarding/start`.
|
|
4212
|
+
*/
|
|
4213
|
+
interface StartOnboardingResponse {
|
|
4214
|
+
sessionId: string;
|
|
4215
|
+
firstStep: OnboardingStep;
|
|
4216
|
+
}
|
|
4217
|
+
/**
|
|
4218
|
+
* Result of `POST /api/onboarding/answer`.
|
|
4219
|
+
*/
|
|
4220
|
+
interface AnswerOnboardingResponse {
|
|
4221
|
+
/** `null` when the engine has reached the final step. */
|
|
4222
|
+
nextStep: OnboardingStep | null;
|
|
4223
|
+
draftPersona: Record<string, unknown>;
|
|
4224
|
+
}
|
|
4225
|
+
/**
|
|
4226
|
+
* Result of `GET /api/onboarding/state`. Returns the active session
|
|
4227
|
+
* (status `"active"`) for `(userId, productId)`, plus the step the
|
|
4228
|
+
* renderer should currently show.
|
|
4229
|
+
*/
|
|
4230
|
+
interface OnboardingStateResponse {
|
|
4231
|
+
session: OnboardingSession | null;
|
|
4232
|
+
currentStep: OnboardingStep | null;
|
|
4233
|
+
}
|
|
4234
|
+
/**
|
|
4235
|
+
* Result of `POST /api/onboarding/complete`.
|
|
4236
|
+
*/
|
|
4237
|
+
interface CompleteOnboardingResponse {
|
|
4238
|
+
/** Opaque persona document — full type lives in `resources/persona.ts`. */
|
|
4239
|
+
persona: Record<string, unknown>;
|
|
4240
|
+
workspaceProfile: WorkspaceProfile;
|
|
4241
|
+
}
|
|
4242
|
+
/**
|
|
4243
|
+
* Result of `POST /api/onboarding/edit`.
|
|
4244
|
+
*/
|
|
4245
|
+
interface EditOnboardingResponse {
|
|
4246
|
+
persona: Record<string, unknown>;
|
|
4247
|
+
/** RFC 6902 JSON Patch describing what changed in the persona. */
|
|
4248
|
+
diff: Array<Record<string, unknown>>;
|
|
4249
|
+
}
|
|
4250
|
+
/**
|
|
4251
|
+
* Adaptive onboarding resource.
|
|
4252
|
+
*
|
|
4253
|
+
* Mounted on the main client as `ecod.onboarding`. Mirrors the seven
|
|
4254
|
+
* tenant-facing routes documented in `design.md` § "API surface".
|
|
4255
|
+
*
|
|
4256
|
+
* @example
|
|
4257
|
+
* ```typescript
|
|
4258
|
+
* await ecod.onboarding.global({
|
|
4259
|
+
* workspaceName: "Acme Health",
|
|
4260
|
+
* displayName: "Alice",
|
|
4261
|
+
* timezone: "Asia/Kolkata",
|
|
4262
|
+
* primaryProduct: "crm",
|
|
4263
|
+
* });
|
|
4264
|
+
*
|
|
4265
|
+
* const { sessionId, firstStep } = await ecod.onboarding.start({ productId: "crm" });
|
|
4266
|
+
* await ecod.onboarding.answer({ sessionId, stepId: firstStep.stepId, answer: "healthcare" });
|
|
4267
|
+
* await ecod.onboarding.complete({ sessionId });
|
|
4268
|
+
* ```
|
|
4269
|
+
*/
|
|
4270
|
+
declare class Onboarding extends APIResource {
|
|
4271
|
+
/**
|
|
4272
|
+
* Submit the four-question global onboarding form (REQ-001).
|
|
4273
|
+
* Updates `ecodrix_organizations.*` columns and
|
|
4274
|
+
* `service_config.global.primaryProduct`.
|
|
4275
|
+
*/
|
|
4276
|
+
global<T = unknown>(payload: GlobalOnboardingPayload): Promise<T>;
|
|
4277
|
+
/**
|
|
4278
|
+
* Open a per-product onboarding session. Called when the user clicks
|
|
4279
|
+
* "Enable {Product}" on `/products/<productId>` (REQ-002).
|
|
4280
|
+
*/
|
|
4281
|
+
start(payload: StartOnboardingPayload): Promise<StartOnboardingResponse>;
|
|
4282
|
+
/**
|
|
4283
|
+
* Record one step's answer and advance the engine. Returns the next
|
|
4284
|
+
* step (or `null` at the end) and the in-progress draft persona.
|
|
4285
|
+
*/
|
|
4286
|
+
answer(payload: AnswerOnboardingPayload): Promise<AnswerOnboardingResponse>;
|
|
4287
|
+
/**
|
|
4288
|
+
* Load the active session for the calling user + product. Used on
|
|
4289
|
+
* page mount + every revisit to support resumability (REQ-010).
|
|
4290
|
+
*/
|
|
4291
|
+
state(productId: string): Promise<OnboardingStateResponse>;
|
|
4292
|
+
/**
|
|
4293
|
+
* Finalise the session, upsert the persona, and materialize the
|
|
4294
|
+
* niche-tuned workspace defaults.
|
|
4295
|
+
*/
|
|
4296
|
+
complete(payload: CompleteOnboardingPayload): Promise<CompleteOnboardingResponse>;
|
|
4297
|
+
/**
|
|
4298
|
+
* Edit a previously-answered step from `/settings/onboarding`. The
|
|
4299
|
+
* server emits a `persona_recomputed` event so the workspace and
|
|
4300
|
+
* persona update in-session (REQ-010).
|
|
4301
|
+
*/
|
|
4302
|
+
edit(payload: EditOnboardingPayload): Promise<EditOnboardingResponse>;
|
|
4303
|
+
/**
|
|
4304
|
+
* Preview the workspace profile that would be materialized if the
|
|
4305
|
+
* session completed right now. Used by the `feature_preview` step.
|
|
4306
|
+
*/
|
|
4307
|
+
previewWorkspace(sessionId: string): Promise<WorkspaceProfile>;
|
|
4308
|
+
}
|
|
4309
|
+
|
|
4310
|
+
/**
|
|
4311
|
+
* Portal Inbox — team-side unified inbox for portal conversations.
|
|
4312
|
+
*
|
|
4313
|
+
* Lists all projects with active client threads, retrieves messages,
|
|
4314
|
+
* and posts replies. Mounted at `/api/saas/portal-inbox`.
|
|
4315
|
+
*
|
|
4316
|
+
* @example
|
|
4317
|
+
* ```typescript
|
|
4318
|
+
* const threads = await ecod.portalInbox.conversations();
|
|
4319
|
+
* const messages = await ecod.portalInbox.messages(projectId);
|
|
4320
|
+
* await ecod.portalInbox.reply(projectId, { body: "We'll get back to you!" });
|
|
4321
|
+
* ```
|
|
4322
|
+
*/
|
|
4323
|
+
declare class PortalInbox extends APIResource {
|
|
4324
|
+
/**
|
|
4325
|
+
* List all projects with active portal conversation threads.
|
|
4326
|
+
* Returns projectId, projectName, lastMessageAt, lastBody, lastSender, unreadCount.
|
|
4327
|
+
*/
|
|
4328
|
+
conversations<T = any>(): Promise<T>;
|
|
4329
|
+
/**
|
|
4330
|
+
* Get paginated messages for a project's portal thread.
|
|
4331
|
+
*/
|
|
4332
|
+
messages<T = any>(projectId: string): Promise<T>;
|
|
4333
|
+
/**
|
|
4334
|
+
* Post a reply from the team to a project's portal thread.
|
|
4335
|
+
*/
|
|
4336
|
+
reply<T = any>(projectId: string, payload: {
|
|
4337
|
+
body: string;
|
|
4338
|
+
attachments?: Array<{
|
|
4339
|
+
name: string;
|
|
4340
|
+
url: string;
|
|
4341
|
+
}>;
|
|
4342
|
+
}): Promise<T>;
|
|
4343
|
+
}
|
|
4344
|
+
|
|
4345
|
+
/**
|
|
4346
|
+
* Project Documents + E-Sign — document management and digital signatures
|
|
4347
|
+
* for CRM projects.
|
|
4348
|
+
*
|
|
4349
|
+
* Mounted at `/api/saas/projects/:projectId/documents`.
|
|
4350
|
+
*
|
|
4351
|
+
* @example
|
|
4352
|
+
* ```typescript
|
|
4353
|
+
* const docs = await ecod.projectDocuments.list(projectId);
|
|
4354
|
+
* await ecod.projectDocuments.upload(projectId, { name: "Contract.pdf", fileKey, mimeType });
|
|
4355
|
+
* await ecod.projectDocuments.toggleSignature(projectId, docId, true);
|
|
4356
|
+
* await ecod.projectDocuments.addSigner(projectId, docId, { role: "client", name: "Alice" });
|
|
4357
|
+
* await ecod.projectDocuments.stampSign(projectId, docId, { signatureImage: base64Png });
|
|
4358
|
+
* ```
|
|
4359
|
+
*/
|
|
4360
|
+
declare class ProjectDocuments extends APIResource {
|
|
4361
|
+
/**
|
|
4362
|
+
* List all documents for a project.
|
|
4363
|
+
*/
|
|
4364
|
+
list<T = any>(projectId: string): Promise<T>;
|
|
4365
|
+
/**
|
|
4366
|
+
* Register an uploaded document (after uploading to R2 via presigned URL).
|
|
4367
|
+
*/
|
|
4368
|
+
upload<T = any>(projectId: string, payload: {
|
|
4369
|
+
name: string;
|
|
4370
|
+
fileKey: string;
|
|
4371
|
+
mimeType: string;
|
|
4372
|
+
sizeBytes?: string;
|
|
4373
|
+
}): Promise<T>;
|
|
4374
|
+
/**
|
|
4375
|
+
* Toggle "Signature Required" on a document.
|
|
4376
|
+
* When enabled, triggers notifications to signers.
|
|
4377
|
+
*/
|
|
4378
|
+
toggleSignature<T = any>(projectId: string, docId: string, required: boolean): Promise<T>;
|
|
4379
|
+
/**
|
|
4380
|
+
* Add a signer to a document.
|
|
4381
|
+
*/
|
|
4382
|
+
addSigner<T = any>(projectId: string, docId: string, signer: {
|
|
4383
|
+
role: "owner" | "client";
|
|
4384
|
+
name: string;
|
|
4385
|
+
email?: string;
|
|
4386
|
+
userId?: string;
|
|
4387
|
+
}): Promise<T>;
|
|
4388
|
+
/**
|
|
4389
|
+
* Team user signs a document (simple mark — no PDF stamp).
|
|
4390
|
+
*/
|
|
4391
|
+
sign<T = any>(projectId: string, docId: string, payload?: {
|
|
4392
|
+
signedFileKey?: string;
|
|
4393
|
+
}): Promise<T>;
|
|
4394
|
+
/**
|
|
4395
|
+
* Team user declines signing a document.
|
|
4396
|
+
*/
|
|
4397
|
+
decline<T = any>(projectId: string, docId: string): Promise<T>;
|
|
4398
|
+
/**
|
|
4399
|
+
* Full signing ceremony — stamps a signature image onto the PDF,
|
|
4400
|
+
* computes an audit seal, and re-uploads the signed copy.
|
|
4401
|
+
*
|
|
4402
|
+
* @param signatureImage - Base64-encoded PNG of the drawn/typed signature
|
|
4403
|
+
* @param signerName - Name to stamp on the PDF
|
|
4404
|
+
* @param position - Optional position override { page?, x?, y?, width?, height? }
|
|
4405
|
+
*/
|
|
4406
|
+
stampSign<T = any>(projectId: string, docId: string, payload: {
|
|
4407
|
+
signatureImage: string;
|
|
4408
|
+
signerName?: string;
|
|
4409
|
+
position?: {
|
|
4410
|
+
page?: number;
|
|
4411
|
+
x?: number;
|
|
4412
|
+
y?: number;
|
|
4413
|
+
width?: number;
|
|
4414
|
+
height?: number;
|
|
4415
|
+
};
|
|
4416
|
+
}): Promise<T>;
|
|
4417
|
+
}
|
|
4418
|
+
|
|
2423
4419
|
interface JobStats {
|
|
2424
4420
|
waiting: number;
|
|
2425
4421
|
active: number;
|
|
@@ -2471,6 +4467,93 @@ declare class Queue extends APIResource {
|
|
|
2471
4467
|
deleteJob<T = any>(jobId: string): Promise<T>;
|
|
2472
4468
|
}
|
|
2473
4469
|
|
|
4470
|
+
/** Relay endpoint provenance. */
|
|
4471
|
+
type RelayOrigin = "seed" | "manual" | "auto";
|
|
4472
|
+
/** Relay egress type. */
|
|
4473
|
+
type RelayType = "cloudflare" | "gcp" | "lambda" | "browser" | "direct";
|
|
4474
|
+
/** Public relay record (secrets are NEVER included). */
|
|
4475
|
+
interface RelayRecord {
|
|
4476
|
+
id: string;
|
|
4477
|
+
type: RelayType;
|
|
4478
|
+
url: string | null;
|
|
4479
|
+
region: string | null;
|
|
4480
|
+
priority: number;
|
|
4481
|
+
enabled: boolean;
|
|
4482
|
+
origin: RelayOrigin;
|
|
4483
|
+
providerResourceId: string | null;
|
|
4484
|
+
provisionedAt: string | null;
|
|
4485
|
+
lastHealthyAt: string | null;
|
|
4486
|
+
health?: RelayEndpointHealth | null;
|
|
4487
|
+
}
|
|
4488
|
+
interface RelayEndpointHealth {
|
|
4489
|
+
key: string;
|
|
4490
|
+
type: RelayType;
|
|
4491
|
+
url?: string;
|
|
4492
|
+
region?: string;
|
|
4493
|
+
healthy: boolean;
|
|
4494
|
+
degradedUntil?: number;
|
|
4495
|
+
requestCount: number;
|
|
4496
|
+
errorCount: number;
|
|
4497
|
+
lastUsedAt?: number;
|
|
4498
|
+
}
|
|
4499
|
+
/** Hot-reloadable relay-fabric tuning. */
|
|
4500
|
+
interface RelayTuning {
|
|
4501
|
+
relayTimeoutMs: number;
|
|
4502
|
+
relayCooldownMs: number;
|
|
4503
|
+
pingIntervalMs: number;
|
|
4504
|
+
pingTimeoutMs: number;
|
|
4505
|
+
maxRetries: number;
|
|
4506
|
+
leadEnrichTimeoutMs: number;
|
|
4507
|
+
aiStepTimeoutMs: number;
|
|
4508
|
+
stuckJobTimeoutMs: number;
|
|
4509
|
+
targetHealthyRelays: number;
|
|
4510
|
+
autoProvisionEnabled: boolean;
|
|
4511
|
+
maxAutoRelaysPerType: number;
|
|
4512
|
+
maxAutoRelaysTotal: number;
|
|
4513
|
+
retireAfterDegradedMs: number;
|
|
4514
|
+
}
|
|
4515
|
+
interface RelayCreatePayload {
|
|
4516
|
+
type: RelayType;
|
|
4517
|
+
url?: string;
|
|
4518
|
+
region?: string;
|
|
4519
|
+
priority?: number;
|
|
4520
|
+
/** Key into the platform secret store — never a plaintext secret. */
|
|
4521
|
+
secretRef?: string;
|
|
4522
|
+
}
|
|
4523
|
+
interface RelayUpdatePayload {
|
|
4524
|
+
enabled?: boolean;
|
|
4525
|
+
priority?: number;
|
|
4526
|
+
region?: string;
|
|
4527
|
+
}
|
|
4528
|
+
interface RelayProvisionPayload {
|
|
4529
|
+
provider?: "lambda" | "cloudflare";
|
|
4530
|
+
region?: string;
|
|
4531
|
+
}
|
|
4532
|
+
/**
|
|
4533
|
+
* Dynamic Relay Fabric control plane. Authenticated with the platform CORE API
|
|
4534
|
+
* key (server-side only). Endpoints live under `/api/laie/v1/relays`.
|
|
4535
|
+
*/
|
|
4536
|
+
declare class Relays extends APIResource {
|
|
4537
|
+
/** List relays + live health (per-type aggregate + per-endpoint). */
|
|
4538
|
+
list<T = any>(): Promise<T>;
|
|
4539
|
+
/** Add a manual relay. */
|
|
4540
|
+
create<T = any>(payload: RelayCreatePayload): Promise<T>;
|
|
4541
|
+
/** Enable/disable/repriority a relay. */
|
|
4542
|
+
update<T = any>(id: string, payload: RelayUpdatePayload): Promise<T>;
|
|
4543
|
+
/** Remove a manual/auto relay (seed relays are never removable). */
|
|
4544
|
+
delete<T = any>(id: string): Promise<T>;
|
|
4545
|
+
/** Read the hot-reloadable tuning config. */
|
|
4546
|
+
getConfig<T = any>(): Promise<T>;
|
|
4547
|
+
/** Update the tuning config (audited). */
|
|
4548
|
+
updateConfig<T = any>(payload: Partial<RelayTuning>): Promise<T>;
|
|
4549
|
+
/** Force a health ping and return the snapshot. */
|
|
4550
|
+
ping<T = any>(): Promise<T>;
|
|
4551
|
+
/** Manually provision a cloud relay (auto-provisioning must be enabled). */
|
|
4552
|
+
provision<T = any>(payload?: RelayProvisionPayload): Promise<T>;
|
|
4553
|
+
/** Manually retire a relay. */
|
|
4554
|
+
retire<T = any>(id: string): Promise<T>;
|
|
4555
|
+
}
|
|
4556
|
+
|
|
2474
4557
|
declare class Clients extends APIResource {
|
|
2475
4558
|
/**
|
|
2476
4559
|
* List all clients in the ecosystem.
|
|
@@ -2591,7 +4674,7 @@ declare class Services extends APIResource {
|
|
|
2591
4674
|
constructor(client: any);
|
|
2592
4675
|
}
|
|
2593
4676
|
|
|
2594
|
-
declare class EmailConfig extends APIResource {
|
|
4677
|
+
declare class EmailConfig$1 extends APIResource {
|
|
2595
4678
|
/**
|
|
2596
4679
|
* Retrieve current email provider configuration and domain verification statuses.
|
|
2597
4680
|
*/
|
|
@@ -2646,7 +4729,7 @@ declare class EmailConfig extends APIResource {
|
|
|
2646
4729
|
listProviders<T = any>(): Promise<T>;
|
|
2647
4730
|
}
|
|
2648
4731
|
declare class Settings extends APIResource {
|
|
2649
|
-
email: EmailConfig;
|
|
4732
|
+
email: EmailConfig$1;
|
|
2650
4733
|
constructor(client: any);
|
|
2651
4734
|
}
|
|
2652
4735
|
|
|
@@ -2818,6 +4901,24 @@ declare class Webhooks {
|
|
|
2818
4901
|
constructEvent(payload: string | Buffer, signature: string | string[] | undefined, secret: string): Promise<any>;
|
|
2819
4902
|
}
|
|
2820
4903
|
|
|
4904
|
+
/**
|
|
4905
|
+
* Broadcast campaign entity returned by `/api/saas/chat/broadcasts`.
|
|
4906
|
+
*
|
|
4907
|
+
* Tracks the lifecycle of a bulk WhatsApp send and its delivery counters.
|
|
4908
|
+
*/
|
|
4909
|
+
interface Broadcast {
|
|
4910
|
+
_id: string;
|
|
4911
|
+
name: string;
|
|
4912
|
+
templateName: string;
|
|
4913
|
+
status: "draft" | "scheduled" | "sending" | "completed" | "failed";
|
|
4914
|
+
recipientCount: number;
|
|
4915
|
+
sentCount: number;
|
|
4916
|
+
deliveredCount: number;
|
|
4917
|
+
readCount: number;
|
|
4918
|
+
createdAt: string;
|
|
4919
|
+
scheduledAt?: string;
|
|
4920
|
+
completedAt?: string;
|
|
4921
|
+
}
|
|
2821
4922
|
interface CreateBroadcastParams {
|
|
2822
4923
|
/** Optional name for the broadcast campaign */
|
|
2823
4924
|
name?: string;
|
|
@@ -2899,6 +5000,28 @@ declare class Broadcasts extends APIResource {
|
|
|
2899
5000
|
delete<T = any>(id: string): Promise<T>;
|
|
2900
5001
|
}
|
|
2901
5002
|
|
|
5003
|
+
/**
|
|
5004
|
+
* Conversation entity returned by `/api/saas/chat/conversations`.
|
|
5005
|
+
*
|
|
5006
|
+
* Represents a single WhatsApp thread between the workspace and an
|
|
5007
|
+
* external phone number. `status` is the conversation lifecycle (open
|
|
5008
|
+
* vs resolved) — distinct from `LeadStatus` on the linked lead.
|
|
5009
|
+
*/
|
|
5010
|
+
interface Conversation {
|
|
5011
|
+
_id: string;
|
|
5012
|
+
phone: string;
|
|
5013
|
+
contactName?: string;
|
|
5014
|
+
lastMessage?: {
|
|
5015
|
+
body: string;
|
|
5016
|
+
timestamp: string;
|
|
5017
|
+
direction: "inbound" | "outbound";
|
|
5018
|
+
};
|
|
5019
|
+
unreadCount: number;
|
|
5020
|
+
status: "open" | "resolved";
|
|
5021
|
+
assignedTo?: string;
|
|
5022
|
+
leadId?: string;
|
|
5023
|
+
updatedAt: string;
|
|
5024
|
+
}
|
|
2902
5025
|
interface ListParams {
|
|
2903
5026
|
limit?: number;
|
|
2904
5027
|
before?: string;
|
|
@@ -3000,6 +5123,20 @@ declare class Conversations extends APIResource {
|
|
|
3000
5123
|
bulkDelete<T = any>(ids: string[]): Promise<T>;
|
|
3001
5124
|
}
|
|
3002
5125
|
|
|
5126
|
+
/**
|
|
5127
|
+
* A single chat message inside a `Conversation`.
|
|
5128
|
+
*/
|
|
5129
|
+
interface Message {
|
|
5130
|
+
_id: string;
|
|
5131
|
+
conversationId: string;
|
|
5132
|
+
body?: string;
|
|
5133
|
+
mediaUrl?: string;
|
|
5134
|
+
mediaType?: "image" | "video" | "audio" | "document";
|
|
5135
|
+
direction: "inbound" | "outbound";
|
|
5136
|
+
status: "sent" | "delivered" | "read" | "failed";
|
|
5137
|
+
timestamp: string;
|
|
5138
|
+
replyToId?: string;
|
|
5139
|
+
}
|
|
3003
5140
|
/**
|
|
3004
5141
|
* Parameters for sending a free-form WhatsApp message.
|
|
3005
5142
|
*/
|
|
@@ -3207,6 +5344,28 @@ declare class Messages extends APIResource {
|
|
|
3207
5344
|
}>;
|
|
3208
5345
|
}
|
|
3209
5346
|
|
|
5347
|
+
/**
|
|
5348
|
+
* Component of a Meta-approved WhatsApp template (HEADER / BODY / FOOTER /
|
|
5349
|
+
* BUTTONS).
|
|
5350
|
+
*/
|
|
5351
|
+
interface TemplateComponent {
|
|
5352
|
+
type: "HEADER" | "BODY" | "FOOTER" | "BUTTONS";
|
|
5353
|
+
text?: string;
|
|
5354
|
+
format?: string;
|
|
5355
|
+
}
|
|
5356
|
+
/**
|
|
5357
|
+
* WhatsApp message template entity.
|
|
5358
|
+
*
|
|
5359
|
+
* Status mirrors Meta's approval pipeline: APPROVED / PENDING / REJECTED.
|
|
5360
|
+
*/
|
|
5361
|
+
interface Template {
|
|
5362
|
+
_id: string;
|
|
5363
|
+
name: string;
|
|
5364
|
+
category: "MARKETING" | "UTILITY" | "AUTHENTICATION";
|
|
5365
|
+
language: string;
|
|
5366
|
+
status: "APPROVED" | "PENDING" | "REJECTED";
|
|
5367
|
+
components: TemplateComponent[];
|
|
5368
|
+
}
|
|
3210
5369
|
interface TemplateMapping {
|
|
3211
5370
|
mappings: any[];
|
|
3212
5371
|
onEmptyVariable: string;
|
|
@@ -3485,10 +5644,30 @@ declare class ECODrIxAPI {
|
|
|
3485
5644
|
readonly settings: Settings;
|
|
3486
5645
|
/** Dynamic Cross-Origin Resource Sharing network policies. */
|
|
3487
5646
|
readonly cors: Cors;
|
|
5647
|
+
/** LAIE Dynamic Relay Fabric control plane (CORE key, server-side only). */
|
|
5648
|
+
readonly relays: Relays;
|
|
3488
5649
|
/** ErixCheckout one-click checkout flow management. */
|
|
3489
5650
|
readonly checkout: Checkout;
|
|
3490
5651
|
/** ERIX-Connect — tenant connections (channels, credentials, DB residency). */
|
|
3491
5652
|
readonly connect: Connect;
|
|
5653
|
+
/** Adaptive onboarding — global + per-product config-driven flows. */
|
|
5654
|
+
readonly onboarding: Onboarding;
|
|
5655
|
+
/**
|
|
5656
|
+
* Platform-admin onboarding control plane (niche packs +
|
|
5657
|
+
* versioned onboarding configs). Server-side only — requires
|
|
5658
|
+
* the elevated `coreApiKey`.
|
|
5659
|
+
*/
|
|
5660
|
+
readonly adminOnboarding: AdminOnboarding;
|
|
5661
|
+
/** AI persona memory — read, reinforce, confidence score. */
|
|
5662
|
+
readonly persona: Persona;
|
|
5663
|
+
/** ERIX-Flow — no-code visual workflow orchestration. */
|
|
5664
|
+
readonly flow: Flow;
|
|
5665
|
+
/** Portal Inbox — team-side unified inbox for portal conversations. */
|
|
5666
|
+
readonly portalInbox: PortalInbox;
|
|
5667
|
+
/** Project Documents + E-Sign — document management and digital signatures. */
|
|
5668
|
+
readonly projectDocuments: ProjectDocuments;
|
|
5669
|
+
/** Invoices — CRM invoice management. */
|
|
5670
|
+
readonly invoices: Invoices;
|
|
3492
5671
|
constructor(options: ECODrIxAPIOptions);
|
|
3493
5672
|
private initSocket;
|
|
3494
5673
|
/**
|
|
@@ -3571,6 +5750,243 @@ declare class ECODrIxAPI {
|
|
|
3571
5750
|
request<T = any>(method: Method, path: string, data?: any, params?: any): Promise<T>;
|
|
3572
5751
|
}
|
|
3573
5752
|
|
|
5753
|
+
/**
|
|
5754
|
+
* Common response envelopes returned by the ERIX API.
|
|
5755
|
+
*/
|
|
5756
|
+
/**
|
|
5757
|
+
* Standard paginated response shape.
|
|
5758
|
+
*
|
|
5759
|
+
* Used by list endpoints that page results (e.g. leads, conversations,
|
|
5760
|
+
* broadcasts). Frontend consumers can rely on `data` + `pagination` being
|
|
5761
|
+
* present.
|
|
5762
|
+
*/
|
|
5763
|
+
interface PaginatedResponse<T> {
|
|
5764
|
+
data: T[];
|
|
5765
|
+
pagination: {
|
|
5766
|
+
page: number;
|
|
5767
|
+
limit: number;
|
|
5768
|
+
total: number;
|
|
5769
|
+
pages: number;
|
|
5770
|
+
};
|
|
5771
|
+
}
|
|
5772
|
+
|
|
5773
|
+
/**
|
|
5774
|
+
* Custom field type system for the ERIX CRM module.
|
|
5775
|
+
*
|
|
5776
|
+
* Defines the FieldType discriminated union, per-type config interfaces,
|
|
5777
|
+
* and the stored value shapes persisted in a lead's `dynamic_fields`
|
|
5778
|
+
* column.
|
|
5779
|
+
*
|
|
5780
|
+
* This is the single contract used by both the backend (server adapters,
|
|
5781
|
+
* validators, formula evaluators) and the saas frontend (designer UI,
|
|
5782
|
+
* editors, renderers). Keep saas + server in sync by sharing this file.
|
|
5783
|
+
*/
|
|
5784
|
+
/** The 16 supported custom field types. */
|
|
5785
|
+
type FieldType = "text" | "number" | "currency" | "dropdown" | "date" | "datetime" | "phone" | "email" | "file" | "formula" | "relation" | "rating" | "progress" | "tags" | "url" | "checkbox";
|
|
5786
|
+
interface BaseConfig {
|
|
5787
|
+
required?: boolean;
|
|
5788
|
+
description?: string;
|
|
5789
|
+
}
|
|
5790
|
+
interface TextConfig extends BaseConfig {
|
|
5791
|
+
minLength?: number;
|
|
5792
|
+
maxLength?: number;
|
|
5793
|
+
pattern?: string;
|
|
5794
|
+
}
|
|
5795
|
+
interface NumberConfig extends BaseConfig {
|
|
5796
|
+
min?: number;
|
|
5797
|
+
max?: number;
|
|
5798
|
+
integer?: boolean;
|
|
5799
|
+
}
|
|
5800
|
+
interface CurrencyConfig extends BaseConfig {
|
|
5801
|
+
/** ISO 4217, default INR */
|
|
5802
|
+
defaultCurrency?: string;
|
|
5803
|
+
min?: number;
|
|
5804
|
+
max?: number;
|
|
5805
|
+
}
|
|
5806
|
+
interface DropdownConfig extends BaseConfig {
|
|
5807
|
+
options: {
|
|
5808
|
+
value: string;
|
|
5809
|
+
label: string;
|
|
5810
|
+
color?: string;
|
|
5811
|
+
}[];
|
|
5812
|
+
}
|
|
5813
|
+
/** ISO date */
|
|
5814
|
+
interface DateConfig extends BaseConfig {
|
|
5815
|
+
min?: string;
|
|
5816
|
+
max?: string;
|
|
5817
|
+
}
|
|
5818
|
+
/** ISO datetime */
|
|
5819
|
+
interface DateTimeConfig extends BaseConfig {
|
|
5820
|
+
min?: string;
|
|
5821
|
+
max?: string;
|
|
5822
|
+
}
|
|
5823
|
+
interface PhoneConfig extends BaseConfig {
|
|
5824
|
+
region?: string;
|
|
5825
|
+
}
|
|
5826
|
+
type EmailConfig = BaseConfig;
|
|
5827
|
+
interface FileConfig extends BaseConfig {
|
|
5828
|
+
maxSizeBytes?: number;
|
|
5829
|
+
accept?: string[];
|
|
5830
|
+
}
|
|
5831
|
+
interface FormulaConfig extends BaseConfig {
|
|
5832
|
+
expression: string;
|
|
5833
|
+
resultType: "number" | "text" | "boolean";
|
|
5834
|
+
}
|
|
5835
|
+
interface RelationConfig extends BaseConfig {
|
|
5836
|
+
targetEntity: "lead";
|
|
5837
|
+
displayField?: string;
|
|
5838
|
+
}
|
|
5839
|
+
interface RatingConfig extends BaseConfig {
|
|
5840
|
+
/** default 5 */
|
|
5841
|
+
max?: 5 | 10;
|
|
5842
|
+
}
|
|
5843
|
+
interface ProgressConfig extends BaseConfig {
|
|
5844
|
+
/** default 0..100 */
|
|
5845
|
+
min?: number;
|
|
5846
|
+
max?: number;
|
|
5847
|
+
}
|
|
5848
|
+
interface TagsConfig extends BaseConfig {
|
|
5849
|
+
options?: {
|
|
5850
|
+
value: string;
|
|
5851
|
+
label: string;
|
|
5852
|
+
color?: string;
|
|
5853
|
+
}[];
|
|
5854
|
+
allowFreeform?: boolean;
|
|
5855
|
+
}
|
|
5856
|
+
type UrlConfig = BaseConfig;
|
|
5857
|
+
type CheckboxConfig = BaseConfig;
|
|
5858
|
+
interface FieldDefBase {
|
|
5859
|
+
id: string;
|
|
5860
|
+
orgId: string;
|
|
5861
|
+
name: string;
|
|
5862
|
+
label: string;
|
|
5863
|
+
order: number;
|
|
5864
|
+
isActive: boolean;
|
|
5865
|
+
createdAt: string;
|
|
5866
|
+
updatedAt: string;
|
|
5867
|
+
}
|
|
5868
|
+
type FieldDefinition = (FieldDefBase & {
|
|
5869
|
+
fieldType: "text";
|
|
5870
|
+
config: TextConfig;
|
|
5871
|
+
}) | (FieldDefBase & {
|
|
5872
|
+
fieldType: "number";
|
|
5873
|
+
config: NumberConfig;
|
|
5874
|
+
}) | (FieldDefBase & {
|
|
5875
|
+
fieldType: "currency";
|
|
5876
|
+
config: CurrencyConfig;
|
|
5877
|
+
}) | (FieldDefBase & {
|
|
5878
|
+
fieldType: "dropdown";
|
|
5879
|
+
config: DropdownConfig;
|
|
5880
|
+
}) | (FieldDefBase & {
|
|
5881
|
+
fieldType: "date";
|
|
5882
|
+
config: DateConfig;
|
|
5883
|
+
}) | (FieldDefBase & {
|
|
5884
|
+
fieldType: "datetime";
|
|
5885
|
+
config: DateTimeConfig;
|
|
5886
|
+
}) | (FieldDefBase & {
|
|
5887
|
+
fieldType: "phone";
|
|
5888
|
+
config: PhoneConfig;
|
|
5889
|
+
}) | (FieldDefBase & {
|
|
5890
|
+
fieldType: "email";
|
|
5891
|
+
config: EmailConfig;
|
|
5892
|
+
}) | (FieldDefBase & {
|
|
5893
|
+
fieldType: "file";
|
|
5894
|
+
config: FileConfig;
|
|
5895
|
+
}) | (FieldDefBase & {
|
|
5896
|
+
fieldType: "formula";
|
|
5897
|
+
config: FormulaConfig;
|
|
5898
|
+
}) | (FieldDefBase & {
|
|
5899
|
+
fieldType: "relation";
|
|
5900
|
+
config: RelationConfig;
|
|
5901
|
+
}) | (FieldDefBase & {
|
|
5902
|
+
fieldType: "rating";
|
|
5903
|
+
config: RatingConfig;
|
|
5904
|
+
}) | (FieldDefBase & {
|
|
5905
|
+
fieldType: "progress";
|
|
5906
|
+
config: ProgressConfig;
|
|
5907
|
+
}) | (FieldDefBase & {
|
|
5908
|
+
fieldType: "tags";
|
|
5909
|
+
config: TagsConfig;
|
|
5910
|
+
}) | (FieldDefBase & {
|
|
5911
|
+
fieldType: "url";
|
|
5912
|
+
config: UrlConfig;
|
|
5913
|
+
}) | (FieldDefBase & {
|
|
5914
|
+
fieldType: "checkbox";
|
|
5915
|
+
config: CheckboxConfig;
|
|
5916
|
+
});
|
|
5917
|
+
type FieldConfig = FieldDefinition["config"];
|
|
5918
|
+
type CurrencyValue = {
|
|
5919
|
+
amount: number;
|
|
5920
|
+
currency: string;
|
|
5921
|
+
};
|
|
5922
|
+
type RelationValue = {
|
|
5923
|
+
leadId: string;
|
|
5924
|
+
};
|
|
5925
|
+
type StoredFieldValue = string | number | boolean | null | string[] | CurrencyValue | RelationValue;
|
|
5926
|
+
type NormalizedFieldValue = StoredFieldValue;
|
|
5927
|
+
|
|
5928
|
+
/**
|
|
5929
|
+
* CRM view configuration and filter model.
|
|
5930
|
+
*
|
|
5931
|
+
* Defines the layout, column, filter, sort, and color-rule shapes that
|
|
5932
|
+
* make up a saved CrmView, plus the adapter-level CustomFieldFilter
|
|
5933
|
+
* passed into leads.list for backend-specific query translation.
|
|
5934
|
+
*/
|
|
5935
|
+
|
|
5936
|
+
type LayoutType = "table" | "kanban" | "cards";
|
|
5937
|
+
interface ColumnConfig {
|
|
5938
|
+
/** default field name or custom field id */
|
|
5939
|
+
fieldKey: string;
|
|
5940
|
+
visible: boolean;
|
|
5941
|
+
/** px */
|
|
5942
|
+
width: number;
|
|
5943
|
+
order: number;
|
|
5944
|
+
}
|
|
5945
|
+
type FilterOperator = "contains" | "equals" | "startsWith" | "isEmpty" | "gt" | "lt" | "between" | "before" | "after" | "isAnyOf" | "isNoneOf";
|
|
5946
|
+
interface FilterRule {
|
|
5947
|
+
fieldKey: string;
|
|
5948
|
+
operator: FilterOperator;
|
|
5949
|
+
value?: unknown;
|
|
5950
|
+
}
|
|
5951
|
+
interface SortRule {
|
|
5952
|
+
fieldKey: string;
|
|
5953
|
+
dir: "asc" | "desc";
|
|
5954
|
+
}
|
|
5955
|
+
interface ColorRule {
|
|
5956
|
+
fieldKey: string;
|
|
5957
|
+
operator: FilterOperator;
|
|
5958
|
+
value?: unknown;
|
|
5959
|
+
color: string;
|
|
5960
|
+
target: "row" | "cell";
|
|
5961
|
+
}
|
|
5962
|
+
interface ViewConfig {
|
|
5963
|
+
columns: ColumnConfig[];
|
|
5964
|
+
sort: SortRule[];
|
|
5965
|
+
filters: FilterRule[];
|
|
5966
|
+
/** stage | source | assignedTo | <dropdown/tags field id> */
|
|
5967
|
+
groupBy?: string;
|
|
5968
|
+
colorRules: ColorRule[];
|
|
5969
|
+
}
|
|
5970
|
+
interface CrmView {
|
|
5971
|
+
id: string;
|
|
5972
|
+
orgId: string;
|
|
5973
|
+
name: string;
|
|
5974
|
+
layoutType: LayoutType;
|
|
5975
|
+
config: ViewConfig;
|
|
5976
|
+
isDefault: boolean;
|
|
5977
|
+
isShared: boolean;
|
|
5978
|
+
createdBy: string;
|
|
5979
|
+
createdAt: string;
|
|
5980
|
+
updatedAt: string;
|
|
5981
|
+
}
|
|
5982
|
+
/** Adapter-level custom-field filter passed into leads.list. */
|
|
5983
|
+
interface CustomFieldFilter {
|
|
5984
|
+
fieldId: string;
|
|
5985
|
+
fieldType: FieldType;
|
|
5986
|
+
operator: FilterOperator;
|
|
5987
|
+
value?: unknown;
|
|
5988
|
+
}
|
|
5989
|
+
|
|
3574
5990
|
/**
|
|
3575
5991
|
* HTTP status code to exception type mapping
|
|
3576
5992
|
* Maps specific HTTP status codes to appropriate typed exceptions
|
|
@@ -3698,4 +6114,4 @@ declare function getRetryConfig(error: any): {
|
|
|
3698
6114
|
readonly reason: "Generic API errors may be transient and worth retrying";
|
|
3699
6115
|
};
|
|
3700
6116
|
|
|
3701
|
-
export { APIError, type ApplyCouponPayload, AuthenticationError, type CheckoutAmountBreakdown, type CheckoutOrderResponse, type CheckoutProduct, type CheckoutSession, type CreateOrderPayload, type CreateSessionPayload, ECODrIxAPI as ECODrIx, ECODrIxAPI, type ECODrIxAPIOptions, ERROR_RETRY_CONFIG, EcodrixError, type FieldManifest, type FieldType, HTTP_STATUS_ERROR_MAP, RateLimitError, type ResourceManifest, type VerifyPayload, ECODrIxAPI as default, getErrorDetails, getRetryConfig, handleAPIError, isAPIError };
|
|
6117
|
+
export { type AIPersona, APIError, AdminOnboarding, type AnswerFollowupBody, type AnswerOnboardingPayload, type AnswerOnboardingResponse, type ApplyCouponPayload, AuthenticationError, type BehaviorRules, type Broadcast, type CheckboxConfig, type CheckoutAmountBreakdown, type CheckoutOrderResponse, type CheckoutProduct, type CheckoutSession, type ColorRule, type ColumnConfig, type CompleteOnboardingPayload, type CompleteOnboardingResponse, type ConfidenceResponse, type Conversation, type ListParams as ConversationListParams, type Correction, type CreateBroadcastParams, type CreateLeadParams, type CreateNichePackPayload, type CreateOnboardingConfigPayload, type CreateOnboardingExperimentPayload, type CreateOrderPayload, type CreatePipelineParams, type CreateSessionPayload, type CrmView, type CurrencyConfig, type CurrencyValue, type CustomFieldFilter, type DateConfig, type DateTimeConfig, type DropdownConfig, ECODrIxAPI as ECODrIx, ECODrIxAPI, type ECODrIxAPIOptions, ERROR_RETRY_CONFIG, EcodrixError, type EditOnboardingPayload, type EditOnboardingResponse, type EmailConfig, type FieldConfig, type FieldDefinition, type FieldManifest, type FieldType, type FileConfig, type FilterOperator, type FilterRule, Flow, type ForkNichePackPayload, type FormulaConfig, type GlobalOnboardingPayload, HTTP_STATUS_ERROR_MAP, type ICP, Invoices, LEAD_STATUS_VALUES, type LayoutType, type Lead, type LeadPattern, type LeadSource, type LeadStatus, type LearningMemory, type ListLeadsParams, type ListNichePacksParams, type ListNichePacksResponse, type ListOnboardingConfigsParams, type ListOnboardingExperimentsParams, type ListOnboardingExperimentsResponse, type ManifestFieldType, type Message, type NichePack, type NichePackResearchConfig, type NichePackResponse, type NichePackStatus, type NichePackSummary, type NormalizedFieldValue, type NumberConfig, Onboarding, type OnboardingAbandonmentResponse, type OnboardingAbandonmentResult, type OnboardingAbandonmentRow, type OnboardingAnalyticsFiltersParams, type OnboardingCohortRange, type OnboardingConfig, type OnboardingExperiment, type OnboardingExperimentResponse, type OnboardingExperimentStatus, type OnboardingExperimentVariant, type OnboardingFunnelResponse, type OnboardingFunnelResult, type OnboardingFunnelStep, type OnboardingMemoryMapping, type OnboardingOption, type OnboardingSession, type OnboardingSessionStatus, type OnboardingStateResponse, type OnboardingStep, type OnboardingStepType, type OnboardingTimeOnStepResponse, type OnboardingTimeOnStepResult, type OnboardingTimeOnStepRow, type OutreachEdit, type PaginatedResponse, Persona, type PersonaFollowupQuestion, type PersonaFollowupsResponse, type PersonaIdentity, type PersonaTimelineEntry, type PersonaTimelineOptions, type PersonaTimelineResponse, type PhoneConfig, type Pipeline, type PipelineStage, type PipelineStageParams, PortalInbox, type ProgressConfig, ProjectDocuments, RateLimitError, type RatingConfig, type ReinforceResponse, type ReinforcementEvent, type RelationConfig, type RelationValue, type RelayCreatePayload, type RelayEndpointHealth, type RelayOrigin, type RelayProvisionPayload, type RelayRecord, type RelayTuning, type RelayType, type RelayUpdatePayload, Relays, type ResourceManifest, type SendMessageParams, type ServiceConfig, type ServiceConfigGlobal, type ServiceConfigPerProduct, type SmokeTestMaterializerAction, type SmokeTestNichePackPayload, type SmokeTestResult, type SortRule, type StartOnboardingPayload, type StartOnboardingResponse, type StoredFieldValue, type SuggestionEvent, type TagsConfig, type Template, type TemplateComponent, type TemplateMapping, type TextConfig, type UpdateNichePackPayload, type UpdateOnboardingConfigPayload, type UpdateOnboardingExperimentPayload, type UpsertLeadParams, type UrlConfig, type VerifyPayload, type ViewConfig, type Vocabulary, type WorkspaceDashboardLayout, type WorkspaceDefaultAutomation, type WorkspaceDefaultField, type WorkspaceDefaultPipeline, type WorkspaceModuleConfig, type WorkspaceProfile, ECODrIxAPI as default, getErrorDetails, getRetryConfig, handleAPIError, isAPIError };
|