@pmate/chat-sdk 0.12.0-next.7 → 0.12.0-next.71

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 (105) hide show
  1. package/README.md +170 -81
  2. package/lib/advanced.d.ts +10 -0
  3. package/lib/advanced.js +10 -0
  4. package/lib/chat.d.ts +5 -0
  5. package/lib/chat.js +11 -0
  6. package/lib/chatContract.d.ts +148 -0
  7. package/lib/chatContract.js +1 -0
  8. package/lib/chatError.d.ts +11 -0
  9. package/lib/chatError.js +13 -0
  10. package/lib/chatTypes.d.ts +121 -0
  11. package/lib/chatTypes.js +1 -0
  12. package/lib/commands.d.ts +20 -0
  13. package/lib/commands.js +12 -0
  14. package/lib/components/ChatInputDesktop.js +5 -4
  15. package/lib/components/ChatInputMobile.js +5 -4
  16. package/lib/components/CommandMenu.d.ts +15 -0
  17. package/lib/components/CommandMenu.js +10 -0
  18. package/lib/credentials.d.ts +26 -0
  19. package/lib/credentials.js +110 -0
  20. package/lib/fileMetadata.d.ts +9 -0
  21. package/lib/fileMetadata.js +18 -0
  22. package/lib/framework.d.ts +11 -0
  23. package/lib/framework.js +12 -0
  24. package/lib/history.d.ts +4 -0
  25. package/lib/history.js +8 -0
  26. package/lib/hooks/useChatSnapshot.d.ts +4 -0
  27. package/lib/hooks/useChatSnapshot.js +9 -0
  28. package/lib/hooks/useComposerSuggestions.d.ts +50 -0
  29. package/lib/hooks/useComposerSuggestions.js +70 -0
  30. package/lib/index.d.ts +5 -0
  31. package/lib/index.js +5 -0
  32. package/lib/internal/chatEngine.d.ts +131 -0
  33. package/lib/internal/chatEngine.js +280 -0
  34. package/lib/internal/chatRegistry.d.ts +4 -0
  35. package/lib/internal/chatRegistry.js +4 -0
  36. package/lib/internal/createPublicChat.d.ts +4 -0
  37. package/lib/internal/createPublicChat.js +52 -0
  38. package/lib/messageView.d.ts +6 -0
  39. package/lib/messageView.js +103 -0
  40. package/lib/runtime/batchedReadIndex.d.ts +16 -3
  41. package/lib/runtime/batchedReadIndex.js +50 -4
  42. package/lib/runtime/cachedMessage.d.ts +12 -0
  43. package/lib/runtime/cachedMessage.js +18 -0
  44. package/lib/runtime/chatClient.d.ts +2 -0
  45. package/lib/runtime/chatClient.js +8 -3
  46. package/lib/runtime/chatError.d.ts +3 -0
  47. package/lib/runtime/chatError.js +15 -0
  48. package/lib/runtime/chatSession.d.ts +127 -13
  49. package/lib/runtime/chatSession.js +727 -40
  50. package/lib/runtime/connectivity.d.ts +4 -0
  51. package/lib/runtime/connectivity.js +8 -0
  52. package/lib/runtime/conversationDirectory.d.ts +37 -0
  53. package/lib/runtime/conversationDirectory.js +116 -0
  54. package/lib/runtime/conversationRead.d.ts +13 -0
  55. package/lib/runtime/conversationRead.js +34 -0
  56. package/lib/runtime/conversationReading.d.ts +28 -0
  57. package/lib/runtime/conversationReading.js +47 -0
  58. package/lib/runtime/createChat.d.ts +11 -7
  59. package/lib/runtime/createChat.js +46 -23
  60. package/lib/runtime/durableSender.d.ts +97 -14
  61. package/lib/runtime/durableSender.js +786 -71
  62. package/lib/runtime/groupClient.d.ts +76 -0
  63. package/lib/runtime/groupClient.js +325 -0
  64. package/lib/runtime/index.d.ts +7 -0
  65. package/lib/runtime/index.js +5 -0
  66. package/lib/runtime/messageClient.d.ts +35 -8
  67. package/lib/runtime/messageClient.js +364 -66
  68. package/lib/runtime/messageControls.d.ts +19 -0
  69. package/lib/runtime/messageControls.js +44 -0
  70. package/lib/runtime/messageLaunch.d.ts +44 -0
  71. package/lib/runtime/messageLaunch.js +137 -0
  72. package/lib/runtime/messageQuotes.d.ts +3 -0
  73. package/lib/runtime/messageQuotes.js +17 -0
  74. package/lib/runtime/messageReaders.d.ts +12 -1
  75. package/lib/runtime/messageReaders.js +67 -3
  76. package/lib/runtime/messageStore.d.ts +40 -2
  77. package/lib/runtime/messageStore.js +227 -11
  78. package/lib/runtime/messageTimeline.d.ts +50 -0
  79. package/lib/runtime/messageTimeline.js +120 -0
  80. package/lib/runtime/outboxSchema.d.ts +5 -0
  81. package/lib/runtime/outboxSchema.js +59 -0
  82. package/lib/runtime/outgoingContent.d.ts +89 -0
  83. package/lib/runtime/outgoingContent.js +113 -0
  84. package/lib/runtime/readBatchJournal.d.ts +35 -0
  85. package/lib/runtime/readBatchJournal.js +210 -0
  86. package/lib/runtime/readCounts.d.ts +15 -1
  87. package/lib/runtime/readCounts.js +97 -9
  88. package/lib/runtime/readIndex.d.ts +68 -7
  89. package/lib/runtime/readIndex.js +460 -22
  90. package/lib/runtime/readSchema.d.ts +2 -0
  91. package/lib/runtime/readSchema.js +58 -0
  92. package/lib/runtime/readSync.d.ts +1 -0
  93. package/lib/runtime/readSync.js +26 -9
  94. package/lib/runtime/readingClient.d.ts +19 -0
  95. package/lib/runtime/readingClient.js +131 -19
  96. package/lib/runtime/readingContent.d.ts +5 -0
  97. package/lib/runtime/readingContent.js +23 -0
  98. package/lib/runtime/responseCache.d.ts +59 -0
  99. package/lib/runtime/responseCache.js +232 -0
  100. package/lib/runtime/socialReadClient.d.ts +4 -2
  101. package/lib/runtime/socialReadClient.js +12 -8
  102. package/lib/runtime/voiceUpload.d.ts +2 -0
  103. package/lib/runtime/voiceUpload.js +27 -0
  104. package/lib/types/chatInput.d.ts +3 -0
  105. package/package.json +27 -2
@@ -123,7 +123,7 @@ export class ChatClient {
123
123
  /** Non-secret identity used to validate a shared browser transport. */
124
124
  identityScope() {
125
125
  const identity = this.session?.identity ?? this.session?.session?.identity;
126
- return { appId: this.options.appId, profileId: this.profileIdValue ?? this.options.profileId, accountId: identity?.accountId, teamId: this.options.teamId };
126
+ return { appId: this.options.appId, profileId: this.profileIdValue ?? this.options.profileId, accountId: identity?.accountId, teamId: this.options.teamId, clientInstanceId: this.instanceId };
127
127
  }
128
128
  watchConnection(handler) {
129
129
  this.connectionHandlers.add(handler);
@@ -161,7 +161,7 @@ export class ChatClient {
161
161
  catch (error) {
162
162
  if (generation !== this.generation)
163
163
  return;
164
- if (error instanceof ChatAckError) {
164
+ if (error instanceof ChatAckError || ["authentication-required", "access-denied"].includes(error?.code ?? "")) {
165
165
  this.close();
166
166
  this.setConnection("authentication_required");
167
167
  }
@@ -295,7 +295,12 @@ export class ChatClient {
295
295
  });
296
296
  }
297
297
  async sendAuth() {
298
- const token = this.session?.token;
298
+ const generation = this.generation;
299
+ const token = this.options.getToken ? await this.options.getToken() : this.session?.token;
300
+ if (generation !== this.generation)
301
+ throw new Error("ChatClient closed");
302
+ if (this.session && token)
303
+ this.session = { ...this.session, token };
299
304
  if (!token) {
300
305
  throw new Error("Missing PMate session token");
301
306
  }
@@ -0,0 +1,3 @@
1
+ import { ChatError } from "../chatError.js";
2
+ export { ChatError, type ChatErrorCode } from "../chatError.js";
3
+ export declare function asChatError(error: unknown): ChatError;
@@ -0,0 +1,15 @@
1
+ import { ChatError } from "../chatError.js";
2
+ export { ChatError } from "../chatError.js";
3
+ export function asChatError(error) {
4
+ if (error instanceof ChatError)
5
+ return error;
6
+ const value = error;
7
+ const status = value?.status, message = value?.message ?? String(error);
8
+ const code = status === 401 ? "authentication-required" : status === 403 || /ACCESS_REVOKED|ACCESS_DENIED|SCOPE_CHANGED/.test(message) ? "access-denied"
9
+ : /CLOSED/.test(message) ? "closed"
10
+ : status === 409 || /REVISION_CONFLICT|PROJECTION_CHANGED/.test(message) ? "conflict"
11
+ : /BACKPRESSURE|TOO_LARGE/.test(message) ? "busy"
12
+ : status === 400 || /INVALID_|CONVERSATION_MISMATCH|CONVERSATION_UNKNOWN|NOT_OWNED/.test(message) ? "invalid-input"
13
+ : /QuotaExceeded|DatabaseClosed|UnknownError|AbortError/.test(value?.name ?? "") || /STORAGE_|DATABASE_|CACHE_WRITE/.test(message) ? "storage-unavailable" : "unavailable";
14
+ return new ChatError(code, message, { cause: error, status });
15
+ }
@@ -1,59 +1,124 @@
1
+ import { type ConversationTarget } from "./conversationDirectory.js";
2
+ import { type ChatGroup } from "./groupClient.js";
3
+ import type { SocialGroup } from "./socialReadClient.js";
4
+ import { type ChatConversation, type OutgoingContent } from "./outgoingContent.js";
5
+ import { type TimelineItem } from "./messageTimeline.js";
6
+ import { type ReadingCandidate, type MessageReadingState } from "./conversationReading.js";
7
+ import type { ConversationReadMessage } from "./conversationRead.js";
8
+ import { type ReadCountsResult } from "./readCounts.js";
9
+ import type { OnlineReachEvent } from "./reach.js";
1
10
  import { type MessageReadersQuery } from "./messageReaders.js";
2
11
  import { type MessageClientOptions, type MessageSnapshot } from "./messageClient.js";
3
- import { DurableChatSender } from "./durableSender.js";
4
- import { type ReadingClientOptions } from "./readingClient.js";
12
+ import { DurableChatSender, type SendMessageInput, type DurableSenderOptions, type VoiceAttachmentLease } from "./durableSender.js";
13
+ import { ReadingClient, type ReadingClientOptions } from "./readingClient.js";
5
14
  import { ChatClient, type ChatClientOptions, type ChatConnectionState } from "./chatClient.js";
6
15
  import { unreadInConversation } from "./readIndex.js";
7
16
  import type { StoredMessage } from "./messageStore.js";
8
- import type { ChatBody, ChatRuntimeMessage } from "./protocol.js";
17
+ import type { ChatRuntimeMessage } from "./protocol.js";
9
18
  export type ChatSessionOptions<T extends StoredMessage> = {
19
+ onDispose?: () => void;
10
20
  messages: MessageClientOptions<T>;
11
21
  connection: ChatClientOptions;
12
22
  sharedConnection?: ChatClient;
23
+ activeThreadId?: string;
24
+ uploadVoice?: DurableSenderOptions["uploadVoice"];
25
+ reconcileOutgoing?: DurableSenderOptions["reconcile"];
26
+ loadGroup?: (groupId: string, signal: AbortSignal) => Promise<SocialGroup>;
13
27
  reading: ReadingClientOptions;
14
28
  decode: (message: ChatRuntimeMessage) => T | undefined;
29
+ readingCandidate?: (message: T) => ReadingCandidate | undefined;
15
30
  onError: (error: unknown) => void;
16
31
  };
17
32
  export type ChatThreadSnapshot<T> = {
18
33
  messages: readonly T[];
34
+ timeline: readonly TimelineItem<T>[];
19
35
  outgoing: ReturnType<DurableChatSender["snapshot"]>;
20
36
  hasEarlier: boolean;
21
37
  resetVersion: number;
22
38
  complete: boolean;
23
- unread: ReturnType<typeof unreadInConversation>;
39
+ group?: ChatGroup;
40
+ readCounts?: ReadCountsResult;
41
+ unread: ReturnType<typeof unreadInConversation> | undefined;
42
+ messageReading: Readonly<Record<string, MessageReadingState>>;
24
43
  };
25
44
  export type ChatSummarySnapshot<T> = {
26
45
  threads: readonly {
27
46
  threadId: string;
28
47
  lastMessage?: T;
48
+ lastItem?: TimelineItem<T>;
49
+ group?: ChatGroup;
29
50
  unread: ChatThreadSnapshot<T>["unread"];
30
51
  outgoingCount: number;
31
52
  }[];
32
- unreadMessageCount: number;
33
- badgeCount: number;
53
+ unreadMessageCount: number | undefined;
54
+ badgeCount: number | undefined;
34
55
  connection: ChatConnectionState;
35
56
  };
36
57
  /** Owns all browser message clients. Hosts subscribe to stable thread snapshots. */
37
58
  export declare class ChatSession<T extends StoredMessage> {
38
59
  private options;
60
+ private conversations;
39
61
  private messages;
40
62
  private connection;
41
63
  private reading;
42
64
  private readers;
65
+ private groups?;
66
+ private counts?;
67
+ private countsReceiver?;
68
+ private countsThread?;
69
+ private countSnapshots;
70
+ private countClosings;
71
+ private countTasks;
72
+ private controlTails;
73
+ private acceptedControls;
74
+ private controlCount;
75
+ private controlBytes;
43
76
  private sender;
44
77
  private listeners;
45
78
  private snapshots;
79
+ private timelineDecoded;
80
+ private decodeTimeline;
81
+ private historyEdges;
82
+ private earlierReads;
46
83
  private off;
47
84
  private globalListeners;
48
85
  private globalSnapshot?;
86
+ private closedThread;
87
+ private closedSummary;
49
88
  private connectionState;
50
89
  private catchUp;
90
+ private readingAllowed;
91
+ private readingListeners;
92
+ private acceptedReading;
93
+ private readingAccess?;
51
94
  private readingStarted;
95
+ private readingStarting?;
96
+ private withdrawn;
97
+ private revoking?;
52
98
  private closed;
53
99
  private starting?;
100
+ private initializing?;
54
101
  private closing?;
55
102
  constructor(options: ChatSessionOptions<T>);
103
+ private scheduleCatchUp;
56
104
  start(): Promise<void>;
105
+ /** Initializes local state and background reading sync without opening a
106
+ * second transport when the host already owns calls/presence. */
107
+ initialize(): Promise<void>;
108
+ private startReading;
109
+ /** One-time migration only: never establishes trusted history coverage. */
110
+ importLegacyMessages(threadId: string, messages: T[]): Promise<void>;
111
+ getReadingSnapshot(): import("./readIndex.js").ReadIndexState | undefined;
112
+ subscribeReading(listener: () => void): () => void;
113
+ private setReadingAllowed;
114
+ private readingAuthority;
115
+ private authorizeReading;
116
+ private readingOperation;
117
+ refreshReading(): void;
118
+ synchronizeReading(cursor?: string, profileId?: string): Promise<import("./readIndex.js").ReadIndexState>;
119
+ /** Explicit text-history acknowledgement; unheard audio stays unread. */
120
+ markRead(threadId: string, messages?: readonly ConversationReadMessage[]): Promise<import("./readIndex.js").ReadIndexState>;
121
+ updateReading(transform: Parameters<ReadingClient["update"]>[0]): Promise<import("./readIndex.js").ReadIndexState>;
57
122
  private assertOpen;
58
123
  getMessages(threadId: string, options?: {
59
124
  limit?: number;
@@ -61,25 +126,74 @@ export declare class ChatSession<T extends StoredMessage> {
61
126
  timestamp: number;
62
127
  id: string;
63
128
  };
129
+ earlier?: boolean;
64
130
  all?: boolean;
65
131
  refresh?: boolean;
66
132
  }): Promise<MessageSnapshot<T>>;
133
+ private confirmMessages;
134
+ private rememberHistoryEdge;
135
+ private readEarlier;
67
136
  private readAll;
68
- sendMessage(threadId: string, input: {
69
- to: string;
70
- body: ChatBody;
71
- recipients?: string[];
137
+ /** Reads trusted local group metadata immediately; SDK refreshes it in the background. */
138
+ getGroup(thread: ChatConversation | string, options?: {
139
+ refresh?: boolean;
140
+ }): Promise<ChatGroup>;
141
+ createGroup(thread: ChatConversation, content: {
142
+ title: string;
143
+ members: readonly string[];
144
+ }): Promise<ChatGroup>;
145
+ updateGroup(target: ChatConversation | string, changes: {
146
+ expectedRevision?: string;
147
+ addMembers?: readonly string[];
148
+ removeMembers?: readonly string[];
149
+ title?: string;
150
+ avatar?: string;
151
+ }): Promise<ChatGroup>;
152
+ sendMessage(threadId: string, input: OutgoingContent, options?: {
153
+ waitFor?: "accepted" | "delivered";
154
+ }): Promise<ChatRuntimeMessage>;
155
+ sendMessage(thread: ChatConversation, input: OutgoingContent, options?: {
156
+ waitFor?: "accepted" | "delivered";
157
+ }): Promise<ChatRuntimeMessage>;
158
+ sendMessage(threadId: string, input: SendMessageInput, options?: {
159
+ waitFor?: "accepted" | "delivered";
72
160
  }): Promise<ChatRuntimeMessage>;
161
+ private sendWire;
162
+ getConversation(target: ConversationTarget): Promise<string>;
163
+ private sendContent;
164
+ private resolveConversation;
165
+ /** Validated target identity survives content redaction; no roster is exposed. */
166
+ getConversationTarget(threadId: string): ChatConversation | undefined;
167
+ private sendControl;
73
168
  getReaders(threadId: string, messageId: string, page?: Omit<MessageReadersQuery, "threadId" | "messageId">, signal?: AbortSignal): Promise<import("./messageReaders.js").MessageReadersPage>;
169
+ /** Resolve voice media uniformly; pending local bytes are loaded only on demand. */
170
+ getVoiceAttachment(threadId: string, messageId: string): Promise<VoiceAttachmentLease>;
74
171
  retryMessage(messageId: string): Promise<ChatRuntimeMessage>;
75
- observeMessages(threadId: string, ids: string[], event: "visible" | "played"): Promise<import("./readIndex.js").ReadIndexState>;
172
+ observeMessages(threadId: string, ids: string[], event: "visible" | "played"): ReturnType<ReadingClient["recordVisible"]>;
173
+ observeMessages(threadId: string | undefined, ids: string[], event: "receipts", clientInstanceId?: string): Promise<void>;
174
+ /** Bridge transports can delegate social events without maintaining clients. */
175
+ handleReach(event: OnlineReachEvent): Promise<"handled" | undefined>;
176
+ private wakeCounts;
177
+ private publishCountSnapshot;
178
+ private publishCounts;
179
+ private watchCounts;
76
180
  getSnapshot(): ChatSummarySnapshot<T>;
77
181
  getSnapshot(threadId: string): ChatThreadSnapshot<T>;
78
- subscribe(listener: () => void): () => void;
79
- subscribe(threadId: string, listener: () => void): () => void;
182
+ private buildThreadSnapshot;
183
+ /** Delivers the current stable snapshot immediately, then only meaningful changes. */
184
+ subscribe(listener: (snapshot: ChatSummarySnapshot<T>) => void): () => void;
185
+ subscribe(threadId: string, listener: (snapshot: ChatThreadSnapshot<T>) => void, fields?: readonly (keyof ChatThreadSnapshot<T>)[]): () => void;
186
+ /** Change-only bridge for useSyncExternalStore and other framework adapters. */
187
+ subscribeChanges(listener: () => void): () => void;
188
+ subscribeChanges(threadId: string, listener: () => void, fields?: readonly (keyof ChatThreadSnapshot<T>)[]): () => void;
80
189
  private publishAll;
81
190
  private buildGlobal;
82
191
  private publishGlobal;
83
192
  private publish;
193
+ /** Permanently retire this identity/team session. UI withdrawal is immediate;
194
+ * completion means all durable stores have crossed the same authority epoch. */
195
+ revokeAccess(): Promise<void>;
196
+ get active(): boolean;
84
197
  close(): Promise<void>;
198
+ private dispose;
85
199
  }