adminizer 4.4.0 → 4.5.0-build.176
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/assets/add-8gey7dzI.js +1 -0
- package/assets/{add-form-Taz9dTw_.js → add-form-BfIXZ_9g.js} +1 -1
- package/assets/add-group-DukHMB0D.js +1 -0
- package/assets/{add-group-form-DMz0_Oo9.js → add-group-form-BkXmTsXF.js} +1 -1
- package/assets/add-user-BMSnrNjG.js +1 -0
- package/assets/{add-user-form-izlXhv2-.js → add-user-form-CeLtuCJN.js} +1 -1
- package/assets/{app-ByR7F4XX.css → app-CUnGKHb5.css} +1 -1
- package/assets/app-layout-BarrICdq.js +1 -0
- package/assets/{app-shell-C8Cnr5Hy.js → app-shell-CggZrBz6.js} +1 -1
- package/assets/{app-sidebar-BCtD_nHo.js → app-sidebar-CiyLPsHp.js} +1 -1
- package/assets/app-sidebar-header-pfquDpHT.js +1 -0
- package/assets/app.js +2 -2
- package/assets/breadcrumbs-BS5uXMaM.js +1 -0
- package/assets/{catalog-DYJ6dK_P.js → catalog-Bf_ljqeu.js} +1 -1
- package/assets/{dashboard-DEVNMK2g.js → dashboard-Bq5BHxQd.js} +1 -1
- package/assets/{date-picker-kW3wZQr_.js → date-picker-BjXNej9c.js} +1 -1
- package/assets/del-modal-P8KiMFNx.js +1 -0
- package/assets/{field-renderer-CVUxftOw.js → field-renderer-CUYWPzfi.js} +3 -3
- package/assets/form-BZYpPjh4.js +1 -0
- package/assets/{form-1GnTJlbE.js → form-DMLPoAW8.js} +1 -1
- package/assets/{geo-json-YeWQOYnT.js → geo-json-CM4o8sUY.js} +1 -1
- package/assets/{home-ipCg51mN.js → home-DOZTBkTR.js} +2 -2
- package/assets/list-BciRbNoe.js +1 -0
- package/assets/{list-table-Do8_doRe.js → list-table-CmYyTdS5.js} +3 -3
- package/assets/manifest.json +75 -75
- package/assets/{media-manager-IknQnWel.js → media-manager-CGPeuOR2.js} +1 -1
- package/assets/{module-Bf9rzSBs.js → module-CXzKzMta.js} +1 -1
- package/assets/{nav-footer-B85HLj-j.js → nav-footer-2ZwcY1Pj.js} +1 -1
- package/assets/{nav-main-UuH4U_0H.js → nav-main-CZa4xkP1.js} +1 -1
- package/assets/{nav-user-DuCZNsZX.js → nav-user-e1Cj0abB.js} +1 -1
- package/assets/{notification-C6X6f-xS.js → notification-DiUY6oAU.js} +1 -1
- package/assets/{pagination-render-io0M2m2O.js → pagination-render-C1OX0c6q.js} +1 -1
- package/assets/{tabs-BhkFoerH.js → tabs-7Dl6--VG.js} +1 -1
- package/assets/theme-switcher-xFldiRZz.js +1 -0
- package/assets/{toast-editor-DwRk6WqT.js → toast-editor-Bso8riqX.js} +1 -1
- package/assets/{user-info-BGQvqBmO.js → user-info-DrdQBvFb.js} +1 -1
- package/assets/{user-menu-content-BDm88xaM.js → user-menu-content-ePAt_cwK.js} +1 -1
- package/assets/{welcome-Cu8G7BE9.js → welcome-BhkcZ9JK.js} +1 -1
- package/controllers/ai/AiAssistantController.d.ts +7 -0
- package/controllers/ai/AiAssistantController.js +92 -0
- package/interfaces/adminpanelConfig.d.ts +5 -0
- package/interfaces/types.d.ts +13 -0
- package/lib/Adminizer.d.ts +2 -0
- package/lib/Adminizer.js +4 -0
- package/lib/ai-assistant/AbstractAiModelService.d.ts +17 -0
- package/lib/ai-assistant/AbstractAiModelService.js +32 -0
- package/lib/ai-assistant/AiAssistantHandler.d.ts +19 -0
- package/lib/ai-assistant/AiAssistantHandler.js +58 -0
- package/lib/ai-assistant/DummyAiModelService.d.ts +8 -0
- package/lib/ai-assistant/DummyAiModelService.js +14 -0
- package/lib/ai-assistant/OpenAiModelService.d.ts +24 -0
- package/lib/ai-assistant/OpenAiModelService.js +185 -0
- package/package.json +6 -3
- package/system/Router.js +7 -0
- package/system/bindAiAssistant.d.ts +2 -0
- package/system/bindAiAssistant.js +30 -0
- package/system/bindInertia.js +4 -0
- package/system/defaults.js +5 -0
- package/assets/add-DFzzaDhZ.js +0 -1
- package/assets/add-group-BVYkGCd9.js +0 -1
- package/assets/add-user-Dq_U0RCT.js +0 -1
- package/assets/app-layout-C7q3_eFS.js +0 -1
- package/assets/app-sidebar-header-Bcpas2Np.js +0 -1
- package/assets/breadcrumbs-DSMzNYiS.js +0 -1
- package/assets/del-modal-DyIWFflP.js +0 -1
- package/assets/form-B4ymMuwj.js +0 -1
- package/assets/list-C_KPYQc4.js +0 -1
- package/assets/theme-switcher-cgyA7_cO.js +0 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AbstractAiModelService } from './AbstractAiModelService';
|
|
2
|
+
import { AiAssistantMessage } from '../../interfaces/types';
|
|
3
|
+
import { UserAP } from '../../models/UserAP';
|
|
4
|
+
import { Adminizer } from '../Adminizer';
|
|
5
|
+
export declare class DummyAiModelService extends AbstractAiModelService {
|
|
6
|
+
constructor(adminizer: Adminizer);
|
|
7
|
+
generateReply(_prompt: string, _history: AiAssistantMessage[], _user: UserAP): Promise<string>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AbstractAiModelService } from './AbstractAiModelService.js';
|
|
2
|
+
const DUMMY_RESPONSE = 'Ai-assystant dummy in deveploment';
|
|
3
|
+
export class DummyAiModelService extends AbstractAiModelService {
|
|
4
|
+
constructor(adminizer) {
|
|
5
|
+
super(adminizer, {
|
|
6
|
+
id: 'dummy',
|
|
7
|
+
name: 'Dummy assistant',
|
|
8
|
+
description: 'Development placeholder model that returns a static response.',
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
async generateReply(_prompt, _history, _user) {
|
|
12
|
+
return DUMMY_RESPONSE;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { AbstractAiModelService } from './AbstractAiModelService';
|
|
2
|
+
import { AiAssistantMessage } from '../../interfaces/types';
|
|
3
|
+
import { UserAP } from '../../models/UserAP';
|
|
4
|
+
import { Adminizer } from '../Adminizer';
|
|
5
|
+
import { ActionType } from '../../interfaces/adminpanelConfig';
|
|
6
|
+
import { Entity } from '../../interfaces/types';
|
|
7
|
+
import { DataAccessor } from '../DataAccessor';
|
|
8
|
+
type DataAccessorFactory = (entity: Entity, user: UserAP, action: ActionType) => DataAccessor;
|
|
9
|
+
export declare class OpenAiModelService extends AbstractAiModelService {
|
|
10
|
+
private readonly createAccessor;
|
|
11
|
+
constructor(adminizer: Adminizer, accessorFactory?: DataAccessorFactory);
|
|
12
|
+
generateReply(prompt: string, _history: AiAssistantMessage[], user: UserAP): Promise<string>;
|
|
13
|
+
private handleCreate;
|
|
14
|
+
private parseInstruction;
|
|
15
|
+
private usageMessage;
|
|
16
|
+
private resolveEntity;
|
|
17
|
+
private normalizeModelConfig;
|
|
18
|
+
private userHasPermission;
|
|
19
|
+
private getPermissionToken;
|
|
20
|
+
private extractPrimaryKey;
|
|
21
|
+
private extractString;
|
|
22
|
+
private extractObject;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { AbstractAiModelService } from './AbstractAiModelService.js';
|
|
2
|
+
import { Adminizer } from '../Adminizer.js';
|
|
3
|
+
import { DataAccessor } from '../DataAccessor.js';
|
|
4
|
+
const ACTION_TOKENS = {
|
|
5
|
+
add: 'create',
|
|
6
|
+
edit: 'update',
|
|
7
|
+
list: 'read',
|
|
8
|
+
view: 'read',
|
|
9
|
+
remove: 'delete',
|
|
10
|
+
};
|
|
11
|
+
export class OpenAiModelService extends AbstractAiModelService {
|
|
12
|
+
createAccessor;
|
|
13
|
+
constructor(adminizer, accessorFactory) {
|
|
14
|
+
super(adminizer, {
|
|
15
|
+
id: 'openai',
|
|
16
|
+
name: 'OpenAI fixture agent',
|
|
17
|
+
description: 'Executes structured commands with DataAccessor using the current user permissions.',
|
|
18
|
+
});
|
|
19
|
+
this.createAccessor = accessorFactory ?? ((entity, user, action) => new DataAccessor(adminizer, user, entity, action));
|
|
20
|
+
}
|
|
21
|
+
async generateReply(prompt, _history, user) {
|
|
22
|
+
const instruction = this.parseInstruction(prompt);
|
|
23
|
+
if (!instruction) {
|
|
24
|
+
return this.usageMessage();
|
|
25
|
+
}
|
|
26
|
+
switch (instruction.action) {
|
|
27
|
+
case 'create':
|
|
28
|
+
return this.handleCreate(instruction, user);
|
|
29
|
+
default:
|
|
30
|
+
return `Unsupported action "${instruction.action}". The OpenAI agent currently supports only the "create" action.`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async handleCreate(instruction, user) {
|
|
34
|
+
const entity = this.resolveEntity(instruction.entity);
|
|
35
|
+
if (!entity || !entity.model) {
|
|
36
|
+
return `Model "${instruction.entity}" is not available in this project.`;
|
|
37
|
+
}
|
|
38
|
+
if (!this.userHasPermission(entity, user, 'add')) {
|
|
39
|
+
return `User "${user.login}" does not have permission to create ${entity.name} records.`;
|
|
40
|
+
}
|
|
41
|
+
if (!instruction.payload || typeof instruction.payload !== 'object') {
|
|
42
|
+
return 'The "create" action requires a "data" object with field values.';
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const accessor = this.createAccessor(entity, user, 'add');
|
|
46
|
+
const created = await entity.model.create(instruction.payload, accessor);
|
|
47
|
+
const preview = JSON.stringify(created, null, 2);
|
|
48
|
+
const recordId = this.extractPrimaryKey(created, entity);
|
|
49
|
+
const idMessage = recordId !== undefined ? ` (id: ${recordId})` : '';
|
|
50
|
+
return `Record created in ${entity.name}${idMessage}:\n${preview}`;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
54
|
+
Adminizer.log.error('OpenAI agent failed to create record', error);
|
|
55
|
+
return `Failed to create ${entity.name} record: ${message}`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
parseInstruction(prompt) {
|
|
59
|
+
try {
|
|
60
|
+
const parsed = JSON.parse(prompt);
|
|
61
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const rawAction = this.extractString(parsed, ['action', 'type']);
|
|
65
|
+
if (!rawAction) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const action = rawAction.toLowerCase();
|
|
69
|
+
if (!['create', 'list', 'update', 'delete'].includes(action)) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const entity = this.extractString(parsed, ['entity', 'model']);
|
|
73
|
+
if (!entity) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const payload = this.extractObject(parsed, ['data', 'payload', 'record']);
|
|
77
|
+
const criteria = this.extractObject(parsed, ['criteria', 'where', 'filter']);
|
|
78
|
+
return {
|
|
79
|
+
action: action,
|
|
80
|
+
entity,
|
|
81
|
+
payload,
|
|
82
|
+
criteria,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
usageMessage() {
|
|
90
|
+
return [
|
|
91
|
+
'Provide JSON instructions so the OpenAI agent can execute them with your permissions.',
|
|
92
|
+
'Example:',
|
|
93
|
+
'```json',
|
|
94
|
+
'{',
|
|
95
|
+
' "action": "create",',
|
|
96
|
+
' "entity": "Example",',
|
|
97
|
+
' "data": { "title": "Hello from the agent" }',
|
|
98
|
+
'}',
|
|
99
|
+
'```',
|
|
100
|
+
'The agent uses DataAccessor, so any field-level restrictions from your account are respected.',
|
|
101
|
+
].join('\n');
|
|
102
|
+
}
|
|
103
|
+
resolveEntity(modelName) {
|
|
104
|
+
const models = this.adminizer.config.models;
|
|
105
|
+
if (!models) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
const loweredName = modelName.toLowerCase();
|
|
109
|
+
const match = Object.entries(models).find(([key, config]) => {
|
|
110
|
+
if (key.toLowerCase() === loweredName) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
if (typeof config === 'object' && config && 'model' in config && typeof config.model === 'string') {
|
|
114
|
+
return config.model.toLowerCase() === loweredName;
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
});
|
|
118
|
+
if (!match) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
const [configName, configValue] = match;
|
|
122
|
+
const normalizedConfig = this.normalizeModelConfig(configName, configValue);
|
|
123
|
+
const model = this.adminizer.modelHandler.model.get(normalizedConfig.model);
|
|
124
|
+
if (!model) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
name: configName,
|
|
129
|
+
uri: `${this.adminizer.config.routePrefix}/model/${configName}`,
|
|
130
|
+
type: 'model',
|
|
131
|
+
config: normalizedConfig,
|
|
132
|
+
model,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
normalizeModelConfig(name, config) {
|
|
136
|
+
const baseConfig = {
|
|
137
|
+
model: name,
|
|
138
|
+
icon: 'description',
|
|
139
|
+
title: name,
|
|
140
|
+
list: true,
|
|
141
|
+
add: true,
|
|
142
|
+
edit: true,
|
|
143
|
+
remove: true,
|
|
144
|
+
view: true,
|
|
145
|
+
};
|
|
146
|
+
if (typeof config === 'boolean') {
|
|
147
|
+
return config ? baseConfig : { ...baseConfig, list: false, add: false, edit: false, remove: false, view: false };
|
|
148
|
+
}
|
|
149
|
+
return { ...baseConfig, ...config };
|
|
150
|
+
}
|
|
151
|
+
userHasPermission(entity, user, action) {
|
|
152
|
+
const token = this.getPermissionToken(entity, action);
|
|
153
|
+
return this.adminizer.accessRightsHelper.hasPermission(token, user);
|
|
154
|
+
}
|
|
155
|
+
getPermissionToken(entity, action) {
|
|
156
|
+
const verb = ACTION_TOKENS[action];
|
|
157
|
+
const modelName = entity.model?.modelname ?? entity.config?.model ?? entity.name;
|
|
158
|
+
return `${verb}-${modelName}-${entity.type}`.toLowerCase();
|
|
159
|
+
}
|
|
160
|
+
extractPrimaryKey(record, entity) {
|
|
161
|
+
if (!record) {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
const primaryKey = entity.model?.primaryKey ?? 'id';
|
|
165
|
+
return record[primaryKey];
|
|
166
|
+
}
|
|
167
|
+
extractString(source, keys) {
|
|
168
|
+
for (const key of keys) {
|
|
169
|
+
const value = source?.[key];
|
|
170
|
+
if (typeof value === 'string' && value.trim().length > 0) {
|
|
171
|
+
return value.trim();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
extractObject(source, keys) {
|
|
177
|
+
for (const key of keys) {
|
|
178
|
+
const value = source?.[key];
|
|
179
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
180
|
+
return value;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adminizer",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.5.0-build.176",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./index.js",
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"crypto-puzzle": "^5.0.2",
|
|
59
59
|
"date-fns": "^3.6.0",
|
|
60
60
|
"deep-object-diff": "^1.1.9",
|
|
61
|
+
"dotenv": "^17.2.2",
|
|
61
62
|
"express": "^4.21.2",
|
|
62
63
|
"express-session": "^1.18.1",
|
|
63
64
|
"image-size": "^2.0.2",
|
|
@@ -69,13 +70,14 @@
|
|
|
69
70
|
"react-cropper": "^2.3.3",
|
|
70
71
|
"react-dnd": "^16.0.1",
|
|
71
72
|
"reflect-metadata": "^0.2.2",
|
|
73
|
+
"sequelize": "^6.37.7",
|
|
72
74
|
"sharp": "^0.33.5",
|
|
73
75
|
"sprintf-js": "^1.1.3",
|
|
74
76
|
"typeorm": "^0.3.20",
|
|
75
77
|
"uuid": "^11.0.5",
|
|
76
78
|
"waterline": "^0.15.2",
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
+
"winston": "^3.17.0",
|
|
80
|
+
"zod": "^4.1.11"
|
|
79
81
|
},
|
|
80
82
|
"devDependencies": {
|
|
81
83
|
"@babel/plugin-proposal-decorators": "^7.27.1",
|
|
@@ -87,6 +89,7 @@
|
|
|
87
89
|
"@handsontable/react": "^15.2.0",
|
|
88
90
|
"@inertiajs/react": "^2.2.0",
|
|
89
91
|
"@monaco-editor/react": "^4.7.0",
|
|
92
|
+
"@openai/agents": "^0.3.2",
|
|
90
93
|
"@radix-ui/react-avatar": "^1.1.3",
|
|
91
94
|
"@radix-ui/react-checkbox": "^1.1.4",
|
|
92
95
|
"@radix-ui/react-collapsible": "^1.1.3",
|
package/system/Router.js
CHANGED
|
@@ -19,6 +19,7 @@ import { thumbController } from "../controllers/media-manager/ThumbController.js
|
|
|
19
19
|
import { Adminizer } from "../lib/Adminizer.js";
|
|
20
20
|
import timezones from "../controllers/timezones.js";
|
|
21
21
|
import { NotificationController } from "../controllers/notifications/NotificationController.js";
|
|
22
|
+
import { AiAssistantController } from "../controllers/ai/AiAssistantController.js";
|
|
22
23
|
export default class Router {
|
|
23
24
|
static onlyOnce = false;
|
|
24
25
|
/**
|
|
@@ -101,6 +102,12 @@ export default class Router {
|
|
|
101
102
|
adminizer.app.put(`${adminizer.config.routePrefix}/notifications/api/read-all`, adminizer.policyManager.bindPolicies(policies, NotificationController.markAllAsRead));
|
|
102
103
|
adminizer.app.post(`${adminizer.config.routePrefix}/notifications/api/search`, adminizer.policyManager.bindPolicies(policies, NotificationController.search));
|
|
103
104
|
}
|
|
105
|
+
if (adminizer.config.aiAssistant?.enabled) {
|
|
106
|
+
adminizer.app.get(`${adminizer.config.routePrefix}/api/ai-assistant/models`, adminizer.policyManager.bindPolicies(policies, AiAssistantController.getModels));
|
|
107
|
+
adminizer.app.get(`${adminizer.config.routePrefix}/api/ai-assistant/history/:modelId`, adminizer.policyManager.bindPolicies(policies, AiAssistantController.getHistory));
|
|
108
|
+
adminizer.app.post(`${adminizer.config.routePrefix}/api/ai-assistant/query`, adminizer.policyManager.bindPolicies(policies, AiAssistantController.sendMessage));
|
|
109
|
+
adminizer.app.delete(`${adminizer.config.routePrefix}/api/ai-assistant/history/:modelId`, adminizer.policyManager.bindPolicies(policies, AiAssistantController.resetHistory));
|
|
110
|
+
}
|
|
104
111
|
/**
|
|
105
112
|
* List of records
|
|
106
113
|
*/
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Adminizer } from '../lib/Adminizer.js';
|
|
2
|
+
import { AiAssistantHandler } from '../lib/ai-assistant/AiAssistantHandler.js';
|
|
3
|
+
import { DummyAiModelService } from '../lib/ai-assistant/DummyAiModelService.js';
|
|
4
|
+
import { OpenAiModelService } from '../lib/ai-assistant/OpenAiModelService.js';
|
|
5
|
+
const modelFactories = {
|
|
6
|
+
dummy: (adminizer) => new DummyAiModelService(adminizer),
|
|
7
|
+
openai: (adminizer) => new OpenAiModelService(adminizer),
|
|
8
|
+
};
|
|
9
|
+
export async function bindAiAssistant(adminizer) {
|
|
10
|
+
// Early return if AI assistant is disabled
|
|
11
|
+
if (!adminizer.config.aiAssistant?.enabled) {
|
|
12
|
+
Adminizer.log.info('AI assistant is disabled in configuration. Skipping initialization.');
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
adminizer.aiAssistantHandler = new AiAssistantHandler(adminizer);
|
|
16
|
+
const configModels = adminizer.config.aiAssistant?.models;
|
|
17
|
+
const requestedModels = Array.isArray(configModels) && configModels.length > 0
|
|
18
|
+
? configModels
|
|
19
|
+
: ['dummy'];
|
|
20
|
+
requestedModels.forEach((modelId) => {
|
|
21
|
+
const factory = modelFactories[modelId];
|
|
22
|
+
if (!factory) {
|
|
23
|
+
Adminizer.log.warn(`AI assistant model "${modelId}" is not registered. Skipping.`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const service = factory(adminizer);
|
|
27
|
+
adminizer.aiAssistantHandler.registerModel(service);
|
|
28
|
+
});
|
|
29
|
+
Adminizer.log.info(`AI assistant initialized with models: ${adminizer.aiAssistantHandler.getModels().map((m) => m.id).join(', ')}`);
|
|
30
|
+
}
|
package/system/bindInertia.js
CHANGED
|
@@ -134,6 +134,10 @@ export function bindInertia(adminizer) {
|
|
|
134
134
|
] : null,
|
|
135
135
|
showVersion: req.adminizer.config.showVersion ?? false,
|
|
136
136
|
notifications: req.adminizer.config.notifications.enabled ?? false,
|
|
137
|
+
aiAssistant: {
|
|
138
|
+
enabled: req.adminizer.config.aiAssistant?.enabled ?? false,
|
|
139
|
+
defaultModel: req.adminizer.config.aiAssistant?.defaultModel ?? null,
|
|
140
|
+
},
|
|
137
141
|
});
|
|
138
142
|
next();
|
|
139
143
|
});
|
package/system/defaults.js
CHANGED
package/assets/add-DFzzaDhZ.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as t,j as o}from"./app.js";import{A as m}from"./app-layout-C7q3_eFS.js";import p from"./add-form-Taz9dTw_.js";import"./jsoneditor-D95dIAP2.js";import"./vendor-wzZzN_Jv.js";import"./monaco-ICtx6xoc.js";import"./handsontable-PVakPtJV.js";import"./app-shell-C8Cnr5Hy.js";import"./app-sidebar-BCtD_nHo.js";import"./nav-main-UuH4U_0H.js";import"./material-icon-DwkE6wKL.js";import"./app-sidebar-header-Bcpas2Np.js";import"./breadcrumbs-DSMzNYiS.js";import"./nav-user-DuCZNsZX.js";import"./user-info-BGQvqBmO.js";import"./user-menu-content-BDm88xaM.js";import"./theme-switcher-cgyA7_cO.js";import"./icon-DpkedrXG.js";import"./field-renderer-CVUxftOw.js";import"./dynamic-controls-BOYmRX_z.js";import"./input-error-CmXZF6xy.js";const i=[];function k(){const r=t();return o.jsx(m,{breadcrumbs:i,children:o.jsx(p,{page:r,catalog:!1})})}export{k as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as r}from"./app.js";import{A as o}from"./app-layout-C7q3_eFS.js";import t from"./add-group-form-DMz0_Oo9.js";import"./jsoneditor-D95dIAP2.js";import"./vendor-wzZzN_Jv.js";import"./monaco-ICtx6xoc.js";import"./handsontable-PVakPtJV.js";import"./app-shell-C8Cnr5Hy.js";import"./app-sidebar-BCtD_nHo.js";import"./nav-main-UuH4U_0H.js";import"./material-icon-DwkE6wKL.js";import"./app-sidebar-header-Bcpas2Np.js";import"./breadcrumbs-DSMzNYiS.js";import"./nav-user-DuCZNsZX.js";import"./user-info-BGQvqBmO.js";import"./user-menu-content-BDm88xaM.js";import"./theme-switcher-cgyA7_cO.js";import"./icon-DpkedrXG.js";const m=[];function E(){return r.jsx(o,{breadcrumbs:m,children:r.jsx(t,{})})}export{E as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as r}from"./app.js";import{A as o}from"./app-layout-C7q3_eFS.js";import t from"./add-user-form-izlXhv2-.js";import"./jsoneditor-D95dIAP2.js";import"./vendor-wzZzN_Jv.js";import"./monaco-ICtx6xoc.js";import"./handsontable-PVakPtJV.js";import"./app-shell-C8Cnr5Hy.js";import"./app-sidebar-BCtD_nHo.js";import"./nav-main-UuH4U_0H.js";import"./material-icon-DwkE6wKL.js";import"./app-sidebar-header-Bcpas2Np.js";import"./breadcrumbs-DSMzNYiS.js";import"./nav-user-DuCZNsZX.js";import"./user-info-BGQvqBmO.js";import"./user-menu-content-BDm88xaM.js";import"./theme-switcher-cgyA7_cO.js";import"./icon-DpkedrXG.js";import"./input-error-CmXZF6xy.js";const m=[];function F(){return r.jsx(o,{breadcrumbs:m,children:r.jsx(t,{})})}export{F as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as i,j as r,V as p,ad as m}from"./app.js";import d from"./app-shell-C8Cnr5Hy.js";import{AppSidebar as n}from"./app-sidebar-BCtD_nHo.js";import{A as x,N as j}from"./app-sidebar-header-Bcpas2Np.js";import{r as o}from"./monaco-ICtx6xoc.js";const c=o.memo(({children:e,breadcrumbs:s=[],className:t})=>{const a=i();return r.jsxs(d,{variant:"sidebar",children:[r.jsx(p,{title:a.props.title}),r.jsx(n,{}),r.jsxs(m,{className:t,children:[r.jsx(x,{breadcrumbs:s}),e]})]})}),S=o.memo(({children:e,className:s,breadcrumbs:t,...a})=>r.jsx(j,{children:r.jsx(c,{breadcrumbs:t,className:s,...a,children:e})}));export{S as A};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as T,j as e,h as f,aH as _,q as H,B as E,aI as J,v as F,w as q,aJ as G,M as K,N as U,E as V,O as W,r as Y,aK as Q,W as X,L as k,aL as Z}from"./app.js";import{Breadcrumbs as ee}from"./breadcrumbs-DSMzNYiS.js";import{NavUser as te}from"./nav-user-DuCZNsZX.js";import{ThemeSwitcher as ae}from"./theme-switcher-cgyA7_cO.js";import{r as n}from"./monaco-ICtx6xoc.js";import se from"./material-icon-DwkE6wKL.js";const I=n.createContext(void 0),ue=({children:i})=>{const[u,p]=n.useState([]),[b,m]=n.useState([]),[g,l]=n.useState([]),[S,y]=n.useState(!1),[r,c]=n.useState(null),[w,M]=n.useState(""),N=T(),[d,j]=n.useState({}),v=[...b,...g],x=async()=>{try{const t=await f.get(`${window.routePrefix}/notifications/api`,{params:{unreadOnly:!0,limit:4}});p(t.data)}catch(t){console.error("Error fetching bell notifications:",t)}},h=async()=>{try{const t=await f.post(`${window.routePrefix}/notifications`);j(t.data)}catch(t){console.log(t)}},C=async()=>{await x()},$=async()=>{try{const t=await f.get(`${window.routePrefix}/notifications/api/get-classes`);t.data&&(c(t.data.activeServices),M(t.data.initTab))}catch(t){console.error("Error fetching tabs:",t)}},D=async(t,s)=>{try{if(!t){await P(s);return}const a=await f.post(`${window.routePrefix}/notifications/api/search`,{s:t,notificationClass:s});l(a.data)}catch(a){console.error("Error searching notifications:",a)}},P=async t=>{y(!0);try{const s=`${window.routePrefix}/notifications/api/${t}`,a=await f.get(s,{params:{limit:20,skip:0,unreadOnly:!1}});return m([]),l(a.data),a.data}catch(s){return console.error("Error fetching all notifications:",s),[]}finally{y(!1)}},L=async(t,s)=>{try{const a=`${window.routePrefix}/notifications/api/${t}`,o=await f.get(a,{params:{limit:20,skip:s,unreadOnly:!1}});return l(z=>[...z,...o.data]),o.data}catch(a){return console.error("Error paginating notifications:",a),[]}};n.useEffect(()=>{if(!N.props.notifications)return;h(),x();const t=new EventSource(`${window.routePrefix}/notifications/api/stream`);return t.addEventListener("connected",s=>{const a=JSON.parse(s.data);console.log("Connected event:",a),$()}),t.addEventListener("notification",s=>{const a=JSON.parse(s.data);m(o=>[a,...o]),p(o=>[a,...o].slice(0,4))}),t.onerror=()=>{console.error("SSE connection error")},()=>t.close()},[]);const O=async(t,s)=>{try{await f.put(`${window.routePrefix}/notifications/api/${t}/${s}/read`,{}),m(a=>a.map(o=>o.id===s?{...o,read:!0}:o)),l(a=>a.map(o=>o.id===s?{...o,read:!0}:o)),p([])}catch(a){console.error("Error marking as read:",a)}},R=async()=>{try{await f.put(`${window.routePrefix}/notifications/api/read-all`),m(t=>t.map(s=>({...s,read:!0}))),l(t=>t.map(s=>({...s,read:!0}))),await x()}catch(t){console.error("Error marking all as read:",t)}},B=u.filter(t=>!t.read).length;return e.jsx(I.Provider,{value:{bellNotifications:u,allNotifications:v,unreadCount:B,getTabs:$,tabs:r,initTab:w,search:D,markAsRead:O,markAllAsRead:R,getLocale:h,messages:d,fetchAllNotifications:P,paginateNotifications:L,loading:S,refreshBellNotifications:C},children:i})},A=()=>{const i=n.useContext(I);if(i===void 0)throw new Error("useNotifications must be used within a NotificationProvider");return i};function re(){const{bellNotifications:i,markAsRead:u,unreadCount:p,refreshBellNotifications:b,messages:m}=A(),[g,l]=n.useState(!1),S=async(r,c)=>{l(!0);try{await u(r,c),await b()}catch(w){console.error("Error marking as read:",w)}finally{l(!1)}},y=r=>{const c=new Date,w=new Date(r),M=c.getTime()-w.getTime(),N=Math.floor(M/1e3),d=new Intl.RelativeTimeFormat("en",{numeric:"auto"});if(N<60)return d.format(-N,"second");const j=Math.floor(N/60);if(j<60)return d.format(-j,"minute");const v=Math.floor(j/60);if(v<24)return d.format(-v,"hour");const x=Math.floor(v/24);if(x<30)return d.format(-x,"day");const h=Math.floor(x/30);if(h<12)return d.format(-h,"month");const C=Math.floor(h/12);return d.format(-C,"year")};return e.jsxs(_,{children:[e.jsx(H,{asChild:!0,className:"cursor-pointer data-[state=open]:bg-sidebar-accent",children:e.jsxs(E,{variant:"ghost",className:"relative",children:[e.jsx(J,{}),p>0&&e.jsx("div",{className:"absolute top-1.5 right-1.5 size-1.5 rounded-full bg-destructive"})]})}),e.jsxs(F,{className:"z-[1002] p-2",align:"end",onCloseAutoFocus:r=>r.preventDefault(),children:[e.jsx(q,{className:`${g?"opacity-50 pointer-events-none":""}`,children:i.length===0?e.jsx("div",{className:"p-4 text-center text-muted-foreground",children:"No notifications"}):i.map(r=>e.jsxs("div",{children:[e.jsx(G,{asChild:!0,className:"cursor-pointer",onSelect:c=>{c.preventDefault(),Y.visit(`${window.routePrefix}/notifications?type=${r.notificationClass}`)},children:e.jsxs("div",{className:"grid grid-cols-[32px_250px] grid-rows-[auto_1fr] items-start gap-x-4 gap-y-2",children:[r.icon?e.jsx(se,{name:r.icon.icon,style:{color:r.icon.iconColor},className:"!text-[32px]"}):e.jsx("div",{}),e.jsxs("div",{className:"flex flex-col",children:[e.jsx("span",{className:"font-medium",children:r.title}),e.jsx("span",{className:"truncate",children:r.message})]}),e.jsxs("div",{className:"col-start-2 flex justify-between flex-nowrap items-center",children:[e.jsx("div",{className:"flex flex-nowrap gap-2 items-center",children:e.jsx("div",{children:y(r.createdAt)})}),e.jsxs(K,{children:[e.jsx(U,{asChild:!0,children:e.jsx(E,{variant:"ghost",size:"icon",className:"size-4",onClick:c=>{c.stopPropagation(),S(r.notificationClass,r.id)},children:e.jsx(V,{className:"text-primary"})})}),e.jsx(W,{side:"left",className:"z-[1003]",children:e.jsx("p",{children:m["Make read"]})})]})]})]})}),e.jsx(Q,{})]},r.id))}),e.jsx(E,{variant:"secondary",asChild:!0,children:e.jsxs(X,{href:`${window.routePrefix}/notifications`,className:`w-full ${g?"opacity-50 pointer-events-none":""}`,children:[m["View All"],g&&e.jsx(k,{className:"h-4 w-4 animate-spin"})]})})]})]})}function oe({breadcrumbs:i=[]}){const{tabs:u}=A(),p=T();return e.jsx("header",{className:"border-sidebar-border/50 flex h-16 shrink-0 items-center gap-2 border-b px-6 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-12 md:px-4",children:e.jsxs("div",{className:"flex justify-between w-full",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Z,{className:"-ml-1"}),e.jsx(ee,{breadcrumbs:i})]}),e.jsxs("div",{className:"flex gap-4 items-center",children:[e.jsx(ae,{}),p.props.notifications&&(u===null?e.jsx("div",{className:"w-[40px] flex-none flex justify-center",children:e.jsx(k,{className:"size-4 animate-spin"})}):u.length?e.jsx(re,{}):null),e.jsx(te,{})]})]})})}const pe=Object.freeze(Object.defineProperty({__proto__:null,AppSidebarHeader:oe},Symbol.toStringTag,{value:"Module"}));export{oe as A,ue as N,pe as a,A as u};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as r,b7 as i,b8 as n,b9 as c,ba as m,bb as d,W as l,bc as h}from"./app.js";import{r as o}from"./monaco-ICtx6xoc.js";import"./jsoneditor-D95dIAP2.js";import"./vendor-wzZzN_Jv.js";import"./handsontable-PVakPtJV.js";function B({breadcrumbs:e}){return r.jsx(r.Fragment,{children:e.length>0&&r.jsx(i,{children:r.jsx(n,{children:e.map((s,t)=>{const a=t===e.length-1;return r.jsxs(o.Fragment,{children:[r.jsx(c,{children:a?r.jsx(m,{children:s.title}):r.jsx(d,{asChild:!0,children:r.jsx(l,{href:s.href,children:s.title})})}),!a&&r.jsx(h,{})]},t)})})})})}export{B as Breadcrumbs};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as s,a9 as x,as as h,B as e,_ as j,ak as m,aa as u,ab as p,ac as D,an as g,ao as r,W as C}from"./app.js";import{r as f}from"./monaco-ICtx6xoc.js";import{Icon as v}from"./icon-DpkedrXG.js";const y=f.forwardRef(({btnTitle:i,link:t,delModal:a,handleDelete:n,variant:l,btnCLass:o,isLink:c=!0},d)=>s.jsxs(x,{children:[s.jsx(h,{asChild:!0,children:s.jsxs(e,{ref:d,size:"list",variant:l??"ghost",className:j("cursor-pointer",o),children:[s.jsx(v,{iconNode:m}),i]})}),s.jsxs(u,{className:"sm:max-w-[425px] z-[1011]",children:[s.jsxs(p,{children:[s.jsx(D,{children:"Delete"}),s.jsx("div",{className:"mt-2 text-base",children:a.text})]}),s.jsxs(g,{children:[s.jsx(r,{asChild:!0,children:c?s.jsx(e,{variant:"destructive",asChild:!0,children:s.jsx(C,{href:t??"#",children:a.yes})}):s.jsx(e,{variant:"destructive",asChild:!0,onClick:n,children:s.jsx("span",{children:a.yes})})}),s.jsx(r,{asChild:!0,children:s.jsx(e,{type:"button",variant:"secondary",children:a.no})})]})]})]}));y.displayName="DeleteModal";export{y as D};
|
package/assets/form-B4ymMuwj.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as r}from"./app.js";import{A as o}from"./app-layout-C7q3_eFS.js";import t from"./form-1GnTJlbE.js";import"./jsoneditor-D95dIAP2.js";import"./vendor-wzZzN_Jv.js";import"./monaco-ICtx6xoc.js";import"./handsontable-PVakPtJV.js";import"./app-shell-C8Cnr5Hy.js";import"./app-sidebar-BCtD_nHo.js";import"./nav-main-UuH4U_0H.js";import"./material-icon-DwkE6wKL.js";import"./app-sidebar-header-Bcpas2Np.js";import"./breadcrumbs-DSMzNYiS.js";import"./nav-user-DuCZNsZX.js";import"./user-info-BGQvqBmO.js";import"./user-menu-content-BDm88xaM.js";import"./theme-switcher-cgyA7_cO.js";import"./icon-DpkedrXG.js";import"./add-form-Taz9dTw_.js";import"./field-renderer-CVUxftOw.js";import"./dynamic-controls-BOYmRX_z.js";import"./input-error-CmXZF6xy.js";const m=[];function g(){return r.jsx(o,{breadcrumbs:m,children:r.jsx(t,{})})}export{g as default};
|
package/assets/list-C_KPYQc4.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as o}from"./app.js";import{A as r}from"./app-layout-C7q3_eFS.js";import t from"./list-table-Do8_doRe.js";import"./jsoneditor-D95dIAP2.js";import"./vendor-wzZzN_Jv.js";import"./monaco-ICtx6xoc.js";import"./handsontable-PVakPtJV.js";import"./app-shell-C8Cnr5Hy.js";import"./app-sidebar-BCtD_nHo.js";import"./nav-main-UuH4U_0H.js";import"./material-icon-DwkE6wKL.js";import"./app-sidebar-header-Bcpas2Np.js";import"./breadcrumbs-DSMzNYiS.js";import"./nav-user-DuCZNsZX.js";import"./user-info-BGQvqBmO.js";import"./user-menu-content-BDm88xaM.js";import"./theme-switcher-cgyA7_cO.js";import"./icon-DpkedrXG.js";import"./del-modal-DyIWFflP.js";import"./pagination-render-io0M2m2O.js";const m=[],E=()=>o.jsx(r,{breadcrumbs:m,className:"overflow-auto h-[calc(100svh-16px)]",children:o.jsx(t,{})});export{E as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{af as i,j as n,B as c,bp as p,bq as m,br as u}from"./app.js";import{Icon as h}from"./icon-DpkedrXG.js";import"./jsoneditor-D95dIAP2.js";import"./vendor-wzZzN_Jv.js";import"./monaco-ICtx6xoc.js";import"./handsontable-PVakPtJV.js";function j(){const{appearance:t,updateAppearance:o}=i(),s={light:"dark",dark:"system",system:"light"},a={light:u,dark:m,system:p},e=()=>o(s[t]),r=a[t];return n.jsx(c,{variant:"ghost",size:"icon",onClick:e,className:"shrink-0",children:n.jsx(h,{iconNode:r})})}export{j as ThemeSwitcher,j as default};
|