@vc-shell/framework 1.2.1 → 1.2.3-beta.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 (231) hide show
  1. package/core/composables/index.ts +2 -0
  2. package/core/composables/useAssets/index.ts +72 -28
  3. package/core/composables/useAsync/index.ts +4 -1
  4. package/core/composables/useBladeRegistry/index.ts +6 -5
  5. package/core/composables/useBreadcrumbs/index.ts +4 -1
  6. package/core/composables/useErrorHandler/index.ts +4 -1
  7. package/core/composables/useFunctions/debounce.ts +0 -1
  8. package/core/composables/useFunctions/delay.ts +0 -1
  9. package/core/composables/useFunctions/index.ts +0 -1
  10. package/core/composables/useFunctions/once.ts +0 -1
  11. package/core/composables/useFunctions/sleep.ts +0 -1
  12. package/core/composables/useFunctions/throttle.ts +0 -1
  13. package/core/composables/useGlobalSearch/index.ts +3 -3
  14. package/core/composables/useMenuService/index.ts +5 -2
  15. package/core/composables/useNotifications/index.ts +5 -2
  16. package/core/composables/useTheme/index.ts +4 -1
  17. package/core/composables/useUser/index.ts +189 -20
  18. package/core/composables/useWidgets/index.ts +5 -2
  19. package/core/constants/defaults.ts +76 -0
  20. package/core/constants/index.ts +2 -0
  21. package/core/constants/ui.ts +68 -0
  22. package/core/interceptors/index.ts +5 -2
  23. package/core/plugins/ai-agent/README.md +336 -0
  24. package/core/plugins/ai-agent/components/VcAiAgentPanel.vue +125 -0
  25. package/core/plugins/ai-agent/components/_internal/VcAiAgentHeader.vue +182 -0
  26. package/core/plugins/ai-agent/components/_internal/VcAiAgentIframe.vue +77 -0
  27. package/core/plugins/ai-agent/components/index.ts +1 -0
  28. package/core/plugins/ai-agent/composables/index.ts +4 -0
  29. package/core/plugins/ai-agent/composables/useAiAgent.ts +231 -0
  30. package/core/plugins/ai-agent/composables/useAiAgentContext.ts +280 -0
  31. package/core/plugins/ai-agent/constants.ts +89 -0
  32. package/core/plugins/ai-agent/index.ts +91 -0
  33. package/core/plugins/ai-agent/services/ai-agent-service.ts +598 -0
  34. package/core/plugins/ai-agent/types.ts +310 -0
  35. package/core/plugins/modularity/index.ts +8 -6
  36. package/core/plugins/modularity/loader.ts +36 -33
  37. package/core/plugins/signalR/index.ts +6 -3
  38. package/core/services/app-bar-menu-service.ts +4 -1
  39. package/core/services/dashboard-service.ts +4 -1
  40. package/core/services/index.ts +2 -0
  41. package/core/services/menu-service.ts +4 -1
  42. package/core/services/settings-menu-service.ts +4 -1
  43. package/core/services/toolbar-service.ts +18 -3
  44. package/core/services/widget-service.ts +7 -4
  45. package/core/types/index.ts +3 -0
  46. package/core/types/services.ts +194 -0
  47. package/core/utilities/errorTypes.ts +126 -0
  48. package/core/utilities/index.ts +2 -0
  49. package/core/utilities/logger.ts +120 -0
  50. package/dist/core/composables/useAssets/index.d.ts.map +1 -1
  51. package/dist/core/composables/useAsync/index.d.ts.map +1 -1
  52. package/dist/core/composables/useBladeRegistry/index.d.ts.map +1 -1
  53. package/dist/core/composables/useBreadcrumbs/index.d.ts.map +1 -1
  54. package/dist/core/composables/useErrorHandler/index.d.ts.map +1 -1
  55. package/dist/core/composables/useFunctions/debounce.d.ts.map +1 -1
  56. package/dist/core/composables/useFunctions/delay.d.ts.map +1 -1
  57. package/dist/core/composables/useFunctions/index.d.ts.map +1 -1
  58. package/dist/core/composables/useFunctions/once.d.ts.map +1 -1
  59. package/dist/core/composables/useFunctions/sleep.d.ts.map +1 -1
  60. package/dist/core/composables/useFunctions/throttle.d.ts.map +1 -1
  61. package/dist/core/composables/useGlobalSearch/index.d.ts.map +1 -1
  62. package/dist/core/composables/useMenuService/index.d.ts.map +1 -1
  63. package/dist/core/composables/useNotifications/index.d.ts.map +1 -1
  64. package/dist/core/composables/useTheme/index.d.ts.map +1 -1
  65. package/dist/core/composables/useUser/index.d.ts +8 -0
  66. package/dist/core/composables/useUser/index.d.ts.map +1 -1
  67. package/dist/core/composables/useWidgets/index.d.ts.map +1 -1
  68. package/dist/core/constants/defaults.d.ts +63 -0
  69. package/dist/core/constants/defaults.d.ts.map +1 -0
  70. package/dist/core/constants/index.d.ts +2 -0
  71. package/dist/core/constants/index.d.ts.map +1 -1
  72. package/dist/core/constants/ui.d.ts +50 -0
  73. package/dist/core/constants/ui.d.ts.map +1 -0
  74. package/dist/core/interceptors/index.d.ts.map +1 -1
  75. package/dist/core/plugins/ai-agent/components/VcAiAgentPanel.vue.d.ts +3 -0
  76. package/dist/core/plugins/ai-agent/components/VcAiAgentPanel.vue.d.ts.map +1 -0
  77. package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentHeader.vue.d.ts +15 -0
  78. package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentHeader.vue.d.ts.map +1 -0
  79. package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentIframe.vue.d.ts +10 -0
  80. package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentIframe.vue.d.ts.map +1 -0
  81. package/dist/core/plugins/ai-agent/components/index.d.ts +2 -0
  82. package/dist/core/plugins/ai-agent/components/index.d.ts.map +1 -0
  83. package/dist/core/plugins/ai-agent/composables/index.d.ts +4 -0
  84. package/dist/core/plugins/ai-agent/composables/index.d.ts.map +1 -0
  85. package/dist/core/plugins/ai-agent/composables/useAiAgent.d.ts +95 -0
  86. package/dist/core/plugins/ai-agent/composables/useAiAgent.d.ts.map +1 -0
  87. package/dist/core/plugins/ai-agent/composables/useAiAgentContext.d.ts +55 -0
  88. package/dist/core/plugins/ai-agent/composables/useAiAgentContext.d.ts.map +1 -0
  89. package/dist/core/plugins/ai-agent/constants.d.ts +47 -0
  90. package/dist/core/plugins/ai-agent/constants.d.ts.map +1 -0
  91. package/dist/core/plugins/ai-agent/index.d.ts +48 -0
  92. package/dist/core/plugins/ai-agent/index.d.ts.map +1 -0
  93. package/dist/core/plugins/ai-agent/services/ai-agent-service.d.ts +45 -0
  94. package/dist/core/plugins/ai-agent/services/ai-agent-service.d.ts.map +1 -0
  95. package/dist/core/plugins/ai-agent/types.d.ts +258 -0
  96. package/dist/core/plugins/ai-agent/types.d.ts.map +1 -0
  97. package/dist/core/plugins/modularity/index.d.ts.map +1 -1
  98. package/dist/core/plugins/modularity/loader.d.ts.map +1 -1
  99. package/dist/core/plugins/signalR/index.d.ts.map +1 -1
  100. package/dist/core/services/app-bar-menu-service.d.ts.map +1 -1
  101. package/dist/core/services/dashboard-service.d.ts.map +1 -1
  102. package/dist/core/services/menu-service.d.ts.map +1 -1
  103. package/dist/core/services/settings-menu-service.d.ts.map +1 -1
  104. package/dist/core/services/toolbar-service.d.ts.map +1 -1
  105. package/dist/core/services/widget-service.d.ts.map +1 -1
  106. package/dist/core/types/index.d.ts.map +1 -1
  107. package/dist/core/types/services.d.ts +169 -0
  108. package/dist/core/types/services.d.ts.map +1 -0
  109. package/dist/core/utilities/errorTypes.d.ts +61 -0
  110. package/dist/core/utilities/errorTypes.d.ts.map +1 -0
  111. package/dist/core/utilities/index.d.ts +2 -0
  112. package/dist/core/utilities/index.d.ts.map +1 -1
  113. package/dist/core/utilities/logger.d.ts +259 -0
  114. package/dist/core/utilities/logger.d.ts.map +1 -0
  115. package/dist/framework.js +9623 -8417
  116. package/dist/index.css +1 -1
  117. package/dist/index.d.ts +19 -0
  118. package/dist/index.d.ts.map +1 -1
  119. package/dist/injection-keys.d.ts +21 -6
  120. package/dist/injection-keys.d.ts.map +1 -1
  121. package/dist/shared/components/app-switcher/composables/useAppSwitcher/index.d.ts.map +1 -1
  122. package/dist/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts.map +1 -1
  123. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts.map +1 -1
  124. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeActions.d.ts.map +1 -1
  125. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.d.ts.map +1 -1
  126. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/routerUtils.d.ts.map +1 -1
  127. package/dist/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.d.ts.map +1 -1
  128. package/dist/shared/components/draggable-dashboard/composables/useLayoutPersistence.d.ts.map +1 -1
  129. package/dist/shared/components/notifications/composables/useContainer/index.d.ts.map +1 -1
  130. package/dist/shared/components/notifications/composables/useInstance/index.d.ts.map +1 -1
  131. package/dist/shared/components/notifications/core/notification.d.ts.map +1 -1
  132. package/dist/shared/components/popup-handler/components/vc-popup-container/vc-popup-container.vue.d.ts.map +1 -1
  133. package/dist/shared/components/sign-in/useExternalProvider.d.ts.map +1 -1
  134. package/dist/shared/composables/index.d.ts +1 -0
  135. package/dist/shared/composables/index.d.ts.map +1 -1
  136. package/dist/shared/composables/useExternalWidgets.d.ts.map +1 -1
  137. package/dist/shared/composables/useMenuExpanded.d.ts.map +1 -1
  138. package/dist/shared/composables/useTableSelection.d.ts +57 -0
  139. package/dist/shared/composables/useTableSelection.d.ts.map +1 -0
  140. package/dist/shared/composables/useTableSort.d.ts.map +1 -1
  141. package/dist/shared/modules/assets-manager/components/assets-manager/assets-manager.vue.d.ts.map +1 -1
  142. package/dist/shared/pages/LoginPage/components/login/Login.vue.d.ts.map +1 -1
  143. package/dist/shared/utilities/colorUtils.d.ts +0 -6
  144. package/dist/shared/utilities/colorUtils.d.ts.map +1 -1
  145. package/dist/tsconfig.tsbuildinfo +1 -1
  146. package/dist/ui/components/atoms/vc-banner/vc-banner.vue.d.ts.map +1 -1
  147. package/dist/ui/components/atoms/vc-button/vc-button.vue.d.ts +0 -15
  148. package/dist/ui/components/atoms/vc-button/vc-button.vue.d.ts.map +1 -1
  149. package/dist/ui/components/atoms/vc-container/vc-container.vue.d.ts.map +1 -1
  150. package/dist/ui/components/atoms/vc-icon/vc-icon.vue.d.ts.map +1 -1
  151. package/dist/ui/components/atoms/vc-icon/vc-lucide-icon.vue.d.ts.map +1 -1
  152. package/dist/ui/components/atoms/vc-image/vc-image.vue.d.ts.map +1 -1
  153. package/dist/ui/components/atoms/vc-link/vc-link.vue.d.ts.map +1 -1
  154. package/dist/ui/components/atoms/vc-loading/vc-loading.vue.d.ts.map +1 -1
  155. package/dist/ui/components/atoms/vc-status/vc-status.vue.d.ts +0 -5
  156. package/dist/ui/components/atoms/vc-status/vc-status.vue.d.ts.map +1 -1
  157. package/dist/ui/components/atoms/vc-tooltip/vc-tooltip.vue.d.ts.map +1 -1
  158. package/dist/ui/components/atoms/vc-video/vc-video.vue.d.ts.map +1 -1
  159. package/dist/ui/components/atoms/vc-widget/vc-widget.vue.d.ts.map +1 -1
  160. package/dist/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue.d.ts.map +1 -1
  161. package/dist/ui/components/molecules/vc-input/vc-input.vue.d.ts.map +1 -1
  162. package/dist/ui/components/molecules/vc-pagination/vc-pagination.vue.d.ts.map +1 -1
  163. package/dist/ui/components/molecules/vc-toast/vc-toast.vue.d.ts.map +1 -1
  164. package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
  165. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/_internal/vc-blade-toolbar-buttons/_internal/vc-blade-toolbar-button/vc-blade-toolbar-button.vue.d.ts.map +1 -1
  166. package/dist/ui/components/organisms/vc-blade/vc-blade.vue.d.ts.map +1 -1
  167. package/dist/ui/components/organisms/vc-login-form/vc-login-form.vue.d.ts.map +1 -1
  168. package/dist/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue.d.ts.map +1 -1
  169. package/dist/ui/components/organisms/vc-table/composables/useTableActions.d.ts.map +1 -1
  170. package/dist/ui/components/organisms/vc-table/composables/useTableColumnResize.d.ts.map +1 -1
  171. package/dist/ui/components/organisms/vc-table/composables/useTableRowReorder.d.ts.map +1 -1
  172. package/dist/ui/components/organisms/vc-table/composables/useTableSelection.d.ts.map +1 -1
  173. package/dist/ui/components/organisms/vc-table/composables/useTableState.d.ts.map +1 -1
  174. package/dist/{vendor-lodash-es-BqkGj3Jl.js → vendor-lodash-es-SgOIjJF8.js} +2 -0
  175. package/package.json +5 -5
  176. package/shared/components/app-switcher/composables/useAppSwitcher/index.ts +4 -1
  177. package/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue +67 -4
  178. package/shared/components/blade-navigation/composables/useBladeNavigation/index.ts +13 -10
  179. package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeActions.ts +7 -4
  180. package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.ts +4 -1
  181. package/shared/components/blade-navigation/composables/useBladeNavigation/internal/routerUtils.ts +4 -1
  182. package/shared/components/change-password/change-password.vue +1 -1
  183. package/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.ts +14 -5
  184. package/shared/components/draggable-dashboard/composables/useLayoutPersistence.ts +5 -2
  185. package/shared/components/index.ts +2 -0
  186. package/shared/components/notifications/composables/useContainer/index.ts +8 -6
  187. package/shared/components/notifications/composables/useInstance/index.ts +4 -1
  188. package/shared/components/notifications/core/notification.ts +10 -7
  189. package/shared/components/popup-handler/components/vc-popup-container/vc-popup-container.vue +20 -1
  190. package/shared/components/sign-in/useExternalProvider.ts +6 -4
  191. package/shared/composables/index.ts +1 -0
  192. package/shared/composables/useExternalWidgets.ts +7 -4
  193. package/shared/composables/useMenuExpanded.ts +15 -1
  194. package/shared/composables/useTableSelection.ts +151 -0
  195. package/shared/composables/useTableSort.ts +4 -4
  196. package/shared/modules/assets-manager/components/assets-manager/assets-manager.vue +6 -3
  197. package/shared/pages/LoginPage/components/login/Login.vue +4 -1
  198. package/shared/utilities/colorUtils.ts +5 -12
  199. package/ui/components/atoms/vc-banner/vc-banner.vue +4 -1
  200. package/ui/components/atoms/vc-button/vc-button.vue +2 -25
  201. package/ui/components/atoms/vc-container/vc-container.vue +12 -3
  202. package/ui/components/atoms/vc-icon/vc-icon.vue +0 -10
  203. package/ui/components/atoms/vc-icon/vc-lucide-icon.vue +5 -2
  204. package/ui/components/atoms/vc-image/vc-image.vue +4 -1
  205. package/ui/components/atoms/vc-link/vc-link.vue +59 -54
  206. package/ui/components/atoms/vc-loading/vc-loading.vue +4 -0
  207. package/ui/components/atoms/vc-status/vc-status.vue +0 -5
  208. package/ui/components/atoms/vc-status-icon/vc-status-icon.vue +4 -4
  209. package/ui/components/atoms/vc-tooltip/vc-tooltip.vue +8 -1
  210. package/ui/components/atoms/vc-video/vc-video.vue +4 -2
  211. package/ui/components/atoms/vc-widget/vc-widget.vue +4 -1
  212. package/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue +7 -2
  213. package/ui/components/molecules/vc-input/vc-input.vue +0 -1
  214. package/ui/components/molecules/vc-pagination/vc-pagination.vue +6 -1
  215. package/ui/components/molecules/vc-rating/vc-rating.vue +1 -1
  216. package/ui/components/molecules/vc-textarea/vc-textarea.vue +1 -1
  217. package/ui/components/molecules/vc-toast/vc-toast.vue +11 -1
  218. package/ui/components/organisms/vc-app/vc-app.vue +22 -3
  219. package/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/_internal/vc-blade-toolbar-buttons/_internal/vc-blade-toolbar-button/vc-blade-toolbar-button.vue +4 -1
  220. package/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/vc-blade-toolbar.vue +14 -14
  221. package/ui/components/organisms/vc-blade/vc-blade.vue +3 -1
  222. package/ui/components/organisms/vc-login-form/vc-login-form.vue +3 -1
  223. package/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue +34 -2
  224. package/ui/components/organisms/vc-table/composables/useTableActions.ts +7 -10
  225. package/ui/components/organisms/vc-table/composables/useTableColumnResize.ts +4 -1
  226. package/ui/components/organisms/vc-table/composables/useTableRowReorder.ts +5 -2
  227. package/ui/components/organisms/vc-table/composables/useTableSelection.ts +26 -18
  228. package/ui/components/organisms/vc-table/composables/useTableState.ts +4 -1
  229. package/core/services/global-search-service.ts +0 -36
  230. package/dist/core/services/global-search-service.d.ts +0 -10
  231. package/dist/core/services/global-search-service.d.ts.map +0 -1
@@ -0,0 +1,310 @@
1
+ import { ComputedRef, Ref } from "vue";
2
+
3
+ // ============================================
4
+ // Core Types
5
+ // ============================================
6
+
7
+ /**
8
+ * Context type for AI agent - determines UI behavior in chatbot
9
+ * - 'list': Multiple selected items from a list blade (shows "X items selected" badge)
10
+ * - 'details': Single item being edited in details blade (shows suggestions UI)
11
+ */
12
+ export type AiAgentContextType = "list" | "details";
13
+
14
+ /**
15
+ * Suggestion card for AI agent
16
+ */
17
+ export interface ISuggestion {
18
+ /** Unique identifier */
19
+ id: string;
20
+ /** Display title */
21
+ title: string;
22
+ /** Icon name */
23
+ icon: string;
24
+ /** Icon color (optional) */
25
+ iconColor?: string;
26
+ /** Prompt text to send when clicked */
27
+ prompt: string;
28
+ }
29
+
30
+ /**
31
+ * Options for useAiAgentContext composable
32
+ */
33
+ export interface UseAiAgentContextOptions<T = Record<string, unknown>> {
34
+ /**
35
+ * Ref with data - accepts both formats:
36
+ * - Ref<T> for DETAILS blade (single object, will be wrapped in array internally)
37
+ * - Ref<T[]> for LIST blade (array of selected objects)
38
+ *
39
+ * When AI agent sends changes back, they will be applied to:
40
+ * - The object directly (for single-object refs)
41
+ * - The first item in array (for array refs)
42
+ */
43
+ dataRef: Ref<T> | Ref<T[]>;
44
+
45
+ /** Custom suggestions for this blade */
46
+ suggestions?: ISuggestion[];
47
+ }
48
+
49
+ /**
50
+ * Return type for useAiAgentContext composable
51
+ */
52
+ export interface UseAiAgentContextReturn {
53
+ /** Preview state (for details blades) */
54
+ previewState: {
55
+ isActive: ComputedRef<boolean>;
56
+ changedFields: ComputedRef<string[]>;
57
+ };
58
+ }
59
+
60
+ // ============================================
61
+ // AI Agent Panel Types
62
+ // ============================================
63
+
64
+ /**
65
+ * State of the AI agent panel
66
+ */
67
+ export type AiAgentPanelState = "closed" | "open" | "expanded";
68
+
69
+ /**
70
+ * Configuration for the AI agent panel
71
+ */
72
+ export interface IAiAgentConfig {
73
+ /** URL of the AI agent iframe */
74
+ url: string;
75
+ /** Panel title (default: "Virto OZ") */
76
+ title?: string;
77
+ /** Panel width in pixels when open (default: 350) */
78
+ width?: number;
79
+ /** Panel width in pixels when expanded (default: 500) */
80
+ expandedWidth?: number;
81
+ /** Allowed origins for postMessage (default: ["*"]) */
82
+ allowedOrigins?: string[];
83
+ /**
84
+ * Tenant identifier for the platform instance.
85
+ * This should be a static value identifying the platform installation (e.g., "virto", "acme-corp").
86
+ * Configured by the host application via VirtoShellFramework options.
87
+ *
88
+ */
89
+ tenantId?: string;
90
+ }
91
+
92
+ /**
93
+ * Current blade information for AI context
94
+ */
95
+ export interface IAiAgentBladeContext {
96
+ /** Blade identifier */
97
+ id: string;
98
+ /** Blade component name */
99
+ name: string;
100
+ /** Blade display title */
101
+ title?: string;
102
+ /** Route parameter (e.g., item ID being edited) */
103
+ param?: string;
104
+ /** Additional blade options */
105
+ options?: Record<string, unknown>;
106
+ }
107
+
108
+ /**
109
+ * User information for AI context
110
+ */
111
+ export interface IAiAgentUserContext {
112
+ id?: string;
113
+ userName?: string;
114
+ isAdministrator?: boolean;
115
+ permissions?: string[];
116
+ }
117
+
118
+ /**
119
+ * Full context passed to the AI agent
120
+ */
121
+ export interface IAiAgentContext {
122
+ /** Current user information */
123
+ user: IAiAgentUserContext | undefined;
124
+ /** Current active blade information */
125
+ currentBlade: IAiAgentBladeContext | null;
126
+ /** Data items (from useAiAgentContext) */
127
+ items: Record<string, unknown>[];
128
+ /** Timestamp of context generation */
129
+ timestamp: number;
130
+ }
131
+
132
+ /**
133
+ * Service for managing AI agent state and communication
134
+ */
135
+ export interface IAiAgentService {
136
+ /** Current panel state */
137
+ panelState: Ref<AiAgentPanelState>;
138
+ /** Panel configuration */
139
+ config: Ref<IAiAgentConfig>;
140
+ /** Current context (reactive) */
141
+ context: ComputedRef<IAiAgentContext>;
142
+ /** Whether panel is open (not closed) */
143
+ isOpen: ComputedRef<boolean>;
144
+ /** Whether panel is in expanded state */
145
+ isExpanded: ComputedRef<boolean>;
146
+ /** Total count of items in current context */
147
+ totalItemsCount: ComputedRef<number>;
148
+
149
+ /** Open the AI panel */
150
+ openPanel: () => void;
151
+ /** Close the AI panel */
152
+ closePanel: () => void;
153
+ /** Toggle panel open/close */
154
+ togglePanel: () => void;
155
+ /** Expand the panel to larger width */
156
+ expandPanel: () => void;
157
+ /** Collapse panel to normal width */
158
+ collapsePanel: () => void;
159
+
160
+ /** Update configuration */
161
+ setConfig: (config: Partial<IAiAgentConfig>) => void;
162
+
163
+ /** Send message to AI agent iframe */
164
+ sendMessage: (type: AiAgentMessageType, payload: unknown) => void;
165
+ /** Register message handler, returns unsubscribe function */
166
+ onMessage: (handler: (event: IAiAgentMessage) => void) => () => void;
167
+ }
168
+
169
+ // ============================================
170
+ // PostMessage Protocol Types
171
+ // ============================================
172
+
173
+ /**
174
+ * Message types sent from Shell to Chatbot
175
+ */
176
+ export type ShellToChatMessageType =
177
+ | "INIT_CONTEXT" // Initial context when chatbot loads
178
+ | "UPDATE_CONTEXT"; // Context updates (items, blade changes)
179
+
180
+ /**
181
+ * Message types sent from Chatbot to Shell
182
+ */
183
+ export type ChatToShellMessageType =
184
+ | "CHAT_READY" // Chatbot is loaded and ready
185
+ | "NAVIGATE_TO_APP" // Request to navigate to a blade
186
+ | "EXPAND_IN_CHAT" // Request to expand item in chat
187
+ | "RELOAD_BLADE" // Request to reload current blade
188
+ | "PREVIEW_CHANGES" // Request to preview changes in form
189
+ | "APPLY_CHANGES" // Request to apply data changes
190
+ | "DOWNLOAD_FILE" // Request to download file
191
+ | "SHOW_MORE" // Request for more results
192
+ | "CHAT_ERROR"; // Error notification
193
+
194
+ /**
195
+ * Combined message types
196
+ */
197
+ export type AiAgentMessageType = ShellToChatMessageType | ChatToShellMessageType;
198
+
199
+ /**
200
+ * Generic message type (for handlers)
201
+ */
202
+ export interface IAiAgentMessage<T = unknown> {
203
+ /** Message type identifier */
204
+ type: AiAgentMessageType;
205
+ /** Message payload */
206
+ payload?: T;
207
+ /** Message timestamp (optional) */
208
+ timestamp?: number;
209
+ }
210
+
211
+ // ============================================
212
+ // Specific Message Payloads
213
+ // ============================================
214
+
215
+ /**
216
+ * Blade context for chatbot (simplified for chat use)
217
+ */
218
+ export interface IChatBladeContext {
219
+ /** Blade identifier */
220
+ id: string;
221
+ /** Blade component name */
222
+ name: string;
223
+ /** Blade display title */
224
+ title: string;
225
+ /** Route parameter (e.g., item ID being edited) */
226
+ param?: string;
227
+ }
228
+
229
+ /** Payload for INIT_CONTEXT message (Shell -> Chat) */
230
+ export interface IInitContextPayload {
231
+ /** Current user ID */
232
+ userId: string;
233
+ /** User locale */
234
+ locale: string;
235
+ /** Tenant identifier (from JWT or host app) */
236
+ tenantId?: string;
237
+ /** Current blade context */
238
+ blade: IChatBladeContext;
239
+ /** Context type - determines chatbot UI behavior */
240
+ contextType: AiAgentContextType;
241
+ /** Data items - always array (1 for details, N for list) */
242
+ items: Record<string, unknown>[];
243
+ /** Custom suggestions (if any) */
244
+ suggestions?: ISuggestion[];
245
+ /** Access token for API calls (automatically refreshed) */
246
+ accessToken?: string;
247
+ }
248
+
249
+ /** Payload for UPDATE_CONTEXT message (Shell -> Chat) */
250
+ export interface IUpdateContextPayload {
251
+ /** Updated blade context (if changed) */
252
+ blade?: IChatBladeContext;
253
+ /** Tenant identifier (from JWT or host app) */
254
+ tenantId?: string;
255
+ /** Context type - determines chatbot UI behavior */
256
+ contextType: AiAgentContextType;
257
+ /** Data items - always array of full objects */
258
+ items: Record<string, unknown>[];
259
+ /** Custom suggestions (if changed) */
260
+ suggestions?: ISuggestion[];
261
+ /** Updated user locale (if changed) */
262
+ locale?: string;
263
+ /** Access token for API calls (automatically refreshed) */
264
+ accessToken?: string;
265
+ }
266
+
267
+ /** Payload for NAVIGATE_TO_APP message (Chat -> Shell) */
268
+ export interface INavigateToAppPayload {
269
+ /** Blade name to open */
270
+ bladeName: string;
271
+ /** Entity ID */
272
+ param?: string;
273
+ /** Additional options */
274
+ options?: Record<string, unknown>;
275
+ }
276
+
277
+ /** Payload for PREVIEW_CHANGES message (Chat -> Shell) */
278
+ export interface IPreviewChangesPayload {
279
+ /** Updated data to preview */
280
+ data: Record<string, unknown>;
281
+ /** List of changed field names */
282
+ changedFields?: string[];
283
+ }
284
+
285
+ /** Payload for APPLY_CHANGES message (Chat -> Shell) */
286
+ export interface IApplyChangesPayload {
287
+ changes: Array<{
288
+ entityId: string;
289
+ entityType: string;
290
+ field: string;
291
+ oldValue: unknown;
292
+ newValue: unknown;
293
+ }>;
294
+ }
295
+
296
+ /** Payload for DOWNLOAD_FILE message (Chat -> Shell) */
297
+ export interface IDownloadFilePayload {
298
+ /** Filename for download */
299
+ filename: string;
300
+ /** MIME type */
301
+ contentType: string;
302
+ /** Base64 encoded content */
303
+ content: string;
304
+ }
305
+
306
+ /** Payload for CHAT_ERROR message (Chat -> Shell) */
307
+ export interface IChatErrorPayload {
308
+ code: string;
309
+ message: string;
310
+ }
@@ -2,12 +2,14 @@ import { App, Component, h, inject, resolveComponent, watch } from "vue";
2
2
  import { i18n } from "./../i18n";
3
3
  import { Router } from "vue-router";
4
4
  import { BladeInstanceConstructor, BladeVNode } from "./../../../shared/components/blade-navigation/types";
5
- import { kebabToPascal } from "./../../utilities";
5
+ import { kebabToPascal, createLogger } from "./../../utilities";
6
6
  import { addMenuItem, useMenuService, useNotifications } from "../../composables";
7
7
  import * as _ from "lodash-es";
8
8
  import { notification } from "../../../shared";
9
9
  import { BladeRegistryKey, IBladeRegistrationData, IBladeRegistryInstance } from "../../composables/useBladeRegistry";
10
10
 
11
+ const logger = createLogger("modularity");
12
+
11
13
  export function createModule(components: { [key: string]: BladeInstanceConstructor }, locales?: unknown) {
12
14
  return {
13
15
  install(app: App): void {
@@ -17,7 +19,7 @@ export function createModule(components: { [key: string]: BladeInstanceConstruct
17
19
  if (app.component(componentName)) {
18
20
  // Remove the existing component
19
21
  // Note: Vue does not provide a method to remove a component, so we can overwrite it
20
- console.warn(
22
+ logger.warn(
21
23
  `Component ${componentName} is already registered. It will be overwritten with the new component.`,
22
24
  );
23
25
  }
@@ -52,11 +54,11 @@ export function createAppModule(
52
54
  if (bladeRegistry && bladeRegistry._registerBladeFn) {
53
55
  registerBladeWithRegistry = bladeRegistry._registerBladeFn;
54
56
  } else {
55
- console.error(
57
+ logger.error(
56
58
  "createAppModule: BladeRegistry or its _registerBladeFn not found via inject. Blade registration will be skipped.",
57
59
  );
58
60
  registerBladeWithRegistry = (name: string, data: IBladeRegistrationData) => {
59
- console.warn(`BladeRegistry (noop): Tried to register '${name}' but _registerBladeFn is missing.`);
61
+ logger.warn(`BladeRegistry (noop): Tried to register '${name}' but _registerBladeFn is missing.`);
60
62
  };
61
63
  }
62
64
 
@@ -83,7 +85,7 @@ export function createAppModule(
83
85
  isWorkspace: page.isWorkspace || false,
84
86
  });
85
87
  } else {
86
- console.warn(
88
+ logger.warn(
87
89
  "createAppModule: Page without URL is missing a name. Cannot register with BladeRegistry.",
88
90
  page,
89
91
  );
@@ -179,7 +181,7 @@ export function createAppModule(
179
181
  // Check if the component is already registered
180
182
  if (app.component(name)) {
181
183
  // Overwrite existing component
182
- console.warn(`Component ${name} is already registered. It will be overwritten with the new component.`);
184
+ logger.warn(`Component ${name} is already registered. It will be overwritten with the new component.`);
183
185
  }
184
186
  app.component(name, component);
185
187
  });
@@ -3,6 +3,9 @@ import { Router } from "vue-router";
3
3
  import { DynamicModulesKey } from "../../../injection-keys";
4
4
  import * as semver from "semver";
5
5
  import { notification } from "../../../shared";
6
+ import { createLogger } from "../../utilities";
7
+
8
+ const logger = createLogger("module-loader");
6
9
 
7
10
  interface ModuleManifest {
8
11
  file: string;
@@ -108,12 +111,12 @@ async function loadVersionInfo(url: string): Promise<VersionInfo | null> {
108
111
  try {
109
112
  const response = await fetch(url);
110
113
  if (!response.ok) {
111
- console.warn(`Failed to load version info: ${response.statusText}`);
114
+ logger.warn(`Failed to load version info: ${response.statusText}`);
112
115
  return null;
113
116
  }
114
117
  return (await response.json()) as VersionInfo;
115
118
  } catch (error) {
116
- console.warn(`Error loading version info: ${error}`);
119
+ logger.warn(`Error loading version info: ${error}`);
117
120
  return null;
118
121
  }
119
122
  }
@@ -145,7 +148,7 @@ function checkVersionCompatibility(
145
148
  moduleVersion.compatibleWith.framework &&
146
149
  !semver.satisfies(frameworkVersion, moduleVersion.compatibleWith.framework, { includePrerelease: true })
147
150
  ) {
148
- console.error(
151
+ logger.error(
149
152
  `Module ${moduleId} requires framework version ${moduleVersion.compatibleWith.framework}, but current framework version is ${frameworkVersion}.`,
150
153
  );
151
154
  notification.error(
@@ -163,12 +166,12 @@ function checkVersionCompatibility(
163
166
  const loadedDepVersion = loadedModulesWithVersions.get(depModuleId);
164
167
 
165
168
  if (!loadedDepVersion) {
166
- console.warn(`Module ${moduleId} depends on ${depModuleId}, but it is not loaded yet.`);
169
+ logger.warn(`Module ${moduleId} depends on ${depModuleId}, but it is not loaded yet.`);
167
170
  continue;
168
171
  }
169
172
 
170
173
  if (!semver.satisfies(loadedDepVersion, versionRange, { includePrerelease: true })) {
171
- console.error(
174
+ logger.error(
172
175
  `Module ${moduleId} requires ${depModuleId} version ${versionRange}, but loaded version is ${loadedDepVersion}.`,
173
176
  );
174
177
  notification.error(
@@ -233,7 +236,7 @@ export function useDynamicModules(
233
236
  const finalConfig = { ...DEFAULT_CONFIG, ...config };
234
237
 
235
238
  if (!config.frameworkVersion && finalConfig.frameworkVersion) {
236
- console.warn(
239
+ logger.warn(
237
240
  `Framework version not specified in the configuration, using default ${finalConfig.frameworkVersion}. This may cause compatibility issues with modules.`,
238
241
  );
239
242
  }
@@ -272,7 +275,7 @@ export function useDynamicModules(
272
275
  manifest: (await response.json()) as Manifest,
273
276
  };
274
277
  } catch (error) {
275
- console.error(error);
278
+ logger.error("Error loading module manifest:", error);
276
279
  return null;
277
280
  }
278
281
  });
@@ -303,12 +306,12 @@ export function useDynamicModules(
303
306
  .filter((file) => file.file.endsWith(".css"))
304
307
  .map((file) => loadCSS(moduleUrl + file.file)),
305
308
  ).catch((error) => {
306
- console.error(`Failed to load styles for module ${moduleId}:`, error);
309
+ logger.error(`Failed to load styles for module ${moduleId}:`, error);
307
310
  }),
308
311
  ]);
309
312
 
310
313
  if (versionInfoFromFile) {
311
- console.info(`Loaded version info for module ${moduleId}: v${versionInfoFromFile.version}`);
314
+ logger.info(`Loaded version info for module ${moduleId}: v${versionInfoFromFile.version}`);
312
315
  }
313
316
 
314
317
  // Import module
@@ -322,7 +325,7 @@ export function useDynamicModules(
322
325
  success: true,
323
326
  };
324
327
  } catch (error) {
325
- console.error(`Failed to load module ${moduleId}:`, error);
328
+ logger.error(`Failed to load module ${moduleId}:`, error);
326
329
  return {
327
330
  moduleId,
328
331
  moduleUrl,
@@ -342,7 +345,7 @@ export function useDynamicModules(
342
345
  moduleLoadResults.filter((result) => result.success).map((result) => [result.moduleId, result]),
343
346
  );
344
347
 
345
- console.log("🔍 LoadResultsMap keys:", Array.from(loadResultsMap.keys()));
348
+ logger.debug("LoadResultsMap keys:", Array.from(loadResultsMap.keys()));
346
349
 
347
350
  // Wait for all modules to register themselves in the global scope
348
351
  const expectedModuleIds = Array.from(loadResultsMap.keys());
@@ -369,9 +372,9 @@ export function useDynamicModules(
369
372
 
370
373
  // Check if modules are already registered
371
374
  if (areAllModulesRegistered()) {
372
- console.log("All modules are already registered, proceeding with installation");
375
+ logger.debug("All modules are already registered, proceeding with installation");
373
376
  } else {
374
- console.log(`🔍 Waiting for ${expectedModuleIds.length} modules to register:`, expectedModuleIds);
377
+ logger.debug(`Waiting for ${expectedModuleIds.length} modules to register:`, expectedModuleIds);
375
378
 
376
379
  // Wait for module registration with timeout
377
380
  await new Promise<void>((resolve) => {
@@ -392,7 +395,7 @@ export function useDynamicModules(
392
395
 
393
396
  const checkAndResolve = () => {
394
397
  if (areAllModulesRegistered()) {
395
- console.log("All modules are registered, proceeding with installation");
398
+ logger.debug("All modules are registered, proceeding with installation");
396
399
  cleanup();
397
400
  resolve();
398
401
  return true;
@@ -410,8 +413,8 @@ export function useDynamicModules(
410
413
  const poll = async () => {
411
414
  while (attempts < maxAttempts) {
412
415
  const availableModules = getAvailableModules();
413
- console.log(
414
- `🔍 Attempt ${attempts + 1}: Available modules:`,
416
+ logger.debug(
417
+ `Attempt ${attempts + 1}: Available modules:`,
415
418
  availableModules,
416
419
  `(${availableModules.length}/${expectedModuleIds.length})`,
417
420
  );
@@ -422,7 +425,7 @@ export function useDynamicModules(
422
425
  await new Promise((r) => setTimeout(r, 100));
423
426
  }
424
427
 
425
- console.warn("⚠️ Timeout waiting for all modules to register, proceeding with available modules");
428
+ logger.warn("Timeout waiting for all modules to register, proceeding with available modules");
426
429
  cleanup();
427
430
  resolve();
428
431
  };
@@ -441,18 +444,18 @@ export function useDynamicModules(
441
444
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
442
445
  const modulesToProcess: [string, any][] = Object.entries(window.VcShellDynamicModules || {});
443
446
 
444
- console.log(
445
- `🚀 Found ${modulesToProcess.length} modules to process:`,
447
+ logger.debug(
448
+ `Found ${modulesToProcess.length} modules to process:`,
446
449
  modulesToProcess.map(([name]) => name),
447
450
  );
448
451
 
449
452
  for (const [moduleName, moduleObject] of modulesToProcess) {
450
453
  if (loadedModules.has(moduleName)) {
451
- console.log(`⏭️ Skipping already loaded module: ${moduleName}`);
454
+ logger.debug(`Skipping already loaded module: ${moduleName}`);
452
455
  continue;
453
456
  }
454
457
 
455
- console.log(`📦 Processing module: ${moduleName}`);
458
+ logger.debug(`Processing module: ${moduleName}`);
456
459
 
457
460
  // Try to find the corresponding load result by matching module names
458
461
  const loadResult =
@@ -469,16 +472,16 @@ export function useDynamicModules(
469
472
 
470
473
  const mainModule = getModuleInstall(moduleObject);
471
474
 
472
- console.log(`🔍 Module ${moduleName} exports:`, Object.keys(moduleObject));
473
- console.log(`🔍 Module ${moduleName} has install function:`, !!mainModule);
475
+ logger.debug(`Module ${moduleName} exports:`, Object.keys(moduleObject));
476
+ logger.debug(`Module ${moduleName} has install function:`, !!mainModule);
474
477
 
475
478
  if (mainModule) {
476
479
  const moduleVersionInfo = (mainModule as ModuleWithNamedExport).version || versionFromFile;
477
480
 
478
481
  try {
479
482
  if (!finalConfig.skipVersionCheck) {
480
- console.log(
481
- `🔎 Checking compatibility for ${moduleName} (version: ${moduleVersionInfo?.version || "N/A"})`,
483
+ logger.debug(
484
+ `Checking compatibility for ${moduleName} (version: ${moduleVersionInfo?.version || "N/A"})`,
482
485
  );
483
486
  checkVersionCompatibility(
484
487
  moduleName,
@@ -488,7 +491,7 @@ export function useDynamicModules(
488
491
  );
489
492
  }
490
493
 
491
- console.log(`🔧 Installing module: ${moduleName}`, {
494
+ logger.debug(`Installing module: ${moduleName}`, {
492
495
  hasLoadResult: !!loadResult,
493
496
  versionFromFile: versionFromFile?.version,
494
497
  moduleVersion: moduleVersionInfo?.version,
@@ -503,31 +506,31 @@ export function useDynamicModules(
503
506
  loadedModulesWithVersions.set(moduleName, moduleVersionInfo.version);
504
507
  }
505
508
 
506
- console.log(
507
- `✅ Module ${moduleName} installed successfully (version: ${
509
+ logger.info(
510
+ `Module ${moduleName} installed successfully (version: ${
508
511
  moduleVersionInfo?.version || "no version info"
509
512
  })`,
510
513
  );
511
514
  } catch (e) {
512
515
  if (e instanceof VersionCompatibilityError) {
513
- console.error(`Compatibility error in module ${e.moduleId}:`, e.details);
516
+ logger.error(`Compatibility error in module ${e.moduleId}:`, e.details);
514
517
  } else {
515
- console.error(`Failed to install module ${moduleName}:`, e);
518
+ logger.error(`Failed to install module ${moduleName}:`, e);
516
519
  notification.error(`Failed to install module ${moduleName}`);
517
520
  }
518
521
  }
519
522
  } else {
520
- console.error(`❌ Module ${moduleName} does not have an 'install' function`);
523
+ logger.error(`Module ${moduleName} does not have an 'install' function`);
521
524
  notification.error(
522
525
  `Module ${moduleName} is not a valid module because it does not have an 'install' function.`,
523
526
  );
524
527
  }
525
528
  }
526
529
 
527
- console.log("🏁 Final loadedModules set:", Array.from(loadedModules));
530
+ logger.debug("Final loadedModules set:", Array.from(loadedModules));
528
531
  }
529
532
  } catch (error) {
530
- console.error("Failed to load modules:", error);
533
+ logger.error("Failed to load modules:", error);
531
534
  }
532
535
 
533
536
  app.config.globalProperties.$dynamicModules = {
@@ -4,6 +4,9 @@ import { PushNotification } from "../../api/platform";
4
4
  import { useNotifications } from "./../../composables/useNotifications";
5
5
  import { useUserManagement } from "../../composables/useUserManagement";
6
6
  import { useCypressSignalRMock } from "cypress-signalr-mock";
7
+ import { createLogger } from "../../utilities";
8
+
9
+ const logger = createLogger("signalR");
7
10
 
8
11
  const { addNotification } = useNotifications();
9
12
  const currentCreator = ref<string | undefined>();
@@ -17,7 +20,7 @@ function setupSystemEventsHandler(connection: any, creator?: string) {
17
20
 
18
21
  // Subscribe to events with the new creator
19
22
  if (creator) {
20
- console.log("[SignalR] Setup handler for creator: ", creator);
23
+ logger.debug("Setup handler for creator: ", creator);
21
24
  connection.on("SendSystemEvents", (message: PushNotification) => {
22
25
  if (message.creator === creator) {
23
26
  addNotification(message);
@@ -48,11 +51,11 @@ export const signalR = {
48
51
  connection
49
52
  .start()
50
53
  .then(() => {
51
- console.log("[SignalR] Connected.");
54
+ logger.info("Connected.");
52
55
  setupSystemEventsHandler(connection, currentCreator.value);
53
56
  })
54
57
  .catch((err) => {
55
- console.log("[SignalR] Connection Error: ", err);
58
+ logger.error("Connection Error: ", err);
56
59
  setTimeout(() => start(), 5000);
57
60
  });
58
61
  };
@@ -1,4 +1,7 @@
1
1
  import { ref, computed, Component, ComputedRef } from "vue";
2
+ import { createLogger } from "../utilities";
3
+
4
+ const logger = createLogger("app-bar-widget-service");
2
5
 
3
6
  export interface AppBarWidget {
4
7
  id: string;
@@ -75,7 +78,7 @@ export function createAppBarWidgetService(): IAppBarWidgetService {
75
78
  try {
76
79
  register(item);
77
80
  } catch (e) {
78
- console.warn(`Failed to register pre-added AppBar widget ${item.id}:`, e);
81
+ logger.warn(`Failed to register pre-added AppBar widget ${item.id}:`, e);
79
82
  }
80
83
  });
81
84
 
@@ -1,6 +1,9 @@
1
1
  import { reactive, Component } from "vue";
2
2
  import { DashboardServiceKey } from "../../injection-keys";
3
3
  import { usePermissions } from "../composables/usePermissions";
4
+ import { createLogger } from "../utilities";
5
+
6
+ const logger = createLogger("dashboard-service");
4
7
 
5
8
  export interface DashboardWidgetSize {
6
9
  width: number;
@@ -102,7 +105,7 @@ export function createDashboardService(): IDashboardService {
102
105
  try {
103
106
  registerWidget(widget);
104
107
  } catch (e) {
105
- console.warn(`Failed to register preregistered widget ${widget.id}:`, e);
108
+ logger.warn(`Failed to register preregistered widget ${widget.id}:`, e);
106
109
  }
107
110
  });
108
111
 
@@ -7,3 +7,5 @@ export * from "./menu-service";
7
7
  export * from "./settings-menu-service";
8
8
  export * from "./toolbar-service";
9
9
  export * from "./widget-service";
10
+ // blade-selection-service and ai-agent-service are now part of the ai-agent plugin
11
+ // export * from "./core/plugins/ai-agent";