@opencxh/domain 1.90.0 → 1.91.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,2 +1,3 @@
1
1
  export * from './types';
2
2
  export * from './preview';
3
+ export * from './seen';
@@ -0,0 +1,10 @@
1
+ import { ReadReceipts } from '../read-state/types';
2
+ import { Activity } from './types';
3
+ /**
4
+ * Users who have seen this activity, derived from high-water read marks: a user
5
+ * has seen the activity when their lastReadAt is at or after the activity's
6
+ * createdAt. Excludes the activity's own author (user-authored) and any
7
+ * explicitly excluded ids - typically the viewing user, whose own receipt we
8
+ * never render.
9
+ */
10
+ export declare function getActivitySeenUserIds(activity: Activity, receipts: ReadReceipts, excludeUserIds?: string[]): string[];
@@ -6,6 +6,11 @@ export interface ChannelSignature {
6
6
  updatedAt?: number;
7
7
  }
8
8
  export type ChannelSignaturesMap = Partial<Record<CommunicationIntent | string, ChannelSignature>>;
9
+ /**
10
+ * Intents die een handtekening dragen. Enkel deze verschijnen in de
11
+ * signature-editor en worden door `applySignature` van een delimiter voorzien.
12
+ */
13
+ export declare const SIGNATURE_INTENTS: Set<string>;
9
14
  /**
10
15
  * Resolve the signature a provider should append for an outbound message
11
16
  * on this channel + intent. Returns null when no signature is configured,
@@ -15,3 +20,13 @@ export type ChannelSignaturesMap = Partial<Record<CommunicationIntent | string,
15
20
  * resulting activity/interaction.
16
21
  */
17
22
  export declare function resolveSignature(channel: Channel, intent: CommunicationIntent | string): ChannelSignature | null;
23
+ /**
24
+ * Append de handtekening voor dit channel + intent aan een uitgaande body.
25
+ * Retourneert de body ongewijzigd wanneer er geen (enabled, niet-lege)
26
+ * handtekening is. Centrale plek voor de delimiter-logica zodat elke provider
27
+ * dezelfde opmaak gebruikt i.p.v. 'm per send-pad te dupliceren:
28
+ * - mail (html) -> RFC-style "-- " scheider
29
+ * - message (html) -> dubbele <br>
30
+ * - text -> dubbele newline (plain-text varianten / timeline)
31
+ */
32
+ export declare function applySignature(channel: Channel | undefined, intent: CommunicationIntent | string, body: string, format?: "html" | "text"): string;
@@ -0,0 +1 @@
1
+ export * from './types';
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Generic read-tracking primitives. Addressing is polymorphic via ResourceRef
3
+ * so read-state (and, later, an audit log) can attach to any resource -
4
+ * interactions, activities, files, kb articles - without per-type schemas.
5
+ */
6
+ /** Polymorphic reference to any resource that can carry read-state. */
7
+ export interface ResourceRef {
8
+ type: string;
9
+ id: string;
10
+ }
11
+ /**
12
+ * A single user's high-water read mark on one resource. `lastReadAt` is the
13
+ * epoch (ms) up to which this user has read the resource; whether they have
14
+ * seen a given child item is derived by comparing it against the item's time.
15
+ */
16
+ export interface ReadState {
17
+ id: string;
18
+ resourceType: string;
19
+ resourceId: string;
20
+ userId: string;
21
+ organizationId: string;
22
+ lastReadAt: number;
23
+ createdAt?: number;
24
+ updatedAt?: number;
25
+ }
26
+ /** Derived map of userId -> lastReadAt for a single resource. */
27
+ export type ReadReceipts = Record<string, number>;
package/dist/index.cjs CHANGED
@@ -1 +1,3 @@
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 o(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?` (${o(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?` (${o(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?` (${o(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 _(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 T(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 D=e=>!!e.assignedUserId||!!e.assignedInboxId,S=e=>e.status==="closed",f=e=>({urgent:10,high:5,normal:2,low:1})[e.priority]||0,N=(e,t=30)=>e.title?.length<=t?e.title:`${e.title.substring(0,t)}...`;function R(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 E=new Set(s.map(a=>a.intent));for(const a of e.extraIntents)E.has(a.intent)||(s.push(a),E.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 L(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 C(e,t){const n=[];for(const r of e){if(!r.enabled)continue;const s=t[r.providerId];if(s)for(const E of u(r,s))n.push({channel:r,description:s,capability:E})}return n}function M(e,t){return t.filter(n=>n.capability.intent===e)}function d(e,t){return t.filter(n=>n.capability.targetSchemes.includes(e))}function b(e,t){return d(e.scheme,t)}function P(e,t,n){const r=[];for(const s of e)for(const E of n)E.capability.intent===t&&E.capability.targetSchemes.includes(s.scheme)&&r.push({channelIntent:E,endpoint:s});return r}var p=(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))(p||{});const G="message_window",U="message_templates",V={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}),y="folder_management",H="remote_search",h={ok:!1,code:"UNSUPPORTED",message:"Provider does not support this op"},$=9e4,F="installation-id";exports.CommunicationScheme=p;exports.FEATURE_FOLDER_MANAGEMENT=y;exports.FEATURE_REMOTE_SEARCH=H;exports.INSTALLATION_HEADER=F;exports.InteractionParticipantRole=V;exports.PRESENCE_ONLINE_WINDOW_MS=$;exports.PROVIDER_FEATURE_MESSAGE_TEMPLATES=U;exports.PROVIDER_FEATURE_MESSAGE_WINDOW=G;exports.UNSUPPORTED=h;exports.buildActivityPreview=_;exports.buildChannelIntents=C;exports.defineIntent=m;exports.disabledIntentsFromCapabilities=L;exports.filterByEndpoint=b;exports.filterByIntent=M;exports.filterByTargetScheme=d;exports.getContactEndpoints=g;exports.getShortTitle=N;exports.getUrgencyScore=f;exports.isAssigned=D;exports.isClosed=S;exports.isInteractionUnseen=R;exports.matchContactToIntents=P;exports.resolveAccountCapabilities=c;exports.resolveChannelIntents=u;exports.resolveSignature=T;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 I(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 _(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:I(_(e)),authorName:e.author?.name??"",direction:e.direction,createdAt:e.createdAt??Date.now()}}function g(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 S=new Set(["mail","message"]);function u(e,t){const n=e.settings?.signatures?.[t];return!n||!n.enabled||!n.body||n.body.trim()===""?null:n}function f(e,t,n,r="html"){if(!e)return n;const s=u(e,t);return s?`${n}${r==="text"?`
2
+
3
+ `:t==="mail"?"<br><br>-- <br>":"<br><br>"}${s.body}`:n}function N(e){return e.endpoints??[]}const D=e=>!!e.assignedUserId||!!e.assignedInboxId,R=e=>e.status==="closed",L=e=>({urgent:10,high:5,normal:2,low:1})[e.priority]||0,O=(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 c(e,t){const n=new Set(e.disabledIntents??[]),r=e.intentOverrides??{},s=t.intents.filter(o=>!n.has(o.intent)).map(o=>b(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 d(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 M(e,t){const n=d(e,t);return Object.entries(n).filter(([,r])=>!r).map(([r])=>r)}function b(e,t){return t?{intent:t.intent??e.intent,targetSchemes:t.targetSchemes??e.targetSchemes,transport:t.transport??e.transport}:e}function m(e,t){const n=[];for(const r of e){if(!r.enabled)continue;const s=t[r.providerId];if(s)for(const a of c(r,s))n.push({channel:r,description:s,capability:a})}return n}function P(e,t){return t.filter(n=>n.capability.intent===e)}function p(e,t){return t.filter(n=>n.capability.targetSchemes.includes(e))}function U(e,t){return p(e.scheme,t)}function G(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 A=(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))(A||{});const y="message_window",V="message_templates",h={FROM:"from",TO:"to",CC:"cc",BCC:"bcc",ORGANIZER:"organizer",PRESENTER:"presenter",ATTENDEE:"attendee",OWNER:"owner",MEMBER:"member",GUEST:"guest",HOST:"host",PARTICIPANT:"participant"},H=(e,t)=>({intent:e,...t}),$="folder_management",F="remote_search",w={ok:!1,code:"UNSUPPORTED",message:"Provider does not support this op"},B=9e4,x="installation-id";exports.CommunicationScheme=A;exports.FEATURE_FOLDER_MANAGEMENT=$;exports.FEATURE_REMOTE_SEARCH=F;exports.INSTALLATION_HEADER=x;exports.InteractionParticipantRole=h;exports.PRESENCE_ONLINE_WINDOW_MS=B;exports.PROVIDER_FEATURE_MESSAGE_TEMPLATES=V;exports.PROVIDER_FEATURE_MESSAGE_WINDOW=y;exports.SIGNATURE_INTENTS=S;exports.UNSUPPORTED=w;exports.applySignature=f;exports.buildActivityPreview=T;exports.buildChannelIntents=m;exports.defineIntent=H;exports.disabledIntentsFromCapabilities=M;exports.filterByEndpoint=U;exports.filterByIntent=P;exports.filterByTargetScheme=p;exports.getActivitySeenUserIds=g;exports.getContactEndpoints=N;exports.getShortTitle=O;exports.getUrgencyScore=L;exports.isAssigned=D;exports.isClosed=R;exports.isInteractionUnseen=C;exports.matchContactToIntents=G;exports.resolveAccountCapabilities=d;exports.resolveChannelIntents=c;exports.resolveSignature=u;exports.stripHtml=i;
package/dist/index.d.ts CHANGED
@@ -16,6 +16,7 @@ export * from './entities/inbox';
16
16
  export * from './entities/interaction';
17
17
  export * from './entities/task';
18
18
  export * from './entities/note';
19
+ export * from './entities/read-state';
19
20
  export * from './entities/team';
20
21
  export * from './entities/organization';
21
22
  export * from './entities/shopify';
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- function l(e) {
1
+ function u(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 u(e) {
4
+ function l(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() || l(t.body ?? "");
17
+ const t = e.payload, n = t.bodySnippet?.trim() || u(t.body ?? "");
18
18
  return t.subject ? `${t.subject} — ${n}` : n;
19
19
  }
20
20
  case "CHAT_MESSAGE_SENT":
@@ -83,41 +83,55 @@ function p(e) {
83
83
  return "";
84
84
  }
85
85
  }
86
- function _(e) {
86
+ function T(e) {
87
87
  return {
88
88
  activityId: e.id,
89
89
  type: e.type,
90
- snippet: u(p(e)),
90
+ snippet: l(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 T(e, t) {
96
+ function g(e, t, n = []) {
97
+ const r = e.createdAt;
98
+ if (!r) return [];
99
+ const s = new Set(n);
100
+ 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);
101
+ }
102
+ const f = /* @__PURE__ */ new Set(["mail", "message"]);
103
+ function d(e, t) {
97
104
  const n = e.settings?.signatures?.[t];
98
105
  return !n || !n.enabled || !n.body || n.body.trim() === "" ? null : n;
99
106
  }
100
- function g(e) {
107
+ function D(e, t, n, r = "html") {
108
+ if (!e) return n;
109
+ const s = d(e, t);
110
+ return s ? `${n}${r === "text" ? `
111
+
112
+ ` : t === "mail" ? "<br><br>-- <br>" : "<br><br>"}${s.body}` : n;
113
+ }
114
+ function N(e) {
101
115
  return e.endpoints ?? [];
102
116
  }
103
- const D = (e) => !!e.assignedUserId || !!e.assignedInboxId, f = (e) => e.status === "closed", L = (e) => ({
117
+ const S = (e) => !!e.assignedUserId || !!e.assignedInboxId, L = (e) => e.status === "closed", R = (e) => ({
104
118
  urgent: 10,
105
119
  high: 5,
106
120
  normal: 2,
107
121
  low: 1
108
- })[e.priority] || 0, N = (e, t = 30) => e.title?.length <= t ? e.title : `${e.title.substring(0, t)}...`;
109
- function S(e, t) {
122
+ })[e.priority] || 0, O = (e, t = 30) => e.title?.length <= t ? e.title : `${e.title.substring(0, t)}...`;
123
+ function C(e, t) {
110
124
  return e.lastActivityAt ? !(e.seenBy ?? []).includes(t) : !1;
111
125
  }
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) => A(a, r[a.intent]));
126
+ function c(e, t) {
127
+ const n = new Set(e.disabledIntents ?? []), r = e.intentOverrides ?? {}, s = t.intents.filter((o) => !n.has(o.intent)).map((o) => A(o, r[o.intent]));
114
128
  if (!e.extraIntents || e.extraIntents.length === 0) return s;
115
- const o = new Set(s.map((a) => a.intent));
116
- for (const a of e.extraIntents)
117
- o.has(a.intent) || (s.push(a), o.add(a.intent));
129
+ const a = new Set(s.map((o) => o.intent));
130
+ for (const o of e.extraIntents)
131
+ a.has(o.intent) || (s.push(o), a.add(o.intent));
118
132
  return s;
119
133
  }
120
- function c(e, t) {
134
+ function i(e, t) {
121
135
  const n = {};
122
136
  for (const r of e.intents) {
123
137
  if (!r.togglable) continue;
@@ -126,8 +140,8 @@ function c(e, t) {
126
140
  }
127
141
  return n;
128
142
  }
129
- function R(e, t) {
130
- const n = c(e, t);
143
+ function M(e, t) {
144
+ const n = i(e, t);
131
145
  return Object.entries(n).filter(([, r]) => !r).map(([r]) => r);
132
146
  }
133
147
  function A(e, t) {
@@ -137,35 +151,35 @@ function A(e, t) {
137
151
  transport: t.transport ?? e.transport
138
152
  } : e;
139
153
  }
140
- function O(e, t) {
154
+ function b(e, t) {
141
155
  const n = [];
142
156
  for (const r of e) {
143
157
  if (!r.enabled) continue;
144
158
  const s = t[r.providerId];
145
159
  if (s)
146
- for (const o of d(r, s))
147
- n.push({ channel: r, description: s, capability: o });
160
+ for (const a of c(r, s))
161
+ n.push({ channel: r, description: s, capability: a });
148
162
  }
149
163
  return n;
150
164
  }
151
- function C(e, t) {
165
+ function P(e, t) {
152
166
  return t.filter((n) => n.capability.intent === e);
153
167
  }
154
- function i(e, t) {
168
+ function I(e, t) {
155
169
  return t.filter((n) => n.capability.targetSchemes.includes(e));
156
170
  }
157
- function M(e, t) {
158
- return i(e.scheme, t);
171
+ function m(e, t) {
172
+ return I(e.scheme, t);
159
173
  }
160
- function b(e, t, n) {
174
+ function G(e, t, n) {
161
175
  const r = [];
162
176
  for (const s of e)
163
- for (const o of n)
164
- o.capability.intent === t && o.capability.targetSchemes.includes(s.scheme) && r.push({ channelIntent: o, endpoint: s });
177
+ for (const a of n)
178
+ a.capability.intent === t && a.capability.targetSchemes.includes(s.scheme) && r.push({ channelIntent: a, endpoint: s });
165
179
  return r;
166
180
  }
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 = {
181
+ var _ = /* @__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))(_ || {});
182
+ const V = "message_window", $ = "message_templates", H = {
169
183
  // E-mail
170
184
  FROM: "from",
171
185
  TO: "to",
@@ -182,33 +196,36 @@ const P = "message_window", V = "message_templates", G = {
182
196
  // Voice/conference
183
197
  HOST: "host",
184
198
  PARTICIPANT: "participant"
185
- }, H = (e, t) => ({ intent: e, ...t }), $ = "folder_management", y = "remote_search", U = { ok: !1, code: "UNSUPPORTED", message: "Provider does not support this op" }, m = 9e4, h = "installation-id";
199
+ }, U = (e, t) => ({ intent: e, ...t }), h = "folder_management", y = "remote_search", w = { ok: !1, code: "UNSUPPORTED", message: "Provider does not support this op" }, x = 9e4, F = "installation-id";
186
200
  export {
187
- I as CommunicationScheme,
188
- $ as FEATURE_FOLDER_MANAGEMENT,
201
+ _ as CommunicationScheme,
202
+ h as FEATURE_FOLDER_MANAGEMENT,
189
203
  y as FEATURE_REMOTE_SEARCH,
190
- h as INSTALLATION_HEADER,
191
- G as InteractionParticipantRole,
192
- m as PRESENCE_ONLINE_WINDOW_MS,
193
- V as PROVIDER_FEATURE_MESSAGE_TEMPLATES,
194
- P as PROVIDER_FEATURE_MESSAGE_WINDOW,
195
- U as UNSUPPORTED,
196
- _ as buildActivityPreview,
197
- O as buildChannelIntents,
198
- H as defineIntent,
199
- R as disabledIntentsFromCapabilities,
200
- M as filterByEndpoint,
201
- C as filterByIntent,
202
- i as filterByTargetScheme,
203
- g as getContactEndpoints,
204
- N as getShortTitle,
205
- L as getUrgencyScore,
206
- D as isAssigned,
207
- f as isClosed,
208
- S as isInteractionUnseen,
209
- b as matchContactToIntents,
210
- c as resolveAccountCapabilities,
211
- d as resolveChannelIntents,
212
- T as resolveSignature,
213
- l as stripHtml
204
+ F as INSTALLATION_HEADER,
205
+ H as InteractionParticipantRole,
206
+ x as PRESENCE_ONLINE_WINDOW_MS,
207
+ $ as PROVIDER_FEATURE_MESSAGE_TEMPLATES,
208
+ V as PROVIDER_FEATURE_MESSAGE_WINDOW,
209
+ f as SIGNATURE_INTENTS,
210
+ w as UNSUPPORTED,
211
+ D as applySignature,
212
+ T as buildActivityPreview,
213
+ b as buildChannelIntents,
214
+ U as defineIntent,
215
+ M as disabledIntentsFromCapabilities,
216
+ m as filterByEndpoint,
217
+ P as filterByIntent,
218
+ I as filterByTargetScheme,
219
+ g as getActivitySeenUserIds,
220
+ N as getContactEndpoints,
221
+ O as getShortTitle,
222
+ R as getUrgencyScore,
223
+ S as isAssigned,
224
+ L as isClosed,
225
+ C as isInteractionUnseen,
226
+ G as matchContactToIntents,
227
+ i as resolveAccountCapabilities,
228
+ c as resolveChannelIntents,
229
+ d as resolveSignature,
230
+ u as stripHtml
214
231
  };
@@ -7,6 +7,13 @@
7
7
  */
8
8
  /** How recently a user's last device activity must be to count as online (ms). */
9
9
  export declare const PRESENCE_ONLINE_WINDOW_MS = 90000;
10
+ /**
11
+ * Effective presence status. `offline` is derived from connectivity (stale
12
+ * `lastSeenAt`) and always wins; the rest are set by the user or a provider.
13
+ */
14
+ export type PresenceStatus = "available" | "away" | "busy" | "dnd" | "out_of_office" | "offline";
15
+ /** Statuses a user (or provider) can set — `offline` is derived, not settable. */
16
+ export type SettablePresenceStatus = Exclude<PresenceStatus, "offline">;
10
17
  /** One tenant user with their derived online status, as returned by GET /presence. */
11
18
  export interface PresenceEntry {
12
19
  userId: string;
@@ -16,10 +23,23 @@ export interface PresenceEntry {
16
23
  lastSeenAt: number;
17
24
  /** `now - lastSeenAt < PRESENCE_ONLINE_WINDOW_MS` at the time of the read. */
18
25
  online: boolean;
26
+ /** Effective status: `offline` when not connected, else set/derived. */
27
+ status: PresenceStatus;
28
+ /** Optional free-text status message (e.g. "Back at 15:00"). */
29
+ message?: string;
19
30
  }
20
- /** SSE payload pushed on an offline->online transition (event `presence:changed`). */
31
+ /** SSE payload pushed when a user's presence changes (event `presence:changed`). */
21
32
  export interface PresenceChange {
22
33
  userId: string;
23
34
  online: boolean;
24
35
  lastSeenAt: number;
36
+ status: PresenceStatus;
37
+ message?: string;
38
+ }
39
+ /** Request body for setting one's own presence status. */
40
+ export interface PresenceStatusInput {
41
+ status: SettablePresenceStatus;
42
+ message?: string;
43
+ /** Unix ms after which the status auto-clears (falls back to derived). */
44
+ expiresAt?: number;
25
45
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencxh/domain",
3
- "version": "1.90.0",
3
+ "version": "1.91.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",