@meistrari/chat-nuxt 1.10.0 → 1.12.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.
Files changed (82) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +15 -0
  3. package/dist/runtime/components/chat/conversation-item.d.vue.ts +6 -1
  4. package/dist/runtime/components/chat/conversation-item.vue +30 -141
  5. package/dist/runtime/components/chat/conversation-item.vue.d.ts +6 -1
  6. package/dist/runtime/components/chat/conversation-list.d.vue.ts +1 -0
  7. package/dist/runtime/components/chat/conversation-list.vue +300 -72
  8. package/dist/runtime/components/chat/conversation-list.vue.d.ts +1 -0
  9. package/dist/runtime/components/chat/conversation-new-group-button.d.vue.ts +7 -0
  10. package/dist/runtime/components/chat/conversation-new-group-button.vue +90 -0
  11. package/dist/runtime/components/chat/conversation-new-group-button.vue.d.ts +7 -0
  12. package/dist/runtime/components/chat/conversation-new-group-popover-content.d.vue.ts +23 -0
  13. package/dist/runtime/components/chat/conversation-new-group-popover-content.vue +75 -0
  14. package/dist/runtime/components/chat/conversation-new-group-popover-content.vue.d.ts +23 -0
  15. package/dist/runtime/components/chat/mobile/shell/drawer.d.vue.ts +2 -2
  16. package/dist/runtime/components/chat/mobile/shell/drawer.vue +370 -41
  17. package/dist/runtime/components/chat/mobile/shell/drawer.vue.d.ts +2 -2
  18. package/dist/runtime/components/chat/mobile/shell/header.d.vue.ts +4 -4
  19. package/dist/runtime/components/chat/mobile/shell/header.vue.d.ts +4 -4
  20. package/dist/runtime/components/chat/mobile/shell/shell.d.vue.ts +20 -20
  21. package/dist/runtime/components/chat/mobile/shell/shell.vue +1 -1
  22. package/dist/runtime/components/chat/mobile/shell/shell.vue.d.ts +20 -20
  23. package/dist/runtime/components/chat/topbar.d.vue.ts +8 -8
  24. package/dist/runtime/components/chat/topbar.vue.d.ts +8 -8
  25. package/dist/runtime/composables/useConversationGroups.d.ts +12 -0
  26. package/dist/runtime/composables/useConversationGroups.js +160 -0
  27. package/dist/runtime/composables/useConversationItem.d.ts +48 -0
  28. package/dist/runtime/composables/useConversationItem.js +176 -0
  29. package/dist/runtime/composables/useConversationList.d.ts +128 -0
  30. package/dist/runtime/composables/useConversationList.js +553 -0
  31. package/dist/runtime/composables/useConversations.d.ts +2 -0
  32. package/dist/runtime/composables/useConversations.js +246 -107
  33. package/dist/runtime/composables/usePendingConversationGroup.d.ts +5 -0
  34. package/dist/runtime/composables/usePendingConversationGroup.js +33 -0
  35. package/dist/runtime/embed/components/ChatConfigurationModal.d.vue.ts +1 -1
  36. package/dist/runtime/embed/components/ChatConfigurationModal.vue.d.ts +1 -1
  37. package/dist/runtime/embed/components/ChatEmbedInner.vue +24 -5
  38. package/dist/runtime/embed/components/configuration/ChatConfigurationContextFilesTab.d.vue.ts +4 -4
  39. package/dist/runtime/embed/components/configuration/ChatConfigurationContextFilesTab.vue.d.ts +4 -4
  40. package/dist/runtime/embed/components/configuration/ChatConfigurationMobileShell.d.vue.ts +2 -2
  41. package/dist/runtime/embed/components/configuration/ChatConfigurationMobileShell.vue.d.ts +2 -2
  42. package/dist/runtime/server/api/chat/conversations/[id]/group.patch.d.ts +1 -0
  43. package/dist/runtime/server/api/chat/conversations/[id]/group.patch.js +1 -0
  44. package/dist/runtime/server/api/chat/conversations/groups/[groupId]/index.delete.d.ts +1 -0
  45. package/dist/runtime/server/api/chat/conversations/groups/[groupId]/index.delete.js +1 -0
  46. package/dist/runtime/server/api/chat/conversations/groups/[groupId]/index.patch.d.ts +1 -0
  47. package/dist/runtime/server/api/chat/conversations/groups/[groupId]/index.patch.js +1 -0
  48. package/dist/runtime/server/api/chat/conversations/groups/index.get.d.ts +1 -0
  49. package/dist/runtime/server/api/chat/conversations/groups/index.get.js +1 -0
  50. package/dist/runtime/server/api/chat/conversations/groups/index.post.d.ts +1 -0
  51. package/dist/runtime/server/api/chat/conversations/groups/index.post.js +1 -0
  52. package/dist/runtime/server/api/chat/conversations/metadata.get.d.ts +1 -0
  53. package/dist/runtime/server/api/chat/conversations/metadata.get.js +1 -0
  54. package/dist/runtime/server/api/conversations/[id]/duplicate.post.js +1 -0
  55. package/dist/runtime/server/api/conversations/[id]/group.patch.d.ts +2 -0
  56. package/dist/runtime/server/api/conversations/[id]/group.patch.js +46 -0
  57. package/dist/runtime/server/api/conversations/groups/[groupId]/index.delete.d.ts +4 -0
  58. package/dist/runtime/server/api/conversations/groups/[groupId]/index.delete.js +25 -0
  59. package/dist/runtime/server/api/conversations/groups/[groupId]/index.patch.d.ts +2 -0
  60. package/dist/runtime/server/api/conversations/groups/[groupId]/index.patch.js +30 -0
  61. package/dist/runtime/server/api/conversations/groups/index.get.d.ts +2 -0
  62. package/dist/runtime/server/api/conversations/groups/index.get.js +13 -0
  63. package/dist/runtime/server/api/conversations/groups/index.post.d.ts +2 -0
  64. package/dist/runtime/server/api/conversations/groups/index.post.js +26 -0
  65. package/dist/runtime/server/api/conversations/index.post.js +1 -0
  66. package/dist/runtime/server/api/conversations/metadata.get.d.ts +2 -0
  67. package/dist/runtime/server/api/conversations/metadata.get.js +20 -0
  68. package/dist/runtime/server/db/schema/conversation-groups.d.ts +143 -0
  69. package/dist/runtime/server/db/schema/conversation-groups.js +20 -0
  70. package/dist/runtime/server/db/schema/conversations.d.ts +17 -0
  71. package/dist/runtime/server/db/schema/conversations.js +3 -0
  72. package/dist/runtime/server/db/schema/index.d.ts +1 -0
  73. package/dist/runtime/server/db/schema/index.js +1 -0
  74. package/dist/runtime/server/utils/conversation-group.d.ts +4 -0
  75. package/dist/runtime/server/utils/conversation-group.js +48 -0
  76. package/dist/runtime/types/chat.d.ts +6 -1
  77. package/dist/runtime/utils/conversation-groups.d.ts +18 -0
  78. package/dist/runtime/utils/conversation-groups.js +30 -0
  79. package/drizzle/0016_dry_aaron_stack.sql +16 -0
  80. package/drizzle/meta/0016_snapshot.json +887 -0
  81. package/drizzle/meta/_journal.json +7 -0
  82. package/package.json +1 -1
@@ -8,15 +8,15 @@ type __VLS_Props = {
8
8
  getFileType: (fileName: string) => string;
9
9
  };
10
10
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
11
- "update:searchQuery": (value: string) => any;
12
11
  handleFileSelect: (event: Event) => any;
13
- removePendingFile: (file: File) => any;
14
12
  removeContextFile: (url: string) => any;
13
+ removePendingFile: (file: File) => any;
14
+ "update:searchQuery": (value: string) => any;
15
15
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
16
- "onUpdate:searchQuery"?: ((value: string) => any) | undefined;
17
16
  onHandleFileSelect?: ((event: Event) => any) | undefined;
18
- onRemovePendingFile?: ((file: File) => any) | undefined;
19
17
  onRemoveContextFile?: ((url: string) => any) | undefined;
18
+ onRemovePendingFile?: ((file: File) => any) | undefined;
19
+ "onUpdate:searchQuery"?: ((value: string) => any) | undefined;
20
20
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
21
  declare const _default: typeof __VLS_export;
22
22
  export default _default;
@@ -15,13 +15,13 @@ type __VLS_Slots = {} & {
15
15
  };
16
16
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
17
17
  close: () => any;
18
- back: () => any;
19
18
  save: () => any;
19
+ back: () => any;
20
20
  selectTab: (value: string) => any;
21
21
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
22
22
  onClose?: (() => any) | undefined;
23
- onBack?: (() => any) | undefined;
24
23
  onSave?: (() => any) | undefined;
24
+ onBack?: (() => any) | undefined;
25
25
  onSelectTab?: ((value: string) => any) | undefined;
26
26
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
27
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -15,13 +15,13 @@ type __VLS_Slots = {} & {
15
15
  };
16
16
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
17
17
  close: () => any;
18
- back: () => any;
19
18
  save: () => any;
19
+ back: () => any;
20
20
  selectTab: (value: string) => any;
21
21
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
22
22
  onClose?: (() => any) | undefined;
23
- onBack?: (() => any) | undefined;
24
23
  onSave?: (() => any) | undefined;
24
+ onBack?: (() => any) | undefined;
25
25
  onSelectTab?: ((value: string) => any) | undefined;
26
26
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
27
27
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -0,0 +1 @@
1
+ export { default } from '../../../conversations/[id]/group.patch.js';
@@ -0,0 +1 @@
1
+ export { default } from "../../../conversations/[id]/group.patch.js";
@@ -0,0 +1 @@
1
+ export { default } from '../../../../conversations/groups/[groupId]/index.delete.js';
@@ -0,0 +1 @@
1
+ export { default } from "../../../../conversations/groups/[groupId]/index.delete.js";
@@ -0,0 +1 @@
1
+ export { default } from '../../../../conversations/groups/[groupId]/index.patch.js';
@@ -0,0 +1 @@
1
+ export { default } from "../../../../conversations/groups/[groupId]/index.patch.js";
@@ -0,0 +1 @@
1
+ export { default } from '../../../conversations/groups/index.get.js';
@@ -0,0 +1 @@
1
+ export { default } from "../../../conversations/groups/index.get.js";
@@ -0,0 +1 @@
1
+ export { default } from '../../../conversations/groups/index.post.js';
@@ -0,0 +1 @@
1
+ export { default } from "../../../conversations/groups/index.post.js";
@@ -0,0 +1 @@
1
+ export { default } from '../../conversations/metadata.get.js';
@@ -0,0 +1 @@
1
+ export { default } from "../../conversations/metadata.get.js";
@@ -26,6 +26,7 @@ export default defineEventHandler(async (event) => {
26
26
  const duplicated = await db.transaction(async (tx) => {
27
27
  const [newConversation] = await tx.insert(schema.conversations).values({
28
28
  workspaceId: context.workspaceId,
29
+ groupId: null,
29
30
  userId: context.user.id,
30
31
  title: `${original.title} (copy)`,
31
32
  createdBy: context.user.email,
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
2
+ export default _default;
@@ -0,0 +1,46 @@
1
+ import { createError, defineEventHandler, getRouterParam, readBody } from "h3";
2
+ import { useDb, schema } from "#chat-runtime/server/db";
3
+ import { resolveChatRuntimeContext } from "#chat-runtime/server/utils/chat-context";
4
+ import { resolveOptionalConversationGroupId, conversationGroupScopeConditions } from "#chat-runtime/server/utils/conversation-group";
5
+ import { conversationScopeConditions } from "#chat-runtime/server/utils/conversation-scope";
6
+ import { logger } from "#chat-runtime/server/utils/logger";
7
+ function hasGroupId(body) {
8
+ return !!body && typeof body === "object" && Object.prototype.hasOwnProperty.call(body, "groupId");
9
+ }
10
+ export default defineEventHandler(async (event) => {
11
+ const context = resolveChatRuntimeContext(event);
12
+ const db = useDb();
13
+ const id = getRouterParam(event, "id");
14
+ if (!id) {
15
+ throw createError({
16
+ statusCode: 400,
17
+ statusMessage: "Conversation ID is required"
18
+ });
19
+ }
20
+ const body = await readBody(event);
21
+ if (!hasGroupId(body)) {
22
+ throw createError({
23
+ statusCode: 400,
24
+ statusMessage: "Group ID is required"
25
+ });
26
+ }
27
+ const groupId = resolveOptionalConversationGroupId(body.groupId);
28
+ if (groupId) {
29
+ const [group] = await db.select({ id: schema.conversationGroups.id }).from(schema.conversationGroups).where(conversationGroupScopeConditions(context, groupId)).limit(1);
30
+ if (!group) {
31
+ throw createError({
32
+ statusCode: 404,
33
+ statusMessage: "Conversation group not found"
34
+ });
35
+ }
36
+ }
37
+ const [updated] = await db.update(schema.conversations).set({ groupId }).where(conversationScopeConditions(context, id)).returning();
38
+ if (!updated) {
39
+ throw createError({
40
+ statusCode: 404,
41
+ statusMessage: "Conversation not found"
42
+ });
43
+ }
44
+ logger.info({ conversationId: id, groupId, workspaceId: context.workspaceId }, "Conversation moved between groups");
45
+ return updated;
46
+ });
@@ -0,0 +1,4 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
+ success: boolean;
3
+ }>>;
4
+ export default _default;
@@ -0,0 +1,25 @@
1
+ import { createError, defineEventHandler, getRouterParam } from "h3";
2
+ import { useDb, schema } from "#chat-runtime/server/db";
3
+ import { resolveChatRuntimeContext } from "#chat-runtime/server/utils/chat-context";
4
+ import { conversationGroupScopeConditions } from "#chat-runtime/server/utils/conversation-group";
5
+ import { logger } from "#chat-runtime/server/utils/logger";
6
+ export default defineEventHandler(async (event) => {
7
+ const context = resolveChatRuntimeContext(event);
8
+ const db = useDb();
9
+ const groupId = getRouterParam(event, "groupId");
10
+ if (!groupId) {
11
+ throw createError({
12
+ statusCode: 400,
13
+ statusMessage: "Group ID is required"
14
+ });
15
+ }
16
+ const [group] = await db.delete(schema.conversationGroups).where(conversationGroupScopeConditions(context, groupId)).returning();
17
+ if (!group) {
18
+ throw createError({
19
+ statusCode: 404,
20
+ statusMessage: "Conversation group not found"
21
+ });
22
+ }
23
+ logger.info({ groupId, workspaceId: context.workspaceId }, "Conversation group deleted");
24
+ return { success: true };
25
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
2
+ export default _default;
@@ -0,0 +1,30 @@
1
+ import { createError, defineEventHandler, getRouterParam, readBody } from "h3";
2
+ import { useDb, schema } from "#chat-runtime/server/db";
3
+ import { resolveChatRuntimeContext } from "#chat-runtime/server/utils/chat-context";
4
+ import { conversationGroupScopeConditions, resolveConversationGroupName } from "#chat-runtime/server/utils/conversation-group";
5
+ import { logger } from "#chat-runtime/server/utils/logger";
6
+ export default defineEventHandler(async (event) => {
7
+ const context = resolveChatRuntimeContext(event);
8
+ const db = useDb();
9
+ const groupId = getRouterParam(event, "groupId");
10
+ if (!groupId) {
11
+ throw createError({
12
+ statusCode: 400,
13
+ statusMessage: "Group ID is required"
14
+ });
15
+ }
16
+ const body = await readBody(event);
17
+ const name = resolveConversationGroupName(body?.name);
18
+ const [group] = await db.update(schema.conversationGroups).set({
19
+ name,
20
+ updatedAt: /* @__PURE__ */ new Date()
21
+ }).where(conversationGroupScopeConditions(context, groupId)).returning();
22
+ if (!group) {
23
+ throw createError({
24
+ statusCode: 404,
25
+ statusMessage: "Conversation group not found"
26
+ });
27
+ }
28
+ logger.info({ groupId, workspaceId: context.workspaceId }, "Conversation group renamed");
29
+ return group;
30
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
2
+ export default _default;
@@ -0,0 +1,13 @@
1
+ import { defineEventHandler } from "h3";
2
+ import { asc } from "drizzle-orm";
3
+ import { useDb, schema } from "#chat-runtime/server/db";
4
+ import { resolveChatRuntimeContext } from "#chat-runtime/server/utils/chat-context";
5
+ import { conversationGroupScopeConditions } from "#chat-runtime/server/utils/conversation-group";
6
+ import { logger } from "#chat-runtime/server/utils/logger";
7
+ export default defineEventHandler(async (event) => {
8
+ const context = resolveChatRuntimeContext(event);
9
+ const db = useDb();
10
+ const groups = await db.select().from(schema.conversationGroups).where(conversationGroupScopeConditions(context)).orderBy(asc(schema.conversationGroups.createdAt), asc(schema.conversationGroups.name));
11
+ logger.debug({ workspaceId: context.workspaceId, count: groups.length }, "Conversation groups listed");
12
+ return groups;
13
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
2
+ export default _default;
@@ -0,0 +1,26 @@
1
+ import { createError, defineEventHandler, readBody } from "h3";
2
+ import { useDb, schema } from "#chat-runtime/server/db";
3
+ import { resolveChatRuntimeContext } from "#chat-runtime/server/utils/chat-context";
4
+ import { resolveConversationGroupName } from "#chat-runtime/server/utils/conversation-group";
5
+ import { logger } from "#chat-runtime/server/utils/logger";
6
+ export default defineEventHandler(async (event) => {
7
+ const context = resolveChatRuntimeContext(event);
8
+ const db = useDb();
9
+ const body = await readBody(event);
10
+ const name = resolveConversationGroupName(body?.name);
11
+ const [group] = await db.insert(schema.conversationGroups).values({
12
+ workspaceId: context.workspaceId,
13
+ telaAgentId: context.telaAgentId,
14
+ conversationScope: context.conversationScope,
15
+ name,
16
+ createdBy: context.user.email
17
+ }).returning();
18
+ if (!group) {
19
+ throw createError({
20
+ statusCode: 500,
21
+ statusMessage: "Failed to create conversation group"
22
+ });
23
+ }
24
+ logger.info({ groupId: group.id, workspaceId: context.workspaceId }, "Conversation group created");
25
+ return group;
26
+ });
@@ -27,6 +27,7 @@ export default defineEventHandler(async (event) => {
27
27
  }
28
28
  const [conversation] = await db.insert(schema.conversations).values({
29
29
  workspaceId: context.workspaceId,
30
+ groupId: null,
30
31
  userId: context.user.id,
31
32
  createdBy: context.user.email,
32
33
  telaAgentId: context.telaAgentId,
@@ -0,0 +1,2 @@
1
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<ConversationListMetadata>>;
2
+ export default _default;
@@ -0,0 +1,20 @@
1
+ import { defineEventHandler } from "h3";
2
+ import { sql } from "drizzle-orm";
3
+ import { useDb, schema } from "#chat-runtime/server/db";
4
+ import { resolveChatRuntimeContext } from "#chat-runtime/server/utils/chat-context";
5
+ import { conversationScopeConditions } from "#chat-runtime/server/utils/conversation-scope";
6
+ import { logger } from "#chat-runtime/server/utils/logger";
7
+ export default defineEventHandler(async (event) => {
8
+ const context = resolveChatRuntimeContext(event);
9
+ const db = useDb();
10
+ const [metadata] = await db.select({
11
+ all: sql`COUNT(*)::int`,
12
+ mine: sql`COUNT(*) FILTER (WHERE ${schema.conversations.userId} = ${context.user.id})::int`
13
+ }).from(schema.conversations).where(conversationScopeConditions(context));
14
+ const counts = {
15
+ all: metadata?.all ?? 0,
16
+ mine: metadata?.mine ?? 0
17
+ };
18
+ logger.debug({ workspaceId: context.workspaceId, counts }, "Conversations metadata loaded");
19
+ return { counts };
20
+ });
@@ -0,0 +1,143 @@
1
+ export declare const conversationGroups: import("drizzle-orm/pg-core").PgTableWithColumns<{
2
+ name: "conversation_groups";
3
+ schema: "chat";
4
+ columns: {
5
+ id: import("drizzle-orm/pg-core").PgColumn<{
6
+ name: "id";
7
+ tableName: "conversation_groups";
8
+ dataType: "string";
9
+ columnType: "PgUUID";
10
+ data: string;
11
+ driverParam: string;
12
+ notNull: true;
13
+ hasDefault: true;
14
+ isPrimaryKey: true;
15
+ isAutoincrement: false;
16
+ hasRuntimeDefault: false;
17
+ enumValues: undefined;
18
+ baseColumn: never;
19
+ identity: undefined;
20
+ generated: undefined;
21
+ }, {}, {}>;
22
+ workspaceId: import("drizzle-orm/pg-core").PgColumn<{
23
+ name: "workspace_id";
24
+ tableName: "conversation_groups";
25
+ dataType: "string";
26
+ columnType: "PgText";
27
+ data: string;
28
+ driverParam: string;
29
+ notNull: true;
30
+ hasDefault: false;
31
+ isPrimaryKey: false;
32
+ isAutoincrement: false;
33
+ hasRuntimeDefault: false;
34
+ enumValues: [string, ...string[]];
35
+ baseColumn: never;
36
+ identity: undefined;
37
+ generated: undefined;
38
+ }, {}, {}>;
39
+ telaAgentId: import("drizzle-orm/pg-core").PgColumn<{
40
+ name: "tela_agent_id";
41
+ tableName: "conversation_groups";
42
+ dataType: "string";
43
+ columnType: "PgText";
44
+ data: string;
45
+ driverParam: string;
46
+ notNull: false;
47
+ hasDefault: false;
48
+ isPrimaryKey: false;
49
+ isAutoincrement: false;
50
+ hasRuntimeDefault: false;
51
+ enumValues: [string, ...string[]];
52
+ baseColumn: never;
53
+ identity: undefined;
54
+ generated: undefined;
55
+ }, {}, {}>;
56
+ conversationScope: import("drizzle-orm/pg-core").PgColumn<{
57
+ name: "conversation_scope";
58
+ tableName: "conversation_groups";
59
+ dataType: "string";
60
+ columnType: "PgText";
61
+ data: string;
62
+ driverParam: string;
63
+ notNull: false;
64
+ hasDefault: false;
65
+ isPrimaryKey: false;
66
+ isAutoincrement: false;
67
+ hasRuntimeDefault: false;
68
+ enumValues: [string, ...string[]];
69
+ baseColumn: never;
70
+ identity: undefined;
71
+ generated: undefined;
72
+ }, {}, {}>;
73
+ name: import("drizzle-orm/pg-core").PgColumn<{
74
+ name: "name";
75
+ tableName: "conversation_groups";
76
+ dataType: "string";
77
+ columnType: "PgText";
78
+ data: string;
79
+ driverParam: string;
80
+ notNull: true;
81
+ hasDefault: false;
82
+ isPrimaryKey: false;
83
+ isAutoincrement: false;
84
+ hasRuntimeDefault: false;
85
+ enumValues: [string, ...string[]];
86
+ baseColumn: never;
87
+ identity: undefined;
88
+ generated: undefined;
89
+ }, {}, {}>;
90
+ createdBy: import("drizzle-orm/pg-core").PgColumn<{
91
+ name: "created_by";
92
+ tableName: "conversation_groups";
93
+ dataType: "string";
94
+ columnType: "PgText";
95
+ data: string;
96
+ driverParam: string;
97
+ notNull: false;
98
+ hasDefault: false;
99
+ isPrimaryKey: false;
100
+ isAutoincrement: false;
101
+ hasRuntimeDefault: false;
102
+ enumValues: [string, ...string[]];
103
+ baseColumn: never;
104
+ identity: undefined;
105
+ generated: undefined;
106
+ }, {}, {}>;
107
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
108
+ name: "created_at";
109
+ tableName: "conversation_groups";
110
+ dataType: "date";
111
+ columnType: "PgTimestamp";
112
+ data: Date;
113
+ driverParam: string;
114
+ notNull: true;
115
+ hasDefault: true;
116
+ isPrimaryKey: false;
117
+ isAutoincrement: false;
118
+ hasRuntimeDefault: false;
119
+ enumValues: undefined;
120
+ baseColumn: never;
121
+ identity: undefined;
122
+ generated: undefined;
123
+ }, {}, {}>;
124
+ updatedAt: import("drizzle-orm/pg-core").PgColumn<{
125
+ name: "updated_at";
126
+ tableName: "conversation_groups";
127
+ dataType: "date";
128
+ columnType: "PgTimestamp";
129
+ data: Date;
130
+ driverParam: string;
131
+ notNull: true;
132
+ hasDefault: true;
133
+ isPrimaryKey: false;
134
+ isAutoincrement: false;
135
+ hasRuntimeDefault: false;
136
+ enumValues: undefined;
137
+ baseColumn: never;
138
+ identity: undefined;
139
+ generated: undefined;
140
+ }, {}, {}>;
141
+ };
142
+ dialect: "pg";
143
+ }>;
@@ -0,0 +1,20 @@
1
+ import { index, text, timestamp, uuid } from "drizzle-orm/pg-core";
2
+ import { chatSchema } from "./_schema.js";
3
+ export const conversationGroups = chatSchema.table("conversation_groups", {
4
+ id: uuid("id").primaryKey().defaultRandom(),
5
+ workspaceId: text("workspace_id").notNull(),
6
+ telaAgentId: text("tela_agent_id"),
7
+ conversationScope: text("conversation_scope"),
8
+ name: text("name").notNull(),
9
+ createdBy: text("created_by"),
10
+ createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
11
+ updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull()
12
+ }, (table) => [
13
+ index("idx_conversation_groups_workspace").on(table.workspaceId),
14
+ index("idx_conversation_groups_runtime_created_at").on(
15
+ table.workspaceId,
16
+ table.telaAgentId,
17
+ table.conversationScope,
18
+ table.createdAt
19
+ )
20
+ ]);
@@ -37,6 +37,23 @@ export declare const conversations: import("drizzle-orm/pg-core").PgTableWithCol
37
37
  identity: undefined;
38
38
  generated: undefined;
39
39
  }, {}, {}>;
40
+ groupId: import("drizzle-orm/pg-core").PgColumn<{
41
+ name: "group_id";
42
+ tableName: "conversations";
43
+ dataType: "string";
44
+ columnType: "PgUUID";
45
+ data: string;
46
+ driverParam: string;
47
+ notNull: false;
48
+ hasDefault: false;
49
+ isPrimaryKey: false;
50
+ isAutoincrement: false;
51
+ hasRuntimeDefault: false;
52
+ enumValues: undefined;
53
+ baseColumn: never;
54
+ identity: undefined;
55
+ generated: undefined;
56
+ }, {}, {}>;
40
57
  userId: import("drizzle-orm/pg-core").PgColumn<{
41
58
  name: "user_id";
42
59
  tableName: "conversations";
@@ -1,8 +1,10 @@
1
1
  import { uuid, text, timestamp, index, jsonb } from "drizzle-orm/pg-core";
2
2
  import { chatSchema } from "./_schema.js";
3
+ import { conversationGroups } from "./conversation-groups.js";
3
4
  export const conversations = chatSchema.table("conversations", {
4
5
  id: uuid("id").primaryKey().defaultRandom(),
5
6
  workspaceId: text("workspace_id").notNull(),
7
+ groupId: uuid("group_id").references(() => conversationGroups.id, { onDelete: "set null" }),
6
8
  userId: text("user_id").notNull(),
7
9
  title: text("title").notNull().default("Nova conversa"),
8
10
  threadSessionId: text("thread_session_id"),
@@ -16,6 +18,7 @@ export const conversations = chatSchema.table("conversations", {
16
18
  updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull()
17
19
  }, (table) => [
18
20
  index("idx_conversations_workspace").on(table.workspaceId),
21
+ index("idx_conversations_group").on(table.groupId),
19
22
  index("idx_conversations_user").on(table.userId),
20
23
  index("idx_conversations_updated").on(table.updatedAt),
21
24
  index("idx_conversations_workspace_tela_agent_updated").on(table.workspaceId, table.telaAgentId, table.updatedAt)
@@ -1,4 +1,5 @@
1
1
  export { CHAT_SCHEMA_NAME, chatSchema } from './_schema.js';
2
+ export { conversationGroups } from './conversation-groups.js';
2
3
  export { conversationUsage, type ConversationUsageMetadata, type ModelUsageEntry } from './conversation-usage.js';
3
4
  export { conversations } from './conversations.js';
4
5
  export { type ExternalSkillInsert, type ExternalSkillRow, externalSkills, externalSkillsRelations } from './external-skills.js';
@@ -1,4 +1,5 @@
1
1
  export { CHAT_SCHEMA_NAME, chatSchema } from "./_schema.js";
2
+ export { conversationGroups } from "./conversation-groups.js";
2
3
  export { conversationUsage } from "./conversation-usage.js";
3
4
  export { conversations } from "./conversations.js";
4
5
  export { externalSkills, externalSkillsRelations } from "./external-skills.js";
@@ -0,0 +1,4 @@
1
+ import type { ChatRuntimeContext } from '#chat-runtime/server/utils/chat-context';
2
+ export declare function conversationGroupScopeConditions(context: ChatRuntimeContext, groupId?: string): import("drizzle-orm").SQL<unknown> | undefined;
3
+ export declare function resolveConversationGroupName(name: unknown): string;
4
+ export declare function resolveOptionalConversationGroupId(groupId: unknown): string | null;
@@ -0,0 +1,48 @@
1
+ import { and, eq, isNull } from "drizzle-orm";
2
+ import { createError } from "h3";
3
+ import { schema } from "#chat-runtime/server/db";
4
+ const MAX_GROUP_NAME_LENGTH = 80;
5
+ export function conversationGroupScopeConditions(context, groupId) {
6
+ const conditions = [
7
+ eq(schema.conversationGroups.workspaceId, context.workspaceId),
8
+ context.telaAgentId ? eq(schema.conversationGroups.telaAgentId, context.telaAgentId) : isNull(schema.conversationGroups.telaAgentId),
9
+ context.conversationScope ? eq(schema.conversationGroups.conversationScope, context.conversationScope) : isNull(schema.conversationGroups.conversationScope)
10
+ ];
11
+ if (groupId) {
12
+ conditions.unshift(eq(schema.conversationGroups.id, groupId));
13
+ }
14
+ return and(...conditions);
15
+ }
16
+ export function resolveConversationGroupName(name) {
17
+ if (typeof name !== "string") {
18
+ throw createError({
19
+ statusCode: 400,
20
+ statusMessage: "Group name is required"
21
+ });
22
+ }
23
+ const trimmedName = name.trim();
24
+ if (!trimmedName) {
25
+ throw createError({
26
+ statusCode: 400,
27
+ statusMessage: "Group name cannot be empty"
28
+ });
29
+ }
30
+ if (trimmedName.length > MAX_GROUP_NAME_LENGTH) {
31
+ throw createError({
32
+ statusCode: 400,
33
+ statusMessage: "Group name is too long"
34
+ });
35
+ }
36
+ return trimmedName;
37
+ }
38
+ export function resolveOptionalConversationGroupId(groupId) {
39
+ if (groupId === null)
40
+ return null;
41
+ if (typeof groupId !== "string" || !groupId.trim()) {
42
+ throw createError({
43
+ statusCode: 400,
44
+ statusMessage: "Invalid group ID"
45
+ });
46
+ }
47
+ return groupId.trim();
48
+ }
@@ -1,11 +1,16 @@
1
1
  import type { InferSelectModel } from 'drizzle-orm';
2
- import type { conversations, messages, ContextFile as SchemaContextFile, ExternalSkill as SchemaExternalSkill, MessageFile as SchemaMessageFile } from '#chat-runtime/server/db/schema';
2
+ import type { conversationGroups, conversations, messages, ContextFile as SchemaContextFile, ExternalSkill as SchemaExternalSkill, MessageFile as SchemaMessageFile } from '#chat-runtime/server/db/schema';
3
3
  export type ContextFile = SchemaContextFile;
4
4
  export type ExternalSkill = SchemaExternalSkill;
5
5
  export type MessageFile = SchemaMessageFile;
6
6
  export type Conversation = InferSelectModel<typeof conversations>;
7
+ export type ConversationGroup = InferSelectModel<typeof conversationGroups>;
7
8
  export type Message = InferSelectModel<typeof messages>;
8
9
  export type ConversationCreatorFilter = 'all' | 'mine';
10
+ export type ConversationCreatorFilterCounts = Record<ConversationCreatorFilter, number>;
11
+ export type ConversationListMetadata = {
12
+ counts: ConversationCreatorFilterCounts;
13
+ };
9
14
  export declare const CONVERSATION_CREATOR_FILTER_OPTIONS: readonly [{
10
15
  readonly label: "Todas";
11
16
  readonly value: "all";
@@ -0,0 +1,18 @@
1
+ export type ConversationGroupLike = {
2
+ id: string;
3
+ name: string;
4
+ createdAt?: Date | string;
5
+ };
6
+ export type ConversationGroupItem = {
7
+ groupId?: string | null;
8
+ updatedAt: Date | string;
9
+ };
10
+ export type ConversationGroupBucket<TGroup extends ConversationGroupLike, TConversation extends ConversationGroupItem> = {
11
+ group: TGroup;
12
+ items: TConversation[];
13
+ };
14
+ export type GroupedConversations<TGroup extends ConversationGroupLike, TConversation extends ConversationGroupItem> = {
15
+ groups: ConversationGroupBucket<TGroup, TConversation>[];
16
+ unfiled: TConversation[];
17
+ };
18
+ export declare function groupConversationsByGroup<TConversation extends ConversationGroupItem, TGroup extends ConversationGroupLike>(conversations: readonly TConversation[], groups: readonly TGroup[]): GroupedConversations<TGroup, TConversation>;