@opencxh/domain 1.52.0 → 1.54.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.
@@ -1,3 +1,4 @@
1
+ import { ToolTraceEntry } from '../../platform/ai-tools';
1
2
  export interface AIMessageInput {
2
3
  text: string;
3
4
  type: "text";
@@ -17,16 +18,19 @@ export interface AIMessage {
17
18
  accountId?: string;
18
19
  model?: string;
19
20
  externalId?: string;
21
+ /** Tools the assistant invoked while producing this message (final, persisted trace). */
22
+ toolTrace?: ToolTraceEntry[];
20
23
  }
24
+ /**
25
+ * Profile-driven ask payload. The selected profile is the source of truth, so
26
+ * the client sends only `profileId`; the server resolves account/model/
27
+ * systemPrompt/enabledTools from it.
28
+ */
21
29
  export interface AIMessageAskPayload {
22
30
  interactionId: string;
23
31
  input: AIMessageInput;
24
- model: string;
25
- accountId: string;
32
+ profileId: string;
26
33
  previousExternalId?: string;
27
- providerConfig?: Record<string, any>;
28
- instructions?: string;
29
- systemPrompt?: string;
30
34
  context?: Record<string, any>;
31
35
  }
32
36
  export interface AIMessageAskResponse {
@@ -13,4 +13,6 @@ export interface AIProfile<T extends Record<string, any> = Record<string, any>>
13
13
  systemPrompt: string;
14
14
  contextIds?: string[];
15
15
  predefinedPrompts?: PredefinedPrompt[];
16
+ /** Namespaced tool names this profile may use (default: none enabled). */
17
+ enabledTools?: string[];
16
18
  }
@@ -8,6 +8,19 @@ export interface ActivityPreview {
8
8
  direction: "inbound" | "outbound" | "internal" | "none";
9
9
  createdAt: number;
10
10
  }
11
+ /** Query for the interaction search endpoint (POST /search/interaction). */
12
+ export interface InteractionSearchQuery {
13
+ /** Match the counterparty subdocument (exact). */
14
+ remoteParty?: {
15
+ scheme?: string;
16
+ resource?: string;
17
+ };
18
+ status?: string;
19
+ /** Only interactions with activity since this epoch-ms; null = no lower bound. */
20
+ since?: number | null;
21
+ page?: number;
22
+ limit?: number;
23
+ }
11
24
  export interface InteractionSource {
12
25
  activityId?: string;
13
26
  activityType?: string;
@@ -0,0 +1 @@
1
+ export * from './types';
@@ -0,0 +1,12 @@
1
+ /** Configuration for an external MCP (Model Context Protocol) server, per organization. */
2
+ export interface McpServerConfig {
3
+ id: string;
4
+ organizationId: string;
5
+ name: string;
6
+ /** Only Streamable HTTP transport is supported for server-side connections. */
7
+ transport: "http";
8
+ url: string;
9
+ /** Optional auth/extra headers sent on connect (e.g. `Authorization`). */
10
+ headers?: Record<string, string>;
11
+ enabled: boolean;
12
+ }
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=140;function i(e){return e.replace(/<style[\s\S]*?<\/style>/gi," ").replace(/<script[\s\S]*?<\/script>/gi," ").replace(/<[^>]+>/g," ").replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/\s+/g," ").trim()}function I(e){const t=e.trim();return t.length<=E?t:t.slice(0,E-1).trimEnd()+"…"}function l(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 A(e){switch(e.type){case"EMAIL_RECEIVED":case"EMAIL_SENT":{const t=e.payload,n=t.bodySnippet?.trim()||i(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?` (${l(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?` (${l(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"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?` (${l(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 T(e){return{activityId:e.id,type:e.type,snippet:I(A(e)),authorName:e.author?.name??"",direction:e.direction,createdAt:e.createdAt??Date.now()}}function g(e,t){const n=e.settings?.signatures?.[t];return!n||!n.enabled||!n.body||n.body.trim()===""?null:n}function f(e){return e.endpoints??[]}const _=e=>!!e.assignedUserId||!!e.assignedInboxId,D=e=>e.status==="closed",L=e=>({urgent:10,high:5,normal:2,low:1})[e.priority]||0,C=(e,t=30)=>e.title?.length<=t?e.title:`${e.title.substring(0,t)}...`;function S(e,t){return e.lastActivityAt?!(e.seenBy??[]).includes(t):!1}function u(e,t){const n=new Set(e.disabledIntents??[]),r=e.intentOverrides??{},s=t.intents.filter(a=>!n.has(a.intent)).map(a=>O(a,r[a.intent]));if(!e.extraIntents||e.extraIntents.length===0)return s;const o=new Set(s.map(a=>a.intent));for(const a of e.extraIntents)o.has(a.intent)||(s.push(a),o.add(a.intent));return s}function c(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 N(e,t){const n=c(e,t);return Object.entries(n).filter(([,r])=>!r).map(([r])=>r)}function O(e,t){return t?{intent:t.intent??e.intent,targetSchemes:t.targetSchemes??e.targetSchemes,transport:t.transport??e.transport}:e}function b(e,t){const n=[];for(const r of e){if(!r.enabled)continue;const s=t[r.providerId];if(s)for(const o of u(r,s))n.push({channel:r,description:s,capability:o})}return n}function R(e,t){return t.filter(n=>n.capability.intent===e)}function p(e,t){return t.filter(n=>n.capability.targetSchemes.includes(e))}function M(e,t){return p(e.scheme,t)}function y(e,t,n){const r=[];for(const s of e)for(const o of n)o.capability.intent===t&&o.capability.targetSchemes.includes(s.scheme)&&r.push({channelIntent:o,endpoint:s});return r}var d=(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.VIBER="viber",e.SMS="sms",e.FAX="fax",e.TEAMS="teams",e.CALENDAR="calendar",e))(d||{});const P={FROM:"from",TO:"to",CC:"cc",BCC:"bcc",ORGANIZER:"organizer",PRESENTER:"presenter",ATTENDEE:"attendee",OWNER:"owner",MEMBER:"member",GUEST:"guest",HOST:"host",PARTICIPANT:"participant"},m=(e,t)=>({intent:e,...t}),V={ok:!1,code:"UNSUPPORTED",message:"Provider does not support this op"},h="installation-id";exports.CommunicationScheme=d;exports.INSTALLATION_HEADER=h;exports.InteractionParticipantRole=P;exports.UNSUPPORTED=V;exports.buildActivityPreview=T;exports.buildChannelIntents=b;exports.defineIntent=m;exports.disabledIntentsFromCapabilities=N;exports.filterByEndpoint=M;exports.filterByIntent=R;exports.filterByTargetScheme=p;exports.getContactEndpoints=f;exports.getShortTitle=C;exports.getUrgencyScore=L;exports.isAssigned=_;exports.isClosed=D;exports.isInteractionUnseen=S;exports.matchContactToIntents=y;exports.resolveAccountCapabilities=c;exports.resolveChannelIntents=u;exports.resolveSignature=g;exports.stripHtml=i;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=140;function i(e){return e.replace(/<style[\s\S]*?<\/style>/gi," ").replace(/<script[\s\S]*?<\/script>/gi," ").replace(/<[^>]+>/g," ").replace(/&nbsp;/g," ").replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/\s+/g," ").trim()}function A(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 I(e){switch(e.type){case"EMAIL_RECEIVED":case"EMAIL_SENT":{const t=e.payload,n=t.bodySnippet?.trim()||i(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"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 T(e){return{activityId:e.id,type:e.type,snippet:A(I(e)),authorName:e.author?.name??"",direction:e.direction,createdAt:e.createdAt??Date.now()}}function _(e,t){const n=e.settings?.signatures?.[t];return!n||!n.enabled||!n.body||n.body.trim()===""?null:n}function g(e){return e.endpoints??[]}const f=e=>!!e.assignedUserId||!!e.assignedInboxId,D=e=>e.status==="closed",S=e=>({urgent:10,high:5,normal:2,low:1})[e.priority]||0,L=(e,t=30)=>e.title?.length<=t?e.title:`${e.title.substring(0,t)}...`;function C(e,t){return e.lastActivityAt?!(e.seenBy??[]).includes(t):!1}function u(e,t){const n=new Set(e.disabledIntents??[]),r=e.intentOverrides??{},s=t.intents.filter(a=>!n.has(a.intent)).map(a=>R(a,r[a.intent]));if(!e.extraIntents||e.extraIntents.length===0)return s;const o=new Set(s.map(a=>a.intent));for(const a of e.extraIntents)o.has(a.intent)||(s.push(a),o.add(a.intent));return s}function p(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 N(e,t){const n=p(e,t);return Object.entries(n).filter(([,r])=>!r).map(([r])=>r)}function R(e,t){return t?{intent:t.intent??e.intent,targetSchemes:t.targetSchemes??e.targetSchemes,transport:t.transport??e.transport}:e}function O(e,t){const n=[];for(const r of e){if(!r.enabled)continue;const s=t[r.providerId];if(s)for(const o of u(r,s))n.push({channel:r,description:s,capability:o})}return n}function b(e,t){return t.filter(n=>n.capability.intent===e)}function d(e,t){return t.filter(n=>n.capability.targetSchemes.includes(e))}function M(e,t){return d(e.scheme,t)}function P(e,t,n){const r=[];for(const s of e)for(const o of n)o.capability.intent===t&&o.capability.targetSchemes.includes(s.scheme)&&r.push({channelIntent:o,endpoint:s});return r}var c=(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))(c||{});const V="message_window",y="message_templates",G={FROM:"from",TO:"to",CC:"cc",BCC:"bcc",ORGANIZER:"organizer",PRESENTER:"presenter",ATTENDEE:"attendee",OWNER:"owner",MEMBER:"member",GUEST:"guest",HOST:"host",PARTICIPANT:"participant"},m=(e,t)=>({intent:e,...t}),U={ok:!1,code:"UNSUPPORTED",message:"Provider does not support this op"},H="installation-id";exports.CommunicationScheme=c;exports.INSTALLATION_HEADER=H;exports.InteractionParticipantRole=G;exports.PROVIDER_FEATURE_MESSAGE_TEMPLATES=y;exports.PROVIDER_FEATURE_MESSAGE_WINDOW=V;exports.UNSUPPORTED=U;exports.buildActivityPreview=T;exports.buildChannelIntents=O;exports.defineIntent=m;exports.disabledIntentsFromCapabilities=N;exports.filterByEndpoint=M;exports.filterByIntent=b;exports.filterByTargetScheme=d;exports.getContactEndpoints=g;exports.getShortTitle=L;exports.getUrgencyScore=S;exports.isAssigned=f;exports.isClosed=D;exports.isInteractionUnseen=C;exports.matchContactToIntents=P;exports.resolveAccountCapabilities=p;exports.resolveChannelIntents=u;exports.resolveSignature=_;exports.stripHtml=i;
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export * from './entities/ai-account';
5
5
  export * from './entities/ai-context';
6
6
  export * from './entities/ai-message';
7
7
  export * from './entities/ai-profile';
8
+ export * from './entities/mcp';
8
9
  export * from './entities/channel';
9
10
  export * from './entities/communication';
10
11
  export * from './entities/contact';
@@ -18,6 +19,7 @@ export * from './entities/organization';
18
19
  export * from './entities/shopify';
19
20
  export * from './entities/transcript';
20
21
  export * from './entities/user';
22
+ export * from './platform/ai-tools';
21
23
  export * from './platform/api';
22
24
  export * from './platform/common';
23
25
  export * from './platform/capabilities';
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- function u(e) {
1
+ function l(e) {
2
2
  return e.replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<[^>]+>/g, " ").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/\s+/g, " ").trim();
3
3
  }
4
- function l(e) {
4
+ function u(e) {
5
5
  const t = e.trim();
6
6
  return t.length <= 140 ? t : t.slice(0, 139).trimEnd() + "…";
7
7
  }
@@ -14,7 +14,7 @@ function p(e) {
14
14
  switch (e.type) {
15
15
  case "EMAIL_RECEIVED":
16
16
  case "EMAIL_SENT": {
17
- const t = e.payload, n = t.bodySnippet?.trim() || u(t.body ?? "");
17
+ const t = e.payload, n = t.bodySnippet?.trim() || l(t.body ?? "");
18
18
  return t.subject ? `${t.subject} — ${n}` : n;
19
19
  }
20
20
  case "CHAT_MESSAGE_SENT":
@@ -83,17 +83,17 @@ function p(e) {
83
83
  return "";
84
84
  }
85
85
  }
86
- function T(e) {
86
+ function _(e) {
87
87
  return {
88
88
  activityId: e.id,
89
89
  type: e.type,
90
- snippet: l(p(e)),
90
+ snippet: u(p(e)),
91
91
  authorName: e.author?.name ?? "",
92
92
  direction: e.direction,
93
93
  createdAt: e.createdAt ?? Date.now()
94
94
  };
95
95
  }
96
- function _(e, t) {
96
+ function T(e, t) {
97
97
  const n = e.settings?.signatures?.[t];
98
98
  return !n || !n.enabled || !n.body || n.body.trim() === "" ? null : n;
99
99
  }
@@ -106,11 +106,11 @@ const f = (e) => !!e.assignedUserId || !!e.assignedInboxId, D = (e) => e.status
106
106
  normal: 2,
107
107
  low: 1
108
108
  })[e.priority] || 0, N = (e, t = 30) => e.title?.length <= t ? e.title : `${e.title.substring(0, t)}...`;
109
- function C(e, t) {
109
+ function S(e, t) {
110
110
  return e.lastActivityAt ? !(e.seenBy ?? []).includes(t) : !1;
111
111
  }
112
112
  function d(e, t) {
113
- const n = new Set(e.disabledIntents ?? []), r = e.intentOverrides ?? {}, s = t.intents.filter((a) => !n.has(a.intent)).map((a) => i(a, r[a.intent]));
113
+ const n = new Set(e.disabledIntents ?? []), r = e.intentOverrides ?? {}, s = t.intents.filter((a) => !n.has(a.intent)).map((a) => A(a, r[a.intent]));
114
114
  if (!e.extraIntents || e.extraIntents.length === 0) return s;
115
115
  const o = new Set(s.map((a) => a.intent));
116
116
  for (const a of e.extraIntents)
@@ -126,11 +126,11 @@ function c(e, t) {
126
126
  }
127
127
  return n;
128
128
  }
129
- function S(e, t) {
129
+ function C(e, t) {
130
130
  const n = c(e, t);
131
131
  return Object.entries(n).filter(([, r]) => !r).map(([r]) => r);
132
132
  }
133
- function i(e, t) {
133
+ function A(e, t) {
134
134
  return t ? {
135
135
  intent: t.intent ?? e.intent,
136
136
  targetSchemes: t.targetSchemes ?? e.targetSchemes,
@@ -151,21 +151,21 @@ function O(e, t) {
151
151
  function R(e, t) {
152
152
  return t.filter((n) => n.capability.intent === e);
153
153
  }
154
- function A(e, t) {
154
+ function i(e, t) {
155
155
  return t.filter((n) => n.capability.targetSchemes.includes(e));
156
156
  }
157
- function b(e, t) {
158
- return A(e.scheme, t);
157
+ function M(e, t) {
158
+ return i(e.scheme, t);
159
159
  }
160
- function M(e, t, n) {
160
+ function b(e, t, n) {
161
161
  const r = [];
162
162
  for (const s of e)
163
163
  for (const o of n)
164
164
  o.capability.intent === t && o.capability.targetSchemes.includes(s.scheme) && r.push({ channelIntent: o, endpoint: s });
165
165
  return r;
166
166
  }
167
- var I = /* @__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.VIBER = "viber", e.SMS = "sms", e.FAX = "fax", e.TEAMS = "teams", e.CALENDAR = "calendar", e))(I || {});
168
- const P = {
167
+ var I = /* @__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))(I || {});
168
+ const P = "message_window", V = "message_templates", G = {
169
169
  // E-mail
170
170
  FROM: "from",
171
171
  TO: "to",
@@ -182,28 +182,30 @@ const P = {
182
182
  // Voice/conference
183
183
  HOST: "host",
184
184
  PARTICIPANT: "participant"
185
- }, V = (e, t) => ({ intent: e, ...t }), H = { ok: !1, code: "UNSUPPORTED", message: "Provider does not support this op" }, $ = "installation-id";
185
+ }, H = (e, t) => ({ intent: e, ...t }), $ = { ok: !1, code: "UNSUPPORTED", message: "Provider does not support this op" }, y = "installation-id";
186
186
  export {
187
187
  I as CommunicationScheme,
188
- $ as INSTALLATION_HEADER,
189
- P as InteractionParticipantRole,
190
- H as UNSUPPORTED,
191
- T as buildActivityPreview,
188
+ y as INSTALLATION_HEADER,
189
+ G as InteractionParticipantRole,
190
+ V as PROVIDER_FEATURE_MESSAGE_TEMPLATES,
191
+ P as PROVIDER_FEATURE_MESSAGE_WINDOW,
192
+ $ as UNSUPPORTED,
193
+ _ as buildActivityPreview,
192
194
  O as buildChannelIntents,
193
- V as defineIntent,
194
- S as disabledIntentsFromCapabilities,
195
- b as filterByEndpoint,
195
+ H as defineIntent,
196
+ C as disabledIntentsFromCapabilities,
197
+ M as filterByEndpoint,
196
198
  R as filterByIntent,
197
- A as filterByTargetScheme,
199
+ i as filterByTargetScheme,
198
200
  g as getContactEndpoints,
199
201
  N as getShortTitle,
200
202
  L as getUrgencyScore,
201
203
  f as isAssigned,
202
204
  D as isClosed,
203
- C as isInteractionUnseen,
204
- M as matchContactToIntents,
205
+ S as isInteractionUnseen,
206
+ b as matchContactToIntents,
205
207
  c as resolveAccountCapabilities,
206
208
  d as resolveChannelIntents,
207
- _ as resolveSignature,
208
- u as stripHtml
209
+ T as resolveSignature,
210
+ l as stripHtml
209
211
  };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Provider-agnostic tool-use contracts for the AI assistant.
3
+ *
4
+ * A tool is described once in this neutral shape; each AI provider adapter
5
+ * translates it to/from its own native function-calling format. Tools can come
6
+ * from internal apps (via the "ai-tool" provider role) or external MCP servers —
7
+ * both surface through the same {@link AiTool} shape.
8
+ */
9
+ /** JSON-Schema object describing a tool's arguments. */
10
+ export interface AiToolParameterSchema {
11
+ type: "object";
12
+ properties: Record<string, unknown>;
13
+ required?: string[];
14
+ }
15
+ /** A callable tool advertised to the model. */
16
+ export interface AiTool {
17
+ /** Namespaced, model-facing name, e.g. `kb__kb_search` or `mcp__<server>__<tool>`. */
18
+ name: string;
19
+ description: string;
20
+ parameters: AiToolParameterSchema;
21
+ }
22
+ /** A model's request to call a tool. */
23
+ export interface AiToolCall {
24
+ id: string;
25
+ name: string;
26
+ arguments: Record<string, unknown>;
27
+ }
28
+ /** The result of executing a tool call, fed back to the model. */
29
+ export interface AiToolResult {
30
+ id: string;
31
+ content: string;
32
+ isError?: boolean;
33
+ }
34
+ /** Returned by an app's `GET /provider/ai-tools/describe`. */
35
+ export type AiToolDescriptor = AiTool;
36
+ /** One step in the assistant's tool-use trace, persisted on the message. */
37
+ export interface ToolTraceEntry {
38
+ call: AiToolCall;
39
+ state: "running" | "done" | "error";
40
+ result?: AiToolResult;
41
+ }
@@ -57,6 +57,8 @@ export declare enum CommunicationScheme {
57
57
  URL = "url",
58
58
  TELEGRAM = "telegram",
59
59
  WHATSAPP = "whatsapp",
60
+ MESSENGER = "messenger",
61
+ INSTAGRAM = "instagram",
60
62
  VIBER = "viber",
61
63
  SMS = "sms",
62
64
  FAX = "fax",
@@ -141,6 +143,62 @@ export interface ProviderDescription {
141
143
  /** Provider feature flags — separate from routing. */
142
144
  features: ProviderFeature[];
143
145
  }
146
+ /**
147
+ * Provider-feature names die de composer generiek interpreteert (geen
148
+ * hardcoding per-provider). Een provider die `message_window` adverteert
149
+ * heeft een tijdgebonden messaging-venster; `message_templates` betekent dat
150
+ * er pre-approved templates beschikbaar zijn buiten dat venster.
151
+ */
152
+ export declare const PROVIDER_FEATURE_MESSAGE_WINDOW = "message_window";
153
+ export declare const PROVIDER_FEATURE_MESSAGE_TEMPLATES = "message_templates";
154
+ /**
155
+ * Eén variabele in een provider-template (bv. WhatsApp HSM body-param `{{1}}`).
156
+ */
157
+ export interface ProviderMessageTemplateVariable {
158
+ /** Stabiele key — voor WhatsApp de 1-based index als string ("1", "2", …). */
159
+ key: string;
160
+ /** Optioneel voorbeeld/placeholder uit de provider. */
161
+ example?: string;
162
+ label?: string;
163
+ }
164
+ /**
165
+ * Pre-approved provider-template (WhatsApp HSM). De composer rendert per
166
+ * `variables` een invoerveld; submit stuurt `templateId` + ingevulde waarden
167
+ * mee. Los van de user-gemaakte canned-reply {@link MessageTemplate}.
168
+ */
169
+ export interface ProviderMessageTemplate {
170
+ id: string;
171
+ name: string;
172
+ language?: string;
173
+ /** Voorbeeld van de samengestelde body (variabelen als placeholders). */
174
+ bodyPreview?: string;
175
+ category?: string;
176
+ variables: ProviderMessageTemplateVariable[];
177
+ }
178
+ /**
179
+ * Geldige tag waarmee buiten het standaard-venster tóch een vrij-tekst bericht
180
+ * verstuurd mag worden (Messenger/Instagram message-tags, human-agent-tag).
181
+ */
182
+ export interface MessageTag {
183
+ id: string;
184
+ label: string;
185
+ description?: string;
186
+ }
187
+ /**
188
+ * Antwoord van `provider/message-context` (read-route op een dispatch-provider
189
+ * met `message_window`/`message_templates`-features). Per interaction vertelt
190
+ * dit de composer of vrij-tekst mag, en zo niet welke templates/tags er zijn.
191
+ */
192
+ export interface MessageContext {
193
+ /** Vrij-tekst toegestaan? false ⇒ composer forceert template of tag. */
194
+ windowOpen: boolean;
195
+ /** Epoch-ms waarop het venster sluit (indien open en bekend). */
196
+ windowExpiresAt?: number;
197
+ /** Beschikbare pre-approved templates (WhatsApp). */
198
+ templates?: ProviderMessageTemplate[];
199
+ /** Geldige message-tags (Messenger/Instagram). */
200
+ tags?: MessageTag[];
201
+ }
144
202
  export interface PersonalAuthOption {
145
203
  id: string;
146
204
  label: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencxh/domain",
3
- "version": "1.52.0",
3
+ "version": "1.54.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",