@happyvertical/smrt-support 0.39.2
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/AGENTS.md +270 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/dist/__smrt-register__.d.ts +2 -0
- package/dist/__smrt-register__.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4358 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.json +6770 -0
- package/dist/models/index.d.ts +17 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/service-time-entry.d.ts +75 -0
- package/dist/models/service-time-entry.d.ts.map +1 -0
- package/dist/models/support-ai-run.d.ts +45 -0
- package/dist/models/support-ai-run.d.ts.map +1 -0
- package/dist/models/support-case-event.d.ts +25 -0
- package/dist/models/support-case-event.d.ts.map +1 -0
- package/dist/models/support-case.d.ts +125 -0
- package/dist/models/support-case.d.ts.map +1 -0
- package/dist/models/support-channel-binding.d.ts +47 -0
- package/dist/models/support-channel-binding.d.ts.map +1 -0
- package/dist/models/support-compensation-plan.d.ts +42 -0
- package/dist/models/support-compensation-plan.d.ts.map +1 -0
- package/dist/models/support-interaction.d.ts +49 -0
- package/dist/models/support-interaction.d.ts.map +1 -0
- package/dist/models/support-plan.d.ts +92 -0
- package/dist/models/support-plan.d.ts.map +1 -0
- package/dist/models/support-policy.d.ts +84 -0
- package/dist/models/support-policy.d.ts.map +1 -0
- package/dist/models/support-service-target.d.ts +90 -0
- package/dist/models/support-service-target.d.ts.map +1 -0
- package/dist/models/support-settlement.d.ts +58 -0
- package/dist/models/support-settlement.d.ts.map +1 -0
- package/dist/models/support-specialist.d.ts +71 -0
- package/dist/models/support-specialist.d.ts.map +1 -0
- package/dist/models/support-work-link.d.ts +31 -0
- package/dist/models/support-work-link.d.ts.map +1 -0
- package/dist/permissions.d.ts +32 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/services/coverage-calendar.d.ts +53 -0
- package/dist/services/coverage-calendar.d.ts.map +1 -0
- package/dist/services/human-handoff-service.d.ts +113 -0
- package/dist/services/human-handoff-service.d.ts.map +1 -0
- package/dist/services/index.d.ts +15 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/keyed-mutex.d.ts +22 -0
- package/dist/services/keyed-mutex.d.ts.map +1 -0
- package/dist/services/service-target-engine.d.ts +133 -0
- package/dist/services/service-target-engine.d.ts.map +1 -0
- package/dist/services/service-time-entry-service.d.ts +73 -0
- package/dist/services/service-time-entry-service.d.ts.map +1 -0
- package/dist/services/support-ai-workflow.d.ts +178 -0
- package/dist/services/support-ai-workflow.d.ts.map +1 -0
- package/dist/services/support-case-service.d.ts +162 -0
- package/dist/services/support-case-service.d.ts.map +1 -0
- package/dist/services/support-intake-service.d.ts +106 -0
- package/dist/services/support-intake-service.d.ts.map +1 -0
- package/dist/services/support-plan-admin-service.d.ts +45 -0
- package/dist/services/support-plan-admin-service.d.ts.map +1 -0
- package/dist/services/support-routing-service.d.ts +117 -0
- package/dist/services/support-routing-service.d.ts.map +1 -0
- package/dist/services/time-entry-approval-service.d.ts +162 -0
- package/dist/services/time-entry-approval-service.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +4242 -0
- package/dist/svelte/components/CaseDetail.svelte +277 -0
- package/dist/svelte/components/CaseDetail.svelte.d.ts +10 -0
- package/dist/svelte/components/CaseDetail.svelte.d.ts.map +1 -0
- package/dist/svelte/components/CaseQueue.svelte +148 -0
- package/dist/svelte/components/CaseQueue.svelte.d.ts +12 -0
- package/dist/svelte/components/CaseQueue.svelte.d.ts.map +1 -0
- package/dist/svelte/components/RoutingRationale.svelte +131 -0
- package/dist/svelte/components/RoutingRationale.svelte.d.ts +11 -0
- package/dist/svelte/components/RoutingRationale.svelte.d.ts.map +1 -0
- package/dist/svelte/components/TargetList.svelte +127 -0
- package/dist/svelte/components/TargetList.svelte.d.ts +9 -0
- package/dist/svelte/components/TargetList.svelte.d.ts.map +1 -0
- package/dist/svelte/components/TimeEntryApprovalQueue.svelte +226 -0
- package/dist/svelte/components/TimeEntryApprovalQueue.svelte.d.ts +11 -0
- package/dist/svelte/components/TimeEntryApprovalQueue.svelte.d.ts.map +1 -0
- package/dist/svelte/components/__tests__/CaseDetail.test.js +86 -0
- package/dist/svelte/components/__tests__/CaseQueue.test.js +67 -0
- package/dist/svelte/components/__tests__/RoutingRationale.test.js +69 -0
- package/dist/svelte/components/__tests__/TargetList.test.js +84 -0
- package/dist/svelte/components/__tests__/TimeEntryApprovalQueue.test.js +105 -0
- package/dist/svelte/index.d.ts +25 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +18 -0
- package/dist/svelte/types.d.ts +129 -0
- package/dist/svelte/types.d.ts.map +1 -0
- package/dist/svelte/types.js +182 -0
- package/dist/types.d.ts +130 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +109 -0
- package/dist/types.js.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model barrel for `@happyvertical/smrt-support`.
|
|
3
|
+
*/
|
|
4
|
+
export { ServiceTimeEntry, ServiceTimeEntryCollection, } from './service-time-entry.js';
|
|
5
|
+
export { SupportAiRun, SupportAiRunCollection, } from './support-ai-run.js';
|
|
6
|
+
export { generateCaseNumber, SupportCase, SupportCaseCollection, } from './support-case.js';
|
|
7
|
+
export { SupportCaseEvent, SupportCaseEventCollection, } from './support-case-event.js';
|
|
8
|
+
export { SupportChannelBinding, SupportChannelBindingCollection, } from './support-channel-binding.js';
|
|
9
|
+
export { SupportCompensationPlan, SupportCompensationPlanCollection, } from './support-compensation-plan.js';
|
|
10
|
+
export { SupportInteraction, SupportInteractionCollection, } from './support-interaction.js';
|
|
11
|
+
export { DEFAULT_TARGET_MINUTES, SupportPlan, SupportPlanCollection, } from './support-plan.js';
|
|
12
|
+
export { DEFAULT_SUPPORT_POLICY, SupportPolicy, SupportPolicyCollection, } from './support-policy.js';
|
|
13
|
+
export { type CheckAndEscalateResult, SupportEscalation, SupportEscalationCollection, SupportServiceTarget, SupportServiceTargetCollection, } from './support-service-target.js';
|
|
14
|
+
export { SupportCharge, SupportChargeCollection, SupportCompensation, SupportCompensationCollection, } from './support-settlement.js';
|
|
15
|
+
export { SupportAvailability, SupportAvailabilityCollection, SupportQualification, SupportQualificationCollection, SupportSpecialist, SupportSpecialistCollection, } from './support-specialist.js';
|
|
16
|
+
export { SupportWorkLink, SupportWorkLinkCollection, } from './support-work-link.js';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,gBAAgB,EAChB,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,YAAY,EACZ,sBAAsB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,qBAAqB,EACrB,+BAA+B,GAChC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,uBAAuB,EACvB,iCAAiC,GAClC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,kBAAkB,EAClB,4BAA4B,GAC7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,sBAAsB,EACtB,WAAW,EACX,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,sBAAsB,EACtB,aAAa,EACb,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,KAAK,sBAAsB,EAC3B,iBAAiB,EACjB,2BAA2B,EAC3B,oBAAoB,EACpB,8BAA8B,GAC/B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,mBAAmB,EACnB,6BAA6B,GAC9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,oBAAoB,EACpB,8BAA8B,EAC9B,iBAAiB,EACjB,2BAA2B,GAC5B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,eAAe,EACf,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
import { ServiceTimeEntrySource, ServiceTimeEntryStatus, SupportParticipantKind, TimeEntryEvidence } from '../types.js';
|
|
3
|
+
export declare class ServiceTimeEntry extends SmrtObject {
|
|
4
|
+
tenantId: string | null;
|
|
5
|
+
/** Support Case context, when the work was support (Support Time Entry). */
|
|
6
|
+
caseId: string | null;
|
|
7
|
+
/**
|
|
8
|
+
* Polymorphic work context for non-case work (planning sessions,
|
|
9
|
+
* development work items): a qualified class name + id. Either `caseId` or
|
|
10
|
+
* a work ref (or both) should identify the context.
|
|
11
|
+
*/
|
|
12
|
+
workRefType: string | null;
|
|
13
|
+
workRefId: string | null;
|
|
14
|
+
/** Specialist role record, when the deliverer is a Support Specialist. */
|
|
15
|
+
specialistId: string | null;
|
|
16
|
+
/** Whether a human or a software agent delivered the work. */
|
|
17
|
+
participantKind: SupportParticipantKind;
|
|
18
|
+
/** Delivering human Participant (Person profile), when human. */
|
|
19
|
+
participantProfileId: string | null;
|
|
20
|
+
/** Delivering agent identity (persona/agent ref), when agent. */
|
|
21
|
+
agentRef: string;
|
|
22
|
+
source: ServiceTimeEntrySource;
|
|
23
|
+
description: string;
|
|
24
|
+
/** Work period bounds (informational; `durationSeconds` is authoritative). */
|
|
25
|
+
startedAt: Date | null;
|
|
26
|
+
endedAt: Date | null;
|
|
27
|
+
/** Authoritative worked duration in seconds. */
|
|
28
|
+
durationSeconds: number;
|
|
29
|
+
/** Work evidence: JSON array of {@link TimeEntryEvidence}. */
|
|
30
|
+
evidence: string;
|
|
31
|
+
status: ServiceTimeEntryStatus;
|
|
32
|
+
submittedAt: Date | null;
|
|
33
|
+
submittedByProfileId: string | null;
|
|
34
|
+
approvedAt: Date | null;
|
|
35
|
+
approvedByProfileId: string | null;
|
|
36
|
+
/** Which approval path accepted the entry (FR-36). */
|
|
37
|
+
approvalPath: string;
|
|
38
|
+
rejectedAt: Date | null;
|
|
39
|
+
rejectedByProfileId: string | null;
|
|
40
|
+
rejectionReason: string;
|
|
41
|
+
/** The approved entry this one explicitly corrects, when a correction. */
|
|
42
|
+
correctionOfId: string | null;
|
|
43
|
+
metadata: string;
|
|
44
|
+
getEvidence(): TimeEntryEvidence[];
|
|
45
|
+
setEvidence(items: TimeEntryEvidence[]): void;
|
|
46
|
+
getMetadata(): Record<string, unknown>;
|
|
47
|
+
setMetadata(value: Record<string, unknown>): void;
|
|
48
|
+
/** Worked duration in decimal hours (UI convenience). */
|
|
49
|
+
durationHours(): number;
|
|
50
|
+
initialize(): Promise<this>;
|
|
51
|
+
save(): Promise<this>;
|
|
52
|
+
protected assertStatusTransition(prior: ServiceTimeEntryStatus | undefined): void;
|
|
53
|
+
/**
|
|
54
|
+
* Once approved, the work-defining fields are immutable — compare against
|
|
55
|
+
* the authoritative persisted row (not just the WeakMap), so an upsert via
|
|
56
|
+
* `create({ id, _skipLoad: true })` cannot bypass the freeze.
|
|
57
|
+
*/
|
|
58
|
+
protected assertApprovedImmutable(prior: {
|
|
59
|
+
status: ServiceTimeEntryStatus;
|
|
60
|
+
frozen: string | null;
|
|
61
|
+
} | undefined): void;
|
|
62
|
+
/** Authoritative prior state read from the DB row (S5 #1390 idiom). */
|
|
63
|
+
protected resolvePriorState(): Promise<{
|
|
64
|
+
status: ServiceTimeEntryStatus;
|
|
65
|
+
frozen: string | null;
|
|
66
|
+
} | undefined>;
|
|
67
|
+
}
|
|
68
|
+
export declare class ServiceTimeEntryCollection extends SmrtCollection<ServiceTimeEntry> {
|
|
69
|
+
static readonly _itemClass: typeof ServiceTimeEntry;
|
|
70
|
+
forCase(caseId: string): Promise<ServiceTimeEntry[]>;
|
|
71
|
+
forSpecialist(specialistId: string): Promise<ServiceTimeEntry[]>;
|
|
72
|
+
pendingApproval(): Promise<ServiceTimeEntry[]>;
|
|
73
|
+
}
|
|
74
|
+
export default ServiceTimeEntry;
|
|
75
|
+
//# sourceMappingURL=service-time-entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-time-entry.d.ts","sourceRoot":"","sources":["../../src/models/service-time-entry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
import { SupportAiRunOutcome, SupportAiRunPhase } from '../types.js';
|
|
3
|
+
export declare class SupportAiRun extends SmrtObject {
|
|
4
|
+
tenantId: string | null;
|
|
5
|
+
caseId: string;
|
|
6
|
+
/** Inbound interaction that triggered this run, when applicable. */
|
|
7
|
+
interactionId: string | null;
|
|
8
|
+
phase: SupportAiRunPhase;
|
|
9
|
+
outcome: SupportAiRunOutcome;
|
|
10
|
+
/**
|
|
11
|
+
* Model-reported confidence in [0, 1] for answer/classify/resolve phases;
|
|
12
|
+
* null when the phase has no confidence semantics (e.g. acknowledge).
|
|
13
|
+
*/
|
|
14
|
+
confidence: number | null;
|
|
15
|
+
/** Classification output JSON: severity, category, sentiment, sensitive. */
|
|
16
|
+
classification: string;
|
|
17
|
+
/** Outbound interaction holding the posted/drafted response, if any. */
|
|
18
|
+
responseInteractionId: string | null;
|
|
19
|
+
/** Knowledge sources consulted (JSON array of `{kind, ref, label?}`). */
|
|
20
|
+
knowledgeRefs: string;
|
|
21
|
+
/** Tool calls attempted during troubleshooting (JSON array). */
|
|
22
|
+
toolCalls: string;
|
|
23
|
+
/** Error detail when `outcome === 'failed'`. */
|
|
24
|
+
error: string;
|
|
25
|
+
/** Correlation id tying this run to AI-call telemetry / feedback signals. */
|
|
26
|
+
correlationId: string;
|
|
27
|
+
/** Model identifier used, when known. */
|
|
28
|
+
model: string;
|
|
29
|
+
startedAt: Date;
|
|
30
|
+
completedAt: Date | null;
|
|
31
|
+
metadata: string;
|
|
32
|
+
getClassification(): Record<string, unknown>;
|
|
33
|
+
setClassification(value: Record<string, unknown>): void;
|
|
34
|
+
getKnowledgeRefs(): Array<Record<string, unknown>>;
|
|
35
|
+
setKnowledgeRefs(refs: Array<Record<string, unknown>>): void;
|
|
36
|
+
getToolCalls(): Array<Record<string, unknown>>;
|
|
37
|
+
setToolCalls(calls: Array<Record<string, unknown>>): void;
|
|
38
|
+
}
|
|
39
|
+
export declare class SupportAiRunCollection extends SmrtCollection<SupportAiRun> {
|
|
40
|
+
static readonly _itemClass: typeof SupportAiRun;
|
|
41
|
+
/** All AI runs for a case, oldest first. */
|
|
42
|
+
forCase(caseId: string): Promise<SupportAiRun[]>;
|
|
43
|
+
}
|
|
44
|
+
export default SupportAiRun;
|
|
45
|
+
//# sourceMappingURL=support-ai-run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"support-ai-run.d.ts","sourceRoot":"","sources":["../../src/models/support-ai-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAGL,cAAc,EACd,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACvB,MAAM,aAAa,CAAC;AAErB,qBAOa,YAAa,SAAQ,UAAU;IAE1C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG/B,MAAM,EAAE,MAAM,CAAM;IAEpB,oEAAoE;IAEpE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAQ;IAGpC,KAAK,EAAE,iBAAiB,CAAiB;IAGzC,OAAO,EAAE,mBAAmB,CAAe;IAE3C;;;OAGG;IAEH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEjC,4EAA4E;IAE5E,cAAc,EAAE,MAAM,CAAQ;IAE9B,wEAAwE;IAExE,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE5C,yEAAyE;IAEzE,aAAa,EAAE,MAAM,CAAQ;IAE7B,gEAAgE;IAEhE,SAAS,EAAE,MAAM,CAAQ;IAEzB,gDAAgD;IAEhD,KAAK,EAAE,MAAM,CAAM;IAEnB,6EAA6E;IAE7E,aAAa,EAAE,MAAM,CAAM;IAE3B,yCAAyC;IAEzC,KAAK,EAAE,MAAM,CAAM;IAEnB,SAAS,EAAE,IAAI,CAAc;IAE7B,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAGhC,QAAQ,EAAE,MAAM,CAAQ;IAExB,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAI5C,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIvD,gBAAgB,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAIlD,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI;IAI5D,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAI9C,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI;CAG1D;AAED,qBAAa,sBAAuB,SAAQ,cAAc,CAAC,YAAY,CAAC;IACtE,MAAM,CAAC,QAAQ,CAAC,UAAU,sBAAgB;IAE1C,4CAA4C;IACtC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CAGvD;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
import { SupportActorKind, SupportCaseEventType } from '../types.js';
|
|
3
|
+
export declare class SupportCaseEvent extends SmrtObject {
|
|
4
|
+
tenantId: string | null;
|
|
5
|
+
caseId: string;
|
|
6
|
+
eventType: SupportCaseEventType;
|
|
7
|
+
actorKind: SupportActorKind;
|
|
8
|
+
actorProfileId: string | null;
|
|
9
|
+
occurredAt: Date;
|
|
10
|
+
/** One-line human-readable summary for the case timeline. */
|
|
11
|
+
summary: string;
|
|
12
|
+
/** Structured event payload (transition from/to, rationale, evidence, …). */
|
|
13
|
+
payload: string;
|
|
14
|
+
getPayload(): Record<string, unknown>;
|
|
15
|
+
setPayload(value: Record<string, unknown>): void;
|
|
16
|
+
}
|
|
17
|
+
export declare class SupportCaseEventCollection extends SmrtCollection<SupportCaseEvent> {
|
|
18
|
+
static readonly _itemClass: typeof SupportCaseEvent;
|
|
19
|
+
/** All events for a case, oldest first. */
|
|
20
|
+
forCase(caseId: string, options?: {
|
|
21
|
+
eventType?: SupportCaseEventType;
|
|
22
|
+
}): Promise<SupportCaseEvent[]>;
|
|
23
|
+
}
|
|
24
|
+
export default SupportCaseEvent;
|
|
25
|
+
//# sourceMappingURL=support-case-event.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"support-case-event.d.ts","sourceRoot":"","sources":["../../src/models/support-case-event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAIL,cAAc,EACd,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAC1B,MAAM,aAAa,CAAC;AAErB,qBAOa,gBAAiB,SAAQ,UAAU;IAE9C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG/B,MAAM,EAAE,MAAM,CAAM;IAGpB,SAAS,EAAE,oBAAoB,CAAU;IAGzC,SAAS,EAAE,gBAAgB,CAAY;IAGvC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IAErC,UAAU,EAAE,IAAI,CAAc;IAE9B,6DAA6D;IAE7D,OAAO,EAAE,MAAM,CAAM;IAErB,6EAA6E;IAE7E,OAAO,EAAE,MAAM,CAAQ;IAEvB,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIrC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGjD;AAED,qBAAa,0BAA2B,SAAQ,cAAc,CAAC,gBAAgB,CAAC;IAC9E,MAAM,CAAC,QAAQ,CAAC,UAAU,0BAAoB;IAE9C,2CAA2C;IACrC,OAAO,CACX,MAAM,EAAE,MAAM,EACd,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,oBAAoB,CAAA;KAAO,GACjD,OAAO,CAAC,gBAAgB,EAAE,CAAC;CAO/B;AAED,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
import { SupportCaseStatus } from '../types.js';
|
|
3
|
+
/** Generate a short human-facing case number (unique enough per tenant). */
|
|
4
|
+
export declare function generateCaseNumber(now?: Date): string;
|
|
5
|
+
export declare class SupportCase extends SmrtObject {
|
|
6
|
+
tenantId: string | null;
|
|
7
|
+
/** Human-facing case reference (e.g. `SUP-…`), generated at open time. */
|
|
8
|
+
caseNumber: string;
|
|
9
|
+
/** Short client-facing summary of the request. */
|
|
10
|
+
subject: string;
|
|
11
|
+
/** Initial request text (the first inbound interaction's body). */
|
|
12
|
+
description: string;
|
|
13
|
+
status: SupportCaseStatus;
|
|
14
|
+
/** Queue ordering priority: `low` | `normal` | `high` | `urgent`. */
|
|
15
|
+
priority: string;
|
|
16
|
+
/**
|
|
17
|
+
* Severity key resolved against the plan's severity definitions (e.g.
|
|
18
|
+
* `sev1`…`sev4`). Empty until triage/classification assigns one.
|
|
19
|
+
*/
|
|
20
|
+
severity: string;
|
|
21
|
+
/** Classification category (AI- or human-assigned). Free vocabulary. */
|
|
22
|
+
category: string;
|
|
23
|
+
/** Whether the subject matter was flagged sensitive (handoff trigger). */
|
|
24
|
+
sensitive: boolean;
|
|
25
|
+
/** Origin transport kind (`chat` | `email` | …). */
|
|
26
|
+
channelKind: string;
|
|
27
|
+
/**
|
|
28
|
+
* The Client this Case belongs to (FR-29) — a `Person` or `Organization`
|
|
29
|
+
* Profile. Nullable so unmatched inbound email can park a Case for triage;
|
|
30
|
+
* intake marks those with `metadata.unresolvedClient`.
|
|
31
|
+
*/
|
|
32
|
+
clientProfileId: string | null;
|
|
33
|
+
/** The person who opened the request, when distinct from the Client. */
|
|
34
|
+
openedByProfileId: string | null;
|
|
35
|
+
/**
|
|
36
|
+
* App-defined Project reference (a client initiative, not a repo board).
|
|
37
|
+
* Deliberately a plain string — the consuming app owns the Project concept.
|
|
38
|
+
*/
|
|
39
|
+
projectId: string | null;
|
|
40
|
+
/** Channel binding that created this case, when intake-created. */
|
|
41
|
+
bindingId: string | null;
|
|
42
|
+
/**
|
|
43
|
+
* Deterministic conversation key used by create-or-join intake dedup
|
|
44
|
+
* (e.g. `chat:<roomId>[:<threadId>]` or `email:<rfc-message-id>`).
|
|
45
|
+
*/
|
|
46
|
+
threadKey: string;
|
|
47
|
+
/** Managed Support Plan governing this case, when one applies. */
|
|
48
|
+
planId: string | null;
|
|
49
|
+
/**
|
|
50
|
+
* JSON snapshot of the plan terms captured when the plan was applied, so
|
|
51
|
+
* later plan edits never rewrite the terms a case was handled under.
|
|
52
|
+
* Read through {@link getPlanSnapshot}.
|
|
53
|
+
*/
|
|
54
|
+
planSnapshot: string;
|
|
55
|
+
assignedSpecialistId: string | null;
|
|
56
|
+
assignedAt: Date | null;
|
|
57
|
+
/** Client/plan preferred specialist considered first by routing (FR-30). */
|
|
58
|
+
preferredSpecialistId: string | null;
|
|
59
|
+
/** Current escalation level (0 = never escalated). */
|
|
60
|
+
escalationLevel: number;
|
|
61
|
+
escalatedAt: Date | null;
|
|
62
|
+
/** First outbound acknowledgement of any kind (starts as `null`). */
|
|
63
|
+
acknowledgedAt: Date | null;
|
|
64
|
+
/** First substantive outbound response (specialist or agent). */
|
|
65
|
+
firstRespondedAt: Date | null;
|
|
66
|
+
/** Set when the client explicitly requested a human (FR-28b). */
|
|
67
|
+
humanRequestedAt: Date | null;
|
|
68
|
+
resolvedAt: Date | null;
|
|
69
|
+
resolvedByProfileId: string | null;
|
|
70
|
+
/** How the case was resolved: `automated` | `human` | `delivery`. */
|
|
71
|
+
resolutionKind: string;
|
|
72
|
+
resolutionSummary: string;
|
|
73
|
+
closedAt: Date | null;
|
|
74
|
+
/** Times this case was reopened; prior resolutions live in case events. */
|
|
75
|
+
reopenCount: number;
|
|
76
|
+
lastReopenedAt: Date | null;
|
|
77
|
+
/** Per-case escape hatch: disable the AI workflow for this case only. */
|
|
78
|
+
aiEnabled: boolean;
|
|
79
|
+
metadata: string;
|
|
80
|
+
/** Whether the case is in an open (not resolved/closed) state. */
|
|
81
|
+
isOpen(): boolean;
|
|
82
|
+
getMetadata(): Record<string, unknown>;
|
|
83
|
+
setMetadata(value: Record<string, unknown>): void;
|
|
84
|
+
updateMetadata(patch: Record<string, unknown>): void;
|
|
85
|
+
getPlanSnapshot(): Record<string, unknown>;
|
|
86
|
+
setPlanSnapshot(value: Record<string, unknown>): void;
|
|
87
|
+
/**
|
|
88
|
+
* Capture the status the row was loaded with so the save-time guard can
|
|
89
|
+
* reject illegal flips made via raw field assignment.
|
|
90
|
+
*/
|
|
91
|
+
initialize(): Promise<this>;
|
|
92
|
+
/** Validate the status transition before persisting, then save. */
|
|
93
|
+
save(): Promise<this>;
|
|
94
|
+
protected assertStatusTransition(prior: SupportCaseStatus | undefined): void;
|
|
95
|
+
/**
|
|
96
|
+
* Resolve the AUTHORITATIVE prior status. The WeakMap only covers rows
|
|
97
|
+
* hydrated through {@link initialize}; a `create({ id, _skipLoad: true })`
|
|
98
|
+
* upsert would otherwise look brand-new and skip the guard, so when the
|
|
99
|
+
* instance carries an id, read the persisted row directly (S5 #1390 idiom).
|
|
100
|
+
*/
|
|
101
|
+
protected resolvePriorStatus(): Promise<SupportCaseStatus | undefined>;
|
|
102
|
+
}
|
|
103
|
+
export declare class SupportCaseCollection extends SmrtCollection<SupportCase> {
|
|
104
|
+
static readonly _itemClass: typeof SupportCase;
|
|
105
|
+
/**
|
|
106
|
+
* Find the open case an inbound interaction should join, by conversation
|
|
107
|
+
* key (create-or-join dedup, FR-28). Returns the most recently updated open
|
|
108
|
+
* case for the key, or `null` when a new case should be created.
|
|
109
|
+
*/
|
|
110
|
+
findOpenByThreadKey(threadKey: string, options?: {
|
|
111
|
+
bindingId?: string | null;
|
|
112
|
+
}): Promise<SupportCase | null>;
|
|
113
|
+
/** Queue listing with common filters, newest first. */
|
|
114
|
+
findQueue(options?: {
|
|
115
|
+
status?: SupportCaseStatus | SupportCaseStatus[];
|
|
116
|
+
assignedSpecialistId?: string | null;
|
|
117
|
+
clientProfileId?: string;
|
|
118
|
+
projectId?: string;
|
|
119
|
+
openOnly?: boolean;
|
|
120
|
+
limit?: number;
|
|
121
|
+
offset?: number;
|
|
122
|
+
}): Promise<SupportCase[]>;
|
|
123
|
+
}
|
|
124
|
+
export default SupportCase;
|
|
125
|
+
//# sourceMappingURL=support-case.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"support-case.d.ts","sourceRoot":"","sources":["../../src/models/support-case.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
import { SupportBindingKind, SupportChannelKind } from '../types.js';
|
|
3
|
+
export declare class SupportChannelBinding extends SmrtObject {
|
|
4
|
+
tenantId: string | null;
|
|
5
|
+
/** Operator-facing binding name (inherited `name` is the display label). */
|
|
6
|
+
name: string;
|
|
7
|
+
bindingKind: SupportBindingKind;
|
|
8
|
+
/** Channel kind interactions from this binding are recorded as. */
|
|
9
|
+
channelKind: SupportChannelKind;
|
|
10
|
+
/**
|
|
11
|
+
* Qualified class of the bound container, e.g.
|
|
12
|
+
* `@happyvertical/smrt-chat:ChatRoom` or
|
|
13
|
+
* `@happyvertical/smrt-messages:EmailAccount`.
|
|
14
|
+
*/
|
|
15
|
+
targetType: string;
|
|
16
|
+
/** Id of the bound container row. */
|
|
17
|
+
targetId: string;
|
|
18
|
+
/**
|
|
19
|
+
* Default Client for cases created from this binding (e.g. a dedicated
|
|
20
|
+
* client support room). When null, intake resolves the client from the
|
|
21
|
+
* interaction author (chat) or sender lookup (email).
|
|
22
|
+
*/
|
|
23
|
+
clientProfileId: string | null;
|
|
24
|
+
/** Default app-defined Project reference for cases from this binding. */
|
|
25
|
+
projectId: string | null;
|
|
26
|
+
/** Managed Support Plan applied to cases created from this binding. */
|
|
27
|
+
planId: string | null;
|
|
28
|
+
enabled: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Addresses belonging to the provider side of an email binding — inbound
|
|
31
|
+
* sync skips messages sent FROM these (they are our own outbound mail).
|
|
32
|
+
* JSON array of e-mail addresses, matched case-insensitively.
|
|
33
|
+
*/
|
|
34
|
+
selfAddresses: string;
|
|
35
|
+
metadata: string;
|
|
36
|
+
getSelfAddresses(): string[];
|
|
37
|
+
setSelfAddresses(addresses: string[]): void;
|
|
38
|
+
getMetadata(): Record<string, unknown>;
|
|
39
|
+
setMetadata(value: Record<string, unknown>): void;
|
|
40
|
+
}
|
|
41
|
+
export declare class SupportChannelBindingCollection extends SmrtCollection<SupportChannelBinding> {
|
|
42
|
+
static readonly _itemClass: typeof SupportChannelBinding;
|
|
43
|
+
/** Find the enabled binding for a transport container, if any. */
|
|
44
|
+
findForTarget(targetType: string, targetId: string): Promise<SupportChannelBinding | null>;
|
|
45
|
+
}
|
|
46
|
+
export default SupportChannelBinding;
|
|
47
|
+
//# sourceMappingURL=support-channel-binding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"support-channel-binding.d.ts","sourceRoot":"","sources":["../../src/models/support-channel-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAIL,cAAc,EACd,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACxB,MAAM,aAAa,CAAC;AAErB,qBAQa,qBAAsB,SAAQ,UAAU;IAEnD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAM;IAGlB,WAAW,EAAE,kBAAkB,CAAe;IAE9C,mEAAmE;IAEnE,WAAW,EAAE,kBAAkB,CAAU;IAEzC;;;;OAIG;IAEH,UAAU,EAAE,MAAM,CAAM;IAExB,qCAAqC;IAErC,QAAQ,EAAE,MAAM,CAAM;IAEtB;;;;OAIG;IAEH,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEtC,yEAAyE;IAEzE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEhC,uEAAuE;IAEvE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG7B,OAAO,EAAE,OAAO,CAAQ;IAExB;;;;OAIG;IAEH,aAAa,EAAE,MAAM,CAAQ;IAG7B,QAAQ,EAAE,MAAM,CAAQ;IAExB,gBAAgB,IAAI,MAAM,EAAE;IAM5B,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI;IAI3C,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAItC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGlD;AAED,qBAAa,+BAAgC,SAAQ,cAAc,CAAC,qBAAqB,CAAC;IACxF,MAAM,CAAC,QAAQ,CAAC,UAAU,+BAAyB;IAEnD,kEAAkE;IAC5D,aAAa,CACjB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;CAOzC;AAED,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
export declare class SupportCompensationPlan extends SmrtObject {
|
|
3
|
+
tenantId: string | null;
|
|
4
|
+
/** Specialist this plan compensates; null = tenant default plan. */
|
|
5
|
+
specialistId: string | null;
|
|
6
|
+
/** Display name (inherited `name`; uniqueness comes from conflictColumns). */
|
|
7
|
+
name: string;
|
|
8
|
+
/** Hourly earning rate for delivered support time. */
|
|
9
|
+
hourlyRate: number;
|
|
10
|
+
currency: string;
|
|
11
|
+
/** Effective-dating: null bounds mean open-ended. */
|
|
12
|
+
effectiveFrom: Date | null;
|
|
13
|
+
effectiveTo: Date | null;
|
|
14
|
+
/** `active` | `archived`. */
|
|
15
|
+
status: string;
|
|
16
|
+
/** Additional agreement terms (JSON object; free-form, snapshotted). */
|
|
17
|
+
terms: string;
|
|
18
|
+
getTerms(): Record<string, unknown>;
|
|
19
|
+
setTerms(value: Record<string, unknown>): void;
|
|
20
|
+
/** Whether the plan is effective at the given instant. */
|
|
21
|
+
isEffectiveAt(at?: Date): boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare class SupportCompensationPlanCollection extends SmrtCollection<SupportCompensationPlan> {
|
|
24
|
+
static readonly _itemClass: typeof SupportCompensationPlan;
|
|
25
|
+
/**
|
|
26
|
+
* Resolve the plan compensating a specialist at a work instant:
|
|
27
|
+
* specialist-specific first, then the tenant default. Ties (overlapping
|
|
28
|
+
* effective ranges) prefer an exact tenant match over a global
|
|
29
|
+
* (NULL-tenant) plan, then the latest `effectiveFrom`.
|
|
30
|
+
*
|
|
31
|
+
* Pass `options.tenantId` (the work's tenant) whenever resolution may run
|
|
32
|
+
* without an ambient tenant context (system/job paths list across
|
|
33
|
+
* tenants): candidates are then limited to that tenant's plans plus
|
|
34
|
+
* global NULL-tenant plans, so another tenant's default can never price
|
|
35
|
+
* this tenant's work.
|
|
36
|
+
*/
|
|
37
|
+
resolveForSpecialist(specialistId: string, at?: Date, options?: {
|
|
38
|
+
tenantId?: string | null;
|
|
39
|
+
}): Promise<SupportCompensationPlan | null>;
|
|
40
|
+
}
|
|
41
|
+
export default SupportCompensationPlan;
|
|
42
|
+
//# sourceMappingURL=support-compensation-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"support-compensation-plan.d.ts","sourceRoot":"","sources":["../../src/models/support-compensation-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAGL,cAAc,EACd,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAOlC,qBAQa,uBAAwB,SAAQ,UAAU;IAErD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B,oEAAoE;IAEpE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEnC,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAM;IAElB,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAO;IAGzB,QAAQ,EAAE,MAAM,CAAS;IAEzB,qDAAqD;IACrD,aAAa,EAAE,IAAI,GAAG,IAAI,CAAQ;IAElC,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEhC,6BAA6B;IAE7B,MAAM,EAAE,MAAM,CAAY;IAE1B,wEAAwE;IAExE,KAAK,EAAE,MAAM,CAAQ;IAErB,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAInC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI9C,0DAA0D;IAC1D,aAAa,CAAC,EAAE,GAAE,IAAiB,GAAG,OAAO;CAM9C;AAED,qBAAa,iCAAkC,SAAQ,cAAc,CAAC,uBAAuB,CAAC;IAC5F,MAAM,CAAC,QAAQ,CAAC,UAAU,iCAA2B;IAErD;;;;;;;;;;;OAWG;IACG,oBAAoB,CACxB,YAAY,EAAE,MAAM,EACpB,EAAE,GAAE,IAAiB,EACrB,OAAO,GAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAO,GACzC,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC;CA6B3C;AAED,eAAe,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
import { SupportActorKind, SupportChannelKind, SupportInteractionDirection } from '../types.js';
|
|
3
|
+
export declare class SupportInteraction extends SmrtObject {
|
|
4
|
+
tenantId: string | null;
|
|
5
|
+
caseId: string;
|
|
6
|
+
direction: SupportInteractionDirection;
|
|
7
|
+
channelKind: SupportChannelKind;
|
|
8
|
+
actorKind: SupportActorKind;
|
|
9
|
+
/** Author identity when known (client contact, specialist, bot profile). */
|
|
10
|
+
authorProfileId: string | null;
|
|
11
|
+
/** When the exchange happened on its channel (not when it was ingested). */
|
|
12
|
+
occurredAt: Date;
|
|
13
|
+
/** Denormalized text body for the case timeline (source stays canonical). */
|
|
14
|
+
body: string;
|
|
15
|
+
/**
|
|
16
|
+
* Qualified class of the source transport record, e.g.
|
|
17
|
+
* `@happyvertical/smrt-chat:ChatMessage` or
|
|
18
|
+
* `@happyvertical/smrt-messages:Email`. Null for manual notes.
|
|
19
|
+
*/
|
|
20
|
+
sourceType: string | null;
|
|
21
|
+
/** Id of the source transport record. Null for manual notes. */
|
|
22
|
+
sourceId: string | null;
|
|
23
|
+
/**
|
|
24
|
+
* Globally unique idempotency key for intake dedup (`conflictColumns`):
|
|
25
|
+
* `chat:<messageId>`, `email:<emailId>`, or `manual:<uuid>` for
|
|
26
|
+
* service-authored notes.
|
|
27
|
+
*/
|
|
28
|
+
sourceKey: string;
|
|
29
|
+
/**
|
|
30
|
+
* RFC 822 Message-ID for email interactions — a first-class column so
|
|
31
|
+
* reply threading (`In-Reply-To` joins) is a keyed lookup instead of a
|
|
32
|
+
* bounded metadata scan. Empty for non-email interactions.
|
|
33
|
+
*/
|
|
34
|
+
rfcMessageId: string;
|
|
35
|
+
metadata: string;
|
|
36
|
+
getMetadata(): Record<string, unknown>;
|
|
37
|
+
setMetadata(value: Record<string, unknown>): void;
|
|
38
|
+
}
|
|
39
|
+
export declare class SupportInteractionCollection extends SmrtCollection<SupportInteraction> {
|
|
40
|
+
static readonly _itemClass: typeof SupportInteraction;
|
|
41
|
+
/** All interactions for a case in channel chronology (oldest first). */
|
|
42
|
+
forCase(caseId: string): Promise<SupportInteraction[]>;
|
|
43
|
+
/** Look up an interaction by its idempotency key. */
|
|
44
|
+
bySourceKey(sourceKey: string): Promise<SupportInteraction | null>;
|
|
45
|
+
/** Keyed lookup of an email interaction by its RFC 822 Message-ID. */
|
|
46
|
+
byRfcMessageId(rfcMessageId: string): Promise<SupportInteraction | null>;
|
|
47
|
+
}
|
|
48
|
+
export default SupportInteraction;
|
|
49
|
+
//# sourceMappingURL=support-interaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"support-interaction.d.ts","sourceRoot":"","sources":["../../src/models/support-interaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAIL,cAAc,EACd,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EACjC,MAAM,aAAa,CAAC;AAErB,qBAQa,kBAAmB,SAAQ,UAAU;IAEhD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAG/B,MAAM,EAAE,MAAM,CAAM;IAGpB,SAAS,EAAE,2BAA2B,CAAa;IAGnD,WAAW,EAAE,kBAAkB,CAAU;IAGzC,SAAS,EAAE,gBAAgB,CAAY;IAEvC,4EAA4E;IAE5E,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEtC,4EAA4E;IAC5E,UAAU,EAAE,IAAI,CAAc;IAE9B,6EAA6E;IAE7E,IAAI,EAAE,MAAM,CAAM;IAElB;;;;OAIG;IAEH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEjC,gEAAgE;IAEhE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;;;OAIG;IAEH,SAAS,EAAE,MAAM,CAAM;IAEvB;;;;OAIG;IAEH,YAAY,EAAE,MAAM,CAAM;IAG1B,QAAQ,EAAE,MAAM,CAAQ;IAExB,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAItC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGlD;AAED,qBAAa,4BAA6B,SAAQ,cAAc,CAAC,kBAAkB,CAAC;IAClF,MAAM,CAAC,QAAQ,CAAC,UAAU,4BAAsB;IAEhD,wEAAwE;IAClE,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAO5D,qDAAqD;IAC/C,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAKxE,sEAAsE;IAChE,cAAc,CAClB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;CAOtC;AAED,eAAe,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
import { CoverageWindow, EscalationStep, ServiceTargetMinutes, SeverityDefinition, TimeApprovalPolicy } from '../types.js';
|
|
3
|
+
/** Default target minutes applied when a plan omits a severity's targets. */
|
|
4
|
+
export declare const DEFAULT_TARGET_MINUTES: ServiceTargetMinutes;
|
|
5
|
+
export declare class SupportPlan extends SmrtObject {
|
|
6
|
+
tenantId: string | null;
|
|
7
|
+
/** Natural key, unique per tenant (`conflictColumns`). */
|
|
8
|
+
planKey: string;
|
|
9
|
+
/** Display name (inherited `name` field). */
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
/** `draft` | `active` | `archived`. */
|
|
13
|
+
status: string;
|
|
14
|
+
/** Channels this plan covers (JSON array of channel kinds). */
|
|
15
|
+
channels: string;
|
|
16
|
+
/** IANA timezone the coverage calendar is expressed in. */
|
|
17
|
+
timezone: string;
|
|
18
|
+
/**
|
|
19
|
+
* Coverage calendar: JSON array of {@link CoverageWindow}. Empty array
|
|
20
|
+
* means 24×7 coverage (clocks always run).
|
|
21
|
+
*/
|
|
22
|
+
coverage: string;
|
|
23
|
+
/** Holiday dates excluded from coverage (JSON array of `YYYY-MM-DD`). */
|
|
24
|
+
holidays: string;
|
|
25
|
+
/**
|
|
26
|
+
* Severity vocabulary for this plan: JSON map of severity key →
|
|
27
|
+
* {@link SeverityDefinition}. Empty object falls back to
|
|
28
|
+
* `DEFAULT_SEVERITY_DEFINITIONS`.
|
|
29
|
+
*/
|
|
30
|
+
severityDefinitions: string;
|
|
31
|
+
/**
|
|
32
|
+
* Service Targets per severity: JSON map of severity key →
|
|
33
|
+
* {@link ServiceTargetMinutes}. Missing severities fall back to
|
|
34
|
+
* `DEFAULT_TARGET_MINUTES`; explicit `null` minutes disable that clock.
|
|
35
|
+
*/
|
|
36
|
+
targets: string;
|
|
37
|
+
/**
|
|
38
|
+
* Case statuses that pause Service Target clocks (FR-29b: waiting periods
|
|
39
|
+
* pause clocks only when the plan says so). JSON array of statuses.
|
|
40
|
+
*/
|
|
41
|
+
pauseStatuses: string;
|
|
42
|
+
/** Escalation policy: JSON array of {@link EscalationStep}, level order. */
|
|
43
|
+
escalationPolicy: string;
|
|
44
|
+
/** Recurring availability/retainer fee (0.0 = pure hourly support). */
|
|
45
|
+
availabilityFeeAmount: number;
|
|
46
|
+
currency: string;
|
|
47
|
+
/** Included support minutes per period (0 = none included). */
|
|
48
|
+
includedMinutes: number;
|
|
49
|
+
/** Metered hourly rate for time beyond the included minutes. */
|
|
50
|
+
overageHourlyRate: number;
|
|
51
|
+
/** Premium hourly rate for on-call work (0.0 = use overage rate). */
|
|
52
|
+
onCallHourlyRate: number;
|
|
53
|
+
/**
|
|
54
|
+
* Time-entry approval policy for work under this plan (FR-36): JSON
|
|
55
|
+
* {@link TimeApprovalPolicy}. Empty object = operator approval.
|
|
56
|
+
*/
|
|
57
|
+
timeApprovalPolicy: string;
|
|
58
|
+
/** Optional `@happyvertical/smrt-subscriptions` plan natural key binding. */
|
|
59
|
+
subscriptionPlanKey: string;
|
|
60
|
+
metadata: string;
|
|
61
|
+
getChannels(): string[];
|
|
62
|
+
setChannels(channels: string[]): void;
|
|
63
|
+
getCoverage(): CoverageWindow[];
|
|
64
|
+
setCoverage(windows: CoverageWindow[]): void;
|
|
65
|
+
getHolidays(): string[];
|
|
66
|
+
setHolidays(dates: string[]): void;
|
|
67
|
+
getSeverityDefinitions(): Record<string, SeverityDefinition>;
|
|
68
|
+
setSeverityDefinitions(defs: Record<string, SeverityDefinition>): void;
|
|
69
|
+
getTargets(): Record<string, Partial<ServiceTargetMinutes>>;
|
|
70
|
+
setTargets(targets: Record<string, Partial<ServiceTargetMinutes>>): void;
|
|
71
|
+
/** Effective target minutes for a severity, with defaults applied. */
|
|
72
|
+
targetsForSeverity(severity: string): ServiceTargetMinutes;
|
|
73
|
+
getPauseStatuses(): string[];
|
|
74
|
+
setPauseStatuses(statuses: string[]): void;
|
|
75
|
+
getEscalationPolicy(): EscalationStep[];
|
|
76
|
+
setEscalationPolicy(steps: EscalationStep[]): void;
|
|
77
|
+
getTimeApprovalPolicy(): TimeApprovalPolicy;
|
|
78
|
+
setTimeApprovalPolicy(policy: TimeApprovalPolicy): void;
|
|
79
|
+
getMetadata(): Record<string, unknown>;
|
|
80
|
+
setMetadata(value: Record<string, unknown>): void;
|
|
81
|
+
/**
|
|
82
|
+
* The plan terms captured onto a case at apply time (`planSnapshot`), so
|
|
83
|
+
* later plan edits never rewrite the terms a case was handled under.
|
|
84
|
+
*/
|
|
85
|
+
snapshotTerms(): Record<string, unknown>;
|
|
86
|
+
}
|
|
87
|
+
export declare class SupportPlanCollection extends SmrtCollection<SupportPlan> {
|
|
88
|
+
static readonly _itemClass: typeof SupportPlan;
|
|
89
|
+
byPlanKey(planKey: string): Promise<SupportPlan | null>;
|
|
90
|
+
}
|
|
91
|
+
export default SupportPlan;
|
|
92
|
+
//# sourceMappingURL=support-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"support-plan.d.ts","sourceRoot":"","sources":["../../src/models/support-plan.ts"],"names":[],"mappings":"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"}
|