@ezychat/web 0.1.46 → 0.1.48

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 (40) hide show
  1. package/dist-lib/chunks/admin-CpYxtKzJ.js +694 -0
  2. package/dist-lib/chunks/admin-Da2uR7mY.js +695 -0
  3. package/dist-lib/chunks/{app-C2A7ZZsu.js → app-3jWCMPbu.js} +3 -1
  4. package/dist-lib/chunks/{app-RX8Fy2Oz.js → app-Diwr0AD0.js} +3 -1
  5. package/dist-lib/chunks/{inbox-DccyncVL.js → inbox-DtLIGOCo.js} +29 -14
  6. package/dist-lib/chunks/{inbox-Bdg6faLa.js → inbox-u9BCZ1IH.js} +29 -14
  7. package/dist-lib/ezychat-web.css +1 -1
  8. package/dist-lib/index.js +10987 -4997
  9. package/dist-lib/types/admin/AdminLayout.d.ts +14 -1
  10. package/dist-lib/types/admin/AiContextPanel.d.ts +10 -5
  11. package/dist-lib/types/admin/AiEditDialog.d.ts +6 -2
  12. package/dist-lib/types/admin/AiMemberPage.d.ts +6 -0
  13. package/dist-lib/types/admin/AiTryIt.d.ts +7 -2
  14. package/dist-lib/types/admin/InboxAccess.d.ts +9 -0
  15. package/dist-lib/types/admin/InboxesPage.d.ts +3 -0
  16. package/dist-lib/types/admin/PresetBadge.d.ts +8 -0
  17. package/dist-lib/types/admin/agent-path.d.ts +6 -0
  18. package/dist-lib/types/admin/ai-status.d.ts +15 -1
  19. package/dist-lib/types/admin/inbox-status.d.ts +16 -0
  20. package/dist-lib/types/api/ai.d.ts +194 -6
  21. package/dist-lib/types/api/inbox-mutations.d.ts +70 -0
  22. package/dist-lib/types/api/queries.d.ts +78 -3
  23. package/dist-lib/types/extensions/agent-section.d.ts +18 -0
  24. package/dist-lib/types/extensions/index.d.ts +1 -0
  25. package/dist-lib/types/extensions/types.d.ts +1 -1
  26. package/dist-lib/types/i18n/resources.d.ts +222 -3
  27. package/dist-lib/types/inbox/ChatFilters.d.ts +4 -1
  28. package/dist-lib/types/inbox/ChatListItem.d.ts +4 -2
  29. package/dist-lib/types/inbox/ConversationHeader.d.ts +4 -2
  30. package/dist-lib/types/inbox/InboxChip.d.ts +6 -0
  31. package/dist-lib/types/inbox/WaBanner.d.ts +6 -1
  32. package/dist-lib/types/inbox/useDirectory.d.ts +26 -4
  33. package/dist-lib/types/inbox/useVisibleInboxes.d.ts +12 -0
  34. package/dist-lib/types/index.d.ts +1 -1
  35. package/dist-lib/types/lib/whatsapp-format.d.ts +5 -0
  36. package/dist-lib/types/setup/AiAssistantStep.d.ts +3 -2
  37. package/dist-lib/types/wa/PhoneLink.d.ts +7 -2
  38. package/package.json +2 -2
  39. package/dist-lib/chunks/admin-CO4a2wgk.js +0 -620
  40. package/dist-lib/chunks/admin-DviFuAwJ.js +0 -621
@@ -1,11 +1,13 @@
1
1
  import { type InfiniteData, type QueryClient } from '@tanstack/react-query';
2
- import { type CreateApiTokenBodyInput, type UpdateApiTokenBody, type Chat, type ChatListResponse, type ChatStatus, type Message, type MessageListResponse, type PatchUserBody, type Settings, type User } from '@ezychat/shared';
2
+ import { type CreateApiTokenBodyInput, type UpdateApiTokenBody, type Chat, type ChatListResponse, type ChatStatus, type DirectoryUser, type InboxStatusPayload, type Message, type MessageListResponse, type PatchUserBody, type Settings, type WaStatus } from '@ezychat/shared';
3
3
  export interface ChatFilters {
4
4
  status?: ChatStatus;
5
5
  assigned: 'me' | 'none' | 'any';
6
6
  q?: string;
7
7
  /** customer tag filter */
8
8
  tag?: string;
9
+ /** One inbox (multi-inbox); unset = every inbox the user may open. */
10
+ inbox?: number;
9
11
  }
10
12
  export declare const qk: {
11
13
  me: readonly ["me"];
@@ -24,6 +26,7 @@ export declare const qk: {
24
26
  users: readonly ["users"];
25
27
  directory: readonly ["users", "directory"];
26
28
  wa: readonly ["wa"];
29
+ inboxes: readonly ["inboxes"];
27
30
  tunnel: readonly ["tunnel"];
28
31
  cloudflareSetup: readonly ["cloudflare-setup"];
29
32
  settings: readonly ["settings"];
@@ -65,6 +68,9 @@ export declare function useMe(): import("@tanstack/react-query").UseQueryResult<
65
68
  locale: "en" | "ms" | "zh-CN" | null;
66
69
  kind?: "human" | "ai" | undefined;
67
70
  aiRole?: "sales" | undefined;
71
+ aiAgentId?: number | undefined;
72
+ aiDeleted?: boolean | undefined;
73
+ inboxIds?: number[] | undefined;
68
74
  } | null, Error>;
69
75
  export declare function useSetupStatus(): import("@tanstack/react-query").UseQueryResult<{
70
76
  needsSetup: boolean;
@@ -86,6 +92,9 @@ export declare function useLogin(): import("@tanstack/react-query").UseMutationR
86
92
  locale: "en" | "ms" | "zh-CN" | null;
87
93
  kind?: "human" | "ai" | undefined;
88
94
  aiRole?: "sales" | undefined;
95
+ aiAgentId?: number | undefined;
96
+ aiDeleted?: boolean | undefined;
97
+ inboxIds?: number[] | undefined;
89
98
  } | null, Error, {
90
99
  username: string;
91
100
  password: string;
@@ -108,6 +117,9 @@ export declare function useSetMyLocale(): import("@tanstack/react-query").UseMut
108
117
  locale: "en" | "ms" | "zh-CN" | null;
109
118
  kind?: "human" | "ai" | undefined;
110
119
  aiRole?: "sales" | undefined;
120
+ aiAgentId?: number | undefined;
121
+ aiDeleted?: boolean | undefined;
122
+ inboxIds?: number[] | undefined;
111
123
  }, Error, "en" | "ms" | "zh-CN" | null, unknown>;
112
124
  export declare function useChangePassword(): import("@tanstack/react-query").UseMutationResult<unknown, Error, {
113
125
  currentPassword: string;
@@ -116,6 +128,8 @@ export declare function useChangePassword(): import("@tanstack/react-query").Use
116
128
  export declare function useChats(filters: ChatFilters): import("@tanstack/react-query").UseInfiniteQueryResult<InfiniteData<{
117
129
  chats: {
118
130
  jid: string;
131
+ inboxId: number;
132
+ waJid: string;
119
133
  type: "dm" | "group";
120
134
  name: string;
121
135
  avatarUrl: string | null;
@@ -134,6 +148,8 @@ export declare function useChats(filters: ChatFilters): import("@tanstack/react-
134
148
  export declare function useChat(jid: string | null | undefined): import("@tanstack/react-query").UseQueryResult<{
135
149
  chat: {
136
150
  jid: string;
151
+ inboxId: number;
152
+ waJid: string;
137
153
  type: "dm" | "group";
138
154
  name: string;
139
155
  avatarUrl: string | null;
@@ -300,6 +316,8 @@ export declare function useRetryMessage(): import("@tanstack/react-query").UseMu
300
316
  }, Error, string, unknown>;
301
317
  export declare function usePatchChat(jid: string): import("@tanstack/react-query").UseMutationResult<{
302
318
  jid: string;
319
+ inboxId: number;
320
+ waJid: string;
303
321
  type: "dm" | "group";
304
322
  name: string;
305
323
  avatarUrl: string | null;
@@ -448,9 +466,12 @@ export declare function useUsers(opts?: {
448
466
  locale: "en" | "ms" | "zh-CN" | null;
449
467
  kind?: "human" | "ai" | undefined;
450
468
  aiRole?: "sales" | undefined;
469
+ aiAgentId?: number | undefined;
470
+ aiDeleted?: boolean | undefined;
471
+ inboxIds?: number[] | undefined;
451
472
  }[], Error>;
452
473
  /** Public team-member fields every logged-in user may see (`GET /api/users/directory`). */
453
- export type DirectoryUser = Pick<User, 'id' | 'displayName' | 'role' | 'disabled' | 'kind' | 'aiRole'>;
474
+ export type { DirectoryUser };
454
475
  /**
455
476
  * Team directory for every role (agents included). Needs the server route
456
477
  * `GET /api/users/directory`; when it is missing (404) or forbidden, resolves to an empty list
@@ -458,7 +479,17 @@ export type DirectoryUser = Pick<User, 'id' | 'displayName' | 'role' | 'disabled
458
479
  */
459
480
  export declare function useUserDirectory(opts?: {
460
481
  enabled?: boolean;
461
- }): import("@tanstack/react-query").UseQueryResult<DirectoryUser[], Error>;
482
+ }): import("@tanstack/react-query").UseQueryResult<{
483
+ id: number;
484
+ displayName: string;
485
+ role: "admin" | "agent";
486
+ disabled: boolean;
487
+ inboxIds: "all" | number[];
488
+ kind?: "human" | "ai" | undefined;
489
+ aiRole?: "sales" | undefined;
490
+ aiAgentId?: number | undefined;
491
+ aiDeleted?: boolean | undefined;
492
+ }[], Error>;
462
493
  export declare function useCreateUser(): import("@tanstack/react-query").UseMutationResult<{
463
494
  id: number;
464
495
  username: string;
@@ -470,6 +501,9 @@ export declare function useCreateUser(): import("@tanstack/react-query").UseMuta
470
501
  locale: "en" | "ms" | "zh-CN" | null;
471
502
  kind?: "human" | "ai" | undefined;
472
503
  aiRole?: "sales" | undefined;
504
+ aiAgentId?: number | undefined;
505
+ aiDeleted?: boolean | undefined;
506
+ inboxIds?: number[] | undefined;
473
507
  }, Error, {
474
508
  username: string;
475
509
  displayName: string;
@@ -487,6 +521,9 @@ export declare function usePatchUser(): import("@tanstack/react-query").UseMutat
487
521
  locale: "en" | "ms" | "zh-CN" | null;
488
522
  kind?: "human" | "ai" | undefined;
489
523
  aiRole?: "sales" | undefined;
524
+ aiAgentId?: number | undefined;
525
+ aiDeleted?: boolean | undefined;
526
+ inboxIds?: number[] | undefined;
490
527
  }, Error, {
491
528
  id: number;
492
529
  patch: PatchUserBody;
@@ -507,6 +544,44 @@ export declare function useWaStatus(opts?: {
507
544
  qr: string | null;
508
545
  lastError: string | null;
509
546
  }, Error>;
547
+ /** The inbox 1 number (the number linked before multi-inbox). */
548
+ export declare const PRIMARY_INBOX_ID = 1;
549
+ /**
550
+ * The inboxes the signed-in user may open (`GET /api/inboxes`; the server filters them). A server
551
+ * without the route (404) counts as one inbox, so no inbox UI shows.
552
+ */
553
+ export declare function useInboxes(opts?: {
554
+ enabled?: boolean;
555
+ }): import("@tanstack/react-query").UseQueryResult<{
556
+ inboxes: {
557
+ id: number;
558
+ name: string;
559
+ tone: "success" | "primary" | "warning" | "info";
560
+ number: string | null;
561
+ status: {
562
+ state: "open" | "qr" | "disconnected" | "connecting" | "logged_out" | "replaced" | "blocked";
563
+ me: {
564
+ jid: string;
565
+ name: string | null;
566
+ lid?: string | null | undefined;
567
+ } | null;
568
+ qr: string | null;
569
+ lastError: string | null;
570
+ };
571
+ removed: boolean;
572
+ aiAgentId: number | null;
573
+ memberIds?: number[] | undefined;
574
+ }[];
575
+ maxInboxes: number;
576
+ canAdd: boolean;
577
+ }, Error>;
578
+ /** Applies a socket `inbox:status` to the cached inbox list. */
579
+ export declare function patchInboxStatusInCache(qc: QueryClient, p: InboxStatusPayload): void;
580
+ /**
581
+ * Connection status of one inbox. Inbox 1 reads `GET /api/wa/status` as before (Lite unchanged);
582
+ * other inboxes read the inbox list, which `inbox:status` keeps current.
583
+ */
584
+ export declare function useInboxStatus(inboxId: number | undefined): WaStatus | undefined;
510
585
  export type WaAction = 'logout' | 'relink' | 'takeover';
511
586
  export declare function useWaAction(): import("@tanstack/react-query").UseMutationResult<unknown, Error, WaAction, unknown>;
512
587
  /** Link by phone number: returns the 8-character code to enter in WhatsApp → Linked devices. */
@@ -0,0 +1,18 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { AiAgentPreset } from '@ezychat/shared';
3
+ /** The AI agent whose page an extension section (`agentSections`) is rendered on. */
4
+ export interface AgentSectionInfo {
5
+ agentId: number;
6
+ displayName: string;
7
+ preset: AiAgentPreset;
8
+ }
9
+ /** Wraps the extension sections of one agent page (core use only). */
10
+ export declare function AgentSectionProvider({ value, children, }: {
11
+ value: AgentSectionInfo;
12
+ children: ReactNode;
13
+ }): import("react").JSX.Element;
14
+ /**
15
+ * Inside an `agentSections` element: the agent whose page shows it (id, saved name and preset).
16
+ * Null anywhere else.
17
+ */
18
+ export declare function useAgentSection(): AgentSectionInfo | null;
@@ -2,3 +2,4 @@ export * from './types';
2
2
  export { WebExtensionsProvider, useWebExtensions } from './context';
3
3
  export { registerExtensionCatalogs, useExtensionTranslation, type ExtensionTranslate, } from './i18n';
4
4
  export { ExtensionBoundary, extensionRoutes } from './routes';
5
+ export { AgentSectionProvider, useAgentSection, type AgentSectionInfo } from './agent-section';
@@ -36,7 +36,7 @@ export interface WebExtensionRoute {
36
36
  section?: WebExtensionAdminSection;
37
37
  }
38
38
  /** Core admin sections an extension admin route may sit under (the `ADMIN_NAV` paths). */
39
- export declare const WEB_EXTENSION_ADMIN_SECTIONS: readonly ["members", "quick-replies", "whatsapp", "tunnel", "settings", "audit"];
39
+ export declare const WEB_EXTENSION_ADMIN_SECTIONS: readonly ["members", "quick-replies", "whatsapp", "inboxes", "tunnel", "settings", "audit"];
40
40
  export type WebExtensionAdminSection = (typeof WEB_EXTENSION_ADMIN_SECTIONS)[number];
41
41
  /** A small badge on an admin nav link: a count, or a dot that asks for attention. */
42
42
  export interface WebExtensionNavBadge {
@@ -149,6 +149,8 @@ export declare const enResources: {
149
149
  noInstallerFeed: string;
150
150
  unverifiedFeed: string;
151
151
  releaseNotes: string;
152
+ whatsNew: string;
153
+ updatedTo: string;
152
154
  };
153
155
  share: {
154
156
  title: string;
@@ -531,6 +533,7 @@ export declare const enResources: {
531
533
  ai_unavailable: string;
532
534
  lookup_failed: string;
533
535
  business_rule: string;
536
+ confidential_leak: string;
534
537
  };
535
538
  resolved: string;
536
539
  reopenedByMessage: string;
@@ -628,6 +631,7 @@ export declare const enResources: {
628
631
  waBanner: {
629
632
  settingsShort: string;
630
633
  openSettings: string;
634
+ openInboxes: string;
631
635
  connecting: {
632
636
  title: string;
633
637
  body: string;
@@ -652,6 +656,19 @@ export declare const enResources: {
652
656
  title: string;
653
657
  body: string;
654
658
  };
659
+ inbox: {
660
+ connecting: string;
661
+ disconnected: string;
662
+ qr: string;
663
+ loggedOut: string;
664
+ replaced: string;
665
+ blocked: string;
666
+ };
667
+ };
668
+ inboxFilter: {
669
+ label: string;
670
+ all: string;
671
+ option: string;
655
672
  };
656
673
  phoneLink: {
657
674
  label: string;
@@ -994,6 +1011,13 @@ export declare const enResources: {
994
1011
  apiTokenAuthFailed: string;
995
1012
  mcpEnable: string;
996
1013
  mcpDisable: string;
1014
+ inboxCreate: string;
1015
+ inboxUpdate: string;
1016
+ inboxRemove: string;
1017
+ inboxAccessUpdate: string;
1018
+ aiAgentCreate: string;
1019
+ aiAgentDelete: string;
1020
+ aiAgentInboxUpdate: string;
997
1021
  };
998
1022
  fields: {
999
1023
  chat: string;
@@ -1033,6 +1057,12 @@ export declare const enResources: {
1033
1057
  lanEnabled: string;
1034
1058
  historyDays: string;
1035
1059
  expires: string;
1060
+ inbox: string;
1061
+ inboxes: string;
1062
+ members: string;
1063
+ agent: string;
1064
+ preset: string;
1065
+ internal: string;
1036
1066
  };
1037
1067
  reasons: {
1038
1068
  rateLimited: string;
@@ -1378,7 +1408,6 @@ export declare const enResources: {
1378
1408
  settingsTitle: string;
1379
1409
  settingsDescription: string;
1380
1410
  roleBadge: string;
1381
- addMember: string;
1382
1411
  membersDescription: string;
1383
1412
  assistant: string;
1384
1413
  behavior: string;
@@ -1478,6 +1507,14 @@ export declare const enResources: {
1478
1507
  advanced: string;
1479
1508
  advancedRecommended: string;
1480
1509
  advancedCustomised: string;
1510
+ nextSteps: {
1511
+ title: string;
1512
+ context: string;
1513
+ try: string;
1514
+ turnOn: string;
1515
+ done: string;
1516
+ todo: string;
1517
+ };
1481
1518
  };
1482
1519
  try: {
1483
1520
  label: string;
@@ -1500,6 +1537,12 @@ export declare const enResources: {
1500
1537
  noKnowledge: string;
1501
1538
  model: string;
1502
1539
  failed: string;
1540
+ agentHint: string;
1541
+ safety: string;
1542
+ answeredAs: string;
1543
+ needsConnection: string;
1544
+ noRole: string;
1545
+ confidentialLeak: string;
1503
1546
  };
1504
1547
  voice: {
1505
1548
  title: string;
@@ -1583,10 +1626,39 @@ export declare const enResources: {
1583
1626
  confirmText: string;
1584
1627
  deleteFailed: string;
1585
1628
  namesMore: string;
1629
+ internal: string;
1630
+ internalHint: string;
1631
+ internalIntro: string;
1632
+ internalBadgeTitle: string;
1633
+ internalFilterLabel: string;
1634
+ internalFilterAll: string;
1635
+ internalFilterCustomer: string;
1636
+ internalFilterInternal: string;
1637
+ internalFilterEmpty: string;
1638
+ internalAudience: string;
1639
+ internalAudienceCustomer: string;
1640
+ internalAudienceInternal: string;
1641
+ internalTotal: string;
1642
+ addFileTitle: string;
1643
+ fileLabel: string;
1644
+ itemSaved: string;
1645
+ actions: string;
1646
+ markInternal: string;
1647
+ markCustomer: string;
1648
+ markInternalFor: string;
1649
+ markCustomerFor: string;
1650
+ markedInternal: string;
1651
+ markedCustomer: string;
1586
1652
  };
1587
1653
  defaults: {
1588
- instructions: string;
1589
- handoffRules: string;
1654
+ sales: {
1655
+ instructions: string;
1656
+ handoffRules: string;
1657
+ };
1658
+ faq: {
1659
+ instructions: string;
1660
+ handoffRules: string;
1661
+ };
1590
1662
  };
1591
1663
  replaceKey: string;
1592
1664
  keepKey: string;
@@ -1653,6 +1725,92 @@ export declare const enResources: {
1653
1725
  keyForbidden: string;
1654
1726
  saveAnyway: string;
1655
1727
  };
1728
+ agents: {
1729
+ add: string;
1730
+ aiBadge: string;
1731
+ limitHint: string;
1732
+ noInbox: string;
1733
+ answersInbox: string;
1734
+ newTitle: string;
1735
+ newDescription: string;
1736
+ description: string;
1737
+ pickTitle: string;
1738
+ pickHint: string;
1739
+ nameTitle: string;
1740
+ nameLabel: string;
1741
+ nameHint: string;
1742
+ nameRequired: string;
1743
+ inboxLabel: string;
1744
+ inboxHint: string;
1745
+ inboxNone: string;
1746
+ inboxHas: string;
1747
+ inboxMove: string;
1748
+ roleTitle: string;
1749
+ roleLabel: string;
1750
+ roleHint: string;
1751
+ rolePlaceholder: string;
1752
+ handoffTitle: string;
1753
+ handoffHint: string;
1754
+ handoffPlaceholder: string;
1755
+ useTemplate: string;
1756
+ templateTitle: string;
1757
+ templateBody: string;
1758
+ templateConfirm: string;
1759
+ templateApplied: string;
1760
+ customTemplateNote: string;
1761
+ advanced: string;
1762
+ advancedBlank: string;
1763
+ usingTemplate: string;
1764
+ tryTitle: string;
1765
+ deleteTitle: string;
1766
+ deleteHint: string;
1767
+ delete: string;
1768
+ deleteConfirmTitle: string;
1769
+ deleteConfirmBody_one: string;
1770
+ deleteConfirmBody_other: string;
1771
+ deleted: string;
1772
+ created: string;
1773
+ saved: string;
1774
+ save: string;
1775
+ create: string;
1776
+ limitTitle: string;
1777
+ limitBody: string;
1778
+ limitBodyLite: string;
1779
+ backToMembers: string;
1780
+ notFoundTitle: string;
1781
+ notFoundBody: string;
1782
+ on: string;
1783
+ off: string;
1784
+ errors: {
1785
+ agent_limit: string;
1786
+ inbox_has_agent: string;
1787
+ internal_too_large: string;
1788
+ last_agent: string;
1789
+ agent_not_found: string;
1790
+ };
1791
+ noFreeInbox: string;
1792
+ addInbox: string;
1793
+ createNext: string;
1794
+ };
1795
+ presets: {
1796
+ sales: string;
1797
+ faq: string;
1798
+ custom: string;
1799
+ salesDescription: string;
1800
+ faqDescription: string;
1801
+ customDescription: string;
1802
+ badge: string;
1803
+ };
1804
+ guardrails: {
1805
+ title: string;
1806
+ badge: string;
1807
+ intro: string;
1808
+ rule1: string;
1809
+ rule2: string;
1810
+ rule3: string;
1811
+ rule4: string;
1812
+ };
1813
+ openAgents: string;
1656
1814
  };
1657
1815
  enrichment: {
1658
1816
  title: string;
@@ -1694,6 +1852,67 @@ export declare const enResources: {
1694
1852
  correction: string;
1695
1853
  };
1696
1854
  };
1855
+ inboxes: {
1856
+ title: string;
1857
+ add: string;
1858
+ emptyTitle: string;
1859
+ emptyBody: string;
1860
+ description: string;
1861
+ edit: string;
1862
+ remove: string;
1863
+ status: string;
1864
+ whoCanOpen: string;
1865
+ admin: string;
1866
+ accessHint: string;
1867
+ typeLinkedPhone: string;
1868
+ numberAfterScan: string;
1869
+ limitReached: string;
1870
+ membersField: string;
1871
+ membersFieldHint: string;
1872
+ membersFieldNoAgents: string;
1873
+ membersFieldNone: string;
1874
+ removeTitle: string;
1875
+ removeConfirm: string;
1876
+ removeBodyPhone: string;
1877
+ removed: string;
1878
+ required: string;
1879
+ saved: string;
1880
+ createdPhone: string;
1881
+ addTitle: string;
1882
+ editTitle: string;
1883
+ dialogDescription: string;
1884
+ save: string;
1885
+ name: string;
1886
+ nameHint: string;
1887
+ scanTitle: string;
1888
+ scanBody: string;
1889
+ scanSteps: string;
1890
+ linkedAs: string;
1891
+ relink: string;
1892
+ offlineTitle: string;
1893
+ offlineBody: string;
1894
+ state: {
1895
+ connected: string;
1896
+ waiting_scan: string;
1897
+ phone_offline: string;
1898
+ };
1899
+ membersAccess: string;
1900
+ membersAccessAll: string;
1901
+ membersAccessNone: string;
1902
+ membersAccessTitle: string;
1903
+ membersAccessDescription: string;
1904
+ membersAccessNoInboxes: string;
1905
+ membersAccessSave: string;
1906
+ membersAccessSaved: string;
1907
+ aiAgent: string;
1908
+ aiAgentNone: string;
1909
+ aiAgentField: string;
1910
+ aiAgentFieldHint: string;
1911
+ aiAgentOption: string;
1912
+ aiAgentMove: string;
1913
+ aiAgentReplace: string;
1914
+ aiAgentRemove: string;
1915
+ };
1697
1916
  };
1698
1917
  errors: {
1699
1918
  generic: string;
@@ -1,6 +1,9 @@
1
+ import type { Inbox } from '@ezychat/shared';
1
2
  import { type ChatFilters as Filters } from '../api/queries';
2
3
  export interface ChatFiltersProps {
3
4
  value: Filters;
4
5
  onChange(next: Filters): void;
6
+ /** The active inboxes the user may open; the inbox filter shows with two or more. */
7
+ inboxes?: readonly Inbox[];
5
8
  }
6
- export declare function ChatFilters({ value, onChange }: ChatFiltersProps): import("react").JSX.Element;
9
+ export declare function ChatFilters({ value, onChange, inboxes }: ChatFiltersProps): import("react").JSX.Element;
@@ -1,4 +1,4 @@
1
- import type { Chat } from '@ezychat/shared';
1
+ import type { Chat, Inbox } from '@ezychat/shared';
2
2
  export interface ChatListItemProps {
3
3
  chat: Chat;
4
4
  active: boolean;
@@ -6,8 +6,10 @@ export interface ChatListItemProps {
6
6
  assigneeName: string | null;
7
7
  /** The current user owns this chat: the chip gets the accent outline. */
8
8
  assignedToMe?: boolean;
9
+ /** The chat's inbox, only while the user sees two or more inboxes. */
10
+ inbox?: Pick<Inbox, 'name' | 'tone'>;
9
11
  }
10
12
  export declare function GroupIcon({ className }: {
11
13
  className?: string;
12
14
  }): import("react").JSX.Element;
13
- export declare function ChatListItem({ chat, active, assigneeName, assignedToMe, }: ChatListItemProps): import("react").JSX.Element;
15
+ export declare function ChatListItem({ chat, active, assigneeName, assignedToMe, inbox, }: ChatListItemProps): import("react").JSX.Element;
@@ -1,4 +1,4 @@
1
- import type { Chat } from '@ezychat/shared';
1
+ import type { Chat, Inbox } from '@ezychat/shared';
2
2
  import type { Directory } from './useDirectory';
3
3
  export interface ConversationHeaderProps {
4
4
  chat: Chat;
@@ -20,6 +20,8 @@ export interface ConversationHeaderProps {
20
20
  onOpenInfo?(): void;
21
21
  /** Group chats: WhatsApp's member count, shown under the name once known. */
22
22
  memberCount?: number | null;
23
+ /** The chat's inbox, only while the user sees two or more inboxes (replies leave from it). */
24
+ inbox?: Pick<Inbox, 'name' | 'tone'>;
23
25
  busy?: boolean;
24
26
  }
25
- export declare function ConversationHeader({ chat, directory, onBack, onAssign, onToggleStatus, notesOpen, notesCount, onToggleNotes, showCustomer, customerOpen, onToggleCustomer, onOpenInfo, memberCount, busy, }: ConversationHeaderProps): import("react").JSX.Element;
27
+ export declare function ConversationHeader({ chat, directory, onBack, onAssign, onToggleStatus, notesOpen, notesCount, onToggleNotes, showCustomer, customerOpen, onToggleCustomer, onOpenInfo, memberCount, inbox, busy, }: ConversationHeaderProps): import("react").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import type { Inbox } from '@ezychat/shared';
2
+ /** The inbox a chat belongs to, in that inbox's colour (shown only with two or more inboxes). */
3
+ export declare function InboxChip({ inbox, className, }: Readonly<{
4
+ inbox: Pick<Inbox, 'name' | 'tone'>;
5
+ className?: string;
6
+ }>): import("react").JSX.Element;
@@ -4,6 +4,11 @@ type WaStateName = WaStatus['state'];
4
4
  export declare function waQueuesMessages(state: WaStateName | undefined): boolean;
5
5
  /** States where sending is pointless until an admin acts (composer disabled). */
6
6
  export declare function waSendingBlocked(state: WaStateName | undefined): boolean;
7
- /** Top-of-inbox banner shown whenever the WhatsApp connection isn't open. */
7
+ /**
8
+ * Top-of-inbox banner shown whenever a WhatsApp connection isn't open. With one inbox (Lite) it is
9
+ * today's single banner; with two or more visible inboxes there is one per inbox that is not open,
10
+ * titled with that inbox's name. A user who sees one inbox other than inbox 1 gets that inbox's
11
+ * banner (named, never inbox 1's state); with several inboxes and none visible there is no banner.
12
+ */
8
13
  export declare function WaBanner(): import("react").JSX.Element | null;
9
14
  export {};
@@ -1,18 +1,40 @@
1
1
  import type { User } from '@ezychat/shared';
2
2
  import { type DirectoryUser } from '../api/queries';
3
+ /**
4
+ * A team member as the inbox knows them: the directory row (agents), or the full user (admins read
5
+ * `GET /api/users`, where `inboxIds` is set for agents only). No `inboxIds` means every inbox only
6
+ * in a single-inbox install; with several inboxes it means no inbox (fail closed).
7
+ */
8
+ export type DirectoryEntry = Omit<DirectoryUser, 'inboxIds'> & {
9
+ inboxIds?: DirectoryUser['inboxIds'];
10
+ };
11
+ /**
12
+ * The member may open chats of this inbox (admins and the AI member open every inbox). A row without
13
+ * `inboxIds` opens every inbox only when `multiInbox` is false (one inbox, no inbox UI).
14
+ */
15
+ export declare function canOpenInbox(u: DirectoryEntry, inboxId: number, multiInbox?: boolean): boolean;
3
16
  export interface Directory {
4
17
  me: User | null;
5
18
  isAdmin: boolean;
6
- byId: Map<number, DirectoryUser>;
7
- /** Users that can be picked as assignee (active only). */
8
- assignable: DirectoryUser[];
19
+ byId: Map<number, DirectoryEntry>;
20
+ /** Users that can be picked as assignee (active only; never a deleted AI agent). */
21
+ assignable: DirectoryEntry[];
22
+ /**
23
+ * The assign dropdown of a chat of this inbox: active people who may open it, and the AI agent
24
+ * that answers this inbox (no other AI agent: the server refuses it).
25
+ */
26
+ assignableFor(inboxId: number): DirectoryEntry[];
9
27
  /** Display name for a user id ("You" for the current user when `youLabel`). */
10
28
  nameOf(id: number | null | undefined, opts?: {
11
29
  youLabel?: boolean;
12
30
  }): string | null;
13
31
  }
14
32
  /** Pure builder (exported for tests). */
15
- export declare function buildDirectory(me: User | null, isAdmin: boolean, list: readonly DirectoryUser[] | undefined): Directory;
33
+ export declare function buildDirectory(me: User | null, isAdmin: boolean, list: readonly DirectoryEntry[] | undefined, opts?: {
34
+ multiInbox?: boolean;
35
+ /** Inbox id -> the AI agent that answers it (`Inbox.aiAgentId`); unknown = no AI offered. */
36
+ inboxAgents?: ReadonlyMap<number, number | null>;
37
+ }): Directory;
16
38
  /**
17
39
  * Team member lookup for the inbox. Admins use the full `GET /api/users`; every other role
18
40
  * uses the public `GET /api/users/directory` ({id, displayName, role, disabled}). Ids that are
@@ -0,0 +1,12 @@
1
+ import type { Inbox } from '@ezychat/shared';
2
+ export { useInboxStatus } from '../api/queries';
3
+ /**
4
+ * The active inboxes the signed-in user may open. The server already filters `GET /api/inboxes` by
5
+ * access, so there is no access logic here; removed inboxes (admins only) are left out.
6
+ */
7
+ export declare function useVisibleInboxes(): Inbox[];
8
+ /**
9
+ * The inbox chip of a chat: the chat's inbox while the user sees two or more inboxes, otherwise
10
+ * undefined (one inbox and Lite show no chip). Removed inboxes still name their read-only chats.
11
+ */
12
+ export declare function useInboxOfChat(): (inboxId: number) => Inbox | undefined;
@@ -3,7 +3,7 @@
3
3
  * without forking Lite or deep-importing its modules.
4
4
  */
5
5
  export { createInboxApp, type CreateInboxAppOptions } from './create-app';
6
- export { EXTENSION_NAME_PATTERN, WEB_EXTENSION_ADMIN_SECTIONS, WebExtensionError, extensionKeyPrefix, extensionPath, useExtensionTranslation, validateWebExtensions, type ExtensionTranslate, type WebExtension, type WebExtensionAdminSection, type WebExtensionAgent, type WebExtensionAgentSection, type WebExtensionCatalogs, type WebExtensionLockScreenProps, type WebExtensionNavBadge, type WebExtensionNavItem, type WebExtensionRoute, type WebExtensionSettingsSection, } from './extensions';
6
+ export { EXTENSION_NAME_PATTERN, WEB_EXTENSION_ADMIN_SECTIONS, WebExtensionError, extensionKeyPrefix, extensionPath, useAgentSection, useExtensionTranslation, validateWebExtensions, type AgentSectionInfo, type ExtensionTranslate, type WebExtension, type WebExtensionAdminSection, type WebExtensionAgent, type WebExtensionAgentSection, type WebExtensionCatalogs, type WebExtensionLockScreenProps, type WebExtensionNavBadge, type WebExtensionNavItem, type WebExtensionRoute, type WebExtensionSettingsSection, } from './extensions';
7
7
  export { useAppLinks } from './lib/app-links';
8
8
  export { LITE_APP_LINKS, type AppLinks } from './lib/links';
9
9
  export { PausedScreen } from './access/AccessGate';
@@ -0,0 +1,5 @@
1
+ import type React from 'react';
2
+ /** A message body as WhatsApp shows it (React nodes for a `whitespace-pre-wrap` element). */
3
+ export declare function formatWhatsApp(text: string): React.ReactNode[];
4
+ /** The same text without the marks WhatsApp hides, for one-line previews (quotes, chat list). */
5
+ export declare function plainWhatsApp(text: string): string;