@opencxh/domain 1.119.0 → 1.124.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.
@@ -102,7 +102,24 @@ export interface Playbook {
102
102
  autoActions: number;
103
103
  };
104
104
  }
105
- export type RunStatus = "pending" | "running" | "awaiting_approval" | "awaiting_reply" | "done" | "escalated" | "failed" | "timed_out" | "stopped";
105
+ /**
106
+ * Levenscyclus van een run. Geen `pending`: runs worden ingevoegd als `running` en
107
+ * de `PLAYBOOK_STARTED`-activity dekt "hij is begonnen" al. (Die status bestond,
108
+ * werd nooit geproduceerd, en had wél een label in de UI.)
109
+ */
110
+ export type RunStatus = "running" | "awaiting_approval" | "awaiting_reply" | "done" | "escalated" | "failed" | "timed_out" | "stopped";
111
+ /** Eindstanden: hier komt een run niet meer vanzelf uit. */
112
+ export declare const TERMINAL_RUN_STATUSES: readonly ["done", "escalated", "failed", "timed_out", "stopped"];
113
+ /** Wacht deze run op iets externs? */
114
+ export declare const PAUSED_RUN_STATUSES: readonly ["awaiting_approval", "awaiting_reply"];
115
+ export declare function isTerminal(status: RunStatus | string): boolean;
116
+ /**
117
+ * Statussen waarvan een run opnieuw gestart mag worden. Een lopende of
118
+ * mens-gepauzeerde run blijft met rust, zodat een retry nooit over live uitvoering
119
+ * heen loopt of een openstaand voorstel overschrijft — vandaar: precies de eindstanden.
120
+ */
121
+ export declare function isRetryable(status: RunStatus | string): boolean;
122
+ export declare function isPaused(status: RunStatus | string): boolean;
106
123
  export interface RunStepTrace {
107
124
  path: string;
108
125
  type: string;
@@ -126,29 +143,31 @@ export interface PlaybookRun {
126
143
  trace: RunStepTrace[];
127
144
  /** Snapshot of the playbook steps at run start — version-pinned resume (docs 11.4). */
128
145
  steps?: Step[];
129
- /** Held action(s) awaiting human approval (autonomy: suggest) — a batch per paused step. */
146
+ /**
147
+ * Held action(s) awaiting human approval (autonomy: suggest) — a batch per paused
148
+ * step. `null` wanneer het veld gewist is; de store schrijft `null`, dus dat staat
149
+ * ook in het type in plaats van dat elke lezer drie toestanden moet aankunnen.
150
+ */
130
151
  pending?: {
131
- stepIndex: number;
132
- actions: {
133
- action: string;
134
- params: Record<string, unknown>;
135
- }[];
136
- };
152
+ action: string;
153
+ params: Record<string, unknown>;
154
+ }[] | null;
137
155
  /** 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;
156
+ proposalActivityId?: string | null;
157
+ /**
158
+ * Index van de stap waarop de flow pauzeerde — voor zowel `awaiting_approval` als
159
+ * `awaiting_reply`. (Was `resumeIndex` naast `pending.stepIndex`: twee velden voor
160
+ * hetzelfde feit, in twee takken geschreven en in twee takken gelezen.)
161
+ */
162
+ pausedAt?: number | null;
144
163
  rounds?: number;
145
164
  /** Denormalized interaction audience for efficient list-filtering. */
146
165
  audience?: string[];
147
166
  createdBy: string;
148
- approvedBy?: string;
167
+ approvedBy?: string | null;
149
168
  result?: {
150
169
  ok: boolean;
151
170
  error?: string;
152
- };
171
+ } | null;
153
172
  lastStepAt?: number;
154
173
  }
@@ -0,0 +1 @@
1
+ export * from './types';
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Persoonlijke "kom hier later op terug"-markering op een resource, per
3
+ * (resourceType, resourceId, userId) - dezelfde ResourceRef-vorm die read-state
4
+ * gebruikt.
5
+ *
6
+ * Anders dan een snooze raakt dit de resource zelf niet: het team blijft het
7
+ * gesprek gewoon in zijn lijst zien, alleen jouw aandachtsstapel slaat het over.
8
+ */
9
+ export interface ResourceReminder {
10
+ id: string;
11
+ resourceType: string;
12
+ resourceId: string;
13
+ userId: string;
14
+ organizationId: string;
15
+ /** Epoch-ms waarop het item weer in beeld mag komen. */
16
+ remindAt: number;
17
+ /**
18
+ * Epoch-ms waarop geparkeerd werd. Bepaalt of latere activiteit de
19
+ * herinnering opheft - expliciet veld, niet het framework-`updatedAt`, zodat
20
+ * de vervalregel deterministisch en testbaar is.
21
+ */
22
+ parkedAt: number;
23
+ createdAt?: number;
24
+ updatedAt?: number;
25
+ }
package/dist/index.cjs CHANGED
@@ -1,10 +1,10 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=140;function A(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 D(e){const t=e.trim();return t.length<=c?t:t.slice(0,c-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 O(e){switch(e.type){case"EMAIL_RECEIVED":case"EMAIL_SENT":{const t=e.payload,n=t.bodySnippet?.trim()||A(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"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?` (${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 L(e){return{activityId:e.id,type:e.type,snippet:D(O(e)),authorName:e.author?.name??"",direction:e.direction,createdAt:e.createdAt??Date.now()}}function M(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 C=[{id:"agent",label:"Agent",labelSource:"user"},{id:"team",label:"Team",labelSource:"team"},{id:"inbox",label:"Inbox",labelSource:"inbox"},{id:"channel",label:"Kanaal",labelSource:"channel"},{id:"provider",label:"Provider",labelSource:"raw"},{id:"status",label:"Status",labelSource:"raw"},{id:"handledBy",label:"Afhandelaar",labelSource:"raw"},{id:"time",label:"Tijd",labelSource:"raw"}];function m(e){const t=[];for(const n of Object.keys(e))for(const r of Object.keys(e[n]))t.push({lang:n,key:r,value:e[n][r]});return t}function i(e){return e<10?`0${e}`:`${e}`}function g(e,t){const n=new Date(e),r=`${n.getUTCFullYear()}-${i(n.getUTCMonth()+1)}-${i(n.getUTCDate())}`;return t==="day"?r:`${r}T${i(n.getUTCHours())}`}function _(e,t){const n=new Date(e);return n.setUTCMinutes(0,0,0),t==="day"&&n.setUTCHours(0),n.getTime()}const h=36e5,y=864e5;function P(e,t,n){const r=n==="hour"?h:y,s=[];for(let a=_(e,n);a<=t;a+=r)s.push(g(a,n));return s}const U=new Set(["mail","message"]);function I(e,t){const n=e.settings?.signatures?.[t];return!n||!n.enabled||!n.body||n.body.trim()===""?null:n}function $(e,t,n,r="html"){if(!e)return n;const s=I(e,t);return s?`${n}${r==="text"?`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=140;function A(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 M(e){const t=e.trim();return t.length<=c?t:t.slice(0,c-1).trimEnd()+"…"}function i(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 C(e){switch(e.type){case"EMAIL_RECEIVED":case"EMAIL_SENT":{const t=e.payload,n=t.bodySnippet?.trim()||A(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?` (${i(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?` (${i(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?` (${i(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 y(e){return{activityId:e.id,type:e.type,snippet:M(C(e)),authorName:e.author?.name??"",direction:e.direction,createdAt:e.createdAt??Date.now()}}function U(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 P=[{id:"agent",label:"Agent",labelSource:"user"},{id:"team",label:"Team",labelSource:"team"},{id:"inbox",label:"Inbox",labelSource:"inbox"},{id:"channel",label:"Kanaal",labelSource:"channel"},{id:"provider",label:"Provider",labelSource:"raw"},{id:"status",label:"Status",labelSource:"raw"},{id:"handledBy",label:"Afhandelaar",labelSource:"raw"},{id:"time",label:"Tijd",labelSource:"raw"}];function h(e){const t=[];for(const n of Object.keys(e))for(const r of Object.keys(e[n]))t.push({lang:n,key:r,value:e[n][r]});return t}function l(e){return e<10?`0${e}`:`${e}`}function g(e,t){const n=new Date(e),r=`${n.getUTCFullYear()}-${l(n.getUTCMonth()+1)}-${l(n.getUTCDate())}`;return t==="day"?r:`${r}T${l(n.getUTCHours())}`}function f(e,t){const n=new Date(e);return n.setUTCMinutes(0,0,0),t==="day"&&n.setUTCHours(0),n.getTime()}const $=36e5,G=864e5;function H(e,t,n){const r=n==="hour"?$:G,s=[];for(let a=f(e,n);a<=t;a+=r)s.push(g(a,n));return s}const _=["done","escalated","failed","timed_out","stopped"],I=["awaiting_approval","awaiting_reply"];function T(e){return _.includes(e)}function k(e){return T(e)}function V(e){return I.includes(e)}const w=new Set(["mail","message"]);function S(e,t){const n=e.settings?.signatures?.[t];return!n||!n.enabled||!n.body||n.body.trim()===""?null:n}function B(e,t,n,r="html"){if(!e)return n;const s=S(e,t);return s?`${n}${r==="text"?`
2
2
 
3
- `:t==="mail"?"<br><br>-- <br>":"<br><br>"}${s.body}`:n}function G(e){return e.endpoints??[]}const H=e=>!!e.assignedUserId||!!e.assignedInboxId,V=e=>e.status==="closed",k=e=>({urgent:10,high:5,normal:2,low:1})[e.priority]||0,w=(e,t=30)=>e.title?.length<=t?e.title:`${e.title.substring(0,t)}...`;function B(e,t){return e.lastActivityAt?!(e.seenBy??[]).includes(t):!1}const F=[/<blockquote/i,/class="?gmail_quote/i,/id="?[^"]*divRplyFwdMsg/i,/id="?[^"]*mail-editor-reference-message-container/i,/-{3,}\s*Original Message\s*-{3,}/i,/\n_{5,}\s*\n/,/\bOn\b[\s\S]{0,200}?\bwrote:/i],u=/^\s*(?:>+\s*)?(?:from|van|sent|verzonden|to|aan|cc|subject|onderwerp|date|datum)\s*:/i,x=/^\s*(?:on|op)\b.{0,200}?\b(?:wrote|schreef|geschreven)\s*:?\s*$/i;function j(e){const t=e.split(`
4
- `);for(let n=0;n<t.length;n++)if(x.test(t[n])||u.test(t[n])&&t.slice(n+1,n+4).some(r=>u.test(r)))return t.slice(0,n).join(`
3
+ `:t==="mail"?"<br><br>-- <br>":"<br><br>"}${s.body}`:n}function F(e){return e.endpoints??[]}const x=e=>!!e.assignedUserId||!!e.assignedInboxId,j=e=>e.status==="closed",W=e=>({urgent:10,high:5,normal:2,low:1})[e.priority]||0,K=(e,t=30)=>e.title?.length<=t?e.title:`${e.title.substring(0,t)}...`;function Y(e,t){return e.lastActivityAt?!(e.seenBy??[]).includes(t):!1}const q=[/<blockquote/i,/class="?gmail_quote/i,/id="?[^"]*divRplyFwdMsg/i,/id="?[^"]*mail-editor-reference-message-container/i,/-{3,}\s*Original Message\s*-{3,}/i,/\n_{5,}\s*\n/,/\bOn\b[\s\S]{0,200}?\bwrote:/i],u=/^\s*(?:>+\s*)?(?:from|van|sent|verzonden|to|aan|cc|subject|onderwerp|date|datum)\s*:/i,v=/^\s*(?:on|op)\b.{0,200}?\b(?:wrote|schreef|geschreven)\s*:?\s*$/i;function z(e){const t=e.split(`
4
+ `);for(let n=0;n<t.length;n++)if(v.test(t[n])||u.test(t[n])&&t.slice(n+1,n+4).some(r=>u.test(r)))return t.slice(0,n).join(`
5
5
  `).trim();return e}function E(e){let t=e;return t=t.replace(/<(script|style)[\s\S]*?<\/\1>/gi,""),t=t.replace(/<br\s*\/?>/gi,`
6
6
  `),t=t.replace(/<\/(p|div|li|tr|h[1-6]|ul|ol|table)>/gi,`
7
7
  `),t=t.replace(/<[^>]+>/g,""),t=t.replace(/<[^>]*$/,""),t}function d(e){return e.replace(/&nbsp;/gi," ").replace(/&lt;/gi,"<").replace(/&gt;/gi,">").replace(/&quot;/gi,'"').replace(/&#39;/gi,"'").replace(/&#(\d+);/g,(t,n)=>String.fromCharCode(Number(n))).replace(/&amp;/gi,"&")}function p(e){return e.replace(/\r/g,"").replace(/[ \t]+/g," ").replace(/ *\n */g,`
8
8
  `).replace(/\n{3,}/g,`
9
9
 
10
- `).trim()}function W(e){if(typeof e!="string"||!e)return"";let t=e.length;for(const a of F){const o=e.search(a);o>=0&&o<t&&(t=o)}const n=e.slice(0,t);let r=p(d(E(n)));return r||(r=p(d(E(e)))),j(r)||r}const Y=/(^|[._+-])(no-?reply|noreply|donotreply|do-not-reply|newsletter|nieuwsbrief|mailer|mailing|notifications?|bounce|postmaster|marketing)@/i,K=/\b(unsubscribe|afmelden|uitschrijven|opt[\s-]?out|manage (your )?preferences|geen (e-?mails?|nieuwsbrief|berichten) meer)\b/i;function q(e,t){return!!(e&&Y.test(e)||t&&K.test(t))}const T=3,f=600;function z(e,t){return e>=T||t>=f}function S(e,t){const n=new Set(e.disabledIntents??[]),r=e.intentOverrides??{},s=t.intents.filter(o=>!n.has(o.intent)).map(o=>Q(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 b(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 J(e,t){const n=b(e,t);return Object.entries(n).filter(([,r])=>!r).map(([r])=>r)}function Q(e,t){return t?{intent:t.intent??e.intent,targetSchemes:t.targetSchemes??e.targetSchemes,transport:t.transport??e.transport}:e}function X(e,t){const n=[];for(const r of e){if(!r.enabled)continue;const s=t[r.providerId];if(s)for(const a of S(r,s))n.push({channel:r,description:s,capability:a})}return n}function Z(e,t){return t.filter(n=>n.capability.intent===e)}function N(e,t){return t.filter(n=>n.capability.targetSchemes.includes(e))}function v(e,t){return N(e.scheme,t)}function ee(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 R=(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))(R||{});const te="message_window",ne="message_templates",re={FROM:"from",TO:"to",CC:"cc",BCC:"bcc",ORGANIZER:"organizer",PRESENTER:"presenter",ATTENDEE:"attendee",OWNER:"owner",MEMBER:"member",GUEST:"guest",HOST:"host",PARTICIPANT:"participant"},se=(e,t)=>({intent:e,...t}),ae="folder_management",oe="remote_search",le={ok:!1,code:"UNSUPPORTED",message:"Provider does not support this op"},ie=9e4,ce="installation-id";exports.CORE_DIMENSIONS=C;exports.CommunicationScheme=R;exports.FEATURE_FOLDER_MANAGEMENT=ae;exports.FEATURE_REMOTE_SEARCH=oe;exports.INSTALLATION_HEADER=ce;exports.InteractionParticipantRole=re;exports.PRESENCE_ONLINE_WINDOW_MS=ie;exports.PROVIDER_FEATURE_MESSAGE_TEMPLATES=ne;exports.PROVIDER_FEATURE_MESSAGE_WINDOW=te;exports.SIGNATURE_INTENTS=U;exports.SUMMARY_MIN_LAST_CHARS=f;exports.SUMMARY_MIN_MESSAGES=T;exports.UNSUPPORTED=le;exports.applySignature=$;exports.buildActivityPreview=L;exports.buildChannelIntents=X;exports.cleanMessageText=W;exports.defineIntent=se;exports.disabledIntentsFromCapabilities=J;exports.filterByEndpoint=v;exports.filterByIntent=Z;exports.filterByTargetScheme=N;exports.flattenLocales=m;exports.floorToPeriod=_;exports.formatPeriod=g;exports.getActivitySeenUserIds=M;exports.getContactEndpoints=G;exports.getShortTitle=w;exports.getUrgencyScore=k;exports.isAssigned=H;exports.isClosed=V;exports.isInteractionUnseen=B;exports.isLikelyBulk=q;exports.isThreadLongEnough=z;exports.matchContactToIntents=ee;exports.periodsInRange=P;exports.resolveAccountCapabilities=b;exports.resolveChannelIntents=S;exports.resolveSignature=I;exports.stripHtml=A;
10
+ `).trim()}function J(e){if(typeof e!="string"||!e)return"";let t=e.length;for(const a of q){const o=e.search(a);o>=0&&o<t&&(t=o)}const n=e.slice(0,t);let r=p(d(E(n)));return r||(r=p(d(E(e)))),z(r)||r}const Q=/(^|[._+-])(no-?reply|noreply|donotreply|do-not-reply|newsletter|nieuwsbrief|mailer|mailing|notifications?|bounce|postmaster|marketing)@/i,X=/\b(unsubscribe|afmelden|uitschrijven|opt[\s-]?out|manage (your )?preferences|geen (e-?mails?|nieuwsbrief|berichten) meer)\b/i;function Z(e,t){return!!(e&&Q.test(e)||t&&X.test(t))}const R=3,N=600;function ee(e,t){return e>=R||t>=N}function b(e,t){const n=new Set(e.disabledIntents??[]),r=e.intentOverrides??{},s=t.intents.filter(o=>!n.has(o.intent)).map(o=>ne(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 te(e,t){const n=D(e,t);return Object.entries(n).filter(([,r])=>!r).map(([r])=>r)}function ne(e,t){return t?{intent:t.intent??e.intent,targetSchemes:t.targetSchemes??e.targetSchemes,transport:t.transport??e.transport}:e}function re(e,t){const n=[];for(const r of e){if(!r.enabled)continue;const s=t[r.providerId];if(s)for(const a of b(r,s))n.push({channel:r,description:s,capability:a})}return n}function se(e,t){return t.filter(n=>n.capability.intent===e)}function m(e,t){return t.filter(n=>n.capability.targetSchemes.includes(e))}function ae(e,t){return m(e.scheme,t)}function oe(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 O=(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))(O||{});const ie="message_window",le="message_templates",ce={FROM:"from",TO:"to",CC:"cc",BCC:"bcc",ORGANIZER:"organizer",PRESENTER:"presenter",ATTENDEE:"attendee",OWNER:"owner",MEMBER:"member",GUEST:"guest",HOST:"host",PARTICIPANT:"participant"},ue=(e,t)=>({intent:e,...t}),Ee="folder_management",de="remote_search",pe={ok:!1,code:"UNSUPPORTED",message:"Provider does not support this op"};function L(e){switch(e.kind){case"user":return`user:${e.userId}`;case"team":return`team:${e.teamId}`;case"org":return"org"}}function Ae(e){if(typeof e!="string")return;const t=e.trim();if(t==="org")return{kind:"org"};const n=t.indexOf(":");if(n<=0)return;const r=t.slice(0,n),s=t.slice(n+1).trim();if(s){if(r==="user")return{kind:"user",userId:s};if(r==="team")return{kind:"team",teamId:s}}}function ge(e){return L(e)}const fe=9e4,_e="installation-id";exports.CORE_DIMENSIONS=P;exports.CommunicationScheme=O;exports.FEATURE_FOLDER_MANAGEMENT=Ee;exports.FEATURE_REMOTE_SEARCH=de;exports.INSTALLATION_HEADER=_e;exports.InteractionParticipantRole=ce;exports.PAUSED_RUN_STATUSES=I;exports.PRESENCE_ONLINE_WINDOW_MS=fe;exports.PROVIDER_FEATURE_MESSAGE_TEMPLATES=le;exports.PROVIDER_FEATURE_MESSAGE_WINDOW=ie;exports.SIGNATURE_INTENTS=w;exports.SUMMARY_MIN_LAST_CHARS=N;exports.SUMMARY_MIN_MESSAGES=R;exports.TERMINAL_RUN_STATUSES=_;exports.UNSUPPORTED=pe;exports.actingIdentityKey=ge;exports.applySignature=B;exports.buildActivityPreview=y;exports.buildChannelIntents=re;exports.cleanMessageText=J;exports.defineIntent=ue;exports.disabledIntentsFromCapabilities=te;exports.filterByEndpoint=ae;exports.filterByIntent=se;exports.filterByTargetScheme=m;exports.flattenLocales=h;exports.floorToPeriod=f;exports.formatActingIdentity=L;exports.formatPeriod=g;exports.getActivitySeenUserIds=U;exports.getContactEndpoints=F;exports.getShortTitle=K;exports.getUrgencyScore=W;exports.isAssigned=x;exports.isClosed=j;exports.isInteractionUnseen=Y;exports.isLikelyBulk=Z;exports.isPaused=V;exports.isRetryable=k;exports.isTerminal=T;exports.isThreadLongEnough=ee;exports.matchContactToIntents=oe;exports.parseActingIdentity=Ae;exports.periodsInRange=H;exports.resolveAccountCapabilities=D;exports.resolveChannelIntents=b;exports.resolveSignature=S;exports.stripHtml=A;
package/dist/index.d.ts CHANGED
@@ -21,6 +21,7 @@ export * from './entities/interaction';
21
21
  export * from './entities/task';
22
22
  export * from './entities/note';
23
23
  export * from './entities/read-state';
24
+ export * from './entities/resource-reminder';
24
25
  export * from './entities/team';
25
26
  export * from './entities/organization';
26
27
  export * from './entities/shopify';
@@ -37,6 +38,7 @@ export * from './platform/capabilities';
37
38
  export * from './platform/context';
38
39
  export * from './platform/communication';
39
40
  export * from './platform/federated';
41
+ export * from './platform/identity';
40
42
  export * from './platform/intents';
41
43
  export * from './platform/kernel';
42
44
  export * from './platform/lifecycle';
package/dist/index.js CHANGED
@@ -1,16 +1,16 @@
1
1
  function p(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 g(e) {
4
+ function f(e) {
5
5
  const t = e.trim();
6
6
  return t.length <= 140 ? t : t.slice(0, 139).trimEnd() + "…";
7
7
  }
8
- function l(e) {
8
+ function i(e) {
9
9
  if (!e || e < 0) return "";
10
10
  const t = Math.floor(e / 60), n = Math.floor(e % 60);
11
11
  return `${t}:${n.toString().padStart(2, "0")}`;
12
12
  }
13
- function A(e) {
13
+ function g(e) {
14
14
  switch (e.type) {
15
15
  case "EMAIL_RECEIVED":
16
16
  case "EMAIL_SENT": {
@@ -29,7 +29,7 @@ function A(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 ? ` (${l(e.payload.duration)})` : ""}`;
32
+ return `Gesprek beëindigd${e.payload.duration ? ` (${i(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 A(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 ? ` (${l(e.payload.duration)})` : ""}`;
49
+ return `Gesprek beëindigd${e.payload.duration ? ` (${i(e.payload.duration)})` : ""}`;
50
50
  case "VOICE_CALL_MISSED":
51
51
  case "VIDEO_CALL_MISSED":
52
52
  return "Gemiste oproep";
@@ -72,7 +72,7 @@ function A(e) {
72
72
  case "MEETING_STARTED":
73
73
  return `Vergadering gestart: ${e.payload.title}`;
74
74
  case "MEETING_ENDED":
75
- return `Vergadering beëindigd${e.payload.duration ? ` (${l(e.payload.duration)})` : ""}`;
75
+ return `Vergadering beëindigd${e.payload.duration ? ` (${i(e.payload.duration)})` : ""}`;
76
76
  case "MEETING_PARTICIPANT_JOINED":
77
77
  return `${e.payload.name} deelgenomen`;
78
78
  case "MEETING_PARTICIPANT_LEFT":
@@ -91,23 +91,23 @@ function A(e) {
91
91
  return "";
92
92
  }
93
93
  }
94
- function $(e) {
94
+ function w(e) {
95
95
  return {
96
96
  activityId: e.id,
97
97
  type: e.type,
98
- snippet: g(A(e)),
98
+ snippet: f(g(e)),
99
99
  authorName: e.author?.name ?? "",
100
100
  direction: e.direction,
101
101
  createdAt: e.createdAt ?? Date.now()
102
102
  };
103
103
  }
104
- function U(e, t, n = []) {
104
+ function G(e, t, n = []) {
105
105
  const r = e.createdAt;
106
106
  if (!r) return [];
107
107
  const s = new Set(n);
108
108
  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);
109
109
  }
110
- const H = [
110
+ const V = [
111
111
  { id: "agent", label: "Agent", labelSource: "user" },
112
112
  { id: "team", label: "Team", labelSource: "team" },
113
113
  { id: "inbox", label: "Inbox", labelSource: "inbox" },
@@ -117,56 +117,66 @@ const H = [
117
117
  { id: "handledBy", label: "Afhandelaar", labelSource: "raw" },
118
118
  { id: "time", label: "Tijd", labelSource: "raw" }
119
119
  ];
120
- function G(e) {
120
+ function x(e) {
121
121
  const t = [];
122
122
  for (const n of Object.keys(e))
123
123
  for (const r of Object.keys(e[n]))
124
124
  t.push({ lang: n, key: r, value: e[n][r] });
125
125
  return t;
126
126
  }
127
- function i(e) {
127
+ function l(e) {
128
128
  return e < 10 ? `0${e}` : `${e}`;
129
129
  }
130
- function f(e, t) {
131
- const n = new Date(e), r = `${n.getUTCFullYear()}-${i(n.getUTCMonth() + 1)}-${i(n.getUTCDate())}`;
132
- return t === "day" ? r : `${r}T${i(n.getUTCHours())}`;
130
+ function A(e, t) {
131
+ const n = new Date(e), r = `${n.getUTCFullYear()}-${l(n.getUTCMonth() + 1)}-${l(n.getUTCDate())}`;
132
+ return t === "day" ? r : `${r}T${l(n.getUTCHours())}`;
133
133
  }
134
134
  function _(e, t) {
135
135
  const n = new Date(e);
136
136
  return n.setUTCMinutes(0, 0, 0), t === "day" && n.setUTCHours(0), n.getTime();
137
137
  }
138
- const T = 36e5, I = 864e5;
139
- function V(e, t, n) {
140
- const r = n === "hour" ? T : I, s = [];
138
+ const I = 36e5, T = 864e5;
139
+ function B(e, t, n) {
140
+ const r = n === "hour" ? I : T, s = [];
141
141
  for (let a = _(e, n); a <= t; a += r)
142
- s.push(f(a, n));
142
+ s.push(A(a, n));
143
143
  return s;
144
144
  }
145
- const w = /* @__PURE__ */ new Set(["mail", "message"]);
146
- function S(e, t) {
145
+ const S = ["done", "escalated", "failed", "timed_out", "stopped"], b = ["awaiting_approval", "awaiting_reply"];
146
+ function N(e) {
147
+ return S.includes(e);
148
+ }
149
+ function F(e) {
150
+ return N(e);
151
+ }
152
+ function j(e) {
153
+ return b.includes(e);
154
+ }
155
+ const W = /* @__PURE__ */ new Set(["mail", "message"]);
156
+ function D(e, t) {
147
157
  const n = e.settings?.signatures?.[t];
148
158
  return !n || !n.enabled || !n.body || n.body.trim() === "" ? null : n;
149
159
  }
150
- function k(e, t, n, r = "html") {
160
+ function K(e, t, n, r = "html") {
151
161
  if (!e) return n;
152
- const s = S(e, t);
162
+ const s = D(e, t);
153
163
  return s ? `${n}${r === "text" ? `
154
164
 
155
165
  ` : t === "mail" ? "<br><br>-- <br>" : "<br><br>"}${s.body}` : n;
156
166
  }
157
- function x(e) {
167
+ function Y(e) {
158
168
  return e.endpoints ?? [];
159
169
  }
160
- const B = (e) => !!e.assignedUserId || !!e.assignedInboxId, F = (e) => e.status === "closed", j = (e) => ({
170
+ const q = (e) => !!e.assignedUserId || !!e.assignedInboxId, X = (e) => e.status === "closed", z = (e) => ({
161
171
  urgent: 10,
162
172
  high: 5,
163
173
  normal: 2,
164
174
  low: 1
165
- })[e.priority] || 0, W = (e, t = 30) => e.title?.length <= t ? e.title : `${e.title.substring(0, t)}...`;
166
- function K(e, t) {
175
+ })[e.priority] || 0, J = (e, t = 30) => e.title?.length <= t ? e.title : `${e.title.substring(0, t)}...`;
176
+ function Q(e, t) {
167
177
  return e.lastActivityAt ? !(e.seenBy ?? []).includes(t) : !1;
168
178
  }
169
- const b = [
179
+ const m = [
170
180
  /<blockquote/i,
171
181
  /class="?gmail_quote/i,
172
182
  // Gmail quote container
@@ -179,12 +189,12 @@ const b = [
179
189
  // Outlook underscore separator before "From:"
180
190
  /\bOn\b[\s\S]{0,200}?\bwrote:/i
181
191
  // Gmail "On <date> <name> wrote:"
182
- ], u = /^\s*(?:>+\s*)?(?:from|van|sent|verzonden|to|aan|cc|subject|onderwerp|date|datum)\s*:/i, D = /^\s*(?:on|op)\b.{0,200}?\b(?:wrote|schreef|geschreven)\s*:?\s*$/i;
183
- function N(e) {
192
+ ], u = /^\s*(?:>+\s*)?(?:from|van|sent|verzonden|to|aan|cc|subject|onderwerp|date|datum)\s*:/i, L = /^\s*(?:on|op)\b.{0,200}?\b(?:wrote|schreef|geschreven)\s*:?\s*$/i;
193
+ function O(e) {
184
194
  const t = e.split(`
185
195
  `);
186
196
  for (let n = 0; n < t.length; n++)
187
- if (D.test(t[n]) || u.test(t[n]) && t.slice(n + 1, n + 4).some((r) => u.test(r)))
197
+ if (L.test(t[n]) || u.test(t[n]) && t.slice(n + 1, n + 4).some((r) => u.test(r)))
188
198
  return t.slice(0, n).join(`
189
199
  `).trim();
190
200
  return e;
@@ -195,43 +205,43 @@ function c(e) {
195
205
  `), t = t.replace(/<\/(p|div|li|tr|h[1-6]|ul|ol|table)>/gi, `
196
206
  `), t = t.replace(/<[^>]+>/g, ""), t = t.replace(/<[^>]*$/, ""), t;
197
207
  }
198
- function E(e) {
208
+ function d(e) {
199
209
  return e.replace(/&nbsp;/gi, " ").replace(/&lt;/gi, "<").replace(/&gt;/gi, ">").replace(/&quot;/gi, '"').replace(/&#39;/gi, "'").replace(/&#(\d+);/g, (t, n) => String.fromCharCode(Number(n))).replace(/&amp;/gi, "&");
200
210
  }
201
- function d(e) {
211
+ function E(e) {
202
212
  return e.replace(/\r/g, "").replace(/[ \t]+/g, " ").replace(/ *\n */g, `
203
213
  `).replace(/\n{3,}/g, `
204
214
 
205
215
  `).trim();
206
216
  }
207
- function Y(e) {
217
+ function Z(e) {
208
218
  if (typeof e != "string" || !e) return "";
209
219
  let t = e.length;
210
- for (const a of b) {
220
+ for (const a of m) {
211
221
  const o = e.search(a);
212
222
  o >= 0 && o < t && (t = o);
213
223
  }
214
224
  const n = e.slice(0, t);
215
- let r = d(E(c(n)));
216
- return r || (r = d(E(c(e)))), N(r) || r;
225
+ let r = E(d(c(n)));
226
+ return r || (r = E(d(c(e)))), O(r) || r;
217
227
  }
218
- const L = /(^|[._+-])(no-?reply|noreply|donotreply|do-not-reply|newsletter|nieuwsbrief|mailer|mailing|notifications?|bounce|postmaster|marketing)@/i, O = /\b(unsubscribe|afmelden|uitschrijven|opt[\s-]?out|manage (your )?preferences|geen (e-?mails?|nieuwsbrief|berichten) meer)\b/i;
219
- function q(e, t) {
220
- return !!(e && L.test(e) || t && O.test(t));
228
+ const R = /(^|[._+-])(no-?reply|noreply|donotreply|do-not-reply|newsletter|nieuwsbrief|mailer|mailing|notifications?|bounce|postmaster|marketing)@/i, C = /\b(unsubscribe|afmelden|uitschrijven|opt[\s-]?out|manage (your )?preferences|geen (e-?mails?|nieuwsbrief|berichten) meer)\b/i;
229
+ function v(e, t) {
230
+ return !!(e && R.test(e) || t && C.test(t));
221
231
  }
222
- const R = 3, m = 600;
223
- function X(e, t) {
224
- return e >= R || t >= m;
232
+ const M = 3, y = 600;
233
+ function ee(e, t) {
234
+ return e >= M || t >= y;
225
235
  }
226
- function C(e, t) {
227
- const n = new Set(e.disabledIntents ?? []), r = e.intentOverrides ?? {}, s = t.intents.filter((o) => !n.has(o.intent)).map((o) => h(o, r[o.intent]));
236
+ function h(e, t) {
237
+ 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]));
228
238
  if (!e.extraIntents || e.extraIntents.length === 0) return s;
229
239
  const a = new Set(s.map((o) => o.intent));
230
240
  for (const o of e.extraIntents)
231
241
  a.has(o.intent) || (s.push(o), a.add(o.intent));
232
242
  return s;
233
243
  }
234
- function M(e, t) {
244
+ function P(e, t) {
235
245
  const n = {};
236
246
  for (const r of e.intents) {
237
247
  if (!r.togglable) continue;
@@ -240,46 +250,46 @@ function M(e, t) {
240
250
  }
241
251
  return n;
242
252
  }
243
- function z(e, t) {
244
- const n = M(e, t);
253
+ function te(e, t) {
254
+ const n = P(e, t);
245
255
  return Object.entries(n).filter(([, r]) => !r).map(([r]) => r);
246
256
  }
247
- function h(e, t) {
257
+ function U(e, t) {
248
258
  return t ? {
249
259
  intent: t.intent ?? e.intent,
250
260
  targetSchemes: t.targetSchemes ?? e.targetSchemes,
251
261
  transport: t.transport ?? e.transport
252
262
  } : e;
253
263
  }
254
- function J(e, t) {
264
+ function ne(e, t) {
255
265
  const n = [];
256
266
  for (const r of e) {
257
267
  if (!r.enabled) continue;
258
268
  const s = t[r.providerId];
259
269
  if (s)
260
- for (const a of C(r, s))
270
+ for (const a of h(r, s))
261
271
  n.push({ channel: r, description: s, capability: a });
262
272
  }
263
273
  return n;
264
274
  }
265
- function Q(e, t) {
275
+ function re(e, t) {
266
276
  return t.filter((n) => n.capability.intent === e);
267
277
  }
268
- function P(e, t) {
278
+ function $(e, t) {
269
279
  return t.filter((n) => n.capability.targetSchemes.includes(e));
270
280
  }
271
- function Z(e, t) {
272
- return P(e.scheme, t);
281
+ function se(e, t) {
282
+ return $(e.scheme, t);
273
283
  }
274
- function v(e, t, n) {
284
+ function ae(e, t, n) {
275
285
  const r = [];
276
286
  for (const s of e)
277
287
  for (const a of n)
278
288
  a.capability.intent === t && a.capability.targetSchemes.includes(s.scheme) && r.push({ channelIntent: a, endpoint: s });
279
289
  return r;
280
290
  }
281
- var y = /* @__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))(y || {});
282
- const ee = "message_window", te = "message_templates", ne = {
291
+ var k = /* @__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))(k || {});
292
+ const oe = "message_window", ie = "message_templates", le = {
283
293
  // E-mail
284
294
  FROM: "from",
285
295
  TO: "to",
@@ -296,46 +306,80 @@ const ee = "message_window", te = "message_templates", ne = {
296
306
  // Voice/conference
297
307
  HOST: "host",
298
308
  PARTICIPANT: "participant"
299
- }, re = (e, t) => ({ intent: e, ...t }), se = "folder_management", ae = "remote_search", oe = { ok: !1, code: "UNSUPPORTED", message: "Provider does not support this op" }, le = 9e4, ie = "installation-id";
309
+ }, ue = (e, t) => ({ intent: e, ...t }), ce = "folder_management", de = "remote_search", Ee = { ok: !1, code: "UNSUPPORTED", message: "Provider does not support this op" };
310
+ function H(e) {
311
+ switch (e.kind) {
312
+ case "user":
313
+ return `user:${e.userId}`;
314
+ case "team":
315
+ return `team:${e.teamId}`;
316
+ case "org":
317
+ return "org";
318
+ }
319
+ }
320
+ function pe(e) {
321
+ if (typeof e != "string") return;
322
+ const t = e.trim();
323
+ if (t === "org") return { kind: "org" };
324
+ const n = t.indexOf(":");
325
+ if (n <= 0) return;
326
+ const r = t.slice(0, n), s = t.slice(n + 1).trim();
327
+ if (s) {
328
+ if (r === "user") return { kind: "user", userId: s };
329
+ if (r === "team") return { kind: "team", teamId: s };
330
+ }
331
+ }
332
+ function fe(e) {
333
+ return H(e);
334
+ }
335
+ const ge = 9e4, Ae = "installation-id";
300
336
  export {
301
- H as CORE_DIMENSIONS,
302
- y as CommunicationScheme,
303
- se as FEATURE_FOLDER_MANAGEMENT,
304
- ae as FEATURE_REMOTE_SEARCH,
305
- ie as INSTALLATION_HEADER,
306
- ne as InteractionParticipantRole,
307
- le as PRESENCE_ONLINE_WINDOW_MS,
308
- te as PROVIDER_FEATURE_MESSAGE_TEMPLATES,
309
- ee as PROVIDER_FEATURE_MESSAGE_WINDOW,
310
- w as SIGNATURE_INTENTS,
311
- m as SUMMARY_MIN_LAST_CHARS,
312
- R as SUMMARY_MIN_MESSAGES,
313
- oe as UNSUPPORTED,
314
- k as applySignature,
315
- $ as buildActivityPreview,
316
- J as buildChannelIntents,
317
- Y as cleanMessageText,
318
- re as defineIntent,
319
- z as disabledIntentsFromCapabilities,
320
- Z as filterByEndpoint,
321
- Q as filterByIntent,
322
- P as filterByTargetScheme,
323
- G as flattenLocales,
337
+ V as CORE_DIMENSIONS,
338
+ k as CommunicationScheme,
339
+ ce as FEATURE_FOLDER_MANAGEMENT,
340
+ de as FEATURE_REMOTE_SEARCH,
341
+ Ae as INSTALLATION_HEADER,
342
+ le as InteractionParticipantRole,
343
+ b as PAUSED_RUN_STATUSES,
344
+ ge as PRESENCE_ONLINE_WINDOW_MS,
345
+ ie as PROVIDER_FEATURE_MESSAGE_TEMPLATES,
346
+ oe as PROVIDER_FEATURE_MESSAGE_WINDOW,
347
+ W as SIGNATURE_INTENTS,
348
+ y as SUMMARY_MIN_LAST_CHARS,
349
+ M as SUMMARY_MIN_MESSAGES,
350
+ S as TERMINAL_RUN_STATUSES,
351
+ Ee as UNSUPPORTED,
352
+ fe as actingIdentityKey,
353
+ K as applySignature,
354
+ w as buildActivityPreview,
355
+ ne as buildChannelIntents,
356
+ Z as cleanMessageText,
357
+ ue as defineIntent,
358
+ te as disabledIntentsFromCapabilities,
359
+ se as filterByEndpoint,
360
+ re as filterByIntent,
361
+ $ as filterByTargetScheme,
362
+ x as flattenLocales,
324
363
  _ as floorToPeriod,
325
- f as formatPeriod,
326
- U as getActivitySeenUserIds,
327
- x as getContactEndpoints,
328
- W as getShortTitle,
329
- j as getUrgencyScore,
330
- B as isAssigned,
331
- F as isClosed,
332
- K as isInteractionUnseen,
333
- q as isLikelyBulk,
334
- X as isThreadLongEnough,
335
- v as matchContactToIntents,
336
- V as periodsInRange,
337
- M as resolveAccountCapabilities,
338
- C as resolveChannelIntents,
339
- S as resolveSignature,
364
+ H as formatActingIdentity,
365
+ A as formatPeriod,
366
+ G as getActivitySeenUserIds,
367
+ Y as getContactEndpoints,
368
+ J as getShortTitle,
369
+ z as getUrgencyScore,
370
+ q as isAssigned,
371
+ X as isClosed,
372
+ Q as isInteractionUnseen,
373
+ v as isLikelyBulk,
374
+ j as isPaused,
375
+ F as isRetryable,
376
+ N as isTerminal,
377
+ ee as isThreadLongEnough,
378
+ ae as matchContactToIntents,
379
+ pe as parseActingIdentity,
380
+ B as periodsInRange,
381
+ P as resolveAccountCapabilities,
382
+ h as resolveChannelIntents,
383
+ D as resolveSignature,
340
384
  p as stripHtml
341
385
  };
@@ -31,8 +31,39 @@ export interface AiToolResult {
31
31
  content: string;
32
32
  isError?: boolean;
33
33
  }
34
- /** Returned by an app's `GET /provider/ai-tools/describe`. */
35
- export type AiToolDescriptor = AiTool;
34
+ /**
35
+ * Returned by an app's `GET /provider/ai-tools/describe`.
36
+ *
37
+ * Beide extra velden zijn optioneel en additief: een tool die ze niet zet gedraagt
38
+ * zich exact als voorheen. Ze bestaan zodat generieke lagen (de suggest-gate, de
39
+ * scope-gate in `registerAiToolProvider`) een tool kunnen beoordelen **zonder hem
40
+ * te kennen** — nu zit die kennis in `AIProfile.toolPolicy` met "onbekend = write".
41
+ */
42
+ export interface AiToolDescriptor extends AiTool {
43
+ /** Muteert deze tool iets? Bepaalt de suggest-gate. Afwezig = onbekend. */
44
+ access?: "read" | "write";
45
+ /**
46
+ * De resource waarop deze tool werkt, zodat een generieke gate hem kan
47
+ * autoriseren: `{ param: "interactionId", kind: "interaction" }` betekent
48
+ * "autoriseer `interaction:<args.interactionId>` voor de acting identity".
49
+ */
50
+ scope?: {
51
+ param: string;
52
+ kind: string;
53
+ };
54
+ }
55
+ /**
56
+ * Body van `POST /provider/ai-tools/invoke`. Vervangt vijf inline structurele
57
+ * types (de beller in de ai-app plus de vier ontvangende apps).
58
+ *
59
+ * De acting identity zit hier **niet** in: die reist als header mee
60
+ * (`ACTING_IDENTITY_HEADER` in `@opencxh/platform-api`). Gemeten in fase 0 dat dat
61
+ * werkt vanuit een request, een job én een subscriber — dus geen tweede kanaal.
62
+ */
63
+ export interface AiToolInvokeRequest {
64
+ tool: string;
65
+ arguments?: Record<string, unknown>;
66
+ }
36
67
  /** One step in the assistant's tool-use trace, persisted on the message. */
37
68
  export interface ToolTraceEntry {
38
69
  call: AiToolCall;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Namens wie een actie gebeurt.
3
+ *
4
+ * Orthogonaal aan *wie* er belt (dat is `Caller` in `@opencxh/platform-api`): een
5
+ * app kan bellen namens een gebruiker, namens een team, of namens de organisatie.
6
+ * Een app-to-app call draagt van zichzelf geen bruikbare identiteit — de auth die
7
+ * de runtime meestuurt is die van de oorspronkelijke beller, niet van degene
8
+ * namens wie gehandeld wordt. Vandaar dit eigen, expliciete kanaal.
9
+ *
10
+ * `MutationAuthor` wordt hieruit *afgeleid* (attributie is een projectie van
11
+ * identiteit), niet parallel bijgehouden. Zie `resolveAuthor`.
12
+ */
13
+ export type ActingIdentity = {
14
+ kind: "user";
15
+ userId: string;
16
+ } | {
17
+ kind: "team";
18
+ teamId: string;
19
+ } | {
20
+ kind: "org";
21
+ };
22
+ /**
23
+ * Compacte, header-veilige vorm: `"user:<id>"` | `"team:<id>"` | `"org"`.
24
+ * ASCII, geen JSON — een header hoort geen gestructureerde payload te dragen, en
25
+ * dit blijft leesbaar in logs.
26
+ */
27
+ export declare function formatActingIdentity(actor: ActingIdentity): string;
28
+ /**
29
+ * Leest de compacte vorm terug. Strikt: een onbekende soort, een ontbrekende of
30
+ * lege ref levert `undefined` — nooit een gok en nooit een half-gevulde identiteit
31
+ * zoals `{ kind: "user", userId: "" }`, want die zou als geldig door een gate
32
+ * glippen.
33
+ *
34
+ * Round-trip: `parseActingIdentity(formatActingIdentity(a))` is diep gelijk aan `a`.
35
+ */
36
+ export declare function parseActingIdentity(raw: string | null | undefined): ActingIdentity | undefined;
37
+ /**
38
+ * Stabiele sleutel om identiteiten te vergelijken of te dedupliceren (bijvoorbeeld
39
+ * "één autorisatie-call per distincte actor"). Gelijk aan de wire-vorm; apart
40
+ * genoemd omdat de bedoeling anders is dan transporteren.
41
+ */
42
+ export declare function actingIdentityKey(actor: ActingIdentity): string;
@@ -1,10 +1,4 @@
1
- /**
2
- * Cross-app scope-authorization contract. A resource is addressed by an opaque
3
- * scopeKey ("<kind>:<ref>", e.g. "interaction:abc"); the app that owns that kind
4
- * answers "may this user access it?" over the `scope` provider role. Consumed by
5
- * the AI live-assistant (conversation access) and, from fase 2, the attribute store.
6
- * Implementation: authorizeScope / assertScopeAccess in @opencxh/platform-api.
7
- */
1
+ import { ActingIdentity } from './identity';
8
2
  /** Access decision + whether the scope anchor is team-shared + the SSE audience. */
9
3
  export interface ScopeAuth {
10
4
  allowed: boolean;
@@ -14,9 +8,27 @@ export interface ScopeAuth {
14
8
  /** GET /provider/scope/describe response: the scopeKey prefixes an app owns. */
15
9
  export interface ScopeDescribe {
16
10
  kinds: string[];
11
+ /**
12
+ * Welke soorten acting identity deze provider daadwerkelijk evalueert.
13
+ * Afwezig = alleen het klassieke `userId`-contract.
14
+ *
15
+ * Dit is een fail-closed schakelaar, geen documentatie: een provider die
16
+ * `actor` negeert ziet bij een team-actor een lege `userId` en zou dat als
17
+ * "trusted system caller" lezen — dus volledige toegang. `authorizeIdentity`
18
+ * weigert daarom een `team`-actor zolang de eigenaar `"team"` niet declareert.
19
+ */
20
+ actorKinds?: ActingIdentity["kind"][];
17
21
  }
18
- /** POST /provider/scope/authorize body. userId omitted = trusted system caller. */
22
+ /**
23
+ * POST /provider/scope/authorize body.
24
+ *
25
+ * `userId` blijft voor back-compat: bestaande providers lezen alleen dat veld, en
26
+ * een `user`-actor vult het mee zodat zij ongewijzigd blijven werken. `userId`
27
+ * afwezig = trusted system caller (ruim!), dus zie de waarschuwing bij
28
+ * {@link ScopeDescribe.actorKinds}.
29
+ */
19
30
  export interface ScopeAuthorizeRequest {
20
31
  scopeKey: string;
21
32
  userId?: string;
33
+ actor?: ActingIdentity;
22
34
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencxh/domain",
3
- "version": "1.119.0",
3
+ "version": "1.124.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",