@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.
- package/dist/entities/playbook/types.d.ts +35 -16
- package/dist/entities/resource-reminder/index.d.ts +1 -0
- package/dist/entities/resource-reminder/types.d.ts +25 -0
- package/dist/index.cjs +4 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.js +141 -97
- 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
|
@@ -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,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
|
-
/**
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
/**
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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(/ /g," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/\s+/g," ").trim()}function
|
|
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(/ /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()||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
|
|
4
|
-
`);for(let n=0;n<t.length;n++)if(
|
|
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(/ /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 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(/ /g, " ").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/\s+/g, " ").trim();
|
|
3
3
|
}
|
|
4
|
-
function
|
|
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
|
|
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 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 ? ` (${
|
|
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 w(e) {
|
|
95
95
|
return {
|
|
96
96
|
activityId: e.id,
|
|
97
97
|
type: e.type,
|
|
98
|
-
snippet: g(
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 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(
|
|
142
|
+
s.push(A(a, n));
|
|
143
143
|
return s;
|
|
144
144
|
}
|
|
145
|
-
const
|
|
146
|
-
function
|
|
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
|
|
160
|
+
function K(e, t, n, r = "html") {
|
|
151
161
|
if (!e) return n;
|
|
152
|
-
const s =
|
|
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
|
|
167
|
+
function Y(e) {
|
|
158
168
|
return e.endpoints ?? [];
|
|
159
169
|
}
|
|
160
|
-
const
|
|
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,
|
|
166
|
-
function
|
|
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
|
|
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,
|
|
183
|
-
function
|
|
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 (
|
|
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
|
|
208
|
+
function d(e) {
|
|
199
209
|
return e.replace(/ /gi, " ").replace(/</gi, "<").replace(/>/gi, ">").replace(/"/gi, '"').replace(/'/gi, "'").replace(/&#(\d+);/g, (t, n) => String.fromCharCode(Number(n))).replace(/&/gi, "&");
|
|
200
210
|
}
|
|
201
|
-
function
|
|
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
|
|
217
|
+
function Z(e) {
|
|
208
218
|
if (typeof e != "string" || !e) return "";
|
|
209
219
|
let t = e.length;
|
|
210
|
-
for (const a of
|
|
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(
|
|
216
|
-
return r || (r = d(
|
|
225
|
+
let r = E(d(c(n)));
|
|
226
|
+
return r || (r = E(d(c(e)))), O(r) || r;
|
|
217
227
|
}
|
|
218
|
-
const
|
|
219
|
-
function
|
|
220
|
-
return !!(e &&
|
|
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
|
|
223
|
-
function
|
|
224
|
-
return e >=
|
|
232
|
+
const M = 3, y = 600;
|
|
233
|
+
function ee(e, t) {
|
|
234
|
+
return e >= M || t >= y;
|
|
225
235
|
}
|
|
226
|
-
function
|
|
227
|
-
const n = new Set(e.disabledIntents ?? []), r = e.intentOverrides ?? {}, s = t.intents.filter((o) => !n.has(o.intent)).map((o) =>
|
|
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
|
|
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
|
|
244
|
-
const n =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
275
|
+
function re(e, t) {
|
|
266
276
|
return t.filter((n) => n.capability.intent === e);
|
|
267
277
|
}
|
|
268
|
-
function
|
|
278
|
+
function $(e, t) {
|
|
269
279
|
return t.filter((n) => n.capability.targetSchemes.includes(e));
|
|
270
280
|
}
|
|
271
|
-
function
|
|
272
|
-
return
|
|
281
|
+
function se(e, t) {
|
|
282
|
+
return $(e.scheme, t);
|
|
273
283
|
}
|
|
274
|
-
function
|
|
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
|
|
282
|
-
const
|
|
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
|
-
},
|
|
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
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
Z as
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
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
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
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
|
-
/**
|
|
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
|
}
|