@meistrari/chat-nuxt 3.9.1 → 3.10.0
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.
- package/README.md +50 -440
- package/dist/module.d.mts +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +56 -3
- package/dist/runtime/assets/css/markstream.css +1 -1
- package/dist/runtime/conversations/components/chat-conversation-creator-filter.vue +11 -67
- package/dist/runtime/conversations/components/chat-conversation-item.d.vue.ts +2 -1
- package/dist/runtime/conversations/components/chat-conversation-item.vue +29 -33
- package/dist/runtime/conversations/components/chat-conversation-item.vue.d.ts +2 -1
- package/dist/runtime/conversations/components/chat-conversation-list.d.vue.ts +0 -1
- package/dist/runtime/conversations/components/chat-conversation-list.vue +117 -158
- package/dist/runtime/conversations/components/chat-conversation-list.vue.d.ts +0 -1
- package/dist/runtime/conversations/components/chat-conversation-new-group-button.vue +34 -73
- package/dist/runtime/conversations/components/chat-conversation-search.vue +1 -21
- package/dist/runtime/conversations/components/chat-widget-history-list.d.vue.ts +12 -0
- package/dist/runtime/conversations/components/chat-widget-history-list.vue +27 -0
- package/dist/runtime/conversations/components/chat-widget-history-list.vue.d.ts +12 -0
- package/dist/runtime/conversations/composables/conversation-groups.d.ts +1 -0
- package/dist/runtime/conversations/composables/conversation-groups.js +2 -0
- package/dist/runtime/conversations/composables/conversation-item.js +4 -4
- package/dist/runtime/conversations/composables/conversation-list.js +14 -5
- package/dist/runtime/embed/components/chat-configuration-modal.d.vue.ts +3 -3
- package/dist/runtime/embed/components/chat-configuration-modal.vue.d.ts +3 -3
- package/dist/runtime/embed/components/chat-embed-inner.d.vue.ts +6 -3
- package/dist/runtime/embed/components/chat-embed-inner.vue +365 -152
- package/dist/runtime/embed/components/chat-embed-inner.vue.d.ts +6 -3
- package/dist/runtime/embed/components/chat-embed.d.vue.ts +31 -4
- package/dist/runtime/embed/components/chat-embed.vue +10 -4
- package/dist/runtime/embed/components/chat-embed.vue.d.ts +31 -4
- package/dist/runtime/embed/components/chat-topbar.vue +83 -85
- package/dist/runtime/embed/components/meistrari-chat-embed.d.vue.ts +5 -3
- package/dist/runtime/embed/components/meistrari-chat-embed.vue +118 -57
- package/dist/runtime/embed/components/meistrari-chat-embed.vue.d.ts +5 -3
- package/dist/runtime/embed/components/mobile/chat-mobile-drawer.d.vue.ts +0 -1
- package/dist/runtime/embed/components/mobile/chat-mobile-drawer.vue +2 -45
- package/dist/runtime/embed/components/mobile/chat-mobile-drawer.vue.d.ts +0 -1
- package/dist/runtime/embed/components/mobile/chat-mobile-home-suggestions.d.vue.ts +9 -5
- package/dist/runtime/embed/components/mobile/chat-mobile-home-suggestions.vue +14 -25
- package/dist/runtime/embed/components/mobile/chat-mobile-home-suggestions.vue.d.ts +9 -5
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.d.vue.ts +6 -6
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.vue +2 -3
- package/dist/runtime/embed/components/mobile/chat-mobile-shell.vue.d.ts +6 -6
- package/dist/runtime/embed/feature-config.d.ts +7 -0
- package/dist/runtime/embed/types.d.ts +47 -8
- package/dist/runtime/files/icons.d.ts +1 -1
- package/dist/runtime/files/icons.js +1 -1
- package/dist/runtime/messages/components/chat-mention-dropdown.d.vue.ts +6 -1
- package/dist/runtime/messages/components/chat-mention-dropdown.vue +46 -22
- package/dist/runtime/messages/components/chat-mention-dropdown.vue.d.ts +6 -1
- package/dist/runtime/messages/components/chat-message-bubble.vue +53 -71
- package/dist/runtime/messages/components/chat-message-feedback.vue +25 -229
- package/dist/runtime/messages/components/chat-message-input.vue +176 -134
- package/dist/runtime/messages/components/chat-message-list.d.vue.ts +6 -0
- package/dist/runtime/messages/components/chat-message-list.vue +27 -23
- package/dist/runtime/messages/components/chat-message-list.vue.d.ts +6 -0
- package/dist/runtime/messages/components/chat-model-selector.vue +10 -22
- package/dist/runtime/messages/components/reasoning/chat-reasoning-message.vue +2 -3
- package/dist/runtime/messages/components/reasoning/chat-reasoning-thought.vue +60 -69
- package/dist/runtime/messages/components/reasoning/chat-thinking-indicator.vue +3 -9
- package/dist/runtime/messages/components/widgets/chat-bash-widget.vue +3 -12
- package/dist/runtime/messages/components/widgets/chat-doc-sdk-widget.vue +3 -12
- package/dist/runtime/messages/components/widgets/chat-generic-tool-widget.vue +3 -12
- package/dist/runtime/messages/components/widgets/chat-grep-widget.vue +7 -17
- package/dist/runtime/messages/components/widgets/chat-read-widget.vue +7 -17
- package/dist/runtime/messages/components/widgets/chat-tela-skill-widget.vue +4 -13
- package/dist/runtime/messages/components/widgets/chat-thinking-widget.vue +11 -22
- package/dist/runtime/messages/components/widgets/chat-web-search-widget.vue +13 -40
- package/dist/runtime/messages/components/widgets/chat-workstation-query-widget.vue +52 -65
- package/dist/runtime/messages/components/widgets/chat-write-widget.vue +8 -18
- package/dist/runtime/messages/composables/mention-autocomplete.js +4 -0
- package/dist/runtime/messages/message-reasoning.js +4 -0
- package/dist/runtime/messages/message-state.js +1 -0
- package/dist/runtime/public/files/generic.svg +2 -5
- package/dist/runtime/public/files/image.svg +2 -1
- package/dist/runtime/types/embed.d.ts +1 -1
- package/dist/runtime/types/schemas/chat/conversations.d.ts +2 -0
- package/dist/runtime/types/schemas/chat/conversations.js +3 -0
- package/dist/runtime/types/schemas/chat/messages.d.ts +4 -0
- package/dist/runtime/types/schemas/chat/messages.js +7 -0
- package/dist/types.d.mts +1 -1
- package/package.json +5 -4
- package/dist/runtime/conversations/components/chat-conversation-new-group-popover-content.d.vue.ts +0 -23
- package/dist/runtime/conversations/components/chat-conversation-new-group-popover-content.vue +0 -75
- package/dist/runtime/conversations/components/chat-conversation-new-group-popover-content.vue.d.ts +0 -23
- package/dist/runtime/messages/components/reasoning/chat-reasoning-step-item.d.vue.ts +0 -37
- package/dist/runtime/messages/components/reasoning/chat-reasoning-step-item.vue +0 -125
- package/dist/runtime/messages/components/reasoning/chat-reasoning-step-item.vue.d.ts +0 -37
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Nuxt module that adds a complete AI chat interface to your app. Server-side chat behavior is delegated to the dedicated Chat API; the Nuxt module owns the UI, auth bridge, and local proxy routes.
|
|
4
4
|
|
|
5
|
+
Consumer documentation lives in `docs/guides/` (indexed [below](#guides)); this README covers the package boundary and working on the package itself.
|
|
6
|
+
|
|
5
7
|
## Public Surface
|
|
6
8
|
|
|
7
9
|
`@meistrari/chat-nuxt` is an external package. Its supported consumer surface is intentionally small:
|
|
@@ -14,468 +16,59 @@ Nuxt module that adds a complete AI chat interface to your app. Server-side chat
|
|
|
14
16
|
|
|
15
17
|
Runtime internals under `src/runtime/**`, generated Nuxt aliases, and workspace-only schema package imports are implementation details unless they are explicitly exported above.
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
pnpm add @meistrari/chat-nuxt
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### Required: Vue dedupe via pnpm overrides
|
|
24
|
-
|
|
25
|
-
`@meistrari/tela-build` pins `vue@3.5.13` as a direct dependency, which collides with the Vue that Nuxt installs. Without an override, pnpm installs two Vue copies and you'll hit runtime errors such as `root.ce._hasShadowRoot is not a function` when custom elements register against one Vue and mount against the other.
|
|
26
|
-
|
|
27
|
-
Until tela-build is published with Vue as a peer dependency, pin a single Vue version in your consumer `package.json`:
|
|
28
|
-
|
|
29
|
-
```json
|
|
30
|
-
{
|
|
31
|
-
"pnpm": {
|
|
32
|
-
"overrides": {
|
|
33
|
-
"vue": "3.5.33"
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Keep this entry until `@meistrari/tela-build` moves Vue to `peerDependencies` — at that point the override becomes unnecessary and should be removed.
|
|
40
|
-
|
|
41
|
-
## Setup
|
|
42
|
-
|
|
43
|
-
### 1. Register the modules
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
// nuxt.config.ts
|
|
47
|
-
export default defineNuxtConfig({
|
|
48
|
-
modules: [
|
|
49
|
-
'@meistrari/auth-nuxt', // must come before chat-nuxt
|
|
50
|
-
'@meistrari/chat-nuxt',
|
|
51
|
-
],
|
|
52
|
-
|
|
53
|
-
ssr: false,
|
|
54
|
-
|
|
55
|
-
chatNuxt: {
|
|
56
|
-
chatApiUrl: process.env.CHAT_API_URL,
|
|
57
|
-
validateConfig: 'warn',
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
telaAuth: {
|
|
61
|
-
apiUrl: process.env.AUTH_API_URL ?? '',
|
|
62
|
-
application: {
|
|
63
|
-
enabled: true,
|
|
64
|
-
applicationId: process.env.APPLICATION_ID ?? '',
|
|
65
|
-
redirectUri: process.env.AUTH_REDIRECT_URI ?? 'http://localhost:3000/auth/callback',
|
|
66
|
-
dashboardUrl: process.env.AUTH_DASHBOARD_URL ?? '',
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
})
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### 2. Module options
|
|
73
|
-
|
|
74
|
-
`chatApiUrl` accepts the value inline, or you can leave the option empty and set `CHAT_API_URL`. Resolution order: **module option → existing `runtimeConfig` → env var → empty**.
|
|
75
|
-
|
|
76
|
-
| Option | Required | Env fallback | Description |
|
|
77
|
-
|--------|----------|--------------|-------------|
|
|
78
|
-
| `chatApiUrl` | ✅ Always | `CHAT_API_URL` | Dedicated Chat API base URL used by Nuxt server proxy routes. |
|
|
79
|
-
| `validateConfig` | 🔧 Optional | — | `false` (default), `'warn'`, or `'error'`. Warns or fails fast when `chatApiUrl` is missing. |
|
|
80
|
-
|
|
81
|
-
Set `chatNuxt.validateConfig` to `'warn'` to log a warning when `chatApiUrl` is missing, or `'error'` to fail fast at module setup. The check is off by default since some deployments inject runtime config after build.
|
|
82
|
-
|
|
83
|
-
UI features are configured per component instance, not at the module level: the embed takes a `:features` prop (`ChatFeatureConfig`) and `<ChatConfigurationModal>` takes `show-credentials-tab`.
|
|
84
|
-
|
|
85
|
-
### 3. Auth modes
|
|
86
|
-
|
|
87
|
-
`@meistrari/chat-nuxt` can run with either auth mode exposed by `@meistrari/auth-nuxt`:
|
|
88
|
-
|
|
89
|
-
- Application auth (`telaAuth.application.enabled: true`) delegates chat identity and workspace state to `useTelaApplicationAuth()`.
|
|
90
|
-
- First-party auth delegates chat identity to `useTelaSession()` and workspace state to `useTelaOrganization()`.
|
|
91
|
-
|
|
92
|
-
The module chooses the bridge during Nuxt setup. Host apps should keep registering `@meistrari/auth-nuxt` before `@meistrari/chat-nuxt`.
|
|
93
|
-
|
|
94
|
-
### 4. Setup `app.vue`
|
|
95
|
-
|
|
96
|
-
```vue
|
|
97
|
-
<!-- app.vue -->
|
|
98
|
-
<template>
|
|
99
|
-
<NuxtPage />
|
|
100
|
-
<AppStatusToast />
|
|
101
|
-
</template>
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
`AppStatusToast`, Markstream styles, code block styles, and math delimiter defaults are auto-registered by the module.
|
|
105
|
-
|
|
106
|
-
### 5. Use it
|
|
107
|
-
|
|
108
|
-
```vue
|
|
109
|
-
<!-- pages/index.vue -->
|
|
110
|
-
<template>
|
|
111
|
-
<div h-screen>
|
|
112
|
-
<MeistrariChatEmbed />
|
|
113
|
-
</div>
|
|
114
|
-
</template>
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
The chat workspace is resolved from the authenticated `activeOrganization` provided by `@meistrari/auth-nuxt`.
|
|
19
|
+
`typedoc.ts` at the package root is the documentation barrel for that surface — it is what the published API reference is generated from. Adding an export there makes it public; keep internals out of it.
|
|
118
20
|
|
|
119
|
-
|
|
21
|
+
## Guides
|
|
120
22
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
`conversationScope` works in both runtimes. In default chat mode, it isolates conversations inside the authenticated workspace while the Chat API resolves the correct Tela agent:
|
|
131
|
-
|
|
132
|
-
```vue
|
|
133
|
-
<MeistrariChatEmbed :conversation-scope="`user:${userId}`" />
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
Host apps can also provide Tela agent inputs directly. When `telaAgentInputs` is non-null, the chat sends those inputs with each agent run and does not render the agent variables panel.
|
|
137
|
-
|
|
138
|
-
```vue
|
|
139
|
-
<MeistrariChatEmbed
|
|
140
|
-
tela-agent-id="agent_123"
|
|
141
|
-
:conversation-scope="`customer:${customerId}`"
|
|
142
|
-
:tela-agent-inputs="[
|
|
143
|
-
{ type: 'text', name: 'customer_id', content: customerId },
|
|
144
|
-
]"
|
|
145
|
-
/>
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
In Tela agent mode, `workspaceSettings` and `user` are not accepted by the public prop contract - the Tela agent owns runtime configuration and identity for execution. `features` is still accepted for shared UI controls.
|
|
23
|
+
| Guide | Covers |
|
|
24
|
+
|-------|--------|
|
|
25
|
+
| [Installation and setup](docs/guides/installation.md) | Install, Vue dedupe override, module registration, module options, auth modes |
|
|
26
|
+
| [Embedding in your layout](docs/guides/embedding.md) | Layout, key props, conversation scoping, events, slots |
|
|
27
|
+
| [Chat runtime modes](docs/guides/tela-agent-mode.md) | Default chat mode vs Tela agent mode, agent inputs |
|
|
28
|
+
| [Citations](docs/guides/citations.md) | `cite://` chips, metadata popover, document panel |
|
|
29
|
+
| [Feature flags](docs/guides/feature-flags.md) | Usage tab, debug entry, cancel button, PostHog wiring |
|
|
30
|
+
| [Message feedback](docs/guides/message-feedback.md) | 👍/👎 controls and host-owned persistence |
|
|
31
|
+
| [Workspace settings](docs/guides/workspace-settings.md) | Settings overrides, agent runtime ownership, `<ChatConfigurationModal>` |
|
|
149
32
|
|
|
150
|
-
##
|
|
33
|
+
## API Reference
|
|
151
34
|
|
|
152
|
-
The
|
|
35
|
+
The JSDoc on each type is the source of truth, and the hosted reference is generated from it — Pantry builds it from [`typedoc.ts`](typedoc.ts), the barrel listing every public symbol, using its own pinned TypeDoc. Generated output is never committed here. The `postinstall` hook runs `nuxi prepare` so the Nuxt types `tsconfig.json` depends on exist before that build runs.
|
|
153
36
|
|
|
154
|
-
|
|
155
|
-
<template>
|
|
156
|
-
<div class="my-app-layout">
|
|
157
|
-
<MyHeader />
|
|
37
|
+
To render the reference locally:
|
|
158
38
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
<div style="height: 600px" class="rounded-2xl overflow-hidden border">
|
|
162
|
-
<MeistrariChatEmbed
|
|
163
|
-
v-model:conversation-id="activeConversation"
|
|
164
|
-
:hide-sidebar="true"
|
|
165
|
-
:loading-messages="['Buscando contratos', 'Lendo documentos', 'Preparando resposta']"
|
|
166
|
-
loading-messages-mode="ordered"
|
|
167
|
-
/>
|
|
168
|
-
</div>
|
|
169
|
-
</main>
|
|
170
|
-
</div>
|
|
171
|
-
</template>
|
|
39
|
+
```bash
|
|
40
|
+
bunx --bun typedoc --entryPoints typedoc.ts --out /tmp/chat-nuxt-api --skipErrorChecking
|
|
172
41
|
```
|
|
173
42
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
- **`:hide-sidebar="true"`** — removes the conversation list, keeps just the chat
|
|
177
|
-
- **`v-model:conversation-id`** — sync the active conversation with your app's state
|
|
178
|
-
- **`:initial-conversation-id`** — open a specific conversation on mount
|
|
179
|
-
- **`conversation-scope`** — isolate conversation history inside the same workspace or Tela agent
|
|
43
|
+
The table below is a quick index for reading in-repo. **When you change a prop, update its JSDoc and this row together.**
|
|
180
44
|
|
|
181
|
-
|
|
45
|
+
### `<MeistrariChatEmbed>` props
|
|
182
46
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
```ts
|
|
186
|
-
import type {
|
|
187
|
-
ChatActionPayload,
|
|
188
|
-
ChatFeatureConfig,
|
|
189
|
-
MeistrariChatEmbedProps,
|
|
190
|
-
MessageFeedbackConfig,
|
|
191
|
-
MessageFeedbackPayload,
|
|
192
|
-
MessageFeedbackRating,
|
|
193
|
-
} from '@meistrari/chat-nuxt'
|
|
194
|
-
```
|
|
47
|
+
Declared in `src/runtime/embed/types.ts`; prop, feature-flag, and event payload types are importable from the package root or `@meistrari/chat-nuxt/types/embed`.
|
|
195
48
|
|
|
196
49
|
| Prop | Type | Default | Description |
|
|
197
50
|
|------|------|---------|-------------|
|
|
198
|
-
| `hideSidebar` | `boolean` | `false` | Hide conversation list
|
|
51
|
+
| `hideSidebar` | `boolean` | `false` | Hide the conversation list and render only the active chat surface |
|
|
199
52
|
| `sidebar` | `ChatSidebarConfig` | `undefined` | Sidebar layout: `{ position?, width?, bottomHeight?, collapsible?, defaultCollapsed? }`. `position` (`'left'`\|`'right'`, default `'left'`) picks the edge; `width` is the sidebar width in pixels (default `240`); `bottomHeight` is the `sidebar-bottom` pane height as a percentage 0–100 of the conversation area (default `50`); `collapsible` (default `false`) renders a native collapse handle and animates the sidebar open/closed; `defaultCollapsed` (default `false`) starts it collapsed |
|
|
200
53
|
| `hideSettings` | `boolean` | `false` | Hide workspace settings actions while keeping the chat header and content unchanged |
|
|
201
|
-
| `conversationId` | `string \| null` | `null` | Controlled conversation (supports v-model) |
|
|
202
|
-
| `initialConversationId` | `string \| null` | `null` |
|
|
203
|
-
| `conversationScope` | `string \| null` | `null` | Isolate conversation history by technical scope within the current workspace and runtime |
|
|
204
|
-
| `defaultConversationCreatorFilter` | `'all' \| 'mine'` | `'all'` | Initial sidebar creator filter |
|
|
54
|
+
| `conversationId` | `string \| null` | `null` | Controlled conversation (supports `v-model:conversation-id`) |
|
|
55
|
+
| `initialConversationId` | `string \| null` | `null` | Conversation to open once on mount when `conversationId` is uncontrolled |
|
|
56
|
+
| `conversationScope` | `string \| null` | `null` | Isolate conversation history by technical scope within the current workspace and runtime. Scoped embeds only see same-scope conversations; values are trimmed, blank becomes `null`, and the server accepts 1-200 chars from `A-Z`, `a-z`, `0-9`, `.`, `_`, `:`, `/`, `-` |
|
|
57
|
+
| `defaultConversationCreatorFilter` | `'all' \| 'mine'` | `'all'` | Initial sidebar creator filter: every conversation in scope, or only the current user's |
|
|
205
58
|
| `telaAgentId` | `string` | — | Use Tela agent mode for this embed |
|
|
206
59
|
| `telaAgentInputs` | `TelaAgentExecutionInput[] \| null` | `undefined` | Inputs sent with each Tela agent run; hides the variables panel when non-null |
|
|
207
|
-
| `workspaceSettings` | `WorkspaceSettings \| null` | `null` | Override settings from host app |
|
|
208
|
-
| `user` | `ChatActor \| null` | `null` | Override current user display info |
|
|
209
|
-
| `features` | `Partial<ChatFeatureConfig>` | `{}` | Toggle optional features |
|
|
60
|
+
| `workspaceSettings` | `WorkspaceSettings \| null` | `null` | Override settings from host app; not accepted in Tela agent mode |
|
|
61
|
+
| `user` | `ChatActor \| null` | `null` | Override current user display info; not accepted in Tela agent mode |
|
|
62
|
+
| `features` | `Partial<ChatFeatureConfig>` | `{}` | Toggle optional features: `showUsageTab`, `showDebugOption`, `showCancelButton` (all `false`) |
|
|
210
63
|
| `loadingMessages` | `readonly string[] \| null` | Default chat messages | Override pending-response messages |
|
|
211
|
-
| `loadingMessagesMode` | `'ordered' \| 'random' \| null` | `'ordered'` |
|
|
64
|
+
| `loadingMessagesMode` | `'ordered' \| 'random' \| null` | `'ordered'` | Rotate custom messages in order or at random; only applies when `loadingMessages` has a non-empty message |
|
|
212
65
|
| `customComponents` | `Record<string, Component>` | `undefined` | Custom markdown renderers keyed by markdown node or tag name |
|
|
213
66
|
| `customHtmlTags` | `readonly string[]` | `undefined` | Extra HTML tags allowed by the markdown renderer |
|
|
214
|
-
| `citations` | `ChatCitationsConfig \| null` | `undefined` | Enables `cite://` citations in assistant messages (see Citations
|
|
67
|
+
| `citations` | `ChatCitationsConfig \| null` | `undefined` | Enables `cite://` citations in assistant messages (see [Citations](docs/guides/citations.md)) |
|
|
215
68
|
| `feedbackConfig` | `MessageFeedbackConfig \| null` | `undefined` | Enables 👍/👎 feedback on assistant messages; providing the prop (even `{}`) shows the controls |
|
|
216
69
|
| `messageFeedback` | `Record<string, MessageFeedbackRating> \| null` | `undefined` | Host-persisted votes keyed by message id; when provided, it is the single source of truth for the selected thumbs |
|
|
217
70
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
Use `conversationScope` when you need multiple chat surfaces to share the same authenticated workspace but keep separate histories. This is useful for per-user inboxes, record detail pages, customer workspaces, template previews, workflow steps, or any app route where the same chat should only show conversations for that route's domain object. The scope is applied together with the workspace and, when present, the `telaAgentId`.
|
|
221
|
-
|
|
222
|
-
Scoped embeds only see conversations created with the same scope. Unscoped embeds only see unscoped conversations, so adding a scope will not mix with existing workspace-level history. Scope values are technical identifiers: they are trimmed, blank strings become `null`, and server requests accept 1-200 characters from `A-Z`, `a-z`, `0-9`, `.`, `_`, `:`, `/`, and `-`.
|
|
223
|
-
|
|
224
|
-
```vue
|
|
225
|
-
<!-- Default chat mode: workspace + scope -->
|
|
226
|
-
<MeistrariChatEmbed :conversation-scope="`user:${userId}`" />
|
|
227
|
-
<MeistrariChatEmbed :conversation-scope="`customer:${customerId}`" />
|
|
228
|
-
|
|
229
|
-
<!-- Tela agent mode: workspace + telaAgentId + scope -->
|
|
230
|
-
<MeistrariChatEmbed
|
|
231
|
-
tela-agent-id="agent_123"
|
|
232
|
-
:conversation-scope="`template:${templateId}`"
|
|
233
|
-
/>
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
**Citations (`cite://`):**
|
|
237
|
-
|
|
238
|
-
Hosts whose agents cite retrievable documents can teach them (via prompt) the notation
|
|
239
|
-
|
|
240
|
-
```
|
|
241
|
-
[visible text](cite://<namespace>/<id>[#q=<term>&n=<nth>&p=<page>])
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
and pass `citations` to enable it. The lib detects the notation in assistant messages (markdown links and bare tokens), renders each citation as a chip with a metadata popover, and — when `getDocument` is provided — opens a built-in side panel that shows the document with the cited term highlighted (`#q`, nth occurrence via `#n`). What a namespace means, and every data access, belongs to the host: callbacks run against the host's own backend, carrying the viewing user's authorization. A citation that fails to resolve renders as "unverified" — an agent cannot fabricate a trusted-looking reference, and a viewer without access to a document learns nothing from a citation to it.
|
|
245
|
-
|
|
246
|
-
```vue
|
|
247
|
-
<MeistrariChatEmbed
|
|
248
|
-
tela-agent-id="agent_123"
|
|
249
|
-
:citations="{
|
|
250
|
-
resolve: ref => $fetch(`/api/citations/${ref.namespace}/${encodeURIComponent(ref.id)}`).catch(() => null),
|
|
251
|
-
getDocument: ref => $fetch(`/api/citations/${ref.namespace}/${encodeURIComponent(ref.id)}/document`).catch(() => null),
|
|
252
|
-
locate: (ref, term) => $fetch(`/api/citations/${ref.namespace}/${encodeURIComponent(ref.id)}/occurrences`, { query: { term } }).catch(() => null),
|
|
253
|
-
}"
|
|
254
|
-
/>
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
`ref.id` arrives percent-decoded (natural identifiers may carry pipes, spaces, accents or slashes) — re-encode it when building URLs, as above.
|
|
258
|
-
|
|
259
|
-
`ChatCitationsConfig` (exported from `@meistrari/chat-nuxt/types/citations`): `resolve` maps a citation to display metadata (`null` = unverified); `getDocument` enables the document panel; `locate` returns precise term offsets for highlighting (omit it for a client-side, accent-sensitive fallback); `component` replaces the built-in chip; `onOpen` takes over the click entirely. Without the `citations` prop nothing changes: `cite://` hrefs keep rendering as plain links.
|
|
260
|
-
|
|
261
|
-
**Events:**
|
|
262
|
-
|
|
263
|
-
| Event | Payload | Description |
|
|
264
|
-
|-------|---------|-------------|
|
|
265
|
-
| `update:conversationId` | `string \| null` | Active conversation changed |
|
|
266
|
-
| `action` | `ChatActionPayload` | Custom action triggered from chat content (`{ name, data, messageId? }`) |
|
|
267
|
-
| `messageFeedback` | `MessageFeedbackPayload` | User voted on an assistant message (see [Message Feedback](#optional-message-feedback)) |
|
|
268
|
-
|
|
269
|
-
**Slots:**
|
|
270
|
-
|
|
271
|
-
| Slot | Description |
|
|
272
|
-
|------|-------------|
|
|
273
|
-
| `sidebar-bottom` | Splits the desktop sidebar into two panes and renders your content in the bottom one, below the conversation list. Each pane scrolls independently. Size it with `sidebar.bottomHeight` (percentage, default `50`). Not rendered on mobile or when `hideSidebar` is set. |
|
|
274
|
-
|
|
275
|
-
```vue
|
|
276
|
-
<MeistrariChatEmbed :sidebar="{ position: 'right', width: 300, bottomHeight: 30 }">
|
|
277
|
-
<template #sidebar-bottom>
|
|
278
|
-
<MyPinnedDocuments />
|
|
279
|
-
</template>
|
|
280
|
-
</MeistrariChatEmbed>
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
## Optional: Feature Flags
|
|
284
|
-
|
|
285
|
-
`<MeistrariChatEmbed>` accepts a `:features` prop with three optional toggles. All default to `false`. The host owns the policy - hardcode them, gate by user role, or wire them through a feature-flag provider of your choice.
|
|
286
|
-
|
|
287
|
-
| Flag | Effect |
|
|
288
|
-
|------|--------|
|
|
289
|
-
| `showUsageTab` | Usage tab in the chat topbar (per-conversation token/cost stats) |
|
|
290
|
-
| `showDebugOption` | Debug entry in the topbar overflow menu |
|
|
291
|
-
| `showCancelButton` | "Stop generation" button while a response streams |
|
|
292
|
-
|
|
293
|
-
Static example:
|
|
294
|
-
|
|
295
|
-
```vue
|
|
296
|
-
<MeistrariChatEmbed :features="{ showUsageTab: true, showCancelButton: true }" />
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
### With PostHog
|
|
300
|
-
|
|
301
|
-
`chat-nuxt` ships a small PostHog helper for hosts that want to gate flags dynamically. The flag names live in your app — `chat-nuxt` has no opinion about them.
|
|
302
|
-
|
|
303
|
-
1. Add to `nuxt.config.ts`:
|
|
304
|
-
|
|
305
|
-
```typescript
|
|
306
|
-
runtimeConfig: {
|
|
307
|
-
public: {
|
|
308
|
-
posthogPublicKey: process.env.POSTHOG_PUBLIC_KEY ?? '',
|
|
309
|
-
posthogHost: process.env.POSTHOG_HOST ?? '',
|
|
310
|
-
posthogDefaults: process.env.POSTHOG_DEFAULTS ?? '2026-01-30',
|
|
311
|
-
},
|
|
312
|
-
},
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
2. Initialize in `app.vue`:
|
|
316
|
-
|
|
317
|
-
```vue
|
|
318
|
-
<script setup lang="ts">
|
|
319
|
-
const { posthogPublicKey, posthogHost, posthogDefaults } = useRuntimeConfig().public
|
|
320
|
-
|
|
321
|
-
// Application auth hosts:
|
|
322
|
-
const { user, activeOrganization } = useTelaApplicationAuth()
|
|
323
|
-
|
|
324
|
-
// First-party auth hosts can use this instead:
|
|
325
|
-
// const session = useTelaSession()
|
|
326
|
-
// const organization = useTelaOrganization()
|
|
327
|
-
// const user = session.user
|
|
328
|
-
// const activeOrganization = organization.activeOrganization
|
|
329
|
-
// await organization.getActiveOrganization()
|
|
330
|
-
|
|
331
|
-
onMounted(async () => {
|
|
332
|
-
if (!posthogPublicKey || !posthogHost) return
|
|
333
|
-
await initPosthog(posthogPublicKey, posthogHost, posthogDefaults)
|
|
334
|
-
if (user.value) identifyPosthogUser(user.value)
|
|
335
|
-
if (activeOrganization.value) setPosthogWorkspace(activeOrganization.value)
|
|
336
|
-
})
|
|
337
|
-
</script>
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
3. Thread the flags into the embed:
|
|
341
|
-
|
|
342
|
-
```vue
|
|
343
|
-
<script setup lang="ts">
|
|
344
|
-
const { isFeatureEnabled } = useFeatureFlags()
|
|
345
|
-
|
|
346
|
-
const features = computed(() => ({
|
|
347
|
-
showUsageTab: isFeatureEnabled('enable-usage-tab'),
|
|
348
|
-
showDebugOption: isFeatureEnabled('enable-debug-mode'),
|
|
349
|
-
showCancelButton: isFeatureEnabled('enable-cancel-generation'),
|
|
350
|
-
}))
|
|
351
|
-
</script>
|
|
352
|
-
|
|
353
|
-
<template>
|
|
354
|
-
<MeistrariChatEmbed :features="features" />
|
|
355
|
-
</template>
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
## Optional: Message Feedback
|
|
359
|
-
|
|
360
|
-
Assistant messages can carry 👍/👎 controls. The package renders the controls and collects the vote; **persistence is owned by the host** — nothing is stored by `chat-nuxt`.
|
|
361
|
-
|
|
362
|
-
Passing `feedbackConfig` (even `{}`) enables the controls:
|
|
363
|
-
|
|
364
|
-
```vue
|
|
365
|
-
<script setup lang="ts">
|
|
366
|
-
import type { MessageFeedbackPayload, MessageFeedbackRating } from '@meistrari/chat-nuxt'
|
|
367
|
-
|
|
368
|
-
const votes = ref<Record<string, MessageFeedbackRating>>({})
|
|
369
|
-
|
|
370
|
-
async function onFeedback(payload: MessageFeedbackPayload) {
|
|
371
|
-
// payload: { conversationId, messageId, rating, reasons, comment }
|
|
372
|
-
await saveVoteToMyBackend(payload)
|
|
373
|
-
votes.value = { ...votes.value, [payload.messageId]: payload.rating }
|
|
374
|
-
}
|
|
375
|
-
</script>
|
|
376
|
-
|
|
377
|
-
<template>
|
|
378
|
-
<MeistrariChatEmbed
|
|
379
|
-
:feedback-config="{
|
|
380
|
-
negativeReasons: ['Resposta incorreta', 'Fora do tema', 'Incompleta'],
|
|
381
|
-
requireReason: true,
|
|
382
|
-
}"
|
|
383
|
-
:message-feedback="votes"
|
|
384
|
-
@message-feedback="onFeedback"
|
|
385
|
-
/>
|
|
386
|
-
</template>
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
`MessageFeedbackConfig` fields:
|
|
390
|
-
|
|
391
|
-
| Field | Effect |
|
|
392
|
-
|-------|--------|
|
|
393
|
-
| `positiveReasons` | Reason chips offered on a positive vote. Empty or omitted: 👍 submits directly |
|
|
394
|
-
| `negativeReasons` | Reason chips offered on a negative vote |
|
|
395
|
-
| `requireReason` | Blocks a bare negative vote: requires at least one reason chip when `negativeReasons` are configured, otherwise a non-empty comment |
|
|
396
|
-
|
|
397
|
-
`messageFeedback` controls which thumb renders selected:
|
|
398
|
-
|
|
399
|
-
- **Provided** (controlled): only host-persisted votes render. Update the map as `message-feedback` events are saved — optimistically or after persistence.
|
|
400
|
-
- **Omitted**: votes are kept in component-local state only.
|
|
401
|
-
|
|
402
|
-
## Optional: Custom Workspace Settings
|
|
403
|
-
|
|
404
|
-
Agent-level configuration (system prompt, context files, tools, skills) lives in the workspace's Tela agent and is edited in the Tela app. The module's built-in settings UI manages knowledge sources (Tela workstations) and workspace credentials, persisted by the Chat API service.
|
|
405
|
-
|
|
406
|
-
To override the settings the embed reads, pass them directly from your host app:
|
|
407
|
-
|
|
408
|
-
```vue
|
|
409
|
-
<MeistrariChatEmbed
|
|
410
|
-
:workspace-settings="{
|
|
411
|
-
workspaceId: 'ws_123',
|
|
412
|
-
systemMessage: 'You are a helpful assistant for Acme Corp.',
|
|
413
|
-
contextFiles: null,
|
|
414
|
-
canvasTools: null,
|
|
415
|
-
knowledgeSources: null,
|
|
416
|
-
externalSkills: null,
|
|
417
|
-
updatedAt: new Date(),
|
|
418
|
-
}"
|
|
419
|
-
/>
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
The `server/chat/resolve-workspace-settings.ts` host resolver from earlier versions is no longer invoked: the module proxies chat requests to the Chat API, which owns workspace settings resolution.
|
|
423
|
-
|
|
424
|
-
## Agent Runtime Configuration
|
|
425
|
-
|
|
426
|
-
`chat-nuxt` proxies chat requests to `@meistrari/chat-api`; it does not start agent sessions directly or resolve runtime environment variables. Agent runtime configuration, entitlements, and Tela agent selection are owned by `chat-api` and the Tela agent configuration. Host apps do not need Nuxt-side agent environment resolver files for this module.
|
|
427
|
-
|
|
428
|
-
A skill that calls a host backend must implement its own callback contract with the host backend. In short, callback authorization belongs to the skill and host backend, not `chat-nuxt`. The host backend remains responsible for validating invocation grants, allowed tools, schemas, replay protection, confirmation for writes, and audit logging.
|
|
429
|
-
|
|
430
|
-
## `<ChatConfigurationModal>`
|
|
431
|
-
|
|
432
|
-
A reusable workspace settings modal that any host app can open from any button. It has three tabs:
|
|
433
|
-
|
|
434
|
-
- **`agent`** (Agente) — the workspace's Tela agent status. Shows the generic-chat state, the dedicated agent (id, copy, open in Tela), or — for workspaces whose legacy customization has not been migrated — a setup-required warning with a create-agent action. Agent configuration itself (system prompt, context files, tools, skills) is edited in the Tela app, not here.
|
|
435
|
-
- **`knowledge-sources`** (Tela workstations) — the workstations injected as knowledge sources into new chat sessions.
|
|
436
|
-
- **`credentials`** (Credenciais) — workspace credentials, shown when `showCredentialsTab` is set.
|
|
437
|
-
|
|
438
|
-
By default, the modal uses `useWorkspaceSettings()` to fetch and persist settings. If the host passes the `settings` prop, the host owns workspace settings state and persistence.
|
|
439
|
-
|
|
440
|
-
```vue
|
|
441
|
-
<script setup lang="ts">
|
|
442
|
-
import type { ChatConfigurationTab } from '@meistrari/chat-nuxt/types/workspace-settings'
|
|
443
|
-
|
|
444
|
-
const open = ref(false)
|
|
445
|
-
const initialTab = ref<ChatConfigurationTab>('agent')
|
|
446
|
-
|
|
447
|
-
function openSettings(tab: ChatConfigurationTab = 'agent') {
|
|
448
|
-
initialTab.value = tab
|
|
449
|
-
open.value = true
|
|
450
|
-
}
|
|
451
|
-
</script>
|
|
452
|
-
|
|
453
|
-
<template>
|
|
454
|
-
<button @click="openSettings()">
|
|
455
|
-
Configurações
|
|
456
|
-
</button>
|
|
457
|
-
|
|
458
|
-
<ChatConfigurationModal
|
|
459
|
-
v-model:open="open"
|
|
460
|
-
:initial-tab="initialTab"
|
|
461
|
-
/>
|
|
462
|
-
</template>
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
| Prop | Type | Default | Description |
|
|
466
|
-
|------|------|---------|-------------|
|
|
467
|
-
| `open` | `boolean` | — | Modal visibility (supports `v-model:open`) |
|
|
468
|
-
| `settings` | `WorkspaceSettings \| null` | `undefined` | Optional host-controlled settings. Omit this prop to let the modal fetch and persist via `useWorkspaceSettings()`; pass `null` or a settings object to make the host own state and persistence |
|
|
469
|
-
| `initialTab` | `ChatConfigurationTab` | `'agent'` | Tab to open on: `'agent' \| 'knowledge-sources' \| 'credentials'` |
|
|
470
|
-
| `saving` | `boolean` | `false` | Host-controlled spinner/disable while persistence is in flight |
|
|
471
|
-
| `showCredentialsTab` | `boolean` | `false` | Show the workspace credentials tab |
|
|
472
|
-
|
|
473
|
-
| Event | Payload | Description |
|
|
474
|
-
|-------|---------|-------------|
|
|
475
|
-
| `update:open` | `boolean` | Modal open state changed |
|
|
476
|
-
| `save` | `ChatConfigurationSavePayload` | Emitted only when the host passes `settings`; carries the knowledge-source updates plus `onSaved`; host persists (e.g. via `useWorkspaceSettings().updateSettings()`), calls `onSaved` after persistence succeeds, and closes the modal |
|
|
477
|
-
|
|
478
|
-
Only the knowledge-sources tab produces a `save` payload. The `agent` tab acts immediately through the module's `/api/workspace/agent` endpoints, and the `credentials` tab manages its own data via `/api/workspace/credentials` — neither is part of the `save` payload.
|
|
71
|
+
Events and slots are listed in [Embedding in your layout](docs/guides/embedding.md); `<ChatConfigurationModal>` props and events are in [Workspace settings](docs/guides/workspace-settings.md).
|
|
479
72
|
|
|
480
73
|
## What's Included
|
|
481
74
|
|
|
@@ -485,6 +78,23 @@ The module auto-registers everything — no manual imports needed:
|
|
|
485
78
|
- **Composables**: `useChat`, `useConversations`, `useWorkspaceSettings`, `useFileUpload`, `useFeatureFlags`, and more
|
|
486
79
|
- **Server routes**: thin proxy routes that forward chat requests to the Chat API service
|
|
487
80
|
|
|
81
|
+
## Development
|
|
82
|
+
|
|
83
|
+
Run from this package:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pnpm build # nuxt-module-build + embedded schema/declaration post-processing
|
|
87
|
+
pnpm dev:prepare # stub build for local development
|
|
88
|
+
pnpm typecheck # builds the module, prepares chat-app, typechecks the host app
|
|
89
|
+
pnpm test:types # build + tsc against the consumer type tests
|
|
90
|
+
pnpm smoke:pack # pack the module and install it into a scratch consumer
|
|
91
|
+
pnpm smoke:browser # packed-consumer smoke test with a real browser
|
|
92
|
+
pnpm lint # eslint
|
|
93
|
+
pnpm lint:attrs # guards against stray `!` attribute typos in runtime templates
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Unit tests run from the workspace root (`pnpm test`), which prepares this package before invoking vitest.
|
|
97
|
+
|
|
488
98
|
## Package Dependencies
|
|
489
99
|
|
|
490
100
|
Installing `@meistrari/chat-nuxt` installs the runtime packages used by the layer. The host Nuxt app still owns the Nuxt and Vue versions.
|
|
@@ -515,5 +125,5 @@ Peer dependencies:
|
|
|
515
125
|
|
|
516
126
|
| Package | Version | Purpose |
|
|
517
127
|
|---------|---------|---------|
|
|
518
|
-
| `nuxt` | `^3.17.0` | Host framework |
|
|
128
|
+
| `nuxt` | `^3.17.0 \|\| ^4.0.0` | Host framework |
|
|
519
129
|
| `vue` | `^3.5.0` | Host Vue runtime |
|
package/dist/module.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ChatMessageStatus } from '../dist/runtime/messages/composables/chat-message-terminal.js';
|
|
2
|
-
export { ChatActionPayload, ChatActor, ChatEmbedSharedProps, ChatFeatureConfig, ChatMessageTerminalPayload, ChatSidebarConfig, DefaultChatEmbedProps, MeistrariChatEmbedProps, MessageFeedbackConfig, MessageFeedbackPayload, MessageFeedbackRating, MessageOverviewResponse, TelaAgentChatEmbedProps, TelaAgentExecutionInput } from '../dist/runtime/types/embed.js';
|
|
2
|
+
export { ChatActionPayload, ChatActor, ChatEmbedSharedProps, ChatEmbedVariant, ChatEmbedVariantProps, ChatFeatureConfig, ChatMessageTerminalPayload, ChatSidebarConfig, ChatSuggestion, DefaultChatEmbedProps, MeistrariChatEmbedProps, MessageFeedbackConfig, MessageFeedbackPayload, MessageFeedbackRating, MessageOverviewResponse, TelaAgentChatEmbedProps, TelaAgentExecutionInput } from '../dist/runtime/types/embed.js';
|
|
3
3
|
|
|
4
4
|
type ChatNuxtConfigValidationMode = false | 'warn' | 'error';
|
|
5
5
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -125,6 +125,35 @@ function resolveRuntimeAliases(telaBuildPath) {
|
|
|
125
125
|
return resolvedAliases;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
const QUADRATIC_GUARDS = [
|
|
129
|
+
{ from: "/[^~]*~{2,}[^~]+/", to: "/~{2,}[^~]/" },
|
|
130
|
+
{ from: "/[^*]*\\*[^*]+/", to: "/\\*[^*]/" }
|
|
131
|
+
];
|
|
132
|
+
const STREAM_MARKDOWN_PARSER_GUARD_COUNT = QUADRATIC_GUARDS.length;
|
|
133
|
+
function patchStreamMarkdownParserSource(source) {
|
|
134
|
+
let patched = source;
|
|
135
|
+
let applied = 0;
|
|
136
|
+
for (const { from, to } of QUADRATIC_GUARDS) {
|
|
137
|
+
if (!patched.includes(from)) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
patched = patched.replaceAll(from, to);
|
|
141
|
+
applied++;
|
|
142
|
+
}
|
|
143
|
+
patched = patched.replace(/\n?\/\/# sourceMappingURL=.*\n?$/, "\n");
|
|
144
|
+
return { source: patched, applied };
|
|
145
|
+
}
|
|
146
|
+
function resolvePatchedStreamMarkdownParser(from) {
|
|
147
|
+
try {
|
|
148
|
+
const markstreamEntry = createRequire(from).resolve("markstream-vue");
|
|
149
|
+
const entry = createRequire(markstreamEntry).resolve("stream-markdown-parser");
|
|
150
|
+
const { source, applied } = patchStreamMarkdownParserSource(readFileSync(entry, "utf8"));
|
|
151
|
+
return { entry, source, applied };
|
|
152
|
+
} catch {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
128
157
|
const workspaceSettingsResolverCandidates = [
|
|
129
158
|
"server/chat/resolve-workspace-settings.ts",
|
|
130
159
|
"server/chat/resolve-workspace-settings.js"
|
|
@@ -347,12 +376,25 @@ const module$1 = defineNuxtModule({
|
|
|
347
376
|
nuxt.options.extends = nuxt.options.extends ? [nuxt.options.extends] : [];
|
|
348
377
|
}
|
|
349
378
|
nuxt.options.extends.unshift(telaBuildPath);
|
|
379
|
+
const patchedStreamMarkdownParser = resolvePatchedStreamMarkdownParser(import.meta.url);
|
|
380
|
+
if (patchedStreamMarkdownParser?.applied !== STREAM_MARKDOWN_PARSER_GUARD_COUNT) {
|
|
381
|
+
const cause = patchedStreamMarkdownParser ? `${patchedStreamMarkdownParser.entry}: expected ${STREAM_MARKDOWN_PARSER_GUARD_COUNT} guards, found ${patchedStreamMarkdownParser.applied}` : "not resolvable through markstream-vue";
|
|
382
|
+
console.error(
|
|
383
|
+
`[@meistrari/chat-nuxt] Could not rewrite the quadratic guards in stream-markdown-parser (${cause}). Long unbroken Markdown paragraphs will parse quadratically and can freeze the chat UI. Update QUADRATIC_GUARDS in @meistrari/chat-nuxt, or drop the rewrite if upstream fixed the backtracking.`
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
const streamMarkdownParserAlias = patchedStreamMarkdownParser?.applied === STREAM_MARKDOWN_PARSER_GUARD_COUNT ? addTemplate({
|
|
387
|
+
filename: "chat-nuxt/stream-markdown-parser.mjs",
|
|
388
|
+
write: true,
|
|
389
|
+
getContents: () => patchedStreamMarkdownParser.source
|
|
390
|
+
}).dst : void 0;
|
|
350
391
|
nuxt.options.alias = {
|
|
351
392
|
...nuxt.options.alias,
|
|
352
393
|
"#chat-auth": chatAuthTemplate.dst,
|
|
353
394
|
"#chat-workspace-settings-resolver": workspaceSettingsResolverEntry,
|
|
354
395
|
"#chat-runtime": runtimeDir,
|
|
355
|
-
"@iconify-json/ph": resolvePackageRoot("@iconify-json/ph")
|
|
396
|
+
"@iconify-json/ph": resolvePackageRoot("@iconify-json/ph"),
|
|
397
|
+
...streamMarkdownParserAlias ? { "stream-markdown-parser": streamMarkdownParserAlias } : {}
|
|
356
398
|
};
|
|
357
399
|
const importsOptions = nuxt.options.imports;
|
|
358
400
|
if (importsOptions !== false) {
|
|
@@ -404,10 +446,20 @@ const module$1 = defineNuxtModule({
|
|
|
404
446
|
});
|
|
405
447
|
}
|
|
406
448
|
nuxt.hook("vite:extendConfig", (config, { isServer }) => {
|
|
449
|
+
config.resolve = config.resolve || {};
|
|
450
|
+
if (streamMarkdownParserAlias) {
|
|
451
|
+
if (Array.isArray(config.resolve.alias)) {
|
|
452
|
+
config.resolve.alias.push({ find: "stream-markdown-parser", replacement: streamMarkdownParserAlias });
|
|
453
|
+
} else {
|
|
454
|
+
config.resolve.alias = {
|
|
455
|
+
...config.resolve.alias || {},
|
|
456
|
+
"stream-markdown-parser": streamMarkdownParserAlias
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
}
|
|
407
460
|
if (isServer) {
|
|
408
461
|
return;
|
|
409
462
|
}
|
|
410
|
-
config.resolve = config.resolve || {};
|
|
411
463
|
config.plugins = config.plugins || [];
|
|
412
464
|
if (Array.isArray(config.resolve.alias)) {
|
|
413
465
|
config.resolve.alias.push(...Object.entries(runtimeAliases).map(([find, replacement]) => ({ find, replacement })));
|
|
@@ -451,7 +503,8 @@ export default globalThis.ELK;
|
|
|
451
503
|
...nitroConfig.alias,
|
|
452
504
|
"#chat-auth": chatAuthTemplate.dst,
|
|
453
505
|
"#chat-runtime": runtimeDir,
|
|
454
|
-
"#chat-workspace-settings-resolver": workspaceSettingsResolverEntry
|
|
506
|
+
"#chat-workspace-settings-resolver": workspaceSettingsResolverEntry,
|
|
507
|
+
...streamMarkdownParserAlias ? { "stream-markdown-parser": streamMarkdownParserAlias } : {}
|
|
455
508
|
};
|
|
456
509
|
nitroConfig.publicAssets = nitroConfig.publicAssets || [];
|
|
457
510
|
nitroConfig.publicAssets.push({
|