@opencxh/domain 1.123.0 → 1.125.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entities/activity/types.d.ts +5 -0
- package/dist/entities/playbook/actor.d.ts +16 -0
- package/dist/entities/playbook/index.d.ts +3 -0
- package/dist/entities/playbook/labels.d.ts +9 -0
- package/dist/entities/playbook/trigger-vars.d.ts +61 -0
- package/dist/entities/playbook/types.d.ts +43 -17
- package/dist/index.cjs +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +186 -99
- package/dist/platform/ai-tools.d.ts +33 -2
- package/dist/platform/identity.d.ts +42 -0
- package/dist/platform/scope.d.ts +20 -8
- package/package.json +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ActingIdentity } from '../../platform/identity';
|
|
1
2
|
import { AIMessageInput, AIMessageOutput } from '../ai-message/types';
|
|
2
3
|
import { TranscriptSegment } from '../../platform/media';
|
|
3
4
|
export type CallStatus = "new" | "connecting" | "ringing" | "connected" | "held" | "ended" | "failed";
|
|
@@ -198,6 +199,8 @@ export type AIActionProposedPayload = {
|
|
|
198
199
|
params?: Record<string, unknown>;
|
|
199
200
|
}[];
|
|
200
201
|
status: "pending" | "approved" | "rejected";
|
|
202
|
+
/** Namens wie het voorstel is gedaan, zodat de kaart "namens Finance" kan tonen. */
|
|
203
|
+
actor?: ActingIdentity;
|
|
201
204
|
};
|
|
202
205
|
/** Playbook lifecycle marker in the interaction timeline (system-authored). */
|
|
203
206
|
export type PlaybookLifecyclePayload = {
|
|
@@ -205,6 +208,8 @@ export type PlaybookLifecyclePayload = {
|
|
|
205
208
|
playbookId?: string;
|
|
206
209
|
playbookName?: string;
|
|
207
210
|
status?: string;
|
|
211
|
+
/** Namens wie de run handelde; voorkomt dat de UI de playbook opnieuw moet ophalen. */
|
|
212
|
+
actor?: ActingIdentity;
|
|
208
213
|
};
|
|
209
214
|
export type Activity = (BaseActivity & {
|
|
210
215
|
type: "VOICE_CALL_STARTED";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ActingIdentity } from '../../platform/identity';
|
|
2
|
+
import { OwnerScope } from '../contact/types';
|
|
3
|
+
/**
|
|
4
|
+
* `ownerScope` **is** de actor van een playbook: er is geen apart `runAs`-veld.
|
|
5
|
+
* Zichtbaarheid, werkgebied en toeschrijving volgen dus uit hetzelfde veld.
|
|
6
|
+
*
|
|
7
|
+
* Aan de bewaarkant heet de persoonlijke variant `personal` (zoals bij elke andere
|
|
8
|
+
* entity), aan de uitvoerkant `user` (zoals elke andere acting identity). Deze
|
|
9
|
+
* functie is die vertaling, en de enige plek waar hij hoort.
|
|
10
|
+
*/
|
|
11
|
+
export declare function playbookActor(scope: OwnerScope): ActingIdentity;
|
|
12
|
+
/**
|
|
13
|
+
* Stabiele sleutel om actors te groeperen. Tien playbooks van hetzelfde team horen
|
|
14
|
+
* één autorisatie-call te kosten, niet tien.
|
|
15
|
+
*/
|
|
16
|
+
export declare function actorKey(actor: ActingIdentity): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Leesbare naam van een actie/tool voor een mens: `tool:communication__update_interaction`
|
|
3
|
+
* wordt `communication · update interaction`.
|
|
4
|
+
*
|
|
5
|
+
* Gedeeld, want de proposal-kaart in comms had deze helper al terwijl de run-timeline in
|
|
6
|
+
* de AI-app de rauwe id printte — dus daar las je letterlijk
|
|
7
|
+
* `voorstel: tool:mcp__jira__create_issue`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function humanizeAction(action: string): string;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* De variabelen die de engine onder `vars.trigger` zet bij een activity-trigger.
|
|
3
|
+
*
|
|
4
|
+
* Contract tussen `buildTriggerVars` (server) en de variabelen-picker (builder). Die
|
|
5
|
+
* twee waren uiteengelopen: de picker bood `trigger.fromEmail` en `trigger.channel`
|
|
6
|
+
* aan — die bestaan niet — en miste `subject`, `textRaw`, `direction`, `authorType` en
|
|
7
|
+
* `activityId`. Elk pad dat hij aanbood leverde dus `undefined` op. Eén lijst, aan
|
|
8
|
+
* beide kanten geïmporteerd, kan niet opnieuw uiteenlopen.
|
|
9
|
+
*/
|
|
10
|
+
export declare const TRIGGER_VARS: readonly [{
|
|
11
|
+
readonly name: "text";
|
|
12
|
+
readonly type: "string";
|
|
13
|
+
}, {
|
|
14
|
+
readonly name: "subject";
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
}, {
|
|
17
|
+
readonly name: "from";
|
|
18
|
+
readonly type: "string";
|
|
19
|
+
}, {
|
|
20
|
+
readonly name: "type";
|
|
21
|
+
readonly type: "string";
|
|
22
|
+
}, {
|
|
23
|
+
readonly name: "direction";
|
|
24
|
+
readonly type: "string";
|
|
25
|
+
}, {
|
|
26
|
+
readonly name: "channelId";
|
|
27
|
+
readonly type: "string";
|
|
28
|
+
}, {
|
|
29
|
+
readonly name: "interactionId";
|
|
30
|
+
readonly type: "string";
|
|
31
|
+
}, {
|
|
32
|
+
readonly name: "activityId";
|
|
33
|
+
readonly type: "string";
|
|
34
|
+
}, {
|
|
35
|
+
readonly name: "authorType";
|
|
36
|
+
readonly type: "string";
|
|
37
|
+
}, {
|
|
38
|
+
readonly name: "authorName";
|
|
39
|
+
readonly type: "string";
|
|
40
|
+
}, {
|
|
41
|
+
readonly name: "textRaw";
|
|
42
|
+
readonly type: "string";
|
|
43
|
+
}];
|
|
44
|
+
/** De variabelen die een classify-stap oplevert, per mode. */
|
|
45
|
+
export declare const CLASSIFY_VARS: {
|
|
46
|
+
readonly topics: readonly [{
|
|
47
|
+
readonly name: "topic";
|
|
48
|
+
readonly type: "string";
|
|
49
|
+
}, {
|
|
50
|
+
readonly name: "confidence";
|
|
51
|
+
readonly type: "number";
|
|
52
|
+
}];
|
|
53
|
+
readonly question: readonly [{
|
|
54
|
+
readonly name: "answer";
|
|
55
|
+
readonly type: "boolean";
|
|
56
|
+
}, {
|
|
57
|
+
readonly name: "confidence";
|
|
58
|
+
readonly type: "number";
|
|
59
|
+
}];
|
|
60
|
+
readonly extract: readonly [];
|
|
61
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ActingIdentity } from '../../platform/identity';
|
|
1
2
|
import { OwnerScope } from '../contact/types';
|
|
2
3
|
/**
|
|
3
4
|
* Playbooks — event-driven automation with AI steps. See docs/PLAYBOOKS.md.
|
|
@@ -19,7 +20,6 @@ export type PlaybookTrigger = {
|
|
|
19
20
|
export interface Guardrails {
|
|
20
21
|
maxSteps?: number;
|
|
21
22
|
maxToolCalls?: number;
|
|
22
|
-
policyCaps?: Record<string, unknown>;
|
|
23
23
|
}
|
|
24
24
|
export interface ConditionStep {
|
|
25
25
|
type: "condition";
|
|
@@ -102,7 +102,24 @@ export interface Playbook {
|
|
|
102
102
|
autoActions: number;
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
|
-
|
|
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,38 @@ 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
|
-
/**
|
|
146
|
+
/**
|
|
147
|
+
* Namens wie deze run handelt, vastgepind bij de start — net als `steps`. Anders
|
|
148
|
+
* wisselt een lopende of geparkeerde run stilletjes van identiteit zodra iemand de
|
|
149
|
+
* playbook van "Alleen ik" naar "Team Finance" zet. `resume`/`retry` lezen dit veld,
|
|
150
|
+
* niet `playbook.ownerScope`.
|
|
151
|
+
*/
|
|
152
|
+
actor?: ActingIdentity;
|
|
153
|
+
/**
|
|
154
|
+
* Held action(s) awaiting human approval (autonomy: suggest) — a batch per paused
|
|
155
|
+
* step. `null` wanneer het veld gewist is; de store schrijft `null`, dus dat staat
|
|
156
|
+
* ook in het type in plaats van dat elke lezer drie toestanden moet aankunnen.
|
|
157
|
+
*/
|
|
130
158
|
pending?: {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
params: Record<string, unknown>;
|
|
135
|
-
}[];
|
|
136
|
-
};
|
|
159
|
+
action: string;
|
|
160
|
+
params: Record<string, unknown>;
|
|
161
|
+
}[] | null;
|
|
137
162
|
/** The AI_ACTION_PROPOSED activity created for the current pending batch (for resolve on approve/reject). */
|
|
138
|
-
proposalActivityId?: string;
|
|
139
|
-
/**
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
163
|
+
proposalActivityId?: string | null;
|
|
164
|
+
/**
|
|
165
|
+
* Index van de stap waarop de flow pauzeerde — voor zowel `awaiting_approval` als
|
|
166
|
+
* `awaiting_reply`. (Was `resumeIndex` naast `pending.stepIndex`: twee velden voor
|
|
167
|
+
* hetzelfde feit, in twee takken geschreven en in twee takken gelezen.)
|
|
168
|
+
*/
|
|
169
|
+
pausedAt?: number | null;
|
|
144
170
|
rounds?: number;
|
|
145
171
|
/** Denormalized interaction audience for efficient list-filtering. */
|
|
146
172
|
audience?: string[];
|
|
147
173
|
createdBy: string;
|
|
148
|
-
approvedBy?: string;
|
|
174
|
+
approvedBy?: string | null;
|
|
149
175
|
result?: {
|
|
150
176
|
ok: boolean;
|
|
151
177
|
error?: string;
|
|
152
|
-
};
|
|
178
|
+
} | null;
|
|
153
179
|
lastStepAt?: number;
|
|
154
180
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=140;function
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=140;function g(e){return e.replace(/<style[\s\S]*?<\/style>/gi," ").replace(/<script[\s\S]*?<\/script>/gi," ").replace(/<[^>]+>/g," ").replace(/ /g," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/\s+/g," ").trim()}function 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()||g(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 h(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 $(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 A(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 k=36e5,G=864e5;function V(e,t,n){const r=n==="hour"?k:G,s=[];for(let a=f(e,n);a<=t;a+=r)s.push(A(a,n));return s}function H(e){return(e.startsWith("tool:")?e.slice(5):e).replace(/__/g," · ").replace(/\./g," · ").replace(/_/g," ")}const w=[{name:"text",type:"string"},{name:"subject",type:"string"},{name:"from",type:"string"},{name:"type",type:"string"},{name:"direction",type:"string"},{name:"channelId",type:"string"},{name:"interactionId",type:"string"},{name:"activityId",type:"string"},{name:"authorType",type:"string"},{name:"authorName",type:"string"},{name:"textRaw",type:"string"}],F={topics:[{name:"topic",type:"string"},{name:"confidence",type:"number"}],question:[{name:"answer",type:"boolean"},{name:"confidence",type:"number"}],extract:[]};function I(e){switch(e.kind){case"user":return`user:${e.userId}`;case"team":return`team:${e.teamId}`;case"org":return"org"}}function x(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 _(e){return I(e)}function B(e){switch(e.kind){case"personal":return{kind:"user",userId:e.userId};case"team":return{kind:"team",teamId:e.teamId};case"org":return{kind:"org"}}}function j(e){return _(e)}const S=["done","escalated","failed","timed_out","stopped"],T=["awaiting_approval","awaiting_reply"];function m(e){return S.includes(e)}function W(e){return m(e)}function K(e){return T.includes(e)}const Y=new Set(["mail","message"]);function R(e,t){const n=e.settings?.signatures?.[t];return!n||!n.enabled||!n.body||n.body.trim()===""?null:n}function q(e,t,n,r="html"){if(!e)return n;const s=R(e,t);return s?`${n}${r==="text"?`
|
|
2
2
|
|
|
3
|
-
`:t==="mail"?"<br><br>-- <br>":"<br><br>"}${s.body}`:n}function
|
|
4
|
-
`);for(let n=0;n<t.length;n++)if(
|
|
3
|
+
`:t==="mail"?"<br><br>-- <br>":"<br><br>"}${s.body}`:n}function z(e){return e.endpoints??[]}const v=e=>!!e.assignedUserId||!!e.assignedInboxId,J=e=>e.status==="closed",Q=e=>({urgent:10,high:5,normal:2,low:1})[e.priority]||0,X=(e,t=30)=>e.title?.length<=t?e.title:`${e.title.substring(0,t)}...`;function Z(e,t){return e.lastActivityAt?!(e.seenBy??[]).includes(t):!1}const ee=[/<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,te=/^\s*(?:on|op)\b.{0,200}?\b(?:wrote|schreef|geschreven)\s*:?\s*$/i;function ne(e){const t=e.split(`
|
|
4
|
+
`);for(let n=0;n<t.length;n++)if(te.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(/ /gi," ").replace(/</gi,"<").replace(/>/gi,">").replace(/"/gi,'"').replace(/'/gi,"'").replace(/&#(\d+);/g,(t,n)=>String.fromCharCode(Number(n))).replace(/&/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
|
|
10
|
+
`).trim()}function re(e){if(typeof e!="string"||!e)return"";let t=e.length;for(const a of ee){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)))),ne(r)||r}const se=/(^|[._+-])(no-?reply|noreply|donotreply|do-not-reply|newsletter|nieuwsbrief|mailer|mailing|notifications?|bounce|postmaster|marketing)@/i,ae=/\b(unsubscribe|afmelden|uitschrijven|opt[\s-]?out|manage (your )?preferences|geen (e-?mails?|nieuwsbrief|berichten) meer)\b/i;function oe(e,t){return!!(e&&se.test(e)||t&&ae.test(t))}const b=3,N=600;function ie(e,t){return e>=b||t>=N}function D(e,t){const n=new Set(e.disabledIntents??[]),r=e.intentOverrides??{},s=t.intents.filter(o=>!n.has(o.intent)).map(o=>ce(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 y(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 le(e,t){const n=y(e,t);return Object.entries(n).filter(([,r])=>!r).map(([r])=>r)}function ce(e,t){return t?{intent:t.intent??e.intent,targetSchemes:t.targetSchemes??e.targetSchemes,transport:t.transport??e.transport}:e}function ue(e,t){const n=[];for(const r of e){if(!r.enabled)continue;const s=t[r.providerId];if(s)for(const a of D(r,s))n.push({channel:r,description:s,capability:a})}return n}function Ee(e,t){return t.filter(n=>n.capability.intent===e)}function L(e,t){return t.filter(n=>n.capability.targetSchemes.includes(e))}function de(e,t){return L(e.scheme,t)}function pe(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 ge="message_window",Ae="message_templates",fe={FROM:"from",TO:"to",CC:"cc",BCC:"bcc",ORGANIZER:"organizer",PRESENTER:"presenter",ATTENDEE:"attendee",OWNER:"owner",MEMBER:"member",GUEST:"guest",HOST:"host",PARTICIPANT:"participant"},Ie=(e,t)=>({intent:e,...t}),_e="folder_management",Se="remote_search",Te={ok:!1,code:"UNSUPPORTED",message:"Provider does not support this op"},me=9e4,Re="installation-id";exports.CLASSIFY_VARS=F;exports.CORE_DIMENSIONS=P;exports.CommunicationScheme=O;exports.FEATURE_FOLDER_MANAGEMENT=_e;exports.FEATURE_REMOTE_SEARCH=Se;exports.INSTALLATION_HEADER=Re;exports.InteractionParticipantRole=fe;exports.PAUSED_RUN_STATUSES=T;exports.PRESENCE_ONLINE_WINDOW_MS=me;exports.PROVIDER_FEATURE_MESSAGE_TEMPLATES=Ae;exports.PROVIDER_FEATURE_MESSAGE_WINDOW=ge;exports.SIGNATURE_INTENTS=Y;exports.SUMMARY_MIN_LAST_CHARS=N;exports.SUMMARY_MIN_MESSAGES=b;exports.TERMINAL_RUN_STATUSES=S;exports.TRIGGER_VARS=w;exports.UNSUPPORTED=Te;exports.actingIdentityKey=_;exports.actorKey=j;exports.applySignature=q;exports.buildActivityPreview=h;exports.buildChannelIntents=ue;exports.cleanMessageText=re;exports.defineIntent=Ie;exports.disabledIntentsFromCapabilities=le;exports.filterByEndpoint=de;exports.filterByIntent=Ee;exports.filterByTargetScheme=L;exports.flattenLocales=$;exports.floorToPeriod=f;exports.formatActingIdentity=I;exports.formatPeriod=A;exports.getActivitySeenUserIds=U;exports.getContactEndpoints=z;exports.getShortTitle=X;exports.getUrgencyScore=Q;exports.humanizeAction=H;exports.isAssigned=v;exports.isClosed=J;exports.isInteractionUnseen=Z;exports.isLikelyBulk=oe;exports.isPaused=K;exports.isRetryable=W;exports.isTerminal=m;exports.isThreadLongEnough=ie;exports.matchContactToIntents=pe;exports.parseActingIdentity=x;exports.periodsInRange=V;exports.playbookActor=B;exports.resolveAccountCapabilities=y;exports.resolveChannelIntents=D;exports.resolveSignature=R;exports.stripHtml=g;
|
package/dist/index.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export * from './platform/capabilities';
|
|
|
38
38
|
export * from './platform/context';
|
|
39
39
|
export * from './platform/communication';
|
|
40
40
|
export * from './platform/federated';
|
|
41
|
+
export * from './platform/identity';
|
|
41
42
|
export * from './platform/intents';
|
|
42
43
|
export * from './platform/kernel';
|
|
43
44
|
export * from './platform/lifecycle';
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
function
|
|
1
|
+
function E(e) {
|
|
2
2
|
return e.replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<[^>]+>/g, " ").replace(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/\s+/g, " ").trim();
|
|
3
3
|
}
|
|
4
4
|
function g(e) {
|
|
5
5
|
const t = e.trim();
|
|
6
6
|
return t.length <= 140 ? t : t.slice(0, 139).trimEnd() + "…";
|
|
7
7
|
}
|
|
8
|
-
function
|
|
8
|
+
function 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
|
|
13
|
+
function f(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() ||
|
|
17
|
+
const t = e.payload, n = t.bodySnippet?.trim() || E(t.body ?? "");
|
|
18
18
|
return t.subject ? `${t.subject} — ${n}` : n;
|
|
19
19
|
}
|
|
20
20
|
case "CHAT_MESSAGE_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 ? ` (${
|
|
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 ? ` (${
|
|
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 ? ` (${
|
|
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
|
|
94
|
+
function H(e) {
|
|
95
95
|
return {
|
|
96
96
|
activityId: e.id,
|
|
97
97
|
type: e.type,
|
|
98
|
-
snippet: g(
|
|
98
|
+
snippet: g(f(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
|
|
104
|
+
function V(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
|
|
110
|
+
const x = [
|
|
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,130 @@ const H = [
|
|
|
117
117
|
{ id: "handledBy", label: "Afhandelaar", labelSource: "raw" },
|
|
118
118
|
{ id: "time", label: "Tijd", labelSource: "raw" }
|
|
119
119
|
];
|
|
120
|
-
function
|
|
120
|
+
function B(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
|
|
127
|
+
function l(e) {
|
|
128
128
|
return e < 10 ? `0${e}` : `${e}`;
|
|
129
129
|
}
|
|
130
|
-
function
|
|
131
|
-
const n = new Date(e), r = `${n.getUTCFullYear()}-${
|
|
132
|
-
return t === "day" ? r : `${r}T${
|
|
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
|
|
139
|
-
function
|
|
140
|
-
const r = n === "hour" ?
|
|
138
|
+
const I = 36e5, T = 864e5;
|
|
139
|
+
function F(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(
|
|
142
|
+
s.push(A(a, n));
|
|
143
143
|
return s;
|
|
144
144
|
}
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
function j(e) {
|
|
146
|
+
return (e.startsWith("tool:") ? e.slice(5) : e).replace(/__/g, " · ").replace(/\./g, " · ").replace(/_/g, " ");
|
|
147
|
+
}
|
|
148
|
+
const W = [
|
|
149
|
+
{ name: "text", type: "string" },
|
|
150
|
+
{ name: "subject", type: "string" },
|
|
151
|
+
{ name: "from", type: "string" },
|
|
152
|
+
{ name: "type", type: "string" },
|
|
153
|
+
{ name: "direction", type: "string" },
|
|
154
|
+
{ name: "channelId", type: "string" },
|
|
155
|
+
{ name: "interactionId", type: "string" },
|
|
156
|
+
{ name: "activityId", type: "string" },
|
|
157
|
+
{ name: "authorType", type: "string" },
|
|
158
|
+
{ name: "authorName", type: "string" },
|
|
159
|
+
{ name: "textRaw", type: "string" }
|
|
160
|
+
], K = {
|
|
161
|
+
topics: [
|
|
162
|
+
{ name: "topic", type: "string" },
|
|
163
|
+
{ name: "confidence", type: "number" }
|
|
164
|
+
],
|
|
165
|
+
question: [
|
|
166
|
+
{ name: "answer", type: "boolean" },
|
|
167
|
+
{ name: "confidence", type: "number" }
|
|
168
|
+
],
|
|
169
|
+
extract: []
|
|
170
|
+
};
|
|
171
|
+
function S(e) {
|
|
172
|
+
switch (e.kind) {
|
|
173
|
+
case "user":
|
|
174
|
+
return `user:${e.userId}`;
|
|
175
|
+
case "team":
|
|
176
|
+
return `team:${e.teamId}`;
|
|
177
|
+
case "org":
|
|
178
|
+
return "org";
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function Y(e) {
|
|
182
|
+
if (typeof e != "string") return;
|
|
183
|
+
const t = e.trim();
|
|
184
|
+
if (t === "org") return { kind: "org" };
|
|
185
|
+
const n = t.indexOf(":");
|
|
186
|
+
if (n <= 0) return;
|
|
187
|
+
const r = t.slice(0, n), s = t.slice(n + 1).trim();
|
|
188
|
+
if (s) {
|
|
189
|
+
if (r === "user") return { kind: "user", userId: s };
|
|
190
|
+
if (r === "team") return { kind: "team", teamId: s };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function m(e) {
|
|
194
|
+
return S(e);
|
|
195
|
+
}
|
|
196
|
+
function q(e) {
|
|
197
|
+
switch (e.kind) {
|
|
198
|
+
case "personal":
|
|
199
|
+
return { kind: "user", userId: e.userId };
|
|
200
|
+
case "team":
|
|
201
|
+
return { kind: "team", teamId: e.teamId };
|
|
202
|
+
case "org":
|
|
203
|
+
return { kind: "org" };
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function z(e) {
|
|
207
|
+
return m(e);
|
|
208
|
+
}
|
|
209
|
+
const b = ["done", "escalated", "failed", "timed_out", "stopped"], N = ["awaiting_approval", "awaiting_reply"];
|
|
210
|
+
function D(e) {
|
|
211
|
+
return b.includes(e);
|
|
212
|
+
}
|
|
213
|
+
function X(e) {
|
|
214
|
+
return D(e);
|
|
215
|
+
}
|
|
216
|
+
function J(e) {
|
|
217
|
+
return N.includes(e);
|
|
218
|
+
}
|
|
219
|
+
const Q = /* @__PURE__ */ new Set(["mail", "message"]);
|
|
220
|
+
function R(e, t) {
|
|
147
221
|
const n = e.settings?.signatures?.[t];
|
|
148
222
|
return !n || !n.enabled || !n.body || n.body.trim() === "" ? null : n;
|
|
149
223
|
}
|
|
150
|
-
function
|
|
224
|
+
function Z(e, t, n, r = "html") {
|
|
151
225
|
if (!e) return n;
|
|
152
|
-
const s =
|
|
226
|
+
const s = R(e, t);
|
|
153
227
|
return s ? `${n}${r === "text" ? `
|
|
154
228
|
|
|
155
229
|
` : t === "mail" ? "<br><br>-- <br>" : "<br><br>"}${s.body}` : n;
|
|
156
230
|
}
|
|
157
|
-
function
|
|
231
|
+
function v(e) {
|
|
158
232
|
return e.endpoints ?? [];
|
|
159
233
|
}
|
|
160
|
-
const
|
|
234
|
+
const ee = (e) => !!e.assignedUserId || !!e.assignedInboxId, te = (e) => e.status === "closed", ne = (e) => ({
|
|
161
235
|
urgent: 10,
|
|
162
236
|
high: 5,
|
|
163
237
|
normal: 2,
|
|
164
238
|
low: 1
|
|
165
|
-
})[e.priority] || 0,
|
|
166
|
-
function
|
|
239
|
+
})[e.priority] || 0, re = (e, t = 30) => e.title?.length <= t ? e.title : `${e.title.substring(0, t)}...`;
|
|
240
|
+
function se(e, t) {
|
|
167
241
|
return e.lastActivityAt ? !(e.seenBy ?? []).includes(t) : !1;
|
|
168
242
|
}
|
|
169
|
-
const
|
|
243
|
+
const L = [
|
|
170
244
|
/<blockquote/i,
|
|
171
245
|
/class="?gmail_quote/i,
|
|
172
246
|
// Gmail quote container
|
|
@@ -179,12 +253,12 @@ const b = [
|
|
|
179
253
|
// Outlook underscore separator before "From:"
|
|
180
254
|
/\bOn\b[\s\S]{0,200}?\bwrote:/i
|
|
181
255
|
// Gmail "On <date> <name> wrote:"
|
|
182
|
-
], u = /^\s*(?:>+\s*)?(?:from|van|sent|verzonden|to|aan|cc|subject|onderwerp|date|datum)\s*:/i,
|
|
183
|
-
function
|
|
256
|
+
], u = /^\s*(?:>+\s*)?(?:from|van|sent|verzonden|to|aan|cc|subject|onderwerp|date|datum)\s*:/i, O = /^\s*(?:on|op)\b.{0,200}?\b(?:wrote|schreef|geschreven)\s*:?\s*$/i;
|
|
257
|
+
function y(e) {
|
|
184
258
|
const t = e.split(`
|
|
185
259
|
`);
|
|
186
260
|
for (let n = 0; n < t.length; n++)
|
|
187
|
-
if (
|
|
261
|
+
if (O.test(t[n]) || u.test(t[n]) && t.slice(n + 1, n + 4).some((r) => u.test(r)))
|
|
188
262
|
return t.slice(0, n).join(`
|
|
189
263
|
`).trim();
|
|
190
264
|
return e;
|
|
@@ -195,43 +269,43 @@ function c(e) {
|
|
|
195
269
|
`), t = t.replace(/<\/(p|div|li|tr|h[1-6]|ul|ol|table)>/gi, `
|
|
196
270
|
`), t = t.replace(/<[^>]+>/g, ""), t = t.replace(/<[^>]*$/, ""), t;
|
|
197
271
|
}
|
|
198
|
-
function
|
|
272
|
+
function d(e) {
|
|
199
273
|
return e.replace(/ /gi, " ").replace(/</gi, "<").replace(/>/gi, ">").replace(/"/gi, '"').replace(/'/gi, "'").replace(/&#(\d+);/g, (t, n) => String.fromCharCode(Number(n))).replace(/&/gi, "&");
|
|
200
274
|
}
|
|
201
|
-
function
|
|
275
|
+
function p(e) {
|
|
202
276
|
return e.replace(/\r/g, "").replace(/[ \t]+/g, " ").replace(/ *\n */g, `
|
|
203
277
|
`).replace(/\n{3,}/g, `
|
|
204
278
|
|
|
205
279
|
`).trim();
|
|
206
280
|
}
|
|
207
|
-
function
|
|
281
|
+
function ae(e) {
|
|
208
282
|
if (typeof e != "string" || !e) return "";
|
|
209
283
|
let t = e.length;
|
|
210
|
-
for (const a of
|
|
284
|
+
for (const a of L) {
|
|
211
285
|
const o = e.search(a);
|
|
212
286
|
o >= 0 && o < t && (t = o);
|
|
213
287
|
}
|
|
214
288
|
const n = e.slice(0, t);
|
|
215
|
-
let r = d(
|
|
216
|
-
return r || (r = d(
|
|
289
|
+
let r = p(d(c(n)));
|
|
290
|
+
return r || (r = p(d(c(e)))), y(r) || r;
|
|
217
291
|
}
|
|
218
|
-
const
|
|
219
|
-
function
|
|
220
|
-
return !!(e &&
|
|
292
|
+
const C = /(^|[._+-])(no-?reply|noreply|donotreply|do-not-reply|newsletter|nieuwsbrief|mailer|mailing|notifications?|bounce|postmaster|marketing)@/i, M = /\b(unsubscribe|afmelden|uitschrijven|opt[\s-]?out|manage (your )?preferences|geen (e-?mails?|nieuwsbrief|berichten) meer)\b/i;
|
|
293
|
+
function oe(e, t) {
|
|
294
|
+
return !!(e && C.test(e) || t && M.test(t));
|
|
221
295
|
}
|
|
222
|
-
const
|
|
223
|
-
function
|
|
224
|
-
return e >=
|
|
296
|
+
const h = 3, P = 600;
|
|
297
|
+
function ie(e, t) {
|
|
298
|
+
return e >= h || t >= P;
|
|
225
299
|
}
|
|
226
|
-
function
|
|
227
|
-
const n = new Set(e.disabledIntents ?? []), r = e.intentOverrides ?? {}, s = t.intents.filter((o) => !n.has(o.intent)).map((o) =>
|
|
300
|
+
function U(e, t) {
|
|
301
|
+
const n = new Set(e.disabledIntents ?? []), r = e.intentOverrides ?? {}, s = t.intents.filter((o) => !n.has(o.intent)).map((o) => k(o, r[o.intent]));
|
|
228
302
|
if (!e.extraIntents || e.extraIntents.length === 0) return s;
|
|
229
303
|
const a = new Set(s.map((o) => o.intent));
|
|
230
304
|
for (const o of e.extraIntents)
|
|
231
305
|
a.has(o.intent) || (s.push(o), a.add(o.intent));
|
|
232
306
|
return s;
|
|
233
307
|
}
|
|
234
|
-
function
|
|
308
|
+
function $(e, t) {
|
|
235
309
|
const n = {};
|
|
236
310
|
for (const r of e.intents) {
|
|
237
311
|
if (!r.togglable) continue;
|
|
@@ -240,46 +314,46 @@ function M(e, t) {
|
|
|
240
314
|
}
|
|
241
315
|
return n;
|
|
242
316
|
}
|
|
243
|
-
function
|
|
244
|
-
const n =
|
|
317
|
+
function le(e, t) {
|
|
318
|
+
const n = $(e, t);
|
|
245
319
|
return Object.entries(n).filter(([, r]) => !r).map(([r]) => r);
|
|
246
320
|
}
|
|
247
|
-
function
|
|
321
|
+
function k(e, t) {
|
|
248
322
|
return t ? {
|
|
249
323
|
intent: t.intent ?? e.intent,
|
|
250
324
|
targetSchemes: t.targetSchemes ?? e.targetSchemes,
|
|
251
325
|
transport: t.transport ?? e.transport
|
|
252
326
|
} : e;
|
|
253
327
|
}
|
|
254
|
-
function
|
|
328
|
+
function ue(e, t) {
|
|
255
329
|
const n = [];
|
|
256
330
|
for (const r of e) {
|
|
257
331
|
if (!r.enabled) continue;
|
|
258
332
|
const s = t[r.providerId];
|
|
259
333
|
if (s)
|
|
260
|
-
for (const a of
|
|
334
|
+
for (const a of U(r, s))
|
|
261
335
|
n.push({ channel: r, description: s, capability: a });
|
|
262
336
|
}
|
|
263
337
|
return n;
|
|
264
338
|
}
|
|
265
|
-
function
|
|
339
|
+
function ce(e, t) {
|
|
266
340
|
return t.filter((n) => n.capability.intent === e);
|
|
267
341
|
}
|
|
268
|
-
function
|
|
342
|
+
function w(e, t) {
|
|
269
343
|
return t.filter((n) => n.capability.targetSchemes.includes(e));
|
|
270
344
|
}
|
|
271
|
-
function
|
|
272
|
-
return
|
|
345
|
+
function de(e, t) {
|
|
346
|
+
return w(e.scheme, t);
|
|
273
347
|
}
|
|
274
|
-
function
|
|
348
|
+
function pe(e, t, n) {
|
|
275
349
|
const r = [];
|
|
276
350
|
for (const s of e)
|
|
277
351
|
for (const a of n)
|
|
278
352
|
a.capability.intent === t && a.capability.targetSchemes.includes(s.scheme) && r.push({ channelIntent: a, endpoint: s });
|
|
279
353
|
return r;
|
|
280
354
|
}
|
|
281
|
-
var
|
|
282
|
-
const
|
|
355
|
+
var G = /* @__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))(G || {});
|
|
356
|
+
const Ee = "message_window", ge = "message_templates", fe = {
|
|
283
357
|
// E-mail
|
|
284
358
|
FROM: "from",
|
|
285
359
|
TO: "to",
|
|
@@ -296,46 +370,59 @@ const ee = "message_window", te = "message_templates", ne = {
|
|
|
296
370
|
// Voice/conference
|
|
297
371
|
HOST: "host",
|
|
298
372
|
PARTICIPANT: "participant"
|
|
299
|
-
},
|
|
373
|
+
}, Ae = (e, t) => ({ intent: e, ...t }), _e = "folder_management", Ie = "remote_search", Te = { ok: !1, code: "UNSUPPORTED", message: "Provider does not support this op" }, Se = 9e4, me = "installation-id";
|
|
300
374
|
export {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
z as
|
|
320
|
-
Z as
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
375
|
+
K as CLASSIFY_VARS,
|
|
376
|
+
x as CORE_DIMENSIONS,
|
|
377
|
+
G as CommunicationScheme,
|
|
378
|
+
_e as FEATURE_FOLDER_MANAGEMENT,
|
|
379
|
+
Ie as FEATURE_REMOTE_SEARCH,
|
|
380
|
+
me as INSTALLATION_HEADER,
|
|
381
|
+
fe as InteractionParticipantRole,
|
|
382
|
+
N as PAUSED_RUN_STATUSES,
|
|
383
|
+
Se as PRESENCE_ONLINE_WINDOW_MS,
|
|
384
|
+
ge as PROVIDER_FEATURE_MESSAGE_TEMPLATES,
|
|
385
|
+
Ee as PROVIDER_FEATURE_MESSAGE_WINDOW,
|
|
386
|
+
Q as SIGNATURE_INTENTS,
|
|
387
|
+
P as SUMMARY_MIN_LAST_CHARS,
|
|
388
|
+
h as SUMMARY_MIN_MESSAGES,
|
|
389
|
+
b as TERMINAL_RUN_STATUSES,
|
|
390
|
+
W as TRIGGER_VARS,
|
|
391
|
+
Te as UNSUPPORTED,
|
|
392
|
+
m as actingIdentityKey,
|
|
393
|
+
z as actorKey,
|
|
394
|
+
Z as applySignature,
|
|
395
|
+
H as buildActivityPreview,
|
|
396
|
+
ue as buildChannelIntents,
|
|
397
|
+
ae as cleanMessageText,
|
|
398
|
+
Ae as defineIntent,
|
|
399
|
+
le as disabledIntentsFromCapabilities,
|
|
400
|
+
de as filterByEndpoint,
|
|
401
|
+
ce as filterByIntent,
|
|
402
|
+
w as filterByTargetScheme,
|
|
403
|
+
B as flattenLocales,
|
|
324
404
|
_ as floorToPeriod,
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
405
|
+
S as formatActingIdentity,
|
|
406
|
+
A as formatPeriod,
|
|
407
|
+
V as getActivitySeenUserIds,
|
|
408
|
+
v as getContactEndpoints,
|
|
409
|
+
re as getShortTitle,
|
|
410
|
+
ne as getUrgencyScore,
|
|
411
|
+
j as humanizeAction,
|
|
412
|
+
ee as isAssigned,
|
|
413
|
+
te as isClosed,
|
|
414
|
+
se as isInteractionUnseen,
|
|
415
|
+
oe as isLikelyBulk,
|
|
416
|
+
J as isPaused,
|
|
417
|
+
X as isRetryable,
|
|
418
|
+
D as isTerminal,
|
|
419
|
+
ie as isThreadLongEnough,
|
|
420
|
+
pe as matchContactToIntents,
|
|
421
|
+
Y as parseActingIdentity,
|
|
422
|
+
F as periodsInRange,
|
|
423
|
+
q as playbookActor,
|
|
424
|
+
$ as resolveAccountCapabilities,
|
|
425
|
+
U as resolveChannelIntents,
|
|
426
|
+
R as resolveSignature,
|
|
427
|
+
E as stripHtml
|
|
341
428
|
};
|
|
@@ -31,8 +31,39 @@ export interface AiToolResult {
|
|
|
31
31
|
content: string;
|
|
32
32
|
isError?: boolean;
|
|
33
33
|
}
|
|
34
|
-
/**
|
|
35
|
-
|
|
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;
|
package/dist/platform/scope.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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
|
}
|