@lilaquadrat/chat 0.1.12 → 0.1.14

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.
Files changed (47) hide show
  1. package/dist/app/assets/de-DD_Cd2_H.js +1 -0
  2. package/dist/app/assets/{web-component-Ds4R7Sx0.js → loadFonts-CzCLMM5t.js} +1 -1
  3. package/dist/app/assets/main-DynihIMH.js +2 -0
  4. package/dist/app/assets/preload-helper-BmF9SSsU.js +1 -0
  5. package/dist/app/assets/support-agent-B4Ukp9dc.js +1 -0
  6. package/dist/app/assets/support-j_mB33ro.js +2 -0
  7. package/dist/app/assets/web-component-Dfr0XDoy.js +1 -0
  8. package/dist/app/index.html +2 -1
  9. package/dist/app/support/index.html +43 -0
  10. package/dist/types/src/composables/useChatBootstrap.d.ts +27 -0
  11. package/dist/types/src/config/auth.d.ts +1 -1
  12. package/dist/types/src/config/bootstrap.agent.d.ts +85 -0
  13. package/dist/types/src/config/bootstrap.d.ts +5 -65
  14. package/dist/types/src/config/chatConfig.d.ts +82 -0
  15. package/dist/types/src/config/components.shared.d.ts +18 -0
  16. package/dist/types/src/config/users.d.ts +1 -1
  17. package/dist/types/src/helpers/handleMessages.d.ts +2 -1
  18. package/dist/types/src/helpers/participants.d.ts +25 -0
  19. package/dist/types/src/helpers/supportStatus.d.ts +15 -0
  20. package/dist/types/src/interfaces/Conversation.d.ts +44 -0
  21. package/dist/types/src/interfaces/ConversationSla.d.ts +9 -0
  22. package/dist/types/src/interfaces/IncomingFrame.d.ts +71 -0
  23. package/dist/types/src/interfaces/Message.d.ts +16 -0
  24. package/dist/types/src/interfaces/ParticipantDocument.d.ts +13 -0
  25. package/dist/types/src/libs/StudioSDK.d.ts +44 -19
  26. package/dist/types/src/libs/chatSession.d.ts +2 -1
  27. package/dist/types/src/locales/de.d.ts +26 -0
  28. package/dist/types/src/locales/en.d.ts +26 -0
  29. package/dist/types/src/mixins/groupMessages.d.ts +14 -1
  30. package/dist/types/src/plugins/i18n.d.ts +26 -0
  31. package/dist/types/src/standalone/auth.d.ts +6 -23
  32. package/dist/types/src/standalone/settings.d.ts +29 -8
  33. package/dist/types/src/standalone-support/main.d.ts +1 -0
  34. package/dist/types/src/stores/calls.store.d.ts +3 -3
  35. package/dist/types/src/stores/conversations.store.d.ts +2053 -77
  36. package/dist/types/src/stores/main.store.d.ts +32 -6
  37. package/dist/types/src/stores/supportConversations.store.d.ts +65 -0
  38. package/dist/types/src/support-agent.d.ts +18 -0
  39. package/dist/types/tsconfig.build.tsbuildinfo +1 -1
  40. package/dist/wc/lilaquadrat-studio-chat.js +7 -7
  41. package/dist/wc/lilaquadrat-studio-chat.umd.cjs +1 -1
  42. package/dist/wc-support/lilaquadrat-studio-support.js +9 -0
  43. package/dist/wc-support/lilaquadrat-studio-support.umd.cjs +1 -0
  44. package/package.json +7 -4
  45. package/dist/app/assets/de-BzgVzhC_.js +0 -1
  46. package/dist/app/assets/en-BfL0k26m.js +0 -1
  47. package/dist/app/assets/index-CF9tBDuT.js +0 -1
@@ -15,11 +15,36 @@ export interface ParticipantUser {
15
15
  lastSeen?: string;
16
16
  /** presence: derived server-side from lastSeen freshness, pushed live via user:presence */
17
17
  online?: boolean;
18
+ /**
19
+ * the participant's role in the conversation. `'agent'` for a member of the support team.
20
+ *
21
+ * `null`, not absent, for everyone else: the backend collapses two different absences with an
22
+ * `$ifNull` (no participant doc at all vs. a doc carrying no role) so that both the REST row
23
+ * and the `conversation:new` frame carry the key on every participant. Never test for
24
+ * `undefined` or `'role' in participant` — that would hold on one path and not the other.
25
+ * Optional here only because a local draft's participants are built client-side.
26
+ */
27
+ role?: 'agent' | null;
18
28
  }
19
29
  export type Participant = string | ParticipantUser;
20
30
  /** the user id of a participant, whether it's a bare id or an object */
21
31
  export declare function participantId(participant: Participant): string;
22
32
  /** map a participant list to its ids (e.g. before sending to the backend) */
23
33
  export declare function participantIds(participants?: Participant[]): string[];
34
+ /**
35
+ * the person being helped in a support conversation: the participant NOT marked
36
+ * `role: 'agent'`. There is no separate customer entity — a support conversation is a
37
+ * conversation whose participants carry roles, and this reads the counterpart back out.
38
+ *
39
+ * Matched by inequality against `'agent'`, deliberately: the counterpart's role arrives as
40
+ * `null` from the server and is absent on a client-built draft, so anything testing for
41
+ * `undefined` specifically would hold on one path and not the other.
42
+ *
43
+ * undefined when nothing in the list distinguishes anyone. That is the legacy case
44
+ * (conversations from before roles were stamped mark nobody): with no agent marked, every
45
+ * participant looks alike, and guessing would name an agent as the person being helped.
46
+ * Callers show an unknown counterpart instead.
47
+ */
48
+ export declare function customerParticipant(participants?: Participant[]): ParticipantUser | undefined;
24
49
  /** human-readable name: "lastname, prename", else host name, else the raw id */
25
50
  export declare function participantName(participant: Participant): string;
@@ -0,0 +1,15 @@
1
+ import type { ConversationSla } from '@/interfaces/ConversationSla';
2
+ export declare const SUPPORT_STATUSES: readonly ["awaiting_agent", "awaiting_customer", "resolved"];
3
+ export type SupportStatus = typeof SUPPORT_STATUSES[number];
4
+ export type SupportStatusFilter = SupportStatus | 'all';
5
+ export interface SupportStatusResponse {
6
+ conversation: string;
7
+ status: SupportStatus;
8
+ updatedAt: string;
9
+ version: number;
10
+ sla: ConversationSla | null;
11
+ serverTime: string;
12
+ }
13
+ export declare const DEFAULT_SUPPORT_STATUS: SupportStatus;
14
+ export declare function isSupportStatus(value: unknown): value is SupportStatus;
15
+ export declare function normalizeSupportStatus(value: unknown): SupportStatus;
@@ -0,0 +1,44 @@
1
+ import type { Participant } from '@/helpers/participants';
2
+ import type { SupportStatus } from '@/helpers/supportStatus';
3
+ import type { Message } from '@/interfaces/Message';
4
+ import type { ParticipantDocument } from '@/interfaces/ParticipantDocument';
5
+ import type { ConversationSla } from '@/interfaces/ConversationSla';
6
+ export type ConversationOperationMode = 'chat' | 'support';
7
+ export interface Conversation {
8
+ _id?: string;
9
+ id?: string;
10
+ name?: string;
11
+ participants: Participant[];
12
+ blocked?: string[];
13
+ messagesCount?: number;
14
+ messagesCountSystem?: number;
15
+ createdAt?: string;
16
+ lastActivity?: string;
17
+ operationMode: ConversationOperationMode;
18
+ supportStatus?: SupportStatus;
19
+ supportStatusUpdatedAt?: string;
20
+ supportStatusVersion?: number;
21
+ sla?: ConversationSla | null;
22
+ participant?: ParticipantDocument;
23
+ participantDocs?: ParticipantDocument[];
24
+ lastMessage?: Message;
25
+ oldestMessageId?: number | null;
26
+ messages?: Message[];
27
+ messagesLoaded?: boolean;
28
+ unreadCount?: number;
29
+ unread?: boolean;
30
+ isMember?: boolean;
31
+ isNew?: boolean;
32
+ isTemp?: boolean;
33
+ creator?: string;
34
+ }
35
+ export type ConversationPayload = Omit<Conversation, '_id' | 'operationMode' | 'participants'> & {
36
+ _id: string;
37
+ operationMode?: 'default' | ConversationOperationMode;
38
+ participants?: Participant[];
39
+ };
40
+ export type SupportConversationPage = {
41
+ data: ConversationPayload[];
42
+ hasMore: boolean;
43
+ serverTime?: string;
44
+ };
@@ -0,0 +1,9 @@
1
+ import type { SupportStatus } from '@/helpers/supportStatus';
2
+ export interface ConversationSla {
3
+ conversation: string;
4
+ status: SupportStatus;
5
+ statusVersion: number;
6
+ startedAt: string;
7
+ endAt: string;
8
+ stoppedAt?: string;
9
+ }
@@ -0,0 +1,71 @@
1
+ import type { Participant } from '@/helpers/participants';
2
+ import type { SupportStatus } from '@/helpers/supportStatus';
3
+ import type { ConversationPayload } from '@/interfaces/Conversation';
4
+ import type { Message } from '@/interfaces/Message';
5
+ import type { ConversationSla } from '@/interfaces/ConversationSla';
6
+ export type ConversationNewFrame = ConversationPayload & {
7
+ type: 'conversation:new';
8
+ };
9
+ export type ConversationRenamedFrame = {
10
+ type: 'conversation:renamed';
11
+ conversation: string;
12
+ names: {
13
+ to: string;
14
+ };
15
+ };
16
+ export type ConversationParticipantsFrame = {
17
+ type: 'conversation:participants';
18
+ conversation: string;
19
+ participants: Participant[];
20
+ };
21
+ export type ConversationUserFrame = {
22
+ type: 'conversation:left';
23
+ conversation: string;
24
+ user: string;
25
+ };
26
+ export type ConversationRemovedFrame = {
27
+ type: 'conversation:removed';
28
+ conversation: string;
29
+ };
30
+ export type ConversationMutedFrame = {
31
+ type: 'conversation:muted';
32
+ conversation: string;
33
+ muted: boolean;
34
+ };
35
+ export type ConversationStatusFrame = {
36
+ type: 'conversation:status';
37
+ conversation: string;
38
+ status: SupportStatus;
39
+ version: number;
40
+ updatedAt: string;
41
+ sla: ConversationSla | null;
42
+ serverTime: string;
43
+ };
44
+ export type ConversationRightsFrame = {
45
+ type: 'conversation:rights';
46
+ conversation: string;
47
+ user: string;
48
+ rights: string[];
49
+ };
50
+ export type ConversationTypingFrame = {
51
+ type: 'conversation:typing';
52
+ conversation: string;
53
+ user: string;
54
+ typing: boolean;
55
+ };
56
+ export type UserPresenceFrame = {
57
+ type: 'user:presence';
58
+ user: string;
59
+ online: boolean;
60
+ lastSeen?: string;
61
+ };
62
+ export type ErrorFrame = {
63
+ type: 'error';
64
+ error?: unknown;
65
+ messageType?: string;
66
+ };
67
+ export type MessageFrame = Message & {
68
+ type: 'message';
69
+ };
70
+ export type IncomingFrame = ConversationNewFrame | ConversationRenamedFrame | ConversationParticipantsFrame | ConversationUserFrame | ConversationRemovedFrame | ConversationMutedFrame | ConversationStatusFrame | ConversationRightsFrame | ConversationTypingFrame | UserPresenceFrame | ErrorFrame | MessageFrame;
71
+ export declare function isIncomingFrame(value: unknown): value is IncomingFrame;
@@ -0,0 +1,16 @@
1
+ export type MessageHistory = {
2
+ created: string;
3
+ updated?: string;
4
+ };
5
+ export interface Message {
6
+ _id?: string;
7
+ id: number;
8
+ conversation: string;
9
+ user?: string;
10
+ message?: string;
11
+ origin: 'user' | 'system';
12
+ history: MessageHistory;
13
+ action?: string;
14
+ actionData?: Record<string, unknown>;
15
+ isUser?: boolean;
16
+ }
@@ -0,0 +1,13 @@
1
+ export type ParticipantState = 'active' | 'left' | 'removed' | 'blocked' | 'deleted';
2
+ export interface ParticipantDocument {
3
+ _id?: string;
4
+ conversation: string;
5
+ user: string;
6
+ state: ParticipantState;
7
+ rights: string[];
8
+ lastReadId?: number;
9
+ latestMessageId?: number;
10
+ muted?: boolean;
11
+ role?: 'agent';
12
+ joinedAt?: string;
13
+ }
@@ -1,4 +1,9 @@
1
1
  import { type AxiosResponse, type AxiosRequestConfig } from 'axios';
2
+ import type { SupportStatus, SupportStatusResponse } from '@/helpers/supportStatus';
3
+ import type { ConversationPayload, SupportConversationPage } from '@/interfaces/Conversation';
4
+ import type { Message } from '@/interfaces/Message';
5
+ import type { ParticipantDocument } from '@/interfaces/ParticipantDocument';
6
+ import type { ChatUser } from '@/config/users';
2
7
  type HttpStatusCode = number;
3
8
  export type SDKResponse<T> = {
4
9
  data: T;
@@ -74,9 +79,9 @@ export default class StudioSDK {
74
79
  private getHeaders;
75
80
  static getCacheKeyMock(url: string): string;
76
81
  static getCacheKey(url: string): string;
77
- static getCache(): Record<string, SDKResponse<any> & SDKCache>;
78
- static handleCall<T, D = any>(call: AxiosRequestConfig<D>, options?: SDKCallOptions): Promise<SDKResponse<T>>;
79
- static cache<T>(url: string, response?: AxiosResponse<T>, options?: SDKCallOptions): SDKResponse<any> & SDKCache;
82
+ static getCache(): Record<string, SDKResponse<unknown> & SDKCache>;
83
+ static handleCall<T, D = unknown>(call: AxiosRequestConfig<D>, options?: SDKCallOptions): Promise<SDKResponse<T>>;
84
+ static cache<T>(url: string, response?: AxiosResponse<T>, options?: SDKCallOptions): SDKResponse<T> & SDKCache;
80
85
  static flushCache(group?: string, action?: string): void;
81
86
  /**
82
87
  * one id can hold several entries (one per query string, e.g. every `beforeId` page of a
@@ -85,36 +90,56 @@ export default class StudioSDK {
85
90
  */
86
91
  static flushId(id: string): void;
87
92
  conversations: {
88
- list: () => Promise<SDKResponse<any>>;
89
- activate: () => Promise<SDKResponse<any>>;
93
+ list: () => Promise<SDKResponse<ConversationPayload[]>>;
94
+ activate: () => Promise<SDKResponse<unknown>>;
90
95
  create: (data: {
91
96
  participants: string[];
92
- }) => Promise<SDKResponse<any>>;
93
- rename: (conversationId: string, name: string) => Promise<SDKResponse<any>>;
94
- participants: (conversationId: string, add: string[], remove: string[]) => Promise<SDKResponse<any>>;
95
- leave: (conversationId: string) => Promise<SDKResponse<any>>;
97
+ }) => Promise<SDKResponse<unknown>>;
98
+ rename: (conversationId: string, name: string) => Promise<SDKResponse<unknown>>;
99
+ participants: (conversationId: string, add: string[], remove: string[]) => Promise<SDKResponse<unknown>>;
100
+ leave: (conversationId: string) => Promise<SDKResponse<unknown>>;
96
101
  /**
97
102
  * POST, not DELETE: this removes the conversation for the CALLER only (their participant
98
103
  * state goes to 'deleted' server-side), it does not delete the resource for everyone.
99
104
  */
100
- delete: (conversationId: string) => Promise<SDKResponse<any>>;
101
- listParticipants: (conversationId: string) => Promise<SDKResponse<any>>;
102
- rights: (conversationId: string, user: string, rights: string[]) => Promise<SDKResponse<any>>;
105
+ delete: (conversationId: string) => Promise<SDKResponse<unknown>>;
106
+ listParticipants: (conversationId: string) => Promise<SDKResponse<ParticipantDocument[]>>;
107
+ rights: (conversationId: string, user: string, rights: string[]) => Promise<SDKResponse<unknown>>;
103
108
  /**
104
109
  * silence the conversation for the CALLER only. Stored on their participant doc and never
105
110
  * broadcast to the other members — muting is private.
106
111
  */
107
- mute: (conversationId: string, muted: boolean) => Promise<SDKResponse<any>>;
108
- block: (conversationId: string, user: string, block: boolean) => Promise<SDKResponse<any>>;
112
+ mute: (conversationId: string, muted: boolean) => Promise<SDKResponse<unknown>>;
113
+ block: (conversationId: string, user: string, block: boolean) => Promise<SDKResponse<unknown>>;
109
114
  };
110
115
  contacts: {
111
- list: (search?: string) => Promise<SDKResponse<any>>;
112
- single: (contactId: string) => Promise<SDKResponse<any>>;
113
- block: (contactId: string) => Promise<SDKResponse<any>>;
114
- unblock: (contactId: string) => Promise<SDKResponse<any>>;
116
+ list: (search?: string) => Promise<SDKResponse<ChatUser[]>>;
117
+ single: (contactId: string) => Promise<SDKResponse<ChatUser>>;
118
+ block: (contactId: string) => Promise<SDKResponse<unknown>>;
119
+ unblock: (contactId: string) => Promise<SDKResponse<unknown>>;
115
120
  };
116
121
  messages: {
117
- list: (conversation: string, beforeId?: number) => Promise<SDKResponse<any>>;
122
+ list: (conversation: string, beforeId?: number) => Promise<SDKResponse<Message[]>>;
123
+ };
124
+ support: {
125
+ /**
126
+ * every support conversation the staff can see, newest activity first. Mirrors
127
+ * conversations.list() for the agent side. Keyset pagination — pass the last row's
128
+ * `lastActivity` as `before` and its `_id` as `beforeId`.
129
+ *
130
+ * Its own cache GROUP on purpose, even though the action is now also called 'list'.
131
+ * deleteConversation() and setMuted() flush ('conversations','list') to drop a stale
132
+ * customer list; if this shared that group a flush would take it with it — and, worse, this
133
+ * loader's own reload() flushing 'conversations' would throw away a list the agent console
134
+ * never even loads.
135
+ */
136
+ list: (options?: {
137
+ limit?: number;
138
+ before?: string;
139
+ beforeId?: string;
140
+ status?: SupportStatus;
141
+ }) => Promise<SDKResponse<SupportConversationPage>>;
142
+ setStatus: (conversationId: string, status: SupportStatus, version: number) => Promise<SDKResponse<SupportStatusResponse>>;
118
143
  };
119
144
  health: {
120
145
  health: () => Promise<SDKResponse<void>>;
@@ -1,4 +1,5 @@
1
1
  import type { UseWebSocketOptions } from '@/libs/websocketManager';
2
+ import { type IncomingFrame } from '@/interfaces/IncomingFrame';
2
3
  /**
3
4
  * Session layer on top of the raw websocket transport.
4
5
  *
@@ -32,7 +33,7 @@ export interface ChatSessionOptions {
32
33
  /** the current user id — used to recognize server echoes of own messages */
33
34
  ownUserId?: () => string | undefined;
34
35
  /** domain frames (messages, conversation events) — session frames are filtered out */
35
- onMessage?: (_frame: Record<string, any>) => void;
36
+ onMessage?: (_frame: IncomingFrame) => void;
36
37
  onStateChange?: (_state: SessionState) => void;
37
38
  /** the session became ready again after a loss — the moment to resync missed data */
38
39
  onSessionRestored?: () => void;
@@ -6,8 +6,25 @@ declare const _default: {
6
6
  retry: string;
7
7
  'new chat': string;
8
8
  conversations: string;
9
+ 'no conversations yet': string;
9
10
  'contact support': string;
10
11
  support: string;
12
+ customer: string;
13
+ customers: string;
14
+ agents: string;
15
+ 'load more': string;
16
+ supportStatus: {
17
+ label: string;
18
+ filter: string;
19
+ all: string;
20
+ awaiting_agent: string;
21
+ awaiting_customer: string;
22
+ resolved: string;
23
+ };
24
+ sla: {
25
+ due: string;
26
+ overdue: string;
27
+ };
11
28
  options: string;
12
29
  actions: string;
13
30
  mute: string;
@@ -25,6 +42,14 @@ declare const _default: {
25
42
  close: string;
26
43
  rights: string;
27
44
  members: string;
45
+ 'user details': string;
46
+ 'first name': string;
47
+ 'last name': string;
48
+ email: string;
49
+ online: string;
50
+ offline: string;
51
+ 'last seen': string;
52
+ back: string;
28
53
  'update members': string;
29
54
  read: string;
30
55
  write: string;
@@ -64,6 +89,7 @@ declare const _default: {
64
89
  CONVERSATION_NOT_FOUND: string;
65
90
  CONVERSATION_ALREADY_EXISTS: string;
66
91
  MIN_PARTICIPANTS: string;
92
+ SUPPORT_UNAVAILABLE: string;
67
93
  CONTACT_NOT_FOUND: string;
68
94
  CANNOT_BLOCK_SELF: string;
69
95
  UNKNOWN_MESSAGE_TYPE: string;
@@ -6,8 +6,25 @@ declare const _default: {
6
6
  retry: string;
7
7
  'new chat': string;
8
8
  conversations: string;
9
+ 'no conversations yet': string;
9
10
  'contact support': string;
10
11
  support: string;
12
+ customer: string;
13
+ customers: string;
14
+ agents: string;
15
+ 'load more': string;
16
+ supportStatus: {
17
+ label: string;
18
+ filter: string;
19
+ all: string;
20
+ awaiting_agent: string;
21
+ awaiting_customer: string;
22
+ resolved: string;
23
+ };
24
+ sla: {
25
+ due: string;
26
+ overdue: string;
27
+ };
11
28
  options: string;
12
29
  actions: string;
13
30
  mute: string;
@@ -25,6 +42,14 @@ declare const _default: {
25
42
  close: string;
26
43
  rights: string;
27
44
  members: string;
45
+ 'user details': string;
46
+ 'first name': string;
47
+ 'last name': string;
48
+ email: string;
49
+ online: string;
50
+ offline: string;
51
+ 'last seen': string;
52
+ back: string;
28
53
  'update members': string;
29
54
  read: string;
30
55
  write: string;
@@ -64,6 +89,7 @@ declare const _default: {
64
89
  CONVERSATION_NOT_FOUND: string;
65
90
  CONVERSATION_ALREADY_EXISTS: string;
66
91
  MIN_PARTICIPANTS: string;
92
+ SUPPORT_UNAVAILABLE: string;
67
93
  CONTACT_NOT_FOUND: string;
68
94
  CANNOT_BLOCK_SELF: string;
69
95
  UNKNOWN_MESSAGE_TYPE: string;
@@ -1 +1,14 @@
1
- export default function groupMessages(messages: any, user: string): unknown[];
1
+ import type { Message } from '@/interfaces/Message';
2
+ type MessageGroup = {
3
+ user?: string;
4
+ origin: Message['origin'];
5
+ time: string;
6
+ isUser: boolean;
7
+ messages: Message[];
8
+ };
9
+ type MessageDateGroup = {
10
+ date: string;
11
+ userTimeGroups: MessageGroup[];
12
+ };
13
+ export default function groupMessages(messages: Message[], user: string | undefined): MessageDateGroup[];
14
+ export {};
@@ -10,8 +10,25 @@ declare const i18n: import("vue-i18n").I18n<{
10
10
  retry: string;
11
11
  'new chat': string;
12
12
  conversations: string;
13
+ 'no conversations yet': string;
13
14
  'contact support': string;
14
15
  support: string;
16
+ customer: string;
17
+ customers: string;
18
+ agents: string;
19
+ 'load more': string;
20
+ supportStatus: {
21
+ label: string;
22
+ filter: string;
23
+ all: string;
24
+ awaiting_agent: string;
25
+ awaiting_customer: string;
26
+ resolved: string;
27
+ };
28
+ sla: {
29
+ due: string;
30
+ overdue: string;
31
+ };
15
32
  options: string;
16
33
  actions: string;
17
34
  mute: string;
@@ -29,6 +46,14 @@ declare const i18n: import("vue-i18n").I18n<{
29
46
  close: string;
30
47
  rights: string;
31
48
  members: string;
49
+ 'user details': string;
50
+ 'first name': string;
51
+ 'last name': string;
52
+ email: string;
53
+ online: string;
54
+ offline: string;
55
+ 'last seen': string;
56
+ back: string;
32
57
  'update members': string;
33
58
  read: string;
34
59
  write: string;
@@ -68,6 +93,7 @@ declare const i18n: import("vue-i18n").I18n<{
68
93
  CONVERSATION_NOT_FOUND: string;
69
94
  CONVERSATION_ALREADY_EXISTS: string;
70
95
  MIN_PARTICIPANTS: string;
96
+ SUPPORT_UNAVAILABLE: string;
71
97
  CONTACT_NOT_FOUND: string;
72
98
  CANNOT_BLOCK_SELF: string;
73
99
  UNKNOWN_MESSAGE_TYPE: string;
@@ -1,38 +1,21 @@
1
1
  import type { ParticipantUser } from '@/helpers/participants';
2
2
  import type { StandaloneSettings } from './settings';
3
+ /** Keep post-login navigation on this deployment's origin. */
4
+ export declare function resolveDestination(target?: string): string;
3
5
  export declare class StandaloneAuth {
4
6
  private client?;
5
7
  private dev;
6
8
  private devToken?;
7
9
  private profile?;
8
10
  private get origin();
9
- /** the Auth0 client, guaranteed to exist. Every caller runs after a non-dev init(). */
10
- private get auth0();
11
- /**
12
- * Bring the page into an authenticated state.
13
- *
14
- * Handles the redirect callback, then either resolves (authenticated) or navigates away to
15
- * Auth0 (not authenticated). Resolves `false` when the browser is being redirected, so the
16
- * caller knows not to mount anything.
17
- */
11
+ private get keycloak();
12
+ /** Bring the page into an authenticated Keycloak session. */
18
13
  init(settings: StandaloneSettings): Promise<boolean>;
19
- /**
20
- * Complete the Auth0 redirect: exchange the code, then rewrite the URL back to wherever the
21
- * user came from. A single pathname check replaces a router — the shell has no other routes.
22
- */
23
- private handleCallback;
24
- /**
25
- * A currently-valid access token. Handed to the chat as `getToken`, so every WS (re)auth and
26
- * every HTTP call resolves a fresh one; auth0-spa-js owns the cache and the refresh.
27
- */
14
+ /** Resolve a valid access token; Keycloak refreshes it when it expires within 30 seconds. */
28
15
  getToken(): Promise<string>;
29
- /**
30
- * The current user's own profile. The backend enriches other participants but not the
31
- * requesting user, so the chat needs this to render our own name. Taken from the id-token
32
- * claims — no /me endpoint required.
33
- */
34
16
  getProfile(): ParticipantUser | undefined;
35
17
  private loadProfile;
18
+ private restoreLoginTarget;
36
19
  logout(): void;
37
20
  }
38
21
  declare const _default: StandaloneAuth;
@@ -1,9 +1,10 @@
1
1
  import type { Feature } from '@/stores/main.store';
2
- /** Auth0 SPA client settings. Mirrors the `auth0` key of studio-app's settings.json. */
3
- export interface StandaloneAuth0Settings {
4
- domain: string;
2
+ import type { SupportAgentConfig } from '@/config/bootstrap.agent';
3
+ /** Keycloak SPA client settings. Mirrors the `keycloak` key of studio-app's settings.json. */
4
+ export interface StandaloneKeycloakSettings {
5
+ url: string;
6
+ realm: string;
5
7
  clientId: string;
6
- audience?: string;
7
8
  }
8
9
  /**
9
10
  * Runtime configuration of a standalone deployment, served as a plain file next to the
@@ -11,18 +12,19 @@ export interface StandaloneAuth0Settings {
11
12
  * configured per domain. Same file path and shape as studio-app so ops handling is identical.
12
13
  */
13
14
  export interface StandaloneSettings {
14
- /** dev bypass: skip Auth0 entirely and use `devToken`. Mirrors studio-app's `settings.dev`. */
15
+ /** dev bypass: skip Keycloak entirely and use `devToken`. Mirrors studio-app's `settings.dev`. */
15
16
  dev?: boolean;
16
17
  /** the token handed to the chat when `dev` is set. Pair with the backend's ENV=dev / DEV_USER. */
17
18
  devToken?: string;
18
- /** Auth0 client. Omitted the built-in lilaquadrat defaults are used. */
19
- auth0?: StandaloneAuth0Settings;
19
+ /** Keycloak public client. Required outside dev mode. */
20
+ keycloak?: StandaloneKeycloakSettings;
20
21
  /** passed straight into the chat element's config */
21
22
  chat: {
22
23
  features?: Feature[];
23
24
  wsUrl?: string;
24
25
  apiUrl?: string;
25
26
  mediaUrl?: string;
27
+ /** @deprecated ignored — the backend owns the support team, see ChatModuleConfig.support */
26
28
  support?: {
27
29
  participants: string[];
28
30
  };
@@ -37,6 +39,25 @@ export interface StandaloneSettings {
37
39
  export declare const SETTINGS_URL = "/settings/settings.json";
38
40
  /**
39
41
  * Load the deployment settings. Always uncached — the file is edited in place on the
40
- * server and a stale copy would point the app at the wrong backend or Auth0 client.
42
+ * server and a stale copy would point the app at the wrong backend or Keycloak client.
41
43
  */
42
44
  export default function loadSettings(): Promise<StandaloneSettings>;
45
+ /** the endpoint-ish fields of `chat` the support-agent element accepts. */
46
+ export type SupportAgentEndpoints = Pick<SupportAgentConfig, 'wsUrl' | 'apiUrl' | 'mediaUrl' | 'sound'>;
47
+ /**
48
+ * Narrow the settings' `chat` section to what <lilaquadrat-studio-support> accepts.
49
+ *
50
+ * The same settings.json shape serves both deployments, so the agent shell reads a `chat` section
51
+ * that may legitimately carry customer-only keys. This picks fields EXPLICITLY rather than
52
+ * spreading, and the two it drops are dropped on purpose:
53
+ *
54
+ * - `features`: the agent bundle decides its own mode — applySupportAgentConfig forces
55
+ * ['support']. A host-supplied `features` reaching the console is exactly the confusion
56
+ * `appRole` exists to prevent (a support console rendering the customer's chat header).
57
+ * - `support: { participants }`: already deprecated and ignored — the backend owns the support
58
+ * team (everyone holding the `support:member` scope), so a client-side list can only drift.
59
+ *
60
+ * A spread would smuggle both past SupportAgentConfig's excess-property check, since the check
61
+ * only fires on object literals, not on spread-in values.
62
+ */
63
+ export declare function supportAgentEndpoints(settings: StandaloneSettings): SupportAgentEndpoints;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,13 +1,13 @@
1
1
  export declare const useCallStore: import("pinia").StoreDefinition<"calls", Pick<{
2
- calls: import("vue").Ref<Record<string, "rejected" | "pending" | "resolved">, Record<string, "rejected" | "pending" | "resolved">>;
2
+ calls: import("vue").Ref<Record<string, "resolved" | "rejected" | "pending">, Record<string, "resolved" | "rejected" | "pending">>;
3
3
  addCall: () => string;
4
4
  updateCall: (id: string, state: "pending" | "resolved" | "rejected") => void;
5
5
  }, "calls">, Pick<{
6
- calls: import("vue").Ref<Record<string, "rejected" | "pending" | "resolved">, Record<string, "rejected" | "pending" | "resolved">>;
6
+ calls: import("vue").Ref<Record<string, "resolved" | "rejected" | "pending">, Record<string, "resolved" | "rejected" | "pending">>;
7
7
  addCall: () => string;
8
8
  updateCall: (id: string, state: "pending" | "resolved" | "rejected") => void;
9
9
  }, never>, Pick<{
10
- calls: import("vue").Ref<Record<string, "rejected" | "pending" | "resolved">, Record<string, "rejected" | "pending" | "resolved">>;
10
+ calls: import("vue").Ref<Record<string, "resolved" | "rejected" | "pending">, Record<string, "resolved" | "rejected" | "pending">>;
11
11
  addCall: () => string;
12
12
  updateCall: (id: string, state: "pending" | "resolved" | "rejected") => void;
13
13
  }, "addCall" | "updateCall">>;