@meistrari/chat-nuxt 1.2.2 → 1.3.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 +71 -48
- package/dist/module.d.mts +24 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +37 -19
- package/dist/runtime/components/MeistrariChatEmbed.d.vue.ts +3 -1
- package/dist/runtime/components/MeistrariChatEmbed.vue +5 -3
- package/dist/runtime/components/MeistrariChatEmbed.vue.d.ts +3 -1
- package/dist/runtime/components/chat/thinking-indicator.vue +28 -17
- package/dist/runtime/composables/useEmbedConfig.d.ts +5 -0
- package/dist/runtime/composables/useEmbedConfig.js +11 -3
- package/dist/runtime/embed/components/ChatConfigurationModal.vue +8 -6
- package/dist/runtime/embed/components/ChatEmbed.d.vue.ts +3 -1
- package/dist/runtime/embed/components/ChatEmbed.vue +13 -12
- package/dist/runtime/embed/components/ChatEmbed.vue.d.ts +3 -1
- package/dist/runtime/embed/components/ChatEmbedInner.vue +5 -1
- package/dist/runtime/plugins/markstream.d.ts +2 -0
- package/dist/runtime/plugins/markstream.js +5 -0
- package/dist/runtime/server/api/conversations/[id]/messages/[messageId]/retry.post.js +7 -4
- package/dist/runtime/server/api/conversations/[id]/messages/index.post.js +7 -4
- package/dist/runtime/server/api/conversations/[id]/usage.get.js +1 -1
- package/dist/runtime/server/api/conversations/generate-title.post.js +18 -5
- package/dist/runtime/server/api/workspace/usage.get.js +1 -1
- package/dist/runtime/server/db/index.d.ts +20 -3
- package/dist/runtime/server/db/index.js +87 -10
- package/dist/runtime/server/db/schema/_schema.d.ts +2 -0
- package/dist/runtime/server/db/schema/_schema.js +3 -0
- package/dist/runtime/server/db/schema/conversation-usage.d.ts +1 -1
- package/dist/runtime/server/db/schema/conversation-usage.js +3 -2
- package/dist/runtime/server/db/schema/conversations.d.ts +1 -1
- package/dist/runtime/server/db/schema/conversations.js +3 -2
- package/dist/runtime/server/db/schema/external-skills.d.ts +1 -1
- package/dist/runtime/server/db/schema/external-skills.js +3 -2
- package/dist/runtime/server/db/schema/index.d.ts +1 -0
- package/dist/runtime/server/db/schema/index.js +1 -0
- package/dist/runtime/server/db/schema/messages.d.ts +1 -1
- package/dist/runtime/server/db/schema/messages.js +3 -2
- package/dist/runtime/server/db/schema/workspace-settings.d.ts +1 -1
- package/dist/runtime/server/db/schema/workspace-settings.js +3 -2
- package/dist/runtime/server/plugins/init-db.d.ts +2 -0
- package/dist/runtime/server/plugins/init-db.js +11 -0
- package/dist/runtime/server/utils/billing.d.ts +26 -4
- package/dist/runtime/server/utils/billing.js +52 -13
- package/dist/runtime/server/utils/chat-workspace-settings.js +1 -1
- package/dist/runtime/utils/chat-loading-messages.d.ts +12 -0
- package/dist/runtime/utils/chat-loading-messages.js +40 -0
- package/dist/runtime/utils/features.d.ts +6 -0
- package/dist/runtime/utils/features.js +15 -0
- package/dist/types.d.mts +1 -1
- package/drizzle/0000_material_hiroim.sql +28 -0
- package/drizzle/0001_famous_scalphunter.sql +1 -0
- package/drizzle/0002_gorgeous_big_bertha.sql +1 -0
- package/drizzle/0003_massive_forge.sql +2 -0
- package/drizzle/0004_absent_black_tom.sql +2 -0
- package/drizzle/0005_first_kid_colt.sql +1 -0
- package/drizzle/0006_sloppy_mauler.sql +13 -0
- package/drizzle/0007_grey_rhino.sql +1 -0
- package/drizzle/0008_chilly_blue_blade.sql +27 -0
- package/drizzle/0009_cultured_maddog.sql +16 -0
- package/drizzle/0010_small_barracuda.sql +1 -0
- package/drizzle/0011_fat_lady_mastermind.sql +6 -0
- package/drizzle/0012_puzzling_rick_jones.sql +1 -0
- package/drizzle/0013_blue_gwen_stacy.sql +11 -0
- package/drizzle/meta/0000_snapshot.json +239 -0
- package/drizzle/meta/0001_snapshot.json +245 -0
- package/drizzle/meta/0002_snapshot.json +251 -0
- package/drizzle/meta/0003_snapshot.json +263 -0
- package/drizzle/meta/0004_snapshot.json +275 -0
- package/drizzle/meta/0005_snapshot.json +281 -0
- package/drizzle/meta/0006_snapshot.json +320 -0
- package/drizzle/meta/0007_snapshot.json +326 -0
- package/drizzle/meta/0008_snapshot.json +539 -0
- package/drizzle/meta/0009_snapshot.json +646 -0
- package/drizzle/meta/0010_snapshot.json +653 -0
- package/drizzle/meta/0011_snapshot.json +689 -0
- package/drizzle/meta/0012_snapshot.json +695 -0
- package/drizzle/meta/0013_snapshot.json +699 -0
- package/drizzle/meta/_journal.json +104 -0
- package/package.json +5 -3
- package/dist/runtime/server/tasks/send-daily-usage-report.d.ts +0 -2
- package/dist/runtime/server/tasks/send-daily-usage-report.js +0 -74
- package/dist/runtime/server/utils/auth-api.d.ts +0 -1
- package/dist/runtime/server/utils/auth-api.js +0 -27
package/README.md
CHANGED
|
@@ -41,6 +41,16 @@ export default defineNuxtConfig({
|
|
|
41
41
|
ssr: false,
|
|
42
42
|
|
|
43
43
|
chatNuxt: {
|
|
44
|
+
telaApiUrl: process.env.TELA_API_URL,
|
|
45
|
+
agentApiUrl: process.env.AGENT_API_URL,
|
|
46
|
+
authApiUrl: process.env.AUTH_API_URL,
|
|
47
|
+
vaultUrl: process.env.VAULT_URL,
|
|
48
|
+
databaseUrl: '', // leave empty to use the bundled pglite database
|
|
49
|
+
features: {
|
|
50
|
+
usage: true,
|
|
51
|
+
generateTitle: false,
|
|
52
|
+
credentials: false,
|
|
53
|
+
},
|
|
44
54
|
validateConfig: 'warn',
|
|
45
55
|
},
|
|
46
56
|
|
|
@@ -53,73 +63,83 @@ export default defineNuxtConfig({
|
|
|
53
63
|
dashboardUrl: process.env.AUTH_DASHBOARD_URL ?? '',
|
|
54
64
|
},
|
|
55
65
|
},
|
|
56
|
-
|
|
57
|
-
// Prevents duplicate Vue instances with pnpm
|
|
58
|
-
vite: {
|
|
59
|
-
resolve: {
|
|
60
|
-
dedupe: ['vue', '@vue/runtime-core', '@vue/reactivity', '@vue/runtime-dom', '@vue/shared', 'reka-ui', 'radix-vue', '@floating-ui/vue', '@vueuse/core'],
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
66
|
})
|
|
64
67
|
```
|
|
65
68
|
|
|
66
|
-
### 2.
|
|
69
|
+
### 2. Module options
|
|
67
70
|
|
|
68
|
-
|
|
71
|
+
Every `chatNuxt.*` URL accepts the value inline, or you can leave the option empty and set the matching env var. Resolution order: **module option → existing `runtimeConfig` → env var → empty (or pglite default for `databaseUrl`)**.
|
|
69
72
|
|
|
70
|
-
|
|
|
71
|
-
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `VAULT_URL` | Vault service URL |
|
|
80
|
-
| `VAULT_S3_BUCKET` | Vault S3 bucket name |
|
|
81
|
-
| `CHAT_APP_SERVICE_KEY` | Service key used when resolving workspace credentials |
|
|
73
|
+
| Option | Required | Env fallback | Description |
|
|
74
|
+
|--------|----------|--------------|-------------|
|
|
75
|
+
| `telaApiUrl` | ✅ Always | `TELA_API_URL` | Tela platform API base URL. |
|
|
76
|
+
| `agentApiUrl` | ✅ Always | `AGENT_API_URL` | Agent runtime base URL the chat streams from. |
|
|
77
|
+
| `authApiUrl` | ✅ Always | `AUTH_API_URL` | Auth API base URL used to verify session tokens. |
|
|
78
|
+
| `vaultUrl` | ✅ Always | `VAULT_URL` | Vault API base URL used for file uploads and resolution. |
|
|
79
|
+
| `databaseUrl` | 🔧 Optional | `DATABASE_URL` | Postgres connection string. Falls back to a file-backed pglite database for local dev. |
|
|
80
|
+
| `features` | 🔧 Optional | — | Feature toggles (see below). `usage` defaults to `true`; the rest default to `false`. |
|
|
81
|
+
| `validateConfig` | 🔧 Optional | — | `false` (default), `'warn'`, or `'error'`. Warns or fails fast when required runtime config is missing for the enabled features. |
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
### 3. Set environment-only secrets
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
These never appear in module options — set them via `.env`, Infisical, etc. Whether each one is required depends on which features are enabled.
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
import '@meistrari/chat-nuxt/assets/css/code-theme.css'
|
|
87
|
+
| Variable | Required when | Description |
|
|
88
|
+
|----------|---------------|-------------|
|
|
89
|
+
| `AUTH_API_SECRET` | `features.usage: true` | Bearer token chat-nuxt uses to call the Auth API to resolve workspace billing info for the usage feature. |
|
|
90
|
+
| `TELA_API_KEY` | `features.generateTitle: true` | Authenticates the auto-title-generation endpoint, which executes a Meistrari-owned Tela canvas server-side. |
|
|
91
|
+
| `CHAT_APP_SERVICE_KEY` | `features.credentials: true` | Server-to-server `X-Service-Key` used when chat-nuxt resolves workspace credentials (`POST /workspaces/:id/credentials/resolve`). |
|
|
92
|
+
| `VAULT_S3_BUCKET` | 🔧 Optional | SSRF hardening: when set, `/api/vault/permalink-metadata` only follows S3 redirects to `<bucket>.s3*.amazonaws.com`. Recommended in production. |
|
|
94
93
|
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
### 4. Features
|
|
95
|
+
|
|
96
|
+
`usage` defaults to `true` — the chat experience always tracks per-conversation usage out of the box. `generateTitle` and `credentials` default to `false` and layer on optional behavior with their own runtime requirements.
|
|
97
|
+
|
|
98
|
+
| Feature | What it does | Adds to required config |
|
|
99
|
+
|---------|--------------|-------------------------|
|
|
100
|
+
| `usage` | Per-conversation token & cost tracking, daily aggregated reports, and the usage tab UI surface. | `AUTH_API_SECRET` |
|
|
101
|
+
| `generateTitle` | Auto-generates conversation titles from the first user message via a Tela canvas. Without this, titles fall back to a truncated prefix of the message. | `TELA_API_KEY` |
|
|
102
|
+
| `credentials` | Resolves workspace-level credentials and injects them into agent calls so tools can authenticate as the workspace. | `CHAT_APP_SERVICE_KEY` |
|
|
103
|
+
|
|
104
|
+
Set `chatNuxt.validateConfig` to `'warn'` to log a warning when keys for an enabled feature are missing, or `'error'` to fail fast at module setup. The check is off by default since some deployments inject runtime config after build.
|
|
105
|
+
|
|
106
|
+
### Local mode (no database)
|
|
97
107
|
|
|
108
|
+
When `databaseUrl` is empty, chat-nuxt runs an embedded [pglite](https://pglite.dev) instance — Postgres compiled to WASM, in-process, file-backed at `<rootDir>/.data/chat-nuxt.db`. Migrations are applied automatically on first boot. Tables live under a dedicated `chat` Postgres schema so the database can be safely shared with the host app's own Drizzle setup.
|
|
109
|
+
|
|
110
|
+
This mode is intended for local development, demos, and single-instance prototypes. Caveats:
|
|
111
|
+
|
|
112
|
+
- **Single-process only.** Multi-instance deployments (e.g. Railway with `replicas > 1`) will see divergent local databases — use real Postgres.
|
|
113
|
+
- **Node runtime only.** Pglite needs a filesystem. It won't run on Cloudflare Workers / Vercel Edge.
|
|
114
|
+
- **Roughly 4 MB of WASM** is loaded at server startup. Postgres consumers don't pay this cost (the import is dynamic).
|
|
115
|
+
|
|
116
|
+
To explicitly opt into pglite at a custom path: `databaseUrl: 'pglite:/var/data/chat.db'` or `databaseUrl: 'file:./mydata/chat.db'`.
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
### 5. Setup `app.vue`
|
|
120
|
+
|
|
121
|
+
```vue
|
|
122
|
+
<!-- app.vue -->
|
|
98
123
|
<template>
|
|
99
124
|
<NuxtPage />
|
|
100
125
|
<AppStatusToast />
|
|
101
126
|
</template>
|
|
102
127
|
```
|
|
103
128
|
|
|
104
|
-
`AppStatusToast
|
|
129
|
+
`AppStatusToast`, Markstream styles, code block styles, and math delimiter defaults are auto-registered by the module.
|
|
105
130
|
|
|
106
|
-
###
|
|
131
|
+
### 6. Use it
|
|
107
132
|
|
|
108
133
|
```vue
|
|
109
134
|
<!-- pages/index.vue -->
|
|
110
|
-
<script setup lang="ts">
|
|
111
|
-
const { activeOrganization } = useTelaApplicationAuth()
|
|
112
|
-
const workspaceId = computed(() => activeOrganization.value?.id ?? null)
|
|
113
|
-
</script>
|
|
114
|
-
|
|
115
135
|
<template>
|
|
116
|
-
<div
|
|
117
|
-
<MeistrariChatEmbed
|
|
136
|
+
<div h-screen>
|
|
137
|
+
<MeistrariChatEmbed />
|
|
118
138
|
</div>
|
|
119
139
|
</template>
|
|
120
140
|
```
|
|
121
141
|
|
|
122
|
-
The
|
|
142
|
+
The chat workspace is resolved from the authenticated `activeOrganization` provided by `@meistrari/auth-nuxt`.
|
|
123
143
|
|
|
124
144
|
## Embedding in Your Layout
|
|
125
145
|
|
|
@@ -135,8 +155,9 @@ The main use case: drop the chat inside your existing app UI.
|
|
|
135
155
|
<div style="height: 600px" class="rounded-2xl overflow-hidden border">
|
|
136
156
|
<MeistrariChatEmbed
|
|
137
157
|
v-model:conversation-id="activeConversation"
|
|
138
|
-
:workspace-id="workspaceId"
|
|
139
158
|
:hide-sidebar="true"
|
|
159
|
+
:loading-messages="['Buscando contratos', 'Lendo documentos', 'Preparando resposta']"
|
|
160
|
+
loading-messages-mode="ordered"
|
|
140
161
|
/>
|
|
141
162
|
</div>
|
|
142
163
|
</main>
|
|
@@ -154,13 +175,16 @@ Key props for embedding:
|
|
|
154
175
|
|
|
155
176
|
| Prop | Type | Default | Description |
|
|
156
177
|
|------|------|---------|-------------|
|
|
157
|
-
| `workspaceId` | `string` | — | **Required.** Workspace/org identifier |
|
|
158
178
|
| `hideSidebar` | `boolean` | `false` | Hide conversation list sidebar |
|
|
159
179
|
| `conversationId` | `string \| null` | `null` | Controlled conversation (supports v-model) |
|
|
160
180
|
| `initialConversationId` | `string \| null` | `null` | Open this conversation on mount |
|
|
161
181
|
| `workspaceSettings` | `WorkspaceSettings \| null` | `null` | Override settings from host app |
|
|
162
182
|
| `user` | `ChatActor \| null` | `null` | Override current user display info |
|
|
163
183
|
| `features` | `Partial<ChatFeatureConfig>` | `{}` | Toggle optional features |
|
|
184
|
+
| `loadingMessages` | `string[] \| null` | Default chat messages | Override pending-response messages |
|
|
185
|
+
| `loadingMessagesMode` | `'ordered' \| 'random' \| null` | `'ordered'` | Show custom messages sequentially or randomly |
|
|
186
|
+
|
|
187
|
+
`loadingMessagesMode` only applies when `loadingMessages` has at least one non-empty message.
|
|
164
188
|
|
|
165
189
|
**Events:**
|
|
166
190
|
|
|
@@ -217,14 +241,14 @@ const features = computed(() => ({
|
|
|
217
241
|
</script>
|
|
218
242
|
|
|
219
243
|
<template>
|
|
220
|
-
<MeistrariChatEmbed :
|
|
244
|
+
<MeistrariChatEmbed :features="features" />
|
|
221
245
|
</template>
|
|
222
246
|
```
|
|
223
247
|
|
|
224
248
|
Without PostHog, you can pass features statically:
|
|
225
249
|
|
|
226
250
|
```vue
|
|
227
|
-
<MeistrariChatEmbed :
|
|
251
|
+
<MeistrariChatEmbed :features="{ showUsageTab: true }" />
|
|
228
252
|
```
|
|
229
253
|
|
|
230
254
|
## Optional: Custom Workspace Settings
|
|
@@ -239,7 +263,6 @@ Pass settings directly from your host app:
|
|
|
239
263
|
|
|
240
264
|
```vue
|
|
241
265
|
<MeistrariChatEmbed
|
|
242
|
-
:workspace-id="workspaceId"
|
|
243
266
|
:workspace-settings="{
|
|
244
267
|
workspaceId: 'ws_123',
|
|
245
268
|
systemMessage: 'You are a helpful assistant for Acme Corp.',
|
|
@@ -335,7 +358,7 @@ Installing `@meistrari/chat-nuxt` installs the runtime packages used by the laye
|
|
|
335
358
|
|
|
336
359
|
| Package | Version | Purpose |
|
|
337
360
|
|---------|---------|---------|
|
|
338
|
-
| `@meistrari/auth-nuxt` |
|
|
361
|
+
| `@meistrari/auth-nuxt` | `3.5.0` | Authentication (required) |
|
|
339
362
|
| `@meistrari/tela-build` | `^1.30.0` | UI component library (Nuxt layer) |
|
|
340
363
|
| `@sentry/nuxt` | `^10.0.0` | Client-side error capture used by chat composables |
|
|
341
364
|
| `@iconify/vue` | `^5.0.0` | Icon rendering support |
|
package/dist/module.d.mts
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
type ChatNuxtConfigValidationMode = false | 'warn' | 'error';
|
|
2
|
+
interface ChatNuxtFeatures {
|
|
3
|
+
/** Track and report per-conversation token/cost usage. */
|
|
4
|
+
usage?: boolean;
|
|
5
|
+
/** Auto-generate conversation titles from the first user message. Requires `telaApiKey`. */
|
|
6
|
+
generateTitle?: boolean;
|
|
7
|
+
/** Resolve workspace-level credentials and inject them into agent calls. Requires `chatAppServiceKey`. */
|
|
8
|
+
credentials?: boolean;
|
|
9
|
+
}
|
|
2
10
|
interface ChatNuxtModuleOptions {
|
|
11
|
+
/** Tela platform API base URL (e.g. https://api.tela.com). */
|
|
12
|
+
telaApiUrl?: string;
|
|
13
|
+
/** Agent API base URL — the LLM/agent runtime the chat talks to. */
|
|
14
|
+
agentApiUrl?: string;
|
|
15
|
+
/** Vault API base URL used to upload and resolve user-attached files. */
|
|
16
|
+
vaultUrl?: string;
|
|
17
|
+
/** Postgres connection string. Falls back to a file-backed pglite database for local dev. */
|
|
18
|
+
databaseUrl?: string;
|
|
19
|
+
/** Optional feature toggles. `usage` defaults to `true`; `generateTitle` and `credentials` default to `false`. */
|
|
20
|
+
features?: ChatNuxtFeatures;
|
|
21
|
+
/**
|
|
22
|
+
* Whether to fail fast (`'error'`), warn (`'warn'`), or skip (`false`) when
|
|
23
|
+
* required runtime config keys are unset. Required keys depend on which
|
|
24
|
+
* features are enabled.
|
|
25
|
+
*/
|
|
3
26
|
validateConfig?: ChatNuxtConfigValidationMode;
|
|
4
27
|
}
|
|
5
28
|
declare const _default: any;
|
|
6
29
|
|
|
7
30
|
export { _default as default };
|
|
8
|
-
export type { ChatNuxtModuleOptions };
|
|
31
|
+
export type { ChatNuxtFeatures, ChatNuxtModuleOptions };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -148,17 +148,26 @@ function resolveWorkspaceSettingsResolverEntry(srcDir, fallbackResolverBase) {
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
const _chatNuxtRequire = createRequire(import.meta.url);
|
|
151
|
-
const
|
|
152
|
-
|
|
151
|
+
const DEFAULT_FEATURES = {
|
|
152
|
+
usage: true,
|
|
153
|
+
generateTitle: false,
|
|
154
|
+
credentials: false
|
|
155
|
+
};
|
|
156
|
+
const ALWAYS_REQUIRED_KEYS = [
|
|
153
157
|
"telaApiUrl",
|
|
154
|
-
"telaApiKey",
|
|
155
|
-
"authApiUrl",
|
|
156
|
-
"authApiSecret",
|
|
157
158
|
"agentApiUrl",
|
|
158
|
-
"
|
|
159
|
-
"vaultUrl",
|
|
160
|
-
"chatAppServiceKey"
|
|
159
|
+
"vaultUrl"
|
|
161
160
|
];
|
|
161
|
+
function buildRequiredKeys(features) {
|
|
162
|
+
const required = [...ALWAYS_REQUIRED_KEYS];
|
|
163
|
+
if (features.generateTitle) {
|
|
164
|
+
required.push("telaApiKey");
|
|
165
|
+
}
|
|
166
|
+
if (features.credentials) {
|
|
167
|
+
required.push("chatAppServiceKey");
|
|
168
|
+
}
|
|
169
|
+
return required;
|
|
170
|
+
}
|
|
162
171
|
function resolvePackageRoot(packageName) {
|
|
163
172
|
return dirname(_chatNuxtRequire.resolve(`${packageName}/package.json`));
|
|
164
173
|
}
|
|
@@ -177,11 +186,12 @@ function ensureIconifyPackages(consumerRoot) {
|
|
|
177
186
|
}
|
|
178
187
|
}
|
|
179
188
|
}
|
|
180
|
-
function validateRuntimeConfig(runtimeConfig, mode) {
|
|
189
|
+
function validateRuntimeConfig(runtimeConfig, mode, features) {
|
|
181
190
|
if (!mode) {
|
|
182
191
|
return;
|
|
183
192
|
}
|
|
184
|
-
const
|
|
193
|
+
const required = buildRequiredKeys(features);
|
|
194
|
+
const missingKeys = required.filter((key) => !runtimeConfig[key]);
|
|
185
195
|
if (missingKeys.length === 0) {
|
|
186
196
|
return;
|
|
187
197
|
}
|
|
@@ -246,20 +256,23 @@ const module$1 = defineNuxtModule({
|
|
|
246
256
|
const runtimeDirRegExp = new RegExp(runtimeDir.replace(/\\/g, "/").replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
247
257
|
nuxt.options.imports.transform.include.push(runtimeDirRegExp);
|
|
248
258
|
}
|
|
259
|
+
const features = { ...DEFAULT_FEATURES, ...options.features ?? {} };
|
|
260
|
+
const migrationsDir = resolver.resolve("../drizzle");
|
|
249
261
|
const rc = nuxt.options.runtimeConfig;
|
|
250
|
-
rc.databaseUrl = rc.databaseUrl || process.env.DATABASE_URL || ""
|
|
251
|
-
rc.telaApiUrl = rc.telaApiUrl || process.env.TELA_API_URL || "";
|
|
262
|
+
rc.databaseUrl = options.databaseUrl || rc.databaseUrl || process.env.DATABASE_URL || `pglite:${join(nuxt.options.rootDir, ".data/chat-nuxt.db")}`;
|
|
263
|
+
rc.telaApiUrl = options.telaApiUrl || rc.telaApiUrl || process.env.TELA_API_URL || "";
|
|
252
264
|
rc.telaApiKey = rc.telaApiKey || process.env.TELA_API_KEY || "";
|
|
253
|
-
rc.
|
|
254
|
-
rc.
|
|
255
|
-
rc.agentApiUrl = rc.agentApiUrl || process.env.AGENT_API_URL || "";
|
|
256
|
-
rc.authJwksUrl = rc.authJwksUrl || process.env.AUTH_JWKS_URL || "";
|
|
257
|
-
rc.vaultUrl = rc.vaultUrl || process.env.VAULT_URL || "";
|
|
265
|
+
rc.agentApiUrl = options.agentApiUrl || rc.agentApiUrl || process.env.AGENT_API_URL || "";
|
|
266
|
+
rc.vaultUrl = options.vaultUrl || rc.vaultUrl || process.env.VAULT_URL || "";
|
|
258
267
|
rc.vaultS3Bucket = rc.vaultS3Bucket || process.env.VAULT_S3_BUCKET || "";
|
|
259
268
|
rc.chatAppServiceKey = rc.chatAppServiceKey || process.env.CHAT_APP_SERVICE_KEY || "";
|
|
260
269
|
rc.public = rc.public || {};
|
|
261
|
-
rc.public.agentApiUrl = rc.public.agentApiUrl || process.env.AGENT_API_URL || "";
|
|
262
|
-
|
|
270
|
+
rc.public.agentApiUrl = rc.agentApiUrl || rc.public.agentApiUrl || process.env.AGENT_API_URL || "";
|
|
271
|
+
rc.public.chatNuxtFeatures = features;
|
|
272
|
+
rc.chatNuxt = rc.chatNuxt || {};
|
|
273
|
+
rc.chatNuxt.migrationsDir = rc.chatNuxt.migrationsDir || migrationsDir;
|
|
274
|
+
rc.chatNuxt.features = features;
|
|
275
|
+
validateRuntimeConfig(rc, options.validateConfig ?? false, features);
|
|
263
276
|
addImportsDir(join(runtimeDir, "composables"));
|
|
264
277
|
addImportsDir(join(runtimeDir, "utils"));
|
|
265
278
|
addComponent({
|
|
@@ -315,6 +328,7 @@ export default globalThis.ELK;
|
|
|
315
328
|
const serverDir = join(runtimeDir, "server");
|
|
316
329
|
const publicAssetsDir = join(runtimeDir, "public/assets");
|
|
317
330
|
const publicFilesDir = join(runtimeDir, "public/files");
|
|
331
|
+
const dbInitPluginPath = join(runtimeDir, "server/plugins/init-db");
|
|
318
332
|
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
319
333
|
nitroConfig.scanDirs = nitroConfig.scanDirs || [];
|
|
320
334
|
nitroConfig.scanDirs.push(serverDir);
|
|
@@ -323,6 +337,10 @@ export default globalThis.ELK;
|
|
|
323
337
|
"#chat-runtime": runtimeDir,
|
|
324
338
|
"#chat-workspace-settings-resolver": workspaceSettingsResolverEntry
|
|
325
339
|
};
|
|
340
|
+
nitroConfig.plugins = nitroConfig.plugins || [];
|
|
341
|
+
if (!nitroConfig.plugins.includes(dbInitPluginPath)) {
|
|
342
|
+
nitroConfig.plugins.push(dbInitPluginPath);
|
|
343
|
+
}
|
|
326
344
|
nitroConfig.publicAssets = nitroConfig.publicAssets || [];
|
|
327
345
|
nitroConfig.publicAssets.push({
|
|
328
346
|
dir: publicAssetsDir,
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import type { DeepReadonly } from 'vue';
|
|
2
2
|
import type { WorkspaceSettings } from '../composables/useWorkspaceSettings.js';
|
|
3
|
+
import type { ChatLoadingMessageMode } from '../utils/chat-loading-messages.js';
|
|
3
4
|
import type { ChatActor, ChatFeatureConfig } from '../utils/tela-chat.js';
|
|
4
5
|
type __VLS_Props = {
|
|
5
|
-
workspaceId: string;
|
|
6
6
|
workspaceSettings?: DeepReadonly<WorkspaceSettings> | WorkspaceSettings | null;
|
|
7
7
|
user?: ChatActor | null;
|
|
8
8
|
conversationId?: string | null;
|
|
9
9
|
initialConversationId?: string | null;
|
|
10
10
|
hideSidebar?: boolean;
|
|
11
11
|
features?: Partial<ChatFeatureConfig>;
|
|
12
|
+
loadingMessages?: readonly string[] | null;
|
|
13
|
+
loadingMessagesMode?: ChatLoadingMessageMode | null;
|
|
12
14
|
};
|
|
13
15
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
14
16
|
"update:conversationId": (value: string | null) => any;
|
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
defineProps({
|
|
3
|
-
workspaceId: { type: String, required: true },
|
|
4
3
|
workspaceSettings: { type: null, required: false },
|
|
5
4
|
user: { type: [Object, null], required: false },
|
|
6
5
|
conversationId: { type: [String, null], required: false },
|
|
7
6
|
initialConversationId: { type: [String, null], required: false },
|
|
8
7
|
hideSidebar: { type: Boolean, required: false },
|
|
9
|
-
features: { type: Object, required: false }
|
|
8
|
+
features: { type: Object, required: false },
|
|
9
|
+
loadingMessages: { type: [Array, null], required: false },
|
|
10
|
+
loadingMessagesMode: { type: [String, null], required: false }
|
|
10
11
|
});
|
|
11
12
|
defineEmits(["update:conversationId"]);
|
|
12
13
|
</script>
|
|
13
14
|
|
|
14
15
|
<template>
|
|
15
16
|
<ChatEmbed
|
|
16
|
-
:workspace-id="workspaceId"
|
|
17
17
|
:workspace-settings="workspaceSettings"
|
|
18
18
|
:user="user"
|
|
19
19
|
:conversation-id="conversationId"
|
|
20
20
|
:initial-conversation-id="initialConversationId"
|
|
21
21
|
:hide-sidebar="hideSidebar"
|
|
22
22
|
:features="features"
|
|
23
|
+
:loading-messages="loadingMessages"
|
|
24
|
+
:loading-messages-mode="loadingMessagesMode"
|
|
23
25
|
@update:conversation-id="$emit('update:conversationId', $event)"
|
|
24
26
|
/>
|
|
25
27
|
</template>
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import type { DeepReadonly } from 'vue';
|
|
2
2
|
import type { WorkspaceSettings } from '../composables/useWorkspaceSettings.js';
|
|
3
|
+
import type { ChatLoadingMessageMode } from '../utils/chat-loading-messages.js';
|
|
3
4
|
import type { ChatActor, ChatFeatureConfig } from '../utils/tela-chat.js';
|
|
4
5
|
type __VLS_Props = {
|
|
5
|
-
workspaceId: string;
|
|
6
6
|
workspaceSettings?: DeepReadonly<WorkspaceSettings> | WorkspaceSettings | null;
|
|
7
7
|
user?: ChatActor | null;
|
|
8
8
|
conversationId?: string | null;
|
|
9
9
|
initialConversationId?: string | null;
|
|
10
10
|
hideSidebar?: boolean;
|
|
11
11
|
features?: Partial<ChatFeatureConfig>;
|
|
12
|
+
loadingMessages?: readonly string[] | null;
|
|
13
|
+
loadingMessagesMode?: ChatLoadingMessageMode | null;
|
|
12
14
|
};
|
|
13
15
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
14
16
|
"update:conversationId": (value: string | null) => any;
|
|
@@ -1,34 +1,45 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"Refinando detalhes",
|
|
9
|
-
"Verificando contexto",
|
|
10
|
-
"Conectando conceitos",
|
|
11
|
-
"Preparando resultado",
|
|
12
|
-
"Quase l\xE1",
|
|
13
|
-
"Finalizando an\xE1lise",
|
|
14
|
-
"Estruturando resposta"
|
|
15
|
-
];
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_CHAT_LOADING_MESSAGES,
|
|
4
|
+
getNextChatLoadingMessageIndex,
|
|
5
|
+
resolveChatLoadingMessages
|
|
6
|
+
} from "../../utils/chat-loading-messages";
|
|
7
|
+
const embedConfig = useEmbedConfig();
|
|
16
8
|
const currentTextIndex = ref(0);
|
|
17
9
|
const dotCount = ref(0);
|
|
10
|
+
const loadingState = computed(() => resolveChatLoadingMessages({
|
|
11
|
+
loadingMessages: embedConfig?.loadingMessages.value,
|
|
12
|
+
loadingMessagesMode: embedConfig?.loadingMessagesMode.value
|
|
13
|
+
}));
|
|
18
14
|
const currentText = computed(() => {
|
|
19
|
-
const base =
|
|
15
|
+
const base = loadingState.value.messages[currentTextIndex.value] ?? loadingState.value.messages[0] ?? DEFAULT_CHAT_LOADING_MESSAGES[0];
|
|
20
16
|
const dots = ".".repeat(dotCount.value);
|
|
21
17
|
return `${base}${dots}`;
|
|
22
18
|
});
|
|
19
|
+
watch(loadingState, (state) => {
|
|
20
|
+
if (currentTextIndex.value >= state.messages.length) {
|
|
21
|
+
currentTextIndex.value = 0;
|
|
22
|
+
dotCount.value = 0;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
23
25
|
let dotInterval;
|
|
24
26
|
let textInterval;
|
|
27
|
+
function advanceText() {
|
|
28
|
+
currentTextIndex.value = getNextChatLoadingMessageIndex(
|
|
29
|
+
loadingState.value.mode,
|
|
30
|
+
loadingState.value.messages.length,
|
|
31
|
+
currentTextIndex.value
|
|
32
|
+
);
|
|
33
|
+
dotCount.value = 0;
|
|
34
|
+
}
|
|
25
35
|
onMounted(() => {
|
|
36
|
+
if (loadingState.value.mode === "random")
|
|
37
|
+
advanceText();
|
|
26
38
|
dotInterval = setInterval(() => {
|
|
27
39
|
dotCount.value = (dotCount.value + 1) % 4;
|
|
28
40
|
}, 500);
|
|
29
41
|
textInterval = setInterval(() => {
|
|
30
|
-
|
|
31
|
-
dotCount.value = 0;
|
|
42
|
+
advanceText();
|
|
32
43
|
}, 7e3);
|
|
33
44
|
});
|
|
34
45
|
onUnmounted(() => {
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import type { DeepReadonly, MaybeRefOrGetter, Ref } from 'vue';
|
|
2
|
+
import type { ChatLoadingMessageMode } from '../utils/chat-loading-messages.js';
|
|
2
3
|
import type { WorkspaceSettings } from './useWorkspaceSettings.js';
|
|
3
4
|
export type EmbedConfig = {
|
|
4
5
|
workspaceId: Ref<string>;
|
|
5
6
|
workspaceSettings: Ref<DeepReadonly<WorkspaceSettings> | WorkspaceSettings | null | undefined>;
|
|
6
7
|
hideSidebar: Ref<boolean>;
|
|
8
|
+
loadingMessages: Ref<readonly string[] | null | undefined>;
|
|
9
|
+
loadingMessagesMode: Ref<ChatLoadingMessageMode | null | undefined>;
|
|
7
10
|
};
|
|
8
11
|
type EmbedConfigInput = {
|
|
9
12
|
workspaceId: MaybeRefOrGetter<string>;
|
|
10
13
|
workspaceSettings?: MaybeRefOrGetter<DeepReadonly<WorkspaceSettings> | WorkspaceSettings | null | undefined>;
|
|
11
14
|
hideSidebar?: MaybeRefOrGetter<boolean | undefined>;
|
|
15
|
+
loadingMessages?: MaybeRefOrGetter<readonly string[] | null | undefined>;
|
|
16
|
+
loadingMessagesMode?: MaybeRefOrGetter<ChatLoadingMessageMode | null | undefined>;
|
|
12
17
|
};
|
|
13
18
|
type ProvideEmbedConfigOptions = {
|
|
14
19
|
syncGlobal?: boolean;
|
|
@@ -4,14 +4,18 @@ function useGlobalEmbedConfigState() {
|
|
|
4
4
|
provided: useState("chat-embed-config-provided", () => false),
|
|
5
5
|
workspaceId: useState("chat-embed-config-workspace-id", () => ""),
|
|
6
6
|
workspaceSettings: useState("chat-embed-config-workspace-settings", () => void 0),
|
|
7
|
-
hideSidebar: useState("chat-embed-config-hide-sidebar", () => void 0)
|
|
7
|
+
hideSidebar: useState("chat-embed-config-hide-sidebar", () => void 0),
|
|
8
|
+
loadingMessages: useState("chat-embed-config-loading-messages", () => void 0),
|
|
9
|
+
loadingMessagesMode: useState("chat-embed-config-loading-messages-mode", () => void 0)
|
|
8
10
|
};
|
|
9
11
|
}
|
|
10
12
|
export function provideEmbedConfig(input, options = {}) {
|
|
11
13
|
const config = {
|
|
12
14
|
workspaceId: computed(() => toValue(input.workspaceId)),
|
|
13
15
|
workspaceSettings: computed(() => toValue(input.workspaceSettings)),
|
|
14
|
-
hideSidebar: computed(() => toValue(input.hideSidebar) ?? true)
|
|
16
|
+
hideSidebar: computed(() => toValue(input.hideSidebar) ?? true),
|
|
17
|
+
loadingMessages: computed(() => toValue(input.loadingMessages)),
|
|
18
|
+
loadingMessagesMode: computed(() => toValue(input.loadingMessagesMode))
|
|
15
19
|
};
|
|
16
20
|
const globalConfig = useGlobalEmbedConfigState();
|
|
17
21
|
if (options.syncGlobal ?? true) {
|
|
@@ -20,6 +24,8 @@ export function provideEmbedConfig(input, options = {}) {
|
|
|
20
24
|
globalConfig.workspaceId.value = config.workspaceId.value;
|
|
21
25
|
globalConfig.workspaceSettings.value = config.workspaceSettings.value;
|
|
22
26
|
globalConfig.hideSidebar.value = config.hideSidebar.value;
|
|
27
|
+
globalConfig.loadingMessages.value = config.loadingMessages.value;
|
|
28
|
+
globalConfig.loadingMessagesMode.value = config.loadingMessagesMode.value;
|
|
23
29
|
});
|
|
24
30
|
}
|
|
25
31
|
provide(EMBED_CONFIG_KEY, config);
|
|
@@ -34,6 +40,8 @@ export function useEmbedConfig() {
|
|
|
34
40
|
return {
|
|
35
41
|
workspaceId: computed(() => globalConfig.workspaceId.value),
|
|
36
42
|
workspaceSettings: computed(() => globalConfig.workspaceSettings.value),
|
|
37
|
-
hideSidebar: computed(() => globalConfig.hideSidebar.value ?? true)
|
|
43
|
+
hideSidebar: computed(() => globalConfig.hideSidebar.value ?? true),
|
|
44
|
+
loadingMessages: computed(() => globalConfig.loadingMessages.value),
|
|
45
|
+
loadingMessagesMode: computed(() => globalConfig.loadingMessagesMode.value)
|
|
38
46
|
};
|
|
39
47
|
}
|
|
@@ -18,6 +18,7 @@ const {
|
|
|
18
18
|
fetchSettings,
|
|
19
19
|
updateSettings
|
|
20
20
|
} = useWorkspaceSettings();
|
|
21
|
+
const features = useChatNuxtFeatures();
|
|
21
22
|
const searchQuery = ref("");
|
|
22
23
|
const activeTab = ref(props.initialTab);
|
|
23
24
|
const showDiscardConfirm = ref(false);
|
|
@@ -34,14 +35,14 @@ const telaTools = useWorkspaceTelaTools(canvas, projects, searchQuery, currentCa
|
|
|
34
35
|
const knowledgeSources = useWorkspaceKnowledgeSources(workstations, canvas, projects, searchQuery, currentKnowledgeSources);
|
|
35
36
|
const contextFiles = useWorkspaceContextFiles(searchQuery, currentContextFiles);
|
|
36
37
|
const externalSkills = useWorkspaceExternalSkills(currentExternalSkills, searchQuery);
|
|
37
|
-
const settingsTabs = [
|
|
38
|
+
const settingsTabs = computed(() => [
|
|
38
39
|
{ value: "personalization", label: "Personaliza\xE7\xE3o", icon: "i-ph-sliders" },
|
|
39
40
|
{ value: "context-files", label: "Arquivos de contexto", icon: "i-ph-file-text" },
|
|
40
41
|
{ value: "knowledge-sources", label: "Tela workstations", icon: "i-ph-database" },
|
|
41
42
|
{ value: "tela-tools", label: "Skills Tela", icon: "i-ph-puzzle-piece" },
|
|
42
43
|
{ value: "external-skills", label: "Skills Externas", icon: "i-ph-wrench" },
|
|
43
|
-
{ value: "credentials", label: "Credenciais", icon: "i-ph-password-bold" }
|
|
44
|
-
];
|
|
44
|
+
...features.credentials ? [{ value: "credentials", label: "Credenciais", icon: "i-ph-password-bold" }] : []
|
|
45
|
+
]);
|
|
45
46
|
const hasChanges = computed(
|
|
46
47
|
() => personalization.hasChanges.value || contextFiles.hasChanges.value || telaTools.hasChanges.value || knowledgeSources.hasChanges.value || externalSkills.hasChanges.value
|
|
47
48
|
);
|
|
@@ -84,9 +85,10 @@ function initializeConfigurationState() {
|
|
|
84
85
|
externalSkills.initialize();
|
|
85
86
|
}
|
|
86
87
|
function activateTab(tab) {
|
|
87
|
-
|
|
88
|
+
const isVisible = settingsTabs.value.some((t) => t.value === tab);
|
|
89
|
+
activeTab.value = isVisible ? tab : "personalization";
|
|
88
90
|
searchQuery.value = "";
|
|
89
|
-
if (
|
|
91
|
+
if (activeTab.value === "external-skills")
|
|
90
92
|
void externalSkills.fetchGitHubConnection();
|
|
91
93
|
}
|
|
92
94
|
async function loadSettings() {
|
|
@@ -336,7 +338,7 @@ function cancelDiscard() {
|
|
|
336
338
|
/>
|
|
337
339
|
|
|
338
340
|
<ChatConfigurationCredentialsTab
|
|
339
|
-
v-else-if="activeTab === 'credentials'"
|
|
341
|
+
v-else-if="activeTab === 'credentials' && features.credentials"
|
|
340
342
|
:search-query="searchQuery"
|
|
341
343
|
@update:search-query="searchQuery = $event"
|
|
342
344
|
/>
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import type { DeepReadonly } from 'vue';
|
|
2
2
|
import type { WorkspaceSettings } from '../../composables/useWorkspaceSettings.js';
|
|
3
|
+
import type { ChatLoadingMessageMode } from '../../utils/chat-loading-messages.js';
|
|
3
4
|
import type { ChatActor, ChatFeatureConfig } from '../../utils/tela-chat.js';
|
|
4
5
|
type EmbedUser = ChatActor;
|
|
5
6
|
type __VLS_Props = {
|
|
6
|
-
workspaceId: string;
|
|
7
7
|
workspaceSettings?: DeepReadonly<WorkspaceSettings> | WorkspaceSettings | null;
|
|
8
8
|
conversationId?: string | null;
|
|
9
9
|
initialConversationId?: string | null;
|
|
10
10
|
hideSidebar?: boolean;
|
|
11
11
|
user?: EmbedUser | null;
|
|
12
12
|
features?: Partial<ChatFeatureConfig>;
|
|
13
|
+
loadingMessages?: readonly string[] | null;
|
|
14
|
+
loadingMessagesMode?: ChatLoadingMessageMode | null;
|
|
13
15
|
};
|
|
14
16
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
15
17
|
"update:conversationId": (value: string | null) => any;
|