@composy/chat-core 0.0.1 → 0.0.2

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 (168) hide show
  1. package/README.md +187 -123
  2. package/dist/index.js +2018 -1035
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.min.js +1370 -1644
  5. package/dist/index.min.js.map +1 -0
  6. package/es/.dts-output-manifest.json +1 -0
  7. package/es/.dts.tsbuildinfo +1 -0
  8. package/es/constants/dom.d.ts +3 -19
  9. package/es/constants/dom.js +4 -4
  10. package/es/constants/dom.js.map +1 -1
  11. package/es/core/chat-manager.d.ts +33 -22
  12. package/es/core/chat-manager.js +174 -50
  13. package/es/core/chat-manager.js.map +1 -1
  14. package/es/core/event-emitter.d.ts +0 -1
  15. package/es/core/event-emitter.js +14 -7
  16. package/es/core/event-emitter.js.map +1 -1
  17. package/es/core/mention-engine.d.ts +1 -2
  18. package/es/core/mention-engine.js +9 -9
  19. package/es/core/mention-engine.js.map +1 -1
  20. package/es/core/message-schema.d.ts +19 -0
  21. package/es/core/message-schema.js +197 -0
  22. package/es/core/message-schema.js.map +1 -0
  23. package/es/core/outbox.d.ts +63 -0
  24. package/es/core/outbox.js +160 -0
  25. package/es/core/outbox.js.map +1 -0
  26. package/es/core/transport.d.ts +79 -0
  27. package/es/core/transport.js +102 -0
  28. package/es/core/transport.js.map +1 -0
  29. package/es/index.d.ts +12 -7
  30. package/es/index.js +167 -36
  31. package/es/index.js.map +1 -1
  32. package/es/renderer/dom-renderer.d.ts +16 -4
  33. package/es/renderer/dom-renderer.js +316 -61
  34. package/es/renderer/dom-renderer.js.map +1 -1
  35. package/es/renderer/style-manager.d.ts +14 -38
  36. package/es/renderer/style-manager.js +92 -63
  37. package/es/renderer/style-manager.js.map +1 -1
  38. package/es/theme/theme-manager.d.ts +4 -3
  39. package/es/theme/theme-manager.js +19 -9
  40. package/es/theme/theme-manager.js.map +1 -1
  41. package/es/theme/tokens.d.ts +0 -1
  42. package/es/theme/tokens.js +92 -92
  43. package/es/theme/tokens.js.map +1 -1
  44. package/es/types/index.d.ts +104 -24
  45. package/es/types/index.js +8 -3
  46. package/es/types/index.js.map +1 -0
  47. package/esm/constants/dom.d.ts +3 -19
  48. package/esm/constants/dom.js +4 -4
  49. package/esm/constants/dom.js.map +1 -1
  50. package/esm/core/chat-manager.d.ts +33 -22
  51. package/esm/core/chat-manager.js +174 -50
  52. package/esm/core/chat-manager.js.map +1 -1
  53. package/esm/core/event-emitter.d.ts +0 -1
  54. package/esm/core/event-emitter.js +14 -7
  55. package/esm/core/event-emitter.js.map +1 -1
  56. package/esm/core/mention-engine.d.ts +1 -2
  57. package/esm/core/mention-engine.js +9 -9
  58. package/esm/core/mention-engine.js.map +1 -1
  59. package/esm/core/message-schema.d.ts +19 -0
  60. package/esm/core/message-schema.js +197 -0
  61. package/esm/core/message-schema.js.map +1 -0
  62. package/esm/core/outbox.d.ts +63 -0
  63. package/esm/core/outbox.js +160 -0
  64. package/esm/core/outbox.js.map +1 -0
  65. package/esm/core/transport.d.ts +79 -0
  66. package/esm/core/transport.js +102 -0
  67. package/esm/core/transport.js.map +1 -0
  68. package/esm/index.d.ts +12 -7
  69. package/esm/index.js +169 -38
  70. package/esm/index.js.map +1 -1
  71. package/esm/renderer/dom-renderer.d.ts +16 -4
  72. package/esm/renderer/dom-renderer.js +316 -61
  73. package/esm/renderer/dom-renderer.js.map +1 -1
  74. package/esm/renderer/style-manager.d.ts +14 -38
  75. package/esm/renderer/style-manager.js +92 -63
  76. package/esm/renderer/style-manager.js.map +1 -1
  77. package/esm/theme/theme-manager.d.ts +4 -3
  78. package/esm/theme/theme-manager.js +19 -9
  79. package/esm/theme/theme-manager.js.map +1 -1
  80. package/esm/theme/tokens.d.ts +0 -1
  81. package/esm/theme/tokens.js +92 -92
  82. package/esm/theme/tokens.js.map +1 -1
  83. package/esm/types/index.d.ts +104 -24
  84. package/esm/types/index.js +8 -3
  85. package/esm/types/index.js.map +1 -0
  86. package/lib/constants/dom.cjs +4 -4
  87. package/lib/constants/dom.cjs.map +1 -1
  88. package/lib/constants/dom.d.cts +25 -0
  89. package/lib/constants/dom.d.ts +3 -19
  90. package/lib/core/chat-manager.cjs +174 -50
  91. package/lib/core/chat-manager.cjs.map +1 -1
  92. package/lib/core/chat-manager.d.cts +45 -0
  93. package/lib/core/chat-manager.d.ts +33 -22
  94. package/lib/core/event-emitter.cjs +14 -7
  95. package/lib/core/event-emitter.cjs.map +1 -1
  96. package/lib/core/event-emitter.d.cts +47 -0
  97. package/lib/core/event-emitter.d.ts +0 -1
  98. package/lib/core/mention-engine.cjs +9 -9
  99. package/lib/core/mention-engine.cjs.map +1 -1
  100. package/lib/core/mention-engine.d.cts +40 -0
  101. package/lib/core/mention-engine.d.ts +1 -2
  102. package/lib/core/message-schema.cjs +202 -0
  103. package/lib/core/message-schema.cjs.map +1 -0
  104. package/lib/core/message-schema.d.cts +19 -0
  105. package/lib/core/message-schema.d.ts +19 -0
  106. package/lib/core/outbox.cjs +162 -0
  107. package/lib/core/outbox.cjs.map +1 -0
  108. package/lib/core/outbox.d.cts +63 -0
  109. package/lib/core/outbox.d.ts +63 -0
  110. package/lib/core/transport.cjs +103 -0
  111. package/lib/core/transport.cjs.map +1 -0
  112. package/lib/core/transport.d.cts +79 -0
  113. package/lib/core/transport.d.ts +79 -0
  114. package/lib/index.cjs +175 -35
  115. package/lib/index.cjs.map +1 -1
  116. package/lib/index.d.cts +33 -0
  117. package/lib/index.d.ts +12 -7
  118. package/lib/renderer/dom-renderer.cjs +316 -61
  119. package/lib/renderer/dom-renderer.cjs.map +1 -1
  120. package/lib/renderer/dom-renderer.d.cts +91 -0
  121. package/lib/renderer/dom-renderer.d.ts +16 -4
  122. package/lib/renderer/style-manager.cjs +92 -62
  123. package/lib/renderer/style-manager.cjs.map +1 -1
  124. package/lib/renderer/style-manager.d.cts +34 -0
  125. package/lib/renderer/style-manager.d.ts +14 -38
  126. package/lib/theme/theme-manager.cjs +19 -9
  127. package/lib/theme/theme-manager.cjs.map +1 -1
  128. package/lib/theme/theme-manager.d.cts +34 -0
  129. package/lib/theme/theme-manager.d.ts +4 -3
  130. package/lib/theme/tokens.cjs +92 -92
  131. package/lib/theme/tokens.cjs.map +1 -1
  132. package/lib/theme/tokens.d.cts +56 -0
  133. package/lib/theme/tokens.d.ts +0 -1
  134. package/lib/types/index.cjs +8 -3
  135. package/lib/types/index.cjs.map +1 -0
  136. package/lib/types/index.d.cts +284 -0
  137. package/lib/types/index.d.ts +104 -24
  138. package/package.json +16 -13
  139. package/es/constants/dom.d.ts.map +0 -1
  140. package/es/core/chat-manager.d.ts.map +0 -1
  141. package/es/core/event-emitter.d.ts.map +0 -1
  142. package/es/core/mention-engine.d.ts.map +0 -1
  143. package/es/index.d.ts.map +0 -1
  144. package/es/renderer/dom-renderer.d.ts.map +0 -1
  145. package/es/renderer/style-manager.d.ts.map +0 -1
  146. package/es/theme/theme-manager.d.ts.map +0 -1
  147. package/es/theme/tokens.d.ts.map +0 -1
  148. package/es/types/index.d.ts.map +0 -1
  149. package/esm/constants/dom.d.ts.map +0 -1
  150. package/esm/core/chat-manager.d.ts.map +0 -1
  151. package/esm/core/event-emitter.d.ts.map +0 -1
  152. package/esm/core/mention-engine.d.ts.map +0 -1
  153. package/esm/index.d.ts.map +0 -1
  154. package/esm/renderer/dom-renderer.d.ts.map +0 -1
  155. package/esm/renderer/style-manager.d.ts.map +0 -1
  156. package/esm/theme/theme-manager.d.ts.map +0 -1
  157. package/esm/theme/tokens.d.ts.map +0 -1
  158. package/esm/types/index.d.ts.map +0 -1
  159. package/lib/constants/dom.d.ts.map +0 -1
  160. package/lib/core/chat-manager.d.ts.map +0 -1
  161. package/lib/core/event-emitter.d.ts.map +0 -1
  162. package/lib/core/mention-engine.d.ts.map +0 -1
  163. package/lib/index.d.ts.map +0 -1
  164. package/lib/renderer/dom-renderer.d.ts.map +0 -1
  165. package/lib/renderer/style-manager.d.ts.map +0 -1
  166. package/lib/theme/theme-manager.d.ts.map +0 -1
  167. package/lib/theme/tokens.d.ts.map +0 -1
  168. package/lib/types/index.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,123 +1,187 @@
1
- # @composy/chat-core
2
-
3
- Framework-agnostic chat runtime for LDesign. It renders message lists, bubbles, input, mentions, toolbar actions, voice input hooks, upload/drop callbacks, message status, streaming text, and light/dark/auto themes without depending on a UI framework.
4
-
5
- ## Features
6
-
7
- - Text, image, file, system, custom, revoked, and streaming messages.
8
- - Mention engine with keyboard navigation, name/id filtering, and mention parsing.
9
- - Toolbar callbacks for image upload, file upload, paste, drop, and browser speech recognition.
10
- - Input helpers: `enterToSend`, `clearInputOnSend`, `maxInputLength`, `setInputContent`, `clearInput`, and `onInputChange`.
11
- - Runtime APIs for message CRUD, streaming append/finish, scroll control, loading-more state, and message lookup.
12
- - All generated classes use the `ldesign-` prefix. The default class prefix is `ldesign-chat`.
13
- - Component CSS variables use `--ldesign-chat-*` and map to shared `packages/color` `--color-*` variables plus `packages/size` `--size-*` variables.
14
-
15
- ## Install
16
-
17
- ```bash
18
- pnpm add @composy/chat-core
19
- ```
20
-
21
- Load the global LDesign color and size variable styles before mounting chat UI:
22
-
23
- ```ts
24
- import '@composy/color-core/styles.css';
25
- import '@composy/size-core/styles.css';
26
- ```
27
-
28
- ## Usage
29
-
30
- ```ts
31
- import { createChat } from '@composy/chat-core';
32
-
33
- const chat = createChat({
34
- container: '#chat',
35
- currentUserId: 'u1',
36
- theme: 'auto',
37
- enableMention: true,
38
- mentionMembers: [
39
- { id: 'u2', name: 'Alice' },
40
- ],
41
- onSend(content, mentions) {
42
- console.log(content, mentions);
43
- },
44
- });
45
-
46
- chat.addMessage({
47
- id: 'm1',
48
- type: 'text',
49
- direction: 'incoming',
50
- sender: { id: 'u2', nickname: 'Alice' },
51
- content: 'Hello',
52
- timestamp: Date.now(),
53
- });
54
- ```
55
-
56
- ## Public API
57
-
58
- ```ts
59
- chat.addMessage(message);
60
- chat.prependMessages(messages);
61
- chat.updateMessage(id, updates);
62
- chat.removeMessage(id);
63
- chat.setMessages(messages);
64
- chat.clearMessages();
65
- chat.getMessages();
66
- chat.getMessage(id);
67
-
68
- chat.appendMessageContent(id, chunk);
69
- chat.finishStreaming(id);
70
-
71
- chat.scrollToBottom(true);
72
- chat.isAtBottom();
73
- chat.setLoadingMore(false);
74
-
75
- chat.setTheme('dark');
76
- chat.setMentionMembers(members);
77
-
78
- chat.focusInput();
79
- chat.setInputContent('hello');
80
- chat.getInputContent();
81
- chat.clearInput();
82
-
83
- chat.on('message-retry', (message) => {});
84
- chat.destroy();
85
- ```
86
-
87
- ## Styling Contract
88
-
89
- The renderer normalizes `classPrefix`. If no prefix is passed, generated classes start with `ldesign-chat-*`. If a custom prefix does not start with `ldesign-`, it is normalized to `ldesign-${prefix}`.
90
-
91
- Key classes:
92
-
93
- - `ldesign-chat-container`
94
- - `ldesign-chat-message-list`
95
- - `ldesign-chat-message-row`
96
- - `ldesign-chat-bubble`
97
- - `ldesign-chat-input-area`
98
- - `ldesign-chat-toolbar`
99
- - `ldesign-chat-mention-panel`
100
-
101
- The injected stylesheet defines component variables such as:
102
-
103
- - `--ldesign-chat-bg-primary`
104
- - `--ldesign-chat-text-primary`
105
- - `--ldesign-chat-border-primary`
106
- - `--ldesign-chat-avatar-size`
107
- - `--ldesign-chat-radius-md`
108
- - `--ldesign-chat-transition-fast`
109
-
110
- Defaults are references to `--color-*` and `--size-*` tokens, so consumers can theme chat by loading or overriding the shared token styles.
111
-
112
- ## Build
113
-
114
- ```bash
115
- pnpm --dir libraries/chat/packages/core type-check
116
- pnpm --dir libraries/chat/packages/core build
117
- ```
118
-
119
- The build generates `dist`, `es`, `esm`, and `lib`. `postbuild` verifies required outputs and creates `dist/index.min.js`.
120
-
121
- ## License
122
-
123
- MIT
1
+ # @composy/chat-core
2
+
3
+ Framework-agnostic chat runtime for LDesign. It renders message lists, bubbles, input, mentions,
4
+ toolbar actions, voice input hooks, upload/drop callbacks, message status, streaming text, and
5
+ light/dark/auto themes without depending on a UI framework.
6
+
7
+ ## Features
8
+
9
+ - Text, image, file, system, custom, revoked, and streaming messages.
10
+ - Mention engine with keyboard navigation, name/id filtering, and mention parsing.
11
+ - Toolbar callbacks for image upload, file upload, paste, drop, and browser speech recognition.
12
+ - Input helpers: `enterToSend`, `clearInputOnSend`, `maxInputLength`, `setInputContent`,
13
+ `clearInput`, and `onInputChange`.
14
+ - Runtime APIs for message CRUD, streaming append/finish, scroll control, loading-more state, and
15
+ message lookup.
16
+ - Versioned `ChatContentBlock` schema for text, mention, link, code, image, file, break, and custom
17
+ fallback content; unknown runtime blocks are dropped or rendered as safe text.
18
+ - Idempotent remote merge by `id`/`clientMessageId` with `sequence` filtering, plus transport
19
+ lifecycle (`connect`/`disconnect`/ack/cursor/error) for HTTP, SSE, WebSocket, or native bridges.
20
+ - Offline `ChatOutbox` with replaceable persistence, bounded retry, abort support, attempt tracking,
21
+ and stable idempotency keys.
22
+ - All generated classes use the `ldesign-` prefix. The default class prefix is `ldesign-chat`.
23
+ - Component CSS variables use `--ldesign-chat-*` and map to the generated `--ld-*` color and size
24
+ variables from `packages/color` and `packages/size`.
25
+ - Theme variables are applied per chat instance, so instances can use different themes and can live
26
+ in separate documents such as iframes.
27
+ - Custom HTML messages are sanitized. Scriptable elements, event attributes, inline styles, and
28
+ unsafe URLs are removed; basic text, formatting, list, link, and image elements are supported.
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ pnpm add @composy/chat-core
34
+ ```
35
+
36
+ Load the global LDesign color and size variable styles before mounting chat UI:
37
+
38
+ ```ts
39
+ import '@composy/color-core/styles.css'
40
+ import '@composy/size-core/styles.css'
41
+ ```
42
+
43
+ ## Usage
44
+
45
+ ```ts
46
+ import { createChat } from '@composy/chat-core'
47
+
48
+ const chat = createChat({
49
+ container: '#chat',
50
+ currentUserId: 'u1',
51
+ theme: 'auto',
52
+ enableMention: true,
53
+ mentionMembers: [{ id: 'u2', name: 'Alice' }],
54
+ onSend(content, mentions) {
55
+ console.info(content, mentions)
56
+ },
57
+ })
58
+
59
+ chat.addMessage({
60
+ id: 'm1',
61
+ type: 'text',
62
+ direction: 'incoming',
63
+ sender: { id: 'u2', nickname: 'Alice' },
64
+ content: 'Hello',
65
+ timestamp: Date.now(),
66
+ })
67
+
68
+ chat.addMessage({
69
+ id: 'm2',
70
+ type: 'custom',
71
+ direction: 'incoming',
72
+ sender: { id: 'u2', nickname: 'Alice' },
73
+ contentBlocks: [
74
+ { type: 'text', text: 'See ' },
75
+ { type: 'link', url: 'https://example.com', label: 'the docs' },
76
+ { type: 'break' },
77
+ { type: 'code', code: 'pnpm add @composy/chat-core' },
78
+ ],
79
+ timestamp: Date.now(),
80
+ })
81
+ ```
82
+
83
+ ## Public API
84
+
85
+ ```ts
86
+ chat.addMessage(message)
87
+ chat.prependMessages(messages)
88
+ chat.updateMessage(id, updates)
89
+ chat.removeMessage(id)
90
+ chat.setMessages(messages)
91
+ chat.clearMessages()
92
+ chat.getMessages()
93
+ chat.getMessage(id)
94
+
95
+ chat.beginStreaming(id, generation)
96
+ chat.appendMessageContent(id, chunk, { generation, sequence })
97
+ chat.finishStreaming(id, generation)
98
+ chat.cancelStreaming(id, generation)
99
+
100
+ chat.mergeMessage(remoteMessage, sequence)
101
+ chat.connectTransport(signal)
102
+ chat.disconnectTransport()
103
+ chat.getTransportStatus()
104
+ chat.sendMessage(message, { signal })
105
+ chat.flushOutbox({ maxAttempts, concurrency, signal })
106
+
107
+ chat.scrollToBottom(true)
108
+ chat.isAtBottom()
109
+ chat.setLoadingMore(false)
110
+
111
+ chat.setTheme('dark')
112
+ chat.setMentionMembers(members)
113
+
114
+ chat.focusInput()
115
+ chat.setInputContent('hello')
116
+ chat.getInputContent()
117
+ chat.clearInput()
118
+
119
+ chat.on('message-retry', message => console.info(message))
120
+ chat.destroy()
121
+ ```
122
+
123
+ For AI or network streams, use a generation and monotonically increasing chunk sequence. A late
124
+ chunk from a previous generation then returns `false` instead of mutating the current message:
125
+
126
+ ```ts
127
+ const generation = chat.beginStreaming('m3', 'reply-1')
128
+ chat.appendMessageContent('m3', '第一段', { generation, sequence: 1 })
129
+ chat.appendMessageContent('m3', '第二段', { generation, sequence: 2 })
130
+ chat.finishStreaming('m3', generation)
131
+ ```
132
+
133
+ `ChatConfig.transport` accepts any adapter implementing `ChatTransport`. `sendMessage()` creates a
134
+ stable `clientMessageId`, marks the local message as `sending`, applies the server ack, and marks it
135
+ `failed` on error. Configure `outbox: new ChatOutbox()` when failed messages should survive an
136
+ offline period and call `flushOutbox()` after reconnecting.
137
+
138
+ ## Styling Contract
139
+
140
+ The renderer normalizes `classPrefix`. If no prefix is passed, generated classes start with
141
+ `ldesign-chat-*`. If a custom prefix does not start with `ldesign-`, it is normalized to
142
+ `ldesign-${prefix}`.
143
+
144
+ Key classes:
145
+
146
+ - `ldesign-chat-container`
147
+ - `ldesign-chat-message-list`
148
+ - `ldesign-chat-message-row`
149
+ - `ldesign-chat-bubble`
150
+ - `ldesign-chat-input-area`
151
+ - `ldesign-chat-toolbar`
152
+ - `ldesign-chat-mention-panel`
153
+
154
+ The injected stylesheet defines component variables such as:
155
+
156
+ - `--ldesign-chat-bg-primary`
157
+ - `--ldesign-chat-text-primary`
158
+ - `--ldesign-chat-border-primary`
159
+ - `--ldesign-chat-avatar-size`
160
+ - `--ldesign-chat-radius-md`
161
+ - `--ldesign-chat-transition-fast`
162
+
163
+ Defaults reference `--ld-*` color and size tokens, so consumers should load the shared Color and
164
+ Size styles before mounting chat. Each instance keeps its theme overrides on its own root element.
165
+
166
+ Calling `getMessage()` or `getMessages()` returns defensive copies. Message IDs must be non-empty
167
+ and unique within the list, and an existing message ID cannot be changed with `updateMessage()`.
168
+ Load-more callback rejections are caught and emitted as `load-more-error` through `chat.on()`.
169
+ Messages entering the manager are normalized to schema version 1. Remote messages with an older
170
+ `sequence` are ignored. Use `clientMessageId` as the server idempotency key and persist failed
171
+ messages with `ChatOutbox` when the transport can be offline.
172
+
173
+ ## Build
174
+
175
+ ```bash
176
+ pnpm run type-check
177
+ pnpm run type-check:cjs
178
+ pnpm run build
179
+ ```
180
+
181
+ TypeScript ESM/CJS configurations and the rolldown Builder configuration live in `.ldesign/`. The
182
+ build generates `dist`, `es`, `esm`, and `lib`; `postbuild` normalizes and validates the package
183
+ outputs against the manifest.
184
+
185
+ ## License
186
+
187
+ MIT