@meistrari/chat-nuxt 4.11.0-rc.9 → 4.11.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 CHANGED
@@ -165,13 +165,11 @@ Installing `@meistrari/chat-nuxt` installs the runtime packages used by the laye
165
165
  | `mermaid` | `^11.13.0` | Native markstream Mermaid diagram rendering |
166
166
  | `h3` | `^1.15.0` | Server route utilities provided by Nuxt/Nitro |
167
167
  | `markstream-vue` | `2.0.7` | Markdown streaming renderer |
168
- | `motion` | `^11.13.0` | Animation component runtime |
169
168
  | `nitropack` | `^2.10.0` | Runtime config and task utilities provided by Nuxt/Nitro |
170
169
  | `pdfjs-dist` | `^5.4.530` | PDF file previews |
171
170
  | `posthog-js` | `^1.364.2` | Optional PostHog feature-flag helper |
172
171
  | `stream-diffs` | `0.0.2` | Native markstream rich code and diff rendering |
173
172
  | `virtua` | `^0.42.0` | Virtualized list runtime expected by shared UI |
174
- | `xlsx` | `^0.18.5` | Spreadsheet file previews |
175
173
  | `zod` | `^4.1.13` | Schema validation for API payloads |
176
174
 
177
175
  The chat package does not declare or expect the host application to configure an i18n plugin. Hosts can override the supported conversation-search text through `labels`, using plain strings or their own translator. This is not a full-chat localization API; other UI text retains its existing defaults.
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
3
  "configKey": "chatNuxt",
4
- "version": "4.11.0-rc.9",
4
+ "version": "4.11.0-rc.13",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -5,7 +5,7 @@ const props = defineProps({
5
5
  variant: { type: String, required: false }
6
6
  });
7
7
  const DEFAULT_GROUP_NAME = "Nova pasta";
8
- const { groups, createGroup, pendingRenameGroupId } = useConversationGroups();
8
+ const { visibleGroups, createGroup, pendingRenameGroupId } = useConversationGroups();
9
9
  const isCreating = ref(false);
10
10
  const hasLabel = computed(() => Boolean(props.label?.trim()));
11
11
  const isEmptyState = computed(() => props.variant === "empty-state");
@@ -17,7 +17,7 @@ const buttonClasses = computed(() => {
17
17
  return "h-32px! w-40px! p-0!";
18
18
  });
19
19
  function nextGroupName() {
20
- const names = new Set(groups.value.map((group) => group.name));
20
+ const names = new Set(visibleGroups.value.map((group) => group.name));
21
21
  if (!names.has(DEFAULT_GROUP_NAME))
22
22
  return DEFAULT_GROUP_NAME;
23
23
  let index = 2;
@@ -1,6 +1,7 @@
1
1
  import type { ConversationGroup } from '../../types/schemas/chat/conversations.js';
2
2
  export declare function useConversationGroups(): {
3
3
  groups: any;
4
+ visibleGroups: any;
4
5
  loading: any;
5
6
  error: any;
6
7
  pendingRenameGroupId: any;
@@ -1,5 +1,6 @@
1
1
  import { useChatAuth } from "#chat-auth";
2
2
  import * as Sentry from "@sentry/nuxt";
3
+ import { filterGroupsByCreator } from "../groups.js";
3
4
  import { resolveChatStateScope } from "../scope.js";
4
5
  import { useChatApi } from "../../shared/composables/chat-api.js";
5
6
  import { useConversations } from "./conversations.js";
@@ -15,7 +16,8 @@ function sortConversationGroups(groups) {
15
16
  export function useConversationGroups() {
16
17
  const chatApi = useChatApi();
17
18
  const embedConfig = useEmbedConfig();
18
- const { activeOrganization } = useChatAuth();
19
+ const { user: authUser, activeOrganization } = useChatAuth();
20
+ const { conversationCreatorFilter, clearGroupFromConversations } = useConversations();
19
21
  const groupBuckets = useState("conversation-groups", () => ({}));
20
22
  const loadingBuckets = useState("conversation-groups-loading", () => ({}));
21
23
  const fetchedBuckets = useState("conversation-groups-fetched", () => ({}));
@@ -35,6 +37,9 @@ export function useConversationGroups() {
35
37
  };
36
38
  }
37
39
  });
40
+ const visibleGroups = computed(
41
+ () => filterGroupsByCreator(groups.value, conversationCreatorFilter.value, authUser.value?.email)
42
+ );
38
43
  const loading = computed({
39
44
  get: () => loadingBuckets.value[runtimeScope.value] ?? false,
40
45
  set: (value) => {
@@ -133,7 +138,6 @@ export function useConversationGroups() {
133
138
  const deleteGroup = async (groupId) => {
134
139
  error.value = null;
135
140
  const previousGroups = groups.value;
136
- const { clearGroupFromConversations } = useConversations();
137
141
  removeGroup(groupId);
138
142
  const restoreConversations = clearGroupFromConversations(groupId);
139
143
  try {
@@ -154,6 +158,7 @@ export function useConversationGroups() {
154
158
  };
155
159
  return {
156
160
  groups: readonly(groups),
161
+ visibleGroups: readonly(visibleGroups),
157
162
  loading: readonly(loading),
158
163
  error: readonly(error),
159
164
  pendingRenameGroupId,
@@ -14,7 +14,7 @@ export function useConversationList(options) {
14
14
  const { activeOrganization } = useChatAuth();
15
15
  const { deleteConversation, renameConversation, duplicateConversation, moveConversationToGroup } = useConversations();
16
16
  const { copyConversationLink } = useConversationActions();
17
- const { groups, fetchGroups, createGroup, deleteGroup, renameGroup, error: groupError, pendingRenameGroupId } = useConversationGroups();
17
+ const { groups, visibleGroups, fetchGroups, createGroup, deleteGroup, renameGroup, error: groupError, pendingRenameGroupId } = useConversationGroups();
18
18
  const { setConversation, currentConversation } = useChat();
19
19
  const exportConversationId = ref(null);
20
20
  const debugConversationId = ref(null);
@@ -60,8 +60,8 @@ export function useConversationList(options) {
60
60
  shouldInclude: (conversation) => !conversation.title && conversation.id === options.currentId
61
61
  })
62
62
  );
63
- const filteredGroupedConversations = computed(() => groupConversationsByGroup(filteredConversations.value, groups.value));
64
- const allGroupedConversations = computed(() => groupConversationsByGroup(options.conversations, groups.value));
63
+ const filteredGroupedConversations = computed(() => groupConversationsByGroup(filteredConversations.value, visibleGroups.value));
64
+ const allGroupedConversations = computed(() => groupConversationsByGroup(options.conversations, visibleGroups.value));
65
65
  const groupedConversations = computed(() => {
66
66
  if (!hasConversationSearchQuery.value)
67
67
  return filteredGroupedConversations.value;
@@ -261,12 +261,12 @@ export function useConversationList(options) {
261
261
  const ungroupedConversationLabel = computed(() => `Conversas`);
262
262
  const shouldShowUngroupedHeader = computed(() => groupItems.value.length > 0);
263
263
  const showGroupCreationPrompt = computed(
264
- () => groupsReady.value && !hasConversationSearchQuery.value && groups.value.length === 0
264
+ () => groupsReady.value && !hasConversationSearchQuery.value && visibleGroups.value.length === 0
265
265
  );
266
266
  const hasConversationContent = computed(() => {
267
267
  if (hasConversationSearchQuery.value)
268
268
  return groupItems.value.length > 0 || ungroupedConversations.value.length > 0;
269
- return showGroupCreationPrompt.value || groups.value.length > 0 || filteredConversations.value.length > 0;
269
+ return showGroupCreationPrompt.value || visibleGroups.value.length > 0 || filteredConversations.value.length > 0;
270
270
  });
271
271
  const deleteGroupConfirmationMessage = computed(() => {
272
272
  const target = deleteGroupTarget.value;
@@ -506,7 +506,7 @@ export function useConversationList(options) {
506
506
  const DEFAULT_GROUP_NAME = "Nova pasta";
507
507
  const isCreatingGroup = ref(false);
508
508
  function nextGroupName() {
509
- const names = new Set(groups.value.map((group) => group.name));
509
+ const names = new Set(visibleGroups.value.map((group) => group.name));
510
510
  if (!names.has(DEFAULT_GROUP_NAME))
511
511
  return DEFAULT_GROUP_NAME;
512
512
  let index = 2;
@@ -3,6 +3,16 @@ export type ConversationGroupLike = {
3
3
  name: string;
4
4
  createdAt?: Date | string;
5
5
  };
6
+ export type ConversationGroupCreatorFilter = 'all' | 'mine';
7
+ /**
8
+ * Applies the sidebar creator filter to folders: with `'mine'` only folders the
9
+ * current user created stay visible (`createdBy` is the creator's email, the same
10
+ * value conversations carry); `'all'` keeps every folder. A folder without a
11
+ * creator, or a user without an email, never matches `'mine'`.
12
+ */
13
+ export declare function filterGroupsByCreator<TGroup extends ConversationGroupLike & {
14
+ createdBy?: string | null;
15
+ }>(groups: readonly TGroup[], filter: ConversationGroupCreatorFilter, currentUserEmail: string | null | undefined): TGroup[];
6
16
  export type ConversationGroupItem = {
7
17
  groupId?: string | null;
8
18
  updatedAt: Date | string;
@@ -1,3 +1,15 @@
1
+ function normalizedEmail(value) {
2
+ const email = value?.trim().toLowerCase();
3
+ return email || null;
4
+ }
5
+ export function filterGroupsByCreator(groups, filter, currentUserEmail) {
6
+ if (filter !== "mine")
7
+ return [...groups];
8
+ const email = normalizedEmail(currentUserEmail);
9
+ if (!email)
10
+ return [];
11
+ return groups.filter((group) => normalizedEmail(group.createdBy) === email);
12
+ }
1
13
  function byUpdatedAtDesc(a, b) {
2
14
  return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();
3
15
  }
@@ -31,7 +31,7 @@ let dragOpenGroupTimeout = null;
31
31
  let dragOpenGroupId = null;
32
32
  const embedConfig = useEmbedConfig();
33
33
  const { activeOrganization } = useChatAuth();
34
- const { groups, fetchGroups } = useConversationGroups();
34
+ const { visibleGroups, fetchGroups } = useConversationGroups();
35
35
  const { moveConversationToGroup } = useConversations();
36
36
  const runtimeScope = computed(() => resolveChatStateScope(
37
37
  embedConfig?.workspaceId.value || activeOrganization.value?.id,
@@ -46,8 +46,8 @@ const filteredConversations = computed(
46
46
  })
47
47
  );
48
48
  const hasConversationSearchQuery = computed(() => conversationSearch.value.trim().length > 0);
49
- const filteredGroupedConversations = computed(() => groupConversationsByGroup(filteredConversations.value, groups.value));
50
- const allGroupedConversations = computed(() => groupConversationsByGroup(props.conversations, groups.value));
49
+ const filteredGroupedConversations = computed(() => groupConversationsByGroup(filteredConversations.value, visibleGroups.value));
50
+ const allGroupedConversations = computed(() => groupConversationsByGroup(props.conversations, visibleGroups.value));
51
51
  const groupedConversations = computed(() => {
52
52
  if (!hasConversationSearchQuery.value)
53
53
  return filteredGroupedConversations.value;
@@ -82,7 +82,7 @@ const visibleGroupBuckets = computed(() => groupedConversations.value.groups.fil
82
82
  const hasConversationContent = computed(() => {
83
83
  if (hasConversationSearchQuery.value)
84
84
  return visibleGroupBuckets.value.length > 0 || groupedConversations.value.unfiled.length > 0;
85
- return groups.value.length > 0 || filteredConversations.value.length > 0;
85
+ return visibleGroups.value.length > 0 || filteredConversations.value.length > 0;
86
86
  });
87
87
  const shouldShowUngroupedHeader = computed(() => visibleGroupBuckets.value.length > 0);
88
88
  const ungroupedConversationLabel = computed(() => `Conversas \xB7 ${groupedConversations.value.unfiled.length}`);
@@ -72,8 +72,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
72
72
  copyLink: () => any;
73
73
  debug: () => any;
74
74
  selectConversation: (id: string) => any;
75
- settings: () => any;
76
75
  send: (content: string, files: FileUploadInput[], agentInputs?: TelaAgentExecutionInput[] | undefined) => any;
76
+ settings: () => any;
77
77
  selectExecutionProfile: (profile: ChatExecutionProfile) => any;
78
78
  tabChange: (tab: TopbarTab) => any;
79
79
  newConversation: (groupId?: string | null | undefined) => any;
@@ -94,8 +94,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
94
94
  onCopyLink?: (() => any) | undefined;
95
95
  onDebug?: (() => any) | undefined;
96
96
  onSelectConversation?: ((id: string) => any) | undefined;
97
- onSettings?: (() => any) | undefined;
98
97
  onSend?: ((content: string, files: FileUploadInput[], agentInputs?: TelaAgentExecutionInput[] | undefined) => any) | undefined;
98
+ onSettings?: (() => any) | undefined;
99
99
  onSelectExecutionProfile?: ((profile: ChatExecutionProfile) => any) | undefined;
100
100
  "onUpdate:selectedModel"?: ((value: string | null) => any) | undefined;
101
101
  "onUpdate:selectedReasoningEffort"?: ((value: any) => any) | undefined;
@@ -72,8 +72,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
72
72
  copyLink: () => any;
73
73
  debug: () => any;
74
74
  selectConversation: (id: string) => any;
75
- settings: () => any;
76
75
  send: (content: string, files: FileUploadInput[], agentInputs?: TelaAgentExecutionInput[] | undefined) => any;
76
+ settings: () => any;
77
77
  selectExecutionProfile: (profile: ChatExecutionProfile) => any;
78
78
  tabChange: (tab: TopbarTab) => any;
79
79
  newConversation: (groupId?: string | null | undefined) => any;
@@ -94,8 +94,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
94
94
  onCopyLink?: (() => any) | undefined;
95
95
  onDebug?: (() => any) | undefined;
96
96
  onSelectConversation?: ((id: string) => any) | undefined;
97
- onSettings?: (() => any) | undefined;
98
97
  onSend?: ((content: string, files: FileUploadInput[], agentInputs?: TelaAgentExecutionInput[] | undefined) => any) | undefined;
98
+ onSettings?: (() => any) | undefined;
99
99
  onSelectExecutionProfile?: ((profile: ChatExecutionProfile) => any) | undefined;
100
100
  "onUpdate:selectedModel"?: ((value: string | null) => any) | undefined;
101
101
  "onUpdate:selectedReasoningEffort"?: ((value: any) => any) | undefined;
@@ -38,7 +38,6 @@ export declare const v5ErrorStatus: {
38
38
  readonly invalid_event_limit: 400;
39
39
  readonly invalid_artifact_limit: 400;
40
40
  readonly invalid_user_event_batch: 400;
41
- readonly provider_harness_mismatch: 400;
42
41
  readonly insufficient_role: 403;
43
42
  readonly agent_publication_forbidden: 403;
44
43
  readonly session_not_found: 404;
@@ -32,7 +32,6 @@ export const v5ErrorStatus = {
32
32
  invalid_event_limit: 400,
33
33
  invalid_artifact_limit: 400,
34
34
  invalid_user_event_batch: 400,
35
- provider_harness_mismatch: 400,
36
35
  insufficient_role: 403,
37
36
  agent_publication_forbidden: 403,
38
37
  session_not_found: 404,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meistrari/chat-nuxt",
3
- "version": "4.11.0-rc.9",
3
+ "version": "4.11.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -52,7 +52,7 @@
52
52
  "@iconify-json/ph": "^1.2.2",
53
53
  "@iconify/vue": "^5.0.0",
54
54
  "@meistrari/auth-nuxt": "3.31.0",
55
- "@meistrari/chat-ui-lang": "0.5.0-rc.1",
55
+ "@meistrari/chat-ui-lang": "0.5.0",
56
56
  "@meistrari/logger": "^2.1.3",
57
57
  "@meistrari/tela-build": "^1.79.0",
58
58
  "@openuidev/lang-core": "1.0.0",
@@ -64,14 +64,12 @@
64
64
  "ipaddr.js": "2.5.0",
65
65
  "markstream-vue": "2.0.7",
66
66
  "mermaid": "^11.13.0",
67
- "motion": "^11.13.0",
68
67
  "nitropack": "^2.10.0",
69
68
  "pdfjs-dist": "^5.4.530",
70
69
  "posthog-js": "^1.364.2",
71
70
  "stream-diffs": "0.0.2",
72
71
  "tldts": "^7.4.10",
73
72
  "virtua": "^0.42.0",
74
- "xlsx": "^0.18.5",
75
73
  "zod": "^4.1.13"
76
74
  },
77
75
  "devDependencies": {
@@ -79,7 +77,6 @@
79
77
  "@meistrari/chat-schemas": "workspace:*",
80
78
  "@nuxt/module-builder": "^1.0.2",
81
79
  "@types/node": "^20.19.0",
82
- "dotenv-cli": "^11.0.0",
83
80
  "eslint": "9.16.0",
84
81
  "nuxt": "4.4.8",
85
82
  "pino": "^10.3.1",