@twentyfourg/chat-kit 1.0.0-beta.1

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 (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +222 -0
  3. package/dist/chat-kit.js +1914 -0
  4. package/dist/chat-kit.js.map +1 -0
  5. package/dist/components/AssistantMessage.vue.d.ts +35 -0
  6. package/dist/components/Chat.vue.d.ts +72 -0
  7. package/dist/components/CitationPopover.vue.d.ts +11 -0
  8. package/dist/components/FeedbackRow.vue.d.ts +11 -0
  9. package/dist/components/IconButton.vue.d.ts +17 -0
  10. package/dist/components/InputBar.vue.d.ts +16 -0
  11. package/dist/components/KitIcon.vue.d.ts +12 -0
  12. package/dist/components/MessageList.vue.d.ts +36 -0
  13. package/dist/components/PageImageModal.vue.d.ts +14 -0
  14. package/dist/components/SourceCard.vue.d.ts +21 -0
  15. package/dist/components/SourceList.vue.d.ts +7 -0
  16. package/dist/components/ThinkingAnimation.vue.d.ts +15 -0
  17. package/dist/components/ThinkingIndicator.vue.d.ts +13 -0
  18. package/dist/components/ThinkingProcess.vue.d.ts +8 -0
  19. package/dist/components/UserMessage.vue.d.ts +7 -0
  20. package/dist/composables/useAutoScroll.d.ts +36 -0
  21. package/dist/composables/useChatEngine.d.ts +335 -0
  22. package/dist/composables/useDictation.d.ts +29 -0
  23. package/dist/copy.d.ts +144 -0
  24. package/dist/index.css +1 -0
  25. package/dist/index.d.ts +18 -0
  26. package/dist/services/anonymous-auth.d.ts +63 -0
  27. package/dist/services/base-camp-client.d.ts +66 -0
  28. package/dist/services/citations.d.ts +18 -0
  29. package/dist/services/entities.d.ts +29 -0
  30. package/dist/services/markdown.d.ts +47 -0
  31. package/dist/services/math.d.ts +36 -0
  32. package/dist/services/streaming-message.d.ts +32 -0
  33. package/dist/services/streaming.service.d.ts +84 -0
  34. package/dist/services/typewriter.d.ts +54 -0
  35. package/dist/testing/mock-transport.d.ts +52 -0
  36. package/dist/testing/setup-tests.d.ts +8 -0
  37. package/dist/theme.css +122 -0
  38. package/dist/types.d.ts +389 -0
  39. package/package.json +76 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 24G
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,222 @@
1
+ # @twentyfourg/chat-kit
2
+
3
+ A ready-made chat pane for Vue 3 apps that talk to a Base Camp agent.
4
+
5
+ The Chat component includes the input bar and message list. It handles streaming replies,
6
+ markdown, code blocks and tables, citations (inline popover or a list of source
7
+ cards), thumbs feedback, voice input, and optional math rendering.
8
+ Everything around the chat is yours to build.
9
+
10
+ All the text and all the colors are settings, so two apps using this can look
11
+ and function completely differently from one another.
12
+
13
+ ## Install
14
+
15
+ ```
16
+ pnpm add @twentyfourg/chat-kit
17
+ ```
18
+
19
+ Vue 3.5 or newer is a peer dependency. Import the theme once, in your app
20
+ entry:
21
+
22
+ ```ts
23
+ import '@twentyfourg/chat-kit/theme.css';
24
+ ```
25
+
26
+ ## A working chat
27
+
28
+ ```vue
29
+ <script setup lang="ts">
30
+ import { BaseCampClient, Chat, useChatEngine } from '@twentyfourg/chat-kit';
31
+
32
+ const transport = new BaseCampClient({
33
+ baseUrl: import.meta.env.VITE_BASECAMP_API,
34
+ getAuthToken: () => myAuthToken,
35
+ deployEnv: import.meta.env.VITE_DEPLOY_ENV,
36
+ jobNumber: import.meta.env.VITE_JOB_NUMBER,
37
+ });
38
+
39
+ const engine = useChatEngine({ transport, agentId: import.meta.env.VITE_AGENT_ID });
40
+ </script>
41
+
42
+ <template>
43
+ <Chat :engine="engine" />
44
+ </template>
45
+ ```
46
+
47
+ You create the engine, not the component. That way, your other components can interact with the chat from outside of the kit.
48
+
49
+ `Chat` fills the height it is given and has none of its own, so it needs
50
+ a parent with a real height. There is a worked example in the guide.
51
+
52
+ ## Trying it without a backend
53
+
54
+ `MockTransport` answers with canned replies over the same streaming path the
55
+ real client uses, so you can build the whole interface before anything is
56
+ wired up.
57
+
58
+ ```ts
59
+ import { MockTransport, useChatEngine } from '@twentyfourg/chat-kit';
60
+
61
+ const engine = useChatEngine({
62
+ transport: new MockTransport({ replyTo: () => ({ text: 'Hello.' }) }),
63
+ agentId: 'agent-1',
64
+ });
65
+ ```
66
+
67
+ ## Options
68
+
69
+ There are two places to set things. How the chat behaves goes on the engine,
70
+ what the chat shows goes on `Chat` as a prop. Everything is optional
71
+ except the transport, the agent id, and the engine itself.
72
+
73
+ ### Engine options
74
+
75
+ ```ts
76
+ const engine = useChatEngine({ transport, agentId, typewriter: { speed: 1.5 } });
77
+ ```
78
+
79
+ | Option | Values | Default | What it does |
80
+ | --- | --- | --- | --- |
81
+ | `typewriter` | `true`, `false`, `{ speed }` | `true` | Reveals the answer a few characters at a time instead of in raw network bursts. `speed: 2` types twice as fast, `0.5` half. |
82
+ | `showMath` | `true`, `false`, `{ fontsDirectory }` | `false` | Runs LaTeX parsing on the answer, so `$...$` and `$$...$$` render as formulas. See [Formulas](#formulas). |
83
+ | `isOutOfScope` | `(text) => boolean` | off | Decides whether a finished answer is the agent declining a question. Those replies get marked and skip the thumbs row. |
84
+ | `onEvent` | `(event) => void` | off | Fires on finished turns, thumbs ratings, and citation clicks. See [Analytics](#analytics). |
85
+
86
+ ### Chat props
87
+
88
+ ```vue
89
+ <Chat :engine="engine" :copy="copy" show-mic show-copy citation-type="list" />
90
+ ```
91
+
92
+ | Prop | Values | Default | What it does |
93
+ | --- | --- | --- | --- |
94
+ | `engine` | the engine | required | The conversation to render. Not a setting. |
95
+ | `copy` | copy map | built-in defaults | Every visible string in the kit. Anything you leave out falls back to its default. |
96
+ | `showMic` | `true`, `false` | `false` | Shows the dictation button, in browsers that support speech recognition. |
97
+ | `citationType` | `'inline'`, `'list'` | `'inline'` | `'inline'` swaps the `[^N]` markers in the answer for numbered chips that open a passage popover. `'list'` drops the markers and shows source cards under the answer instead. |
98
+ | `thinkingVariant` | `'ring'`, `'sparkles'`, `'dots'` | `'ring'` | Which animation plays while the answer is being retrieved. |
99
+ | `rotateThinkingLabel` | `true`, `false` | `false` | Cycles the waiting label through `copy.status.thinkingSequence` instead of holding one line. Set that array to your own list, or to an empty array to turn the cycling off from the copy side. |
100
+ | `showThinking` | `true`, `false` | `false` | Shows the model's reasoning: live while you wait, folded up on the finished reply. |
101
+ | `autoScroll` | `'off'`, `'reply'`, `'bottom'` | `'reply'` | How far the view follows a streaming answer. `'reply'` stops once the answer's own header reaches the top, so a long answer can be read from the beginning. `'bottom'` keeps the newest line in view. `'off'` leaves the view alone. Under `'reply'` and `'bottom'`, scrolling up stops the follow until the reader comes back to the bottom. |
102
+ | `showCopy` | `true`, `false` | `false` | Adds a copy button under each finished answer. |
103
+
104
+ ### Slots
105
+
106
+ | Slot | What it's for |
107
+ | --- | --- |
108
+ | `welcome` | Replaces the default welcome block that shows before the first message. Use it for a logo, suggested questions, whatever you want. A text-only welcome can just set `copy.welcome` and skip the slot. |
109
+ | `message-actions` | Scoped, gives you `{ message }`. Sits on the left of the row that holds the thumbs, on finished replies. This is where an app's own button goes, an export for example, and it comes before the kit's copy button so your actions stay together. |
110
+
111
+ ### Events
112
+
113
+ `Chat` emits `rated` with the message and the rating now on it, or `null`
114
+ when the tap cleared it. The kit has already saved the thumb by then, so this is
115
+ for an app that wants to follow up with a form of its own.
116
+
117
+ ```vue
118
+ <Chat :engine="engine" @rated="(message, value) => openFeedbackForm(message, value)" />
119
+ ```
120
+
121
+ ## Theming
122
+
123
+ The components hold no colors, fonts, or spacing of their own. They read CSS
124
+ custom properties, and `theme.css` gives every one of them a plain default so
125
+ the chat is readable in an app that has themed nothing yet.
126
+
127
+ Override them from your own stylesheet. The defaults are written to lose, so an
128
+ ordinary rule in your app wins wherever the import sits.
129
+
130
+ Most values point at another value rather than a color, so a rebrand is
131
+ usually five lines:
132
+
133
+ ```css
134
+ :root {
135
+ --accent: #ffde11;
136
+ --accent-fg: #000;
137
+ --text-primary: #fff;
138
+ --surface-card: #1f2227;
139
+ --font-body: 'Roboto', sans-serif;
140
+ }
141
+ ```
142
+
143
+ The heading, label, and interface fonts follow `--font-body` unless you set
144
+ them. The citation and button accents follow `--accent`. An app that already
145
+ defines the whole set itself can skip the import.
146
+
147
+ One thing to watch. If your own tokens live inside a CSS cascade layer, layer
148
+ order decides the winner before anything else does. Import `theme.css` before
149
+ your layered styles, or state the order yourself:
150
+
151
+ ```css
152
+ @layer chat-kit.theme, app;
153
+ ```
154
+
155
+ ## Formulas
156
+
157
+ Answers containing `$...$` or `$$...$$` can be rendered as formulas. This is
158
+ off by default, because a dollar sign is also a currency symbol and prices
159
+ should stay prices.
160
+
161
+ ```
162
+ pnpm add mathlive
163
+ ```
164
+
165
+ ```ts
166
+ import 'mathlive/static.css';
167
+
168
+ const engine = useChatEngine({ transport, agentId, showMath: true });
169
+ ```
170
+
171
+ MathLive is an optional peer dependency. An app that leaves formulas off never
172
+ installs it and never downloads it.
173
+
174
+ ## Analytics
175
+
176
+ The engine reports completed turns, thumbs ratings, and citation clicks through
177
+ one hook, and your app decides whether any of it gets recorded. The kit never
178
+ sends analytics itself.
179
+
180
+ ```ts
181
+ const engine = useChatEngine({
182
+ transport,
183
+ agentId,
184
+ onEvent: (event) => console.log(event.type, event),
185
+ });
186
+ ```
187
+
188
+ ## Full guide
189
+
190
+ [GUIDE.md](./GUIDE.md) covers every prop, slot, engine option, and copy string,
191
+ plus the layout the chat needs around it and the things it deliberately leaves
192
+ to you.
193
+
194
+ ## House rules
195
+
196
+ These are what keep the package usable by more than one app.
197
+
198
+ 1. **Nothing about a specific app.** No client names in code, file names, CSS
199
+ classes, or comments. Anything app-specific arrives through props, engine
200
+ options, or the copy map.
201
+ 2. **No hardcoded visible text.** Components read the `ChatCopy` map, so an app
202
+ can reword or translate anything.
203
+ 3. **No raw colors or fonts.** Styles use the theme's custom properties. Every
204
+ property a component reads has a default in `theme.css`, and a test fails if
205
+ one is missing or unused.
206
+ 4. **One set of components.** No separate mobile and desktop versions. The
207
+ layout responds instead.
208
+ 5. **Small components.** Around 300 lines each.
209
+ 6. **Props down, events up.** No reaching into a child component.
210
+ 7. **Backend code stays in `services/`.** Components talk to composables, never
211
+ to a service. Swapping the backend means writing one transport.
212
+
213
+ ## Working on the kit
214
+
215
+ ```
216
+ pnpm test # vitest, jsdom
217
+ pnpm type-check
218
+ pnpm lint
219
+ pnpm build # produces dist/, which is what gets published
220
+ ```
221
+
222
+ Tests run against the source, so no build is needed first.