@opencxh/domain 1.91.0 → 1.92.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/entities/activity/types.d.ts +36 -1
- package/dist/entities/ai-profile/types.d.ts +16 -0
- package/dist/entities/playbook/index.d.ts +1 -0
- package/dist/entities/playbook/types.d.ts +154 -0
- package/dist/index.cjs +7 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +145 -98
- package/dist/text/message.d.ts +8 -0
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import { TranscriptSegment } from '../../platform/media';
|
|
|
3
3
|
export type CallStatus = "new" | "connecting" | "ringing" | "connected" | "held" | "ended" | "failed";
|
|
4
4
|
export type CallDirection = "inbound" | "outbound";
|
|
5
5
|
export type CallType = "audio" | "video" | "data" | "screen-share";
|
|
6
|
-
export type ActivityType = "VOICE_CALL_STARTED" | "VOICE_CALL_ANSWERED" | "VOICE_CALL_HOLD" | "VOICE_CALL_UNHOLD" | "VOICE_CALL_ENDED" | "VOICE_CALL_MISSED" | "VOICE_CALL_VOICEMAIL" | "VIDEO_CALL_STARTED" | "VIDEO_CALL_ANSWERED" | "VIDEO_CALL_HOLD" | "VIDEO_CALL_UNHOLD" | "VIDEO_CALL_ENDED" | "VIDEO_CALL_MISSED" | "EMAIL_RECEIVED" | "EMAIL_SENT" | "CHAT_MESSAGE_SENT" | "CHAT_MESSAGE_RECEIVED" | "CHAT_MEMBER_JOINED" | "CHAT_MEMBER_LEFT" | "CHAT_RENAMED" | "CHAT_CALL_STARTED" | "CHAT_CALL_ENDED" | "CHAT_EVENT" | "AI_MESSAGE_ADDED" | "MEETING_SCHEDULED" | "MEETING_STARTED" | "MEETING_ENDED" | "MEETING_PARTICIPANT_JOINED" | "MEETING_PARTICIPANT_LEFT" | "COMMENT_ADDED" | "FILE_UPLOADED" | "INTERACTION_CREATED" | "INTERACTION_STATUS_CHANGED" | "INTERACTION_ASSIGNED" | "VOICE_CALL_FAILED" | "VIDEO_CALL_FAILED" | "TRANSCRIPT_ADDED";
|
|
6
|
+
export type ActivityType = "VOICE_CALL_STARTED" | "VOICE_CALL_ANSWERED" | "VOICE_CALL_HOLD" | "VOICE_CALL_UNHOLD" | "VOICE_CALL_ENDED" | "VOICE_CALL_MISSED" | "VOICE_CALL_VOICEMAIL" | "VIDEO_CALL_STARTED" | "VIDEO_CALL_ANSWERED" | "VIDEO_CALL_HOLD" | "VIDEO_CALL_UNHOLD" | "VIDEO_CALL_ENDED" | "VIDEO_CALL_MISSED" | "EMAIL_RECEIVED" | "EMAIL_SENT" | "CHAT_MESSAGE_SENT" | "CHAT_MESSAGE_RECEIVED" | "CHAT_MEMBER_JOINED" | "CHAT_MEMBER_LEFT" | "CHAT_RENAMED" | "CHAT_CALL_STARTED" | "CHAT_CALL_ENDED" | "CHAT_EVENT" | "AI_MESSAGE_ADDED" | "AI_ACTION_PROPOSED" | "PLAYBOOK_STARTED" | "PLAYBOOK_COMPLETED" | "PLAYBOOK_ESCALATED" | "MEETING_SCHEDULED" | "MEETING_STARTED" | "MEETING_ENDED" | "MEETING_PARTICIPANT_JOINED" | "MEETING_PARTICIPANT_LEFT" | "COMMENT_ADDED" | "FILE_UPLOADED" | "INTERACTION_CREATED" | "INTERACTION_STATUS_CHANGED" | "INTERACTION_ASSIGNED" | "VOICE_CALL_FAILED" | "VIDEO_CALL_FAILED" | "TRANSCRIPT_ADDED";
|
|
7
7
|
export interface Attachment {
|
|
8
8
|
id: string;
|
|
9
9
|
filename: string;
|
|
@@ -183,6 +183,29 @@ export type AIMessageAddedPayload = {
|
|
|
183
183
|
accountId?: string;
|
|
184
184
|
model?: string;
|
|
185
185
|
};
|
|
186
|
+
/**
|
|
187
|
+
* A playbook proposes one or more actions for a human to approve/reject (autonomy:
|
|
188
|
+
* suggest). Rendered inline in the interaction timeline; approve/reject call the ai
|
|
189
|
+
* app's `playbook-run` endpoints. System-authored, so it does not re-trigger playbooks.
|
|
190
|
+
*/
|
|
191
|
+
export type AIActionProposedPayload = {
|
|
192
|
+
runId: string;
|
|
193
|
+
playbookId?: string;
|
|
194
|
+
playbookName?: string;
|
|
195
|
+
/** The held actions, e.g. { action: "tool:mcp__jira__create_issue", params }. */
|
|
196
|
+
actions: {
|
|
197
|
+
action: string;
|
|
198
|
+
params?: Record<string, unknown>;
|
|
199
|
+
}[];
|
|
200
|
+
status: "pending" | "approved" | "rejected";
|
|
201
|
+
};
|
|
202
|
+
/** Playbook lifecycle marker in the interaction timeline (system-authored). */
|
|
203
|
+
export type PlaybookLifecyclePayload = {
|
|
204
|
+
runId: string;
|
|
205
|
+
playbookId?: string;
|
|
206
|
+
playbookName?: string;
|
|
207
|
+
status?: string;
|
|
208
|
+
};
|
|
186
209
|
export type Activity = (BaseActivity & {
|
|
187
210
|
type: "VOICE_CALL_STARTED";
|
|
188
211
|
payload: VoiceCallPayload;
|
|
@@ -264,6 +287,18 @@ export type Activity = (BaseActivity & {
|
|
|
264
287
|
}) | (BaseActivity & {
|
|
265
288
|
type: "AI_MESSAGE_ADDED";
|
|
266
289
|
payload: AIMessageAddedPayload;
|
|
290
|
+
}) | (BaseActivity & {
|
|
291
|
+
type: "AI_ACTION_PROPOSED";
|
|
292
|
+
payload: AIActionProposedPayload;
|
|
293
|
+
}) | (BaseActivity & {
|
|
294
|
+
type: "PLAYBOOK_STARTED";
|
|
295
|
+
payload: PlaybookLifecyclePayload;
|
|
296
|
+
}) | (BaseActivity & {
|
|
297
|
+
type: "PLAYBOOK_COMPLETED";
|
|
298
|
+
payload: PlaybookLifecyclePayload;
|
|
299
|
+
}) | (BaseActivity & {
|
|
300
|
+
type: "PLAYBOOK_ESCALATED";
|
|
301
|
+
payload: PlaybookLifecyclePayload;
|
|
267
302
|
}) | (BaseActivity & {
|
|
268
303
|
type: "MEETING_SCHEDULED";
|
|
269
304
|
payload: MeetingPayload;
|
|
@@ -22,6 +22,22 @@ export interface AIProfile<T extends Record<string, any> = Record<string, any>>
|
|
|
22
22
|
predefinedPrompts?: PredefinedPrompt[];
|
|
23
23
|
/** Namespaced tool names this profile may use (default: none enabled). */
|
|
24
24
|
enabledTools?: string[];
|
|
25
|
+
/**
|
|
26
|
+
* Per-tool confirmation policy. Stored as a LIST (not a keyed map) on purpose:
|
|
27
|
+
* namespaced tool names contain "__", and the SDK client transforms every
|
|
28
|
+
* object KEY between camelCase/snake_case — which mangles map keys (e.g.
|
|
29
|
+
* `communication__compose_email` -> `communication_ComposeEmail`) so they no
|
|
30
|
+
* longer match `enabledTools`. As a list the tool name lives in a string VALUE,
|
|
31
|
+
* which the transform leaves untouched.
|
|
32
|
+
*
|
|
33
|
+
* Under autonomy "suggest", write tools are held for approval; reads run freely.
|
|
34
|
+
* A tool absent from this list defaults to "write" (safe). Also usable by the
|
|
35
|
+
* interactive assistant's requiresConfirmation flow.
|
|
36
|
+
*/
|
|
37
|
+
toolPolicy?: {
|
|
38
|
+
name: string;
|
|
39
|
+
policy: "read" | "write";
|
|
40
|
+
}[];
|
|
25
41
|
/**
|
|
26
42
|
* Whether the acting user's PERSONAL MCP tools (their own per-user connections)
|
|
27
43
|
* are available on this profile, on top of the admin-curated `enabledTools`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types';
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { OwnerScope } from '../contact/types';
|
|
2
|
+
/**
|
|
3
|
+
* Playbooks — event-driven automation with AI steps. See docs/PLAYBOOKS.md.
|
|
4
|
+
* Fase 0 covers the deterministic subset; AI steps are typed here but the
|
|
5
|
+
* executor rejects them until Fase 2.
|
|
6
|
+
*/
|
|
7
|
+
export type Autonomy = "suggest" | "auto";
|
|
8
|
+
export type PlaybookTrigger = {
|
|
9
|
+
kind: "activity";
|
|
10
|
+
activityTypes: string[];
|
|
11
|
+
/** Channel kinds: "mail" | "chat" | "voice" (derived from the activity type). */
|
|
12
|
+
channels?: string[];
|
|
13
|
+
/** Specific channel ids (e.g. per mailbox). Matched against activity.channelId. */
|
|
14
|
+
channelIds?: string[];
|
|
15
|
+
filter?: unknown;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "manual";
|
|
18
|
+
};
|
|
19
|
+
export interface Guardrails {
|
|
20
|
+
maxSteps?: number;
|
|
21
|
+
maxToolCalls?: number;
|
|
22
|
+
policyCaps?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
export interface ConditionStep {
|
|
25
|
+
type: "condition";
|
|
26
|
+
/** JSONLogic expression evaluated against the run vars. */
|
|
27
|
+
if: unknown;
|
|
28
|
+
/** Gate: what to do when the condition is false. "then" = the steps that follow. */
|
|
29
|
+
onFalse: "stop" | "escalate" | "continue";
|
|
30
|
+
}
|
|
31
|
+
export interface ForEachStep {
|
|
32
|
+
type: "for-each";
|
|
33
|
+
in: string;
|
|
34
|
+
as: string;
|
|
35
|
+
body: Step[];
|
|
36
|
+
}
|
|
37
|
+
export interface LookupStep {
|
|
38
|
+
type: "lookup";
|
|
39
|
+
/** "tool:<namespaced>" (Fase 1) or a local source ("interactions"/"tasks"). */
|
|
40
|
+
source: string;
|
|
41
|
+
filter?: unknown;
|
|
42
|
+
as: string;
|
|
43
|
+
}
|
|
44
|
+
export interface ActionStep {
|
|
45
|
+
type: "action";
|
|
46
|
+
/** Local action ("task.create"/"interaction.set"/"notify.user") or "tool:<namespaced>" (Fase 1). */
|
|
47
|
+
action: string;
|
|
48
|
+
params: Record<string, unknown>;
|
|
49
|
+
autonomy?: Autonomy;
|
|
50
|
+
}
|
|
51
|
+
/** AI steps — typed in Fase 0, executed from Fase 2. */
|
|
52
|
+
export interface ClassifyStep {
|
|
53
|
+
type: "classify";
|
|
54
|
+
as: string;
|
|
55
|
+
accountId: string;
|
|
56
|
+
model: string;
|
|
57
|
+
mode: "topics" | "question" | "extract";
|
|
58
|
+
topicIds?: string[];
|
|
59
|
+
question?: string;
|
|
60
|
+
fields?: unknown;
|
|
61
|
+
instruction?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface GenerateStep {
|
|
64
|
+
type: "generate";
|
|
65
|
+
profileId: string;
|
|
66
|
+
goal?: string;
|
|
67
|
+
kind: "reply" | "compose" | "note";
|
|
68
|
+
as?: string;
|
|
69
|
+
}
|
|
70
|
+
export interface AgentStep {
|
|
71
|
+
type: "agent";
|
|
72
|
+
profileId: string;
|
|
73
|
+
goal: string;
|
|
74
|
+
guardrails: Guardrails;
|
|
75
|
+
toolsOverride?: string[];
|
|
76
|
+
autonomy?: Autonomy;
|
|
77
|
+
as?: string;
|
|
78
|
+
}
|
|
79
|
+
export interface WaitForReplyStep {
|
|
80
|
+
type: "wait-for-reply";
|
|
81
|
+
deadline?: number;
|
|
82
|
+
}
|
|
83
|
+
export type Step = ConditionStep | ForEachStep | LookupStep | ActionStep | ClassifyStep | GenerateStep | AgentStep | WaitForReplyStep;
|
|
84
|
+
export interface Playbook {
|
|
85
|
+
id: string;
|
|
86
|
+
organizationId: string;
|
|
87
|
+
ownerScope: OwnerScope;
|
|
88
|
+
name: string;
|
|
89
|
+
description?: string;
|
|
90
|
+
enabled: boolean;
|
|
91
|
+
autonomy: Autonomy;
|
|
92
|
+
trigger: PlaybookTrigger;
|
|
93
|
+
steps: Step[];
|
|
94
|
+
/** Bumped on every change; runs pin to the version they started on. */
|
|
95
|
+
version: number;
|
|
96
|
+
/** Actor of autonomous actions. */
|
|
97
|
+
createdBy: string;
|
|
98
|
+
lastRunAt?: number;
|
|
99
|
+
stats?: {
|
|
100
|
+
runs: number;
|
|
101
|
+
proposals: number;
|
|
102
|
+
autoActions: number;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export type RunStatus = "pending" | "running" | "awaiting_approval" | "awaiting_reply" | "done" | "escalated" | "failed" | "timed_out" | "stopped";
|
|
106
|
+
export interface RunStepTrace {
|
|
107
|
+
path: string;
|
|
108
|
+
type: string;
|
|
109
|
+
ok: boolean;
|
|
110
|
+
note?: string;
|
|
111
|
+
ms?: number;
|
|
112
|
+
}
|
|
113
|
+
export interface PlaybookRun {
|
|
114
|
+
id: string;
|
|
115
|
+
organizationId: string;
|
|
116
|
+
playbookId: string;
|
|
117
|
+
playbookVersion: number;
|
|
118
|
+
interactionId?: string;
|
|
119
|
+
status: RunStatus;
|
|
120
|
+
trigger: {
|
|
121
|
+
activityType?: string;
|
|
122
|
+
activityId?: string;
|
|
123
|
+
event: Record<string, unknown>;
|
|
124
|
+
};
|
|
125
|
+
vars: Record<string, unknown>;
|
|
126
|
+
trace: RunStepTrace[];
|
|
127
|
+
/** Snapshot of the playbook steps at run start — version-pinned resume (docs 11.4). */
|
|
128
|
+
steps?: Step[];
|
|
129
|
+
/** Held action(s) awaiting human approval (autonomy: suggest) — a batch per paused step. */
|
|
130
|
+
pending?: {
|
|
131
|
+
stepIndex: number;
|
|
132
|
+
actions: {
|
|
133
|
+
action: string;
|
|
134
|
+
params: Record<string, unknown>;
|
|
135
|
+
}[];
|
|
136
|
+
};
|
|
137
|
+
/** The AI_ACTION_PROPOSED activity created for the current pending batch (for resolve on approve/reject). */
|
|
138
|
+
proposalActivityId?: string;
|
|
139
|
+
/** Parked run (awaiting_reply): where to continue + correlation + round counter. */
|
|
140
|
+
awaitFor?: {
|
|
141
|
+
interactionId?: string;
|
|
142
|
+
};
|
|
143
|
+
resumeIndex?: number;
|
|
144
|
+
rounds?: number;
|
|
145
|
+
/** Denormalized interaction audience for efficient list-filtering. */
|
|
146
|
+
audience?: string[];
|
|
147
|
+
createdBy: string;
|
|
148
|
+
approvedBy?: string;
|
|
149
|
+
result?: {
|
|
150
|
+
ok: boolean;
|
|
151
|
+
error?: string;
|
|
152
|
+
};
|
|
153
|
+
lastStepAt?: number;
|
|
154
|
+
}
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=140;function
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=140;function p(e){return e.replace(/<style[\s\S]*?<\/style>/gi," ").replace(/<script[\s\S]*?<\/script>/gi," ").replace(/<[^>]+>/g," ").replace(/ /g," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/\s+/g," ").trim()}function T(e){const t=e.trim();return t.length<=l?t:t.slice(0,l-1).trimEnd()+"…"}function E(e){if(!e||e<0)return"";const t=Math.floor(e/60),n=Math.floor(e%60);return`${t}:${n.toString().padStart(2,"0")}`}function f(e){switch(e.type){case"EMAIL_RECEIVED":case"EMAIL_SENT":{const t=e.payload,n=t.bodySnippet?.trim()||p(t.body??"");return t.subject?`${t.subject} — ${n}`:n}case"CHAT_MESSAGE_SENT":case"CHAT_MESSAGE_RECEIVED":return e.payload.text??"";case"CHAT_RENAMED":return`Hernoemd naar "${e.payload.newName}"`;case"CHAT_MEMBER_JOINED":return`${e.payload.members.map(t=>t.name).join(", ")} toegevoegd`;case"CHAT_MEMBER_LEFT":return`${e.payload.members.map(t=>t.name).join(", ")} verlaten`;case"CHAT_CALL_STARTED":return"Gesprek gestart";case"CHAT_CALL_ENDED":return`Gesprek beëindigd${e.payload.duration?` (${E(e.payload.duration)})`:""}`;case"CHAT_EVENT":return e.payload.text??e.payload.eventType;case"VOICE_CALL_STARTED":case"VIDEO_CALL_STARTED":return"Gesprek gestart";case"VOICE_CALL_ANSWERED":case"VIDEO_CALL_ANSWERED":return"Gesprek aangenomen";case"VOICE_CALL_HOLD":case"VIDEO_CALL_HOLD":return"In de wacht";case"VOICE_CALL_UNHOLD":case"VIDEO_CALL_UNHOLD":return"Hervat";case"VOICE_CALL_ENDED":case"VIDEO_CALL_ENDED":return`Gesprek beëindigd${e.payload.duration?` (${E(e.payload.duration)})`:""}`;case"VOICE_CALL_MISSED":case"VIDEO_CALL_MISSED":return"Gemiste oproep";case"VOICE_CALL_FAILED":case"VIDEO_CALL_FAILED":return"Gesprek mislukt";case"VOICE_CALL_VOICEMAIL":return e.payload.transcription?.trim()?e.payload.transcription:"Voicemail ontvangen";case"TRANSCRIPT_ADDED":return(e.payload.segments??[]).map(t=>t.text).join(" ");case"AI_MESSAGE_ADDED":return e.payload.output?.text??e.payload.input?.text??"";case"AI_ACTION_PROPOSED":return`Voorstel wacht op goedkeuring (${e.payload.actions?.length??0} actie(s))`;case"PLAYBOOK_STARTED":return`Playbook gestart${e.payload.playbookName?`: ${e.payload.playbookName}`:""}`;case"PLAYBOOK_COMPLETED":return"Playbook afgerond";case"PLAYBOOK_ESCALATED":return"Playbook geëscaleerd naar een mens";case"MEETING_SCHEDULED":return`Vergadering gepland: ${e.payload.title}`;case"MEETING_STARTED":return`Vergadering gestart: ${e.payload.title}`;case"MEETING_ENDED":return`Vergadering beëindigd${e.payload.duration?` (${E(e.payload.duration)})`:""}`;case"MEETING_PARTICIPANT_JOINED":return`${e.payload.name} deelgenomen`;case"MEETING_PARTICIPANT_LEFT":return`${e.payload.name} verlaten`;case"COMMENT_ADDED":return e.payload.text??"";case"FILE_UPLOADED":return`Bestand: ${e.payload.fileName}`;case"INTERACTION_CREATED":return"Interactie aangemaakt";case"INTERACTION_STATUS_CHANGED":return`Status: ${e.payload.fromStatus} → ${e.payload.toStatus}`;case"INTERACTION_ASSIGNED":return"Interactie toegewezen";default:return""}}function S(e){return{activityId:e.id,type:e.type,snippet:T(f(e)),authorName:e.author?.name??"",direction:e.direction,createdAt:e.createdAt??Date.now()}}function N(e,t,n=[]){const r=e.createdAt;if(!r)return[];const s=new Set(n);return e.author.type==="user"&&e.author.id&&s.add(e.author.id),Object.entries(t).filter(([a,o])=>o>=r&&!s.has(a)).map(([a])=>a)}const D=new Set(["mail","message"]);function d(e,t){const n=e.settings?.signatures?.[t];return!n||!n.enabled||!n.body||n.body.trim()===""?null:n}function O(e,t,n,r="html"){if(!e)return n;const s=d(e,t);return s?`${n}${r==="text"?`
|
|
2
2
|
|
|
3
|
-
`:t==="mail"?"<br><br>-- <br>":"<br><br>"}${s.body}`:n}function
|
|
3
|
+
`:t==="mail"?"<br><br>-- <br>":"<br><br>"}${s.body}`:n}function R(e){return e.endpoints??[]}const L=e=>!!e.assignedUserId||!!e.assignedInboxId,C=e=>e.status==="closed",b=e=>({urgent:10,high:5,normal:2,low:1})[e.priority]||0,M=(e,t=30)=>e.title?.length<=t?e.title:`${e.title.substring(0,t)}...`;function m(e,t){return e.lastActivityAt?!(e.seenBy??[]).includes(t):!1}const P=[/<blockquote/i,/class="?gmail_quote/i,/id="?[^"]*divRplyFwdMsg/i,/-{3,}\s*Original Message\s*-{3,}/i,/\n_{5,}\s*\n/,/\bOn\b[\s\S]{0,200}?\bwrote:/i];function i(e){let t=e;return t=t.replace(/<(script|style)[\s\S]*?<\/\1>/gi,""),t=t.replace(/<br\s*\/?>/gi,`
|
|
4
|
+
`),t=t.replace(/<\/(p|div|li|tr|h[1-6]|ul|ol|table)>/gi,`
|
|
5
|
+
`),t=t.replace(/<[^>]+>/g,""),t=t.replace(/<[^>]*$/,""),t}function c(e){return e.replace(/ /gi," ").replace(/</gi,"<").replace(/>/gi,">").replace(/"/gi,'"').replace(/'/gi,"'").replace(/&#(\d+);/g,(t,n)=>String.fromCharCode(Number(n))).replace(/&/gi,"&")}function u(e){return e.replace(/\r/g,"").replace(/[ \t]+/g," ").replace(/ *\n */g,`
|
|
6
|
+
`).replace(/\n{3,}/g,`
|
|
7
|
+
|
|
8
|
+
`).trim()}function y(e){if(typeof e!="string"||!e)return"";let t=e.length;for(const s of P){const a=e.search(s);a>=0&&a<t&&(t=a)}const n=e.slice(0,t);let r=u(c(i(n)));return r||(r=u(c(i(e)))),r}function A(e,t){const n=new Set(e.disabledIntents??[]),r=e.intentOverrides??{},s=t.intents.filter(o=>!n.has(o.intent)).map(o=>U(o,r[o.intent]));if(!e.extraIntents||e.extraIntents.length===0)return s;const a=new Set(s.map(o=>o.intent));for(const o of e.extraIntents)a.has(o.intent)||(s.push(o),a.add(o.intent));return s}function g(e,t){const n={};for(const r of e.intents){if(!r.togglable)continue;const s=t?.[r.intent];n[r.intent]=s??r.defaultEnabled??!0}return n}function h(e,t){const n=g(e,t);return Object.entries(n).filter(([,r])=>!r).map(([r])=>r)}function U(e,t){return t?{intent:t.intent??e.intent,targetSchemes:t.targetSchemes??e.targetSchemes,transport:t.transport??e.transport}:e}function G(e,t){const n=[];for(const r of e){if(!r.enabled)continue;const s=t[r.providerId];if(s)for(const a of A(r,s))n.push({channel:r,description:s,capability:a})}return n}function V(e,t){return t.filter(n=>n.capability.intent===e)}function I(e,t){return t.filter(n=>n.capability.targetSchemes.includes(e))}function $(e,t){return I(e.scheme,t)}function H(e,t,n){const r=[];for(const s of e)for(const a of n)a.capability.intent===t&&a.capability.targetSchemes.includes(s.scheme)&&r.push({channelIntent:a,endpoint:s});return r}var _=(e=>(e.MAILTO="mailto",e.SIP="sip",e.TEL="tel",e.WEBHOOK="webhook",e.USERNAME="username",e.ID="id",e.CUSTOM="custom",e.URL="url",e.TELEGRAM="telegram",e.WHATSAPP="whatsapp",e.MESSENGER="messenger",e.INSTAGRAM="instagram",e.VIBER="viber",e.SMS="sms",e.FAX="fax",e.TEAMS="teams",e.CALENDAR="calendar",e))(_||{});const F="message_window",k="message_templates",B={FROM:"from",TO:"to",CC:"cc",BCC:"bcc",ORGANIZER:"organizer",PRESENTER:"presenter",ATTENDEE:"attendee",OWNER:"owner",MEMBER:"member",GUEST:"guest",HOST:"host",PARTICIPANT:"participant"},x=(e,t)=>({intent:e,...t}),w="folder_management",W="remote_search",j={ok:!1,code:"UNSUPPORTED",message:"Provider does not support this op"},K=9e4,q="installation-id";exports.CommunicationScheme=_;exports.FEATURE_FOLDER_MANAGEMENT=w;exports.FEATURE_REMOTE_SEARCH=W;exports.INSTALLATION_HEADER=q;exports.InteractionParticipantRole=B;exports.PRESENCE_ONLINE_WINDOW_MS=K;exports.PROVIDER_FEATURE_MESSAGE_TEMPLATES=k;exports.PROVIDER_FEATURE_MESSAGE_WINDOW=F;exports.SIGNATURE_INTENTS=D;exports.UNSUPPORTED=j;exports.applySignature=O;exports.buildActivityPreview=S;exports.buildChannelIntents=G;exports.cleanMessageText=y;exports.defineIntent=x;exports.disabledIntentsFromCapabilities=h;exports.filterByEndpoint=$;exports.filterByIntent=V;exports.filterByTargetScheme=I;exports.getActivitySeenUserIds=N;exports.getContactEndpoints=R;exports.getShortTitle=M;exports.getUrgencyScore=b;exports.isAssigned=L;exports.isClosed=C;exports.isInteractionUnseen=m;exports.matchContactToIntents=H;exports.resolveAccountCapabilities=g;exports.resolveChannelIntents=A;exports.resolveSignature=d;exports.stripHtml=p;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './entities/activity';
|
|
2
|
+
export * from './entities/playbook';
|
|
2
3
|
export * from './entities/kb';
|
|
3
4
|
export * from './entities/topic';
|
|
4
5
|
export * from './entities/ai-account';
|
|
@@ -22,6 +23,7 @@ export * from './entities/organization';
|
|
|
22
23
|
export * from './entities/shopify';
|
|
23
24
|
export * from './entities/transcript';
|
|
24
25
|
export * from './entities/user';
|
|
26
|
+
export * from './text/message';
|
|
25
27
|
export * from './platform/ai-tools';
|
|
26
28
|
export * from './platform/api';
|
|
27
29
|
export * from './platform/common';
|
package/dist/index.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
function
|
|
1
|
+
function p(e) {
|
|
2
2
|
return e.replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<[^>]+>/g, " ").replace(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/\s+/g, " ").trim();
|
|
3
3
|
}
|
|
4
|
-
function
|
|
4
|
+
function i(e) {
|
|
5
5
|
const t = e.trim();
|
|
6
6
|
return t.length <= 140 ? t : t.slice(0, 139).trimEnd() + "…";
|
|
7
7
|
}
|
|
8
|
-
function
|
|
8
|
+
function l(e) {
|
|
9
9
|
if (!e || e < 0) return "";
|
|
10
|
-
const t = Math.floor(e / 60),
|
|
11
|
-
return `${t}:${
|
|
10
|
+
const t = Math.floor(e / 60), r = Math.floor(e % 60);
|
|
11
|
+
return `${t}:${r.toString().padStart(2, "0")}`;
|
|
12
12
|
}
|
|
13
|
-
function
|
|
13
|
+
function d(e) {
|
|
14
14
|
switch (e.type) {
|
|
15
15
|
case "EMAIL_RECEIVED":
|
|
16
16
|
case "EMAIL_SENT": {
|
|
17
|
-
const t = e.payload,
|
|
18
|
-
return t.subject ? `${t.subject} — ${
|
|
17
|
+
const t = e.payload, r = t.bodySnippet?.trim() || p(t.body ?? "");
|
|
18
|
+
return t.subject ? `${t.subject} — ${r}` : r;
|
|
19
19
|
}
|
|
20
20
|
case "CHAT_MESSAGE_SENT":
|
|
21
21
|
case "CHAT_MESSAGE_RECEIVED":
|
|
@@ -29,7 +29,7 @@ function p(e) {
|
|
|
29
29
|
case "CHAT_CALL_STARTED":
|
|
30
30
|
return "Gesprek gestart";
|
|
31
31
|
case "CHAT_CALL_ENDED":
|
|
32
|
-
return `Gesprek beëindigd${e.payload.duration ? ` (${
|
|
32
|
+
return `Gesprek beëindigd${e.payload.duration ? ` (${l(e.payload.duration)})` : ""}`;
|
|
33
33
|
case "CHAT_EVENT":
|
|
34
34
|
return e.payload.text ?? e.payload.eventType;
|
|
35
35
|
case "VOICE_CALL_STARTED":
|
|
@@ -46,7 +46,7 @@ function p(e) {
|
|
|
46
46
|
return "Hervat";
|
|
47
47
|
case "VOICE_CALL_ENDED":
|
|
48
48
|
case "VIDEO_CALL_ENDED":
|
|
49
|
-
return `Gesprek beëindigd${e.payload.duration ? ` (${
|
|
49
|
+
return `Gesprek beëindigd${e.payload.duration ? ` (${l(e.payload.duration)})` : ""}`;
|
|
50
50
|
case "VOICE_CALL_MISSED":
|
|
51
51
|
case "VIDEO_CALL_MISSED":
|
|
52
52
|
return "Gemiste oproep";
|
|
@@ -59,12 +59,20 @@ function p(e) {
|
|
|
59
59
|
return (e.payload.segments ?? []).map((t) => t.text).join(" ");
|
|
60
60
|
case "AI_MESSAGE_ADDED":
|
|
61
61
|
return e.payload.output?.text ?? e.payload.input?.text ?? "";
|
|
62
|
+
case "AI_ACTION_PROPOSED":
|
|
63
|
+
return `Voorstel wacht op goedkeuring (${e.payload.actions?.length ?? 0} actie(s))`;
|
|
64
|
+
case "PLAYBOOK_STARTED":
|
|
65
|
+
return `Playbook gestart${e.payload.playbookName ? `: ${e.payload.playbookName}` : ""}`;
|
|
66
|
+
case "PLAYBOOK_COMPLETED":
|
|
67
|
+
return "Playbook afgerond";
|
|
68
|
+
case "PLAYBOOK_ESCALATED":
|
|
69
|
+
return "Playbook geëscaleerd naar een mens";
|
|
62
70
|
case "MEETING_SCHEDULED":
|
|
63
71
|
return `Vergadering gepland: ${e.payload.title}`;
|
|
64
72
|
case "MEETING_STARTED":
|
|
65
73
|
return `Vergadering gestart: ${e.payload.title}`;
|
|
66
74
|
case "MEETING_ENDED":
|
|
67
|
-
return `Vergadering beëindigd${e.payload.duration ? ` (${
|
|
75
|
+
return `Vergadering beëindigd${e.payload.duration ? ` (${l(e.payload.duration)})` : ""}`;
|
|
68
76
|
case "MEETING_PARTICIPANT_JOINED":
|
|
69
77
|
return `${e.payload.name} deelgenomen`;
|
|
70
78
|
case "MEETING_PARTICIPANT_LEFT":
|
|
@@ -83,103 +91,141 @@ function p(e) {
|
|
|
83
91
|
return "";
|
|
84
92
|
}
|
|
85
93
|
}
|
|
86
|
-
function
|
|
94
|
+
function S(e) {
|
|
87
95
|
return {
|
|
88
96
|
activityId: e.id,
|
|
89
97
|
type: e.type,
|
|
90
|
-
snippet:
|
|
98
|
+
snippet: i(d(e)),
|
|
91
99
|
authorName: e.author?.name ?? "",
|
|
92
100
|
direction: e.direction,
|
|
93
101
|
createdAt: e.createdAt ?? Date.now()
|
|
94
102
|
};
|
|
95
103
|
}
|
|
96
|
-
function
|
|
97
|
-
const
|
|
98
|
-
if (!
|
|
99
|
-
const s = new Set(
|
|
100
|
-
return e.author.type === "user" && e.author.id && s.add(e.author.id), Object.entries(t).filter(([a, o]) => o >=
|
|
101
|
-
}
|
|
102
|
-
const
|
|
103
|
-
function
|
|
104
|
-
const
|
|
105
|
-
return !
|
|
106
|
-
}
|
|
107
|
-
function
|
|
108
|
-
if (!e) return
|
|
109
|
-
const s =
|
|
110
|
-
return s ? `${
|
|
104
|
+
function N(e, t, r = []) {
|
|
105
|
+
const n = e.createdAt;
|
|
106
|
+
if (!n) return [];
|
|
107
|
+
const s = new Set(r);
|
|
108
|
+
return e.author.type === "user" && e.author.id && s.add(e.author.id), Object.entries(t).filter(([a, o]) => o >= n && !s.has(a)).map(([a]) => a);
|
|
109
|
+
}
|
|
110
|
+
const L = /* @__PURE__ */ new Set(["mail", "message"]);
|
|
111
|
+
function A(e, t) {
|
|
112
|
+
const r = e.settings?.signatures?.[t];
|
|
113
|
+
return !r || !r.enabled || !r.body || r.body.trim() === "" ? null : r;
|
|
114
|
+
}
|
|
115
|
+
function O(e, t, r, n = "html") {
|
|
116
|
+
if (!e) return r;
|
|
117
|
+
const s = A(e, t);
|
|
118
|
+
return s ? `${r}${n === "text" ? `
|
|
111
119
|
|
|
112
|
-
` : t === "mail" ? "<br><br>-- <br>" : "<br><br>"}${s.body}` :
|
|
120
|
+
` : t === "mail" ? "<br><br>-- <br>" : "<br><br>"}${s.body}` : r;
|
|
113
121
|
}
|
|
114
|
-
function
|
|
122
|
+
function R(e) {
|
|
115
123
|
return e.endpoints ?? [];
|
|
116
124
|
}
|
|
117
|
-
const
|
|
125
|
+
const b = (e) => !!e.assignedUserId || !!e.assignedInboxId, C = (e) => e.status === "closed", M = (e) => ({
|
|
118
126
|
urgent: 10,
|
|
119
127
|
high: 5,
|
|
120
128
|
normal: 2,
|
|
121
129
|
low: 1
|
|
122
|
-
})[e.priority] || 0,
|
|
123
|
-
function
|
|
130
|
+
})[e.priority] || 0, m = (e, t = 30) => e.title?.length <= t ? e.title : `${e.title.substring(0, t)}...`;
|
|
131
|
+
function P(e, t) {
|
|
124
132
|
return e.lastActivityAt ? !(e.seenBy ?? []).includes(t) : !1;
|
|
125
133
|
}
|
|
126
|
-
|
|
127
|
-
|
|
134
|
+
const g = [
|
|
135
|
+
/<blockquote/i,
|
|
136
|
+
/class="?gmail_quote/i,
|
|
137
|
+
// Gmail quote container
|
|
138
|
+
/id="?[^"]*divRplyFwdMsg/i,
|
|
139
|
+
// Outlook web reply/forward header
|
|
140
|
+
/-{3,}\s*Original Message\s*-{3,}/i,
|
|
141
|
+
/\n_{5,}\s*\n/,
|
|
142
|
+
// Outlook underscore separator before "From:"
|
|
143
|
+
/\bOn\b[\s\S]{0,200}?\bwrote:/i
|
|
144
|
+
// Gmail "On <date> <name> wrote:"
|
|
145
|
+
];
|
|
146
|
+
function E(e) {
|
|
147
|
+
let t = e;
|
|
148
|
+
return t = t.replace(/<(script|style)[\s\S]*?<\/\1>/gi, ""), t = t.replace(/<br\s*\/?>/gi, `
|
|
149
|
+
`), t = t.replace(/<\/(p|div|li|tr|h[1-6]|ul|ol|table)>/gi, `
|
|
150
|
+
`), t = t.replace(/<[^>]+>/g, ""), t = t.replace(/<[^>]*$/, ""), t;
|
|
151
|
+
}
|
|
152
|
+
function u(e) {
|
|
153
|
+
return e.replace(/ /gi, " ").replace(/</gi, "<").replace(/>/gi, ">").replace(/"/gi, '"').replace(/'/gi, "'").replace(/&#(\d+);/g, (t, r) => String.fromCharCode(Number(r))).replace(/&/gi, "&");
|
|
154
|
+
}
|
|
155
|
+
function c(e) {
|
|
156
|
+
return e.replace(/\r/g, "").replace(/[ \t]+/g, " ").replace(/ *\n */g, `
|
|
157
|
+
`).replace(/\n{3,}/g, `
|
|
158
|
+
|
|
159
|
+
`).trim();
|
|
160
|
+
}
|
|
161
|
+
function $(e) {
|
|
162
|
+
if (typeof e != "string" || !e) return "";
|
|
163
|
+
let t = e.length;
|
|
164
|
+
for (const s of g) {
|
|
165
|
+
const a = e.search(s);
|
|
166
|
+
a >= 0 && a < t && (t = a);
|
|
167
|
+
}
|
|
168
|
+
const r = e.slice(0, t);
|
|
169
|
+
let n = c(u(E(r)));
|
|
170
|
+
return n || (n = c(u(E(e)))), n;
|
|
171
|
+
}
|
|
172
|
+
function _(e, t) {
|
|
173
|
+
const r = new Set(e.disabledIntents ?? []), n = e.intentOverrides ?? {}, s = t.intents.filter((o) => !r.has(o.intent)).map((o) => T(o, n[o.intent]));
|
|
128
174
|
if (!e.extraIntents || e.extraIntents.length === 0) return s;
|
|
129
175
|
const a = new Set(s.map((o) => o.intent));
|
|
130
176
|
for (const o of e.extraIntents)
|
|
131
177
|
a.has(o.intent) || (s.push(o), a.add(o.intent));
|
|
132
178
|
return s;
|
|
133
179
|
}
|
|
134
|
-
function
|
|
135
|
-
const
|
|
136
|
-
for (const
|
|
137
|
-
if (!
|
|
138
|
-
const s = t?.[
|
|
139
|
-
n
|
|
180
|
+
function I(e, t) {
|
|
181
|
+
const r = {};
|
|
182
|
+
for (const n of e.intents) {
|
|
183
|
+
if (!n.togglable) continue;
|
|
184
|
+
const s = t?.[n.intent];
|
|
185
|
+
r[n.intent] = s ?? n.defaultEnabled ?? !0;
|
|
140
186
|
}
|
|
141
|
-
return
|
|
187
|
+
return r;
|
|
142
188
|
}
|
|
143
|
-
function
|
|
144
|
-
const
|
|
145
|
-
return Object.entries(
|
|
189
|
+
function h(e, t) {
|
|
190
|
+
const r = I(e, t);
|
|
191
|
+
return Object.entries(r).filter(([, n]) => !n).map(([n]) => n);
|
|
146
192
|
}
|
|
147
|
-
function
|
|
193
|
+
function T(e, t) {
|
|
148
194
|
return t ? {
|
|
149
195
|
intent: t.intent ?? e.intent,
|
|
150
196
|
targetSchemes: t.targetSchemes ?? e.targetSchemes,
|
|
151
197
|
transport: t.transport ?? e.transport
|
|
152
198
|
} : e;
|
|
153
199
|
}
|
|
154
|
-
function
|
|
155
|
-
const
|
|
156
|
-
for (const
|
|
157
|
-
if (!
|
|
158
|
-
const s = t[
|
|
200
|
+
function y(e, t) {
|
|
201
|
+
const r = [];
|
|
202
|
+
for (const n of e) {
|
|
203
|
+
if (!n.enabled) continue;
|
|
204
|
+
const s = t[n.providerId];
|
|
159
205
|
if (s)
|
|
160
|
-
for (const a of
|
|
161
|
-
|
|
206
|
+
for (const a of _(n, s))
|
|
207
|
+
r.push({ channel: n, description: s, capability: a });
|
|
162
208
|
}
|
|
163
|
-
return
|
|
209
|
+
return r;
|
|
164
210
|
}
|
|
165
|
-
function
|
|
166
|
-
return t.filter((
|
|
211
|
+
function V(e, t) {
|
|
212
|
+
return t.filter((r) => r.capability.intent === e);
|
|
167
213
|
}
|
|
168
|
-
function
|
|
169
|
-
return t.filter((
|
|
214
|
+
function f(e, t) {
|
|
215
|
+
return t.filter((r) => r.capability.targetSchemes.includes(e));
|
|
170
216
|
}
|
|
171
|
-
function
|
|
172
|
-
return
|
|
217
|
+
function G(e, t) {
|
|
218
|
+
return f(e.scheme, t);
|
|
173
219
|
}
|
|
174
|
-
function
|
|
175
|
-
const
|
|
220
|
+
function H(e, t, r) {
|
|
221
|
+
const n = [];
|
|
176
222
|
for (const s of e)
|
|
177
|
-
for (const a of
|
|
178
|
-
a.capability.intent === t && a.capability.targetSchemes.includes(s.scheme) &&
|
|
179
|
-
return
|
|
223
|
+
for (const a of r)
|
|
224
|
+
a.capability.intent === t && a.capability.targetSchemes.includes(s.scheme) && n.push({ channelIntent: a, endpoint: s });
|
|
225
|
+
return n;
|
|
180
226
|
}
|
|
181
|
-
var
|
|
182
|
-
const
|
|
227
|
+
var D = /* @__PURE__ */ ((e) => (e.MAILTO = "mailto", e.SIP = "sip", e.TEL = "tel", e.WEBHOOK = "webhook", e.USERNAME = "username", e.ID = "id", e.CUSTOM = "custom", e.URL = "url", e.TELEGRAM = "telegram", e.WHATSAPP = "whatsapp", e.MESSENGER = "messenger", e.INSTAGRAM = "instagram", e.VIBER = "viber", e.SMS = "sms", e.FAX = "fax", e.TEAMS = "teams", e.CALENDAR = "calendar", e))(D || {});
|
|
228
|
+
const U = "message_window", k = "message_templates", x = {
|
|
183
229
|
// E-mail
|
|
184
230
|
FROM: "from",
|
|
185
231
|
TO: "to",
|
|
@@ -196,36 +242,37 @@ const V = "message_window", $ = "message_templates", H = {
|
|
|
196
242
|
// Voice/conference
|
|
197
243
|
HOST: "host",
|
|
198
244
|
PARTICIPANT: "participant"
|
|
199
|
-
},
|
|
245
|
+
}, F = (e, t) => ({ intent: e, ...t }), w = "folder_management", B = "remote_search", W = { ok: !1, code: "UNSUPPORTED", message: "Provider does not support this op" }, j = 9e4, K = "installation-id";
|
|
200
246
|
export {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
N as
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
C as
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
247
|
+
D as CommunicationScheme,
|
|
248
|
+
w as FEATURE_FOLDER_MANAGEMENT,
|
|
249
|
+
B as FEATURE_REMOTE_SEARCH,
|
|
250
|
+
K as INSTALLATION_HEADER,
|
|
251
|
+
x as InteractionParticipantRole,
|
|
252
|
+
j as PRESENCE_ONLINE_WINDOW_MS,
|
|
253
|
+
k as PROVIDER_FEATURE_MESSAGE_TEMPLATES,
|
|
254
|
+
U as PROVIDER_FEATURE_MESSAGE_WINDOW,
|
|
255
|
+
L as SIGNATURE_INTENTS,
|
|
256
|
+
W as UNSUPPORTED,
|
|
257
|
+
O as applySignature,
|
|
258
|
+
S as buildActivityPreview,
|
|
259
|
+
y as buildChannelIntents,
|
|
260
|
+
$ as cleanMessageText,
|
|
261
|
+
F as defineIntent,
|
|
262
|
+
h as disabledIntentsFromCapabilities,
|
|
263
|
+
G as filterByEndpoint,
|
|
264
|
+
V as filterByIntent,
|
|
265
|
+
f as filterByTargetScheme,
|
|
266
|
+
N as getActivitySeenUserIds,
|
|
267
|
+
R as getContactEndpoints,
|
|
268
|
+
m as getShortTitle,
|
|
269
|
+
M as getUrgencyScore,
|
|
270
|
+
b as isAssigned,
|
|
271
|
+
C as isClosed,
|
|
272
|
+
P as isInteractionUnseen,
|
|
273
|
+
H as matchContactToIntents,
|
|
274
|
+
I as resolveAccountCapabilities,
|
|
275
|
+
_ as resolveChannelIntents,
|
|
276
|
+
A as resolveSignature,
|
|
277
|
+
p as stripHtml
|
|
231
278
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clean an inbound message body for display/LLM use: cut the quoted reply /
|
|
3
|
+
* forwarded thread, strip HTML, decode common entities, collapse whitespace.
|
|
4
|
+
* Without this the raw HTML + full Gmail/Outlook quote leaks the OLD message into
|
|
5
|
+
* classify/extract/agent (or history views) instead of the sender's new content.
|
|
6
|
+
* Pure, dependency-free (lives in domain so both server apps can share it).
|
|
7
|
+
*/
|
|
8
|
+
export declare function cleanMessageText(raw: unknown): string;
|