@acorex-platform/extension-ai-formbuilder-client 0.0.21
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.
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, Injectable, NgModule } from '@angular/core';
|
|
3
|
+
import { AXMPlatformManagementModule } from '@acorex-platform/module-platform-management-client';
|
|
4
|
+
import { AXP_OUTPUT_CONTRACT_TRANSCRIPT_SEGMENT_PROVIDER } from '@acorex-platform/framework-client/common';
|
|
5
|
+
import { AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER } from '@acorex-platform/framework-client/core';
|
|
6
|
+
import { provideCommandSetups } from '@acorex-platform/framework-client/runtime';
|
|
7
|
+
import { AXTranslationService } from '@acorex/core/translation';
|
|
8
|
+
import { AXMMiniChatPanelService } from '@acorex-platform/module-conversation-client';
|
|
9
|
+
import { AXPLayoutDesignerHeaderMenuHookKeys } from '@acorex-platform/framework-client/layout/designer';
|
|
10
|
+
import { defineCommand, AXP_COMMAND_DEFINITION_CATEGORY_AI_TOOLS } from '@acorex-platform/framework-shared/runtime';
|
|
11
|
+
|
|
12
|
+
//#region ---- Form designer entity chat ----
|
|
13
|
+
/** Entity type for form-template designer mini chats (`FormTemplateManagement.Template`). */
|
|
14
|
+
const AXE_AI_FORMBUILDER_DESIGNER_ENTITY_TYPE = 'FormTemplateManagement.Template';
|
|
15
|
+
/** Fallback entity id when the designer has no persisted template id yet. */
|
|
16
|
+
const AXE_AI_FORMBUILDER_DESIGNER_DRAFT_ENTITY_ID = 'draft';
|
|
17
|
+
//#endregion
|
|
18
|
+
|
|
19
|
+
//#region ---- Imports ----
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region ---- Service ----
|
|
22
|
+
/**
|
|
23
|
+
* Form-template designer AI assist entry point: opens the entity-scoped mini chat panel
|
|
24
|
+
* bound to the current template (`FormTemplateManagement.Template` + template id).
|
|
25
|
+
*
|
|
26
|
+
* Layout generation from chat responses is handled separately in the conversation layer.
|
|
27
|
+
*/
|
|
28
|
+
class AXEAiFormbuilderDesignerAiAssistService {
|
|
29
|
+
constructor() {
|
|
30
|
+
//#region ---- Services & Dependencies ----
|
|
31
|
+
this.miniChatPanel = inject(AXMMiniChatPanelService);
|
|
32
|
+
this.translationService = inject(AXTranslationService);
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region ---- Public API ----
|
|
36
|
+
/**
|
|
37
|
+
* Opens (or toggles) the mini chat panel for the designer's current template entity.
|
|
38
|
+
*/
|
|
39
|
+
async runFromDesigner(designer) {
|
|
40
|
+
const svc = designer;
|
|
41
|
+
const entityId = svc.templateId()?.trim() || AXE_AI_FORMBUILDER_DESIGNER_DRAFT_ENTITY_ID;
|
|
42
|
+
const title = await this.translationService.translateAsync('@form-template-management:designerAi.dialog-title');
|
|
43
|
+
this.miniChatPanel.toggle({
|
|
44
|
+
entityId,
|
|
45
|
+
entityType: AXE_AI_FORMBUILDER_DESIGNER_ENTITY_TYPE,
|
|
46
|
+
title,
|
|
47
|
+
showInfoBar: false,
|
|
48
|
+
showComposer: true,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEAiFormbuilderDesignerAiAssistService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
52
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEAiFormbuilderDesignerAiAssistService }); }
|
|
53
|
+
}
|
|
54
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEAiFormbuilderDesignerAiAssistService, decorators: [{
|
|
55
|
+
type: Injectable
|
|
56
|
+
}] });
|
|
57
|
+
|
|
58
|
+
//#region ---- Formbuilder designer header root menu ----
|
|
59
|
+
/** Registers the layout designer header root-menu entry for AI assist (wand icon). */
|
|
60
|
+
const AXEAiFormbuilderDesignerRootMenuHookProvider = {
|
|
61
|
+
key: AXPLayoutDesignerHeaderMenuHookKeys.root,
|
|
62
|
+
priority: 40,
|
|
63
|
+
execute: (payload) => {
|
|
64
|
+
const assist = inject(AXEAiFormbuilderDesignerAiAssistService);
|
|
65
|
+
payload.items.push({
|
|
66
|
+
id: 'extensions-ai-formbuilder-layout-assist',
|
|
67
|
+
priority: 20,
|
|
68
|
+
labelKey: 'AI Assist',
|
|
69
|
+
iconClass: 'fa-solid fa-wand-magic-sparkles',
|
|
70
|
+
run: () => {
|
|
71
|
+
void assist.runFromDesigner(payload.designer);
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
return payload;
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
//#endregion
|
|
78
|
+
|
|
79
|
+
//#region ---- Imports ----
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region ---- Formbuilder node segment preset ----
|
|
82
|
+
const FORM_BUILDER_NODE_SEGMENT = {
|
|
83
|
+
name: 'node',
|
|
84
|
+
title: '@ai-management:agents.entities.agent.fields.output-contract.transcript-segment.options.node',
|
|
85
|
+
applicableKinds: ['object'],
|
|
86
|
+
contract: {
|
|
87
|
+
kind: 'object',
|
|
88
|
+
transcriptSegment: 'node',
|
|
89
|
+
validationCommandName: 'AiFormbuilder:ValidateLayoutJsonForAi',
|
|
90
|
+
structuredRetries: 3,
|
|
91
|
+
schemaSummary: 'Chat UI: block-layout or table-layout root with mode edit/view. Form Template designer: document-layout → page-layout → fieldset/flex/grid. No raw CSS keys.',
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Enriches the built-in `node` transcript segment with formbuilder validation and schema hints.
|
|
96
|
+
*/
|
|
97
|
+
class AXPAiFormbuilderOutputContractTranscriptSegmentProvider {
|
|
98
|
+
provide() {
|
|
99
|
+
return [FORM_BUILDER_NODE_SEGMENT];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
|
|
104
|
+
//#region ---- Imports ----
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region ---- Module ----
|
|
107
|
+
class AXEAIFormBuilderExtensionModule {
|
|
108
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEAIFormBuilderExtensionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
109
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: AXEAIFormBuilderExtensionModule, imports: [AXMPlatformManagementModule] }); }
|
|
110
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEAIFormBuilderExtensionModule, providers: [
|
|
111
|
+
AXEAiFormbuilderDesignerAiAssistService,
|
|
112
|
+
provideCommandSetups([
|
|
113
|
+
{
|
|
114
|
+
key: 'AiFormbuilder:ValidateLayoutJsonForAi',
|
|
115
|
+
command: () => Promise.resolve().then(function () { return validateLayoutJsonForAi_command; }).then((c) => c.AXEAiFormbuilderValidateLayoutJsonForAiCommand),
|
|
116
|
+
},
|
|
117
|
+
]),
|
|
118
|
+
{
|
|
119
|
+
provide: AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER,
|
|
120
|
+
multi: true,
|
|
121
|
+
useValue: AXEAiFormbuilderDesignerRootMenuHookProvider,
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
provide: AXP_OUTPUT_CONTRACT_TRANSCRIPT_SEGMENT_PROVIDER,
|
|
125
|
+
useClass: AXPAiFormbuilderOutputContractTranscriptSegmentProvider,
|
|
126
|
+
multi: true,
|
|
127
|
+
},
|
|
128
|
+
], imports: [AXMPlatformManagementModule] }); }
|
|
129
|
+
}
|
|
130
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEAIFormBuilderExtensionModule, decorators: [{
|
|
131
|
+
type: NgModule,
|
|
132
|
+
args: [{
|
|
133
|
+
imports: [AXMPlatformManagementModule],
|
|
134
|
+
providers: [
|
|
135
|
+
AXEAiFormbuilderDesignerAiAssistService,
|
|
136
|
+
provideCommandSetups([
|
|
137
|
+
{
|
|
138
|
+
key: 'AiFormbuilder:ValidateLayoutJsonForAi',
|
|
139
|
+
command: () => Promise.resolve().then(function () { return validateLayoutJsonForAi_command; }).then((c) => c.AXEAiFormbuilderValidateLayoutJsonForAiCommand),
|
|
140
|
+
},
|
|
141
|
+
]),
|
|
142
|
+
{
|
|
143
|
+
provide: AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER,
|
|
144
|
+
multi: true,
|
|
145
|
+
useValue: AXEAiFormbuilderDesignerRootMenuHookProvider,
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
provide: AXP_OUTPUT_CONTRACT_TRANSCRIPT_SEGMENT_PROVIDER,
|
|
149
|
+
useClass: AXPAiFormbuilderOutputContractTranscriptSegmentProvider,
|
|
150
|
+
multi: true,
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
}]
|
|
154
|
+
}] });
|
|
155
|
+
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region ---- Validation helpers ----
|
|
158
|
+
const MAX_ERRORS = 48;
|
|
159
|
+
/** Keys that must not appear on widget nodes — styling belongs in widget options, not DOM/CSS. */
|
|
160
|
+
const FORBIDDEN_LAYOUT_KEYS = new Set([
|
|
161
|
+
'style',
|
|
162
|
+
'styles',
|
|
163
|
+
'css',
|
|
164
|
+
'class',
|
|
165
|
+
'className',
|
|
166
|
+
'classList',
|
|
167
|
+
'innerHTML',
|
|
168
|
+
'dataset',
|
|
169
|
+
]);
|
|
170
|
+
function stripJsonFences(raw) {
|
|
171
|
+
const t = raw.trim();
|
|
172
|
+
const fence = /^```(?:json)?\s*\r?\n?([\s\S]*?)\r?\n?```\s*$/i.exec(t);
|
|
173
|
+
return fence ? fence[1].trim() : t;
|
|
174
|
+
}
|
|
175
|
+
function validateWidgetNodeShape(value, jsonPath, errors) {
|
|
176
|
+
if (errors.length >= MAX_ERRORS) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
180
|
+
errors.push(`${jsonPath}: expected an object (AXPWidgetNode)`);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const o = value;
|
|
184
|
+
const t = o['type'];
|
|
185
|
+
if (typeof t !== 'string' || !t.trim()) {
|
|
186
|
+
errors.push(`${jsonPath}: property "type" must be a non-empty string (widget registry name)`);
|
|
187
|
+
}
|
|
188
|
+
if (t === 'node' && 'content' in o) {
|
|
189
|
+
errors.push(`${jsonPath}: do not use the chat envelope { "type":"node", "content":... }; output the inner widget root only.`);
|
|
190
|
+
}
|
|
191
|
+
for (const key of FORBIDDEN_LAYOUT_KEYS) {
|
|
192
|
+
if (key in o) {
|
|
193
|
+
errors.push(`${jsonPath}: "${key}" is not allowed on AXPWidgetNode — map styling to widget options (e.g. flex-layout, grid-layout, button-action look/color, fieldset-layout), not raw CSS.`);
|
|
194
|
+
if (errors.length >= MAX_ERRORS) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if ('options' in o && o['options'] != null && typeof o['options'] !== 'object') {
|
|
200
|
+
errors.push(`${jsonPath}.options must be a plain object when present`);
|
|
201
|
+
}
|
|
202
|
+
if ('children' in o && o['children'] != null) {
|
|
203
|
+
if (!Array.isArray(o['children'])) {
|
|
204
|
+
errors.push(`${jsonPath}.children must be an array`);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
for (let i = 0; i < o['children'].length; i++) {
|
|
208
|
+
validateWidgetNodeShape(o['children'][i], `${jsonPath}.children[${i}]`, errors);
|
|
209
|
+
if (errors.length >= MAX_ERRORS) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region ---- Command input resolution ----
|
|
217
|
+
/**
|
|
218
|
+
* AI chat normalizes tool args by parsing JSON-like strings into objects. For this command the
|
|
219
|
+
* `json` field may therefore arrive as a string **or** as an already-parsed widget root object.
|
|
220
|
+
*/
|
|
221
|
+
function resolveValidateLayoutJsonString(json) {
|
|
222
|
+
if (typeof json === 'string') {
|
|
223
|
+
return json.trim();
|
|
224
|
+
}
|
|
225
|
+
if (json !== null && json !== undefined && typeof json === 'object') {
|
|
226
|
+
try {
|
|
227
|
+
return JSON.stringify(json);
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
return '';
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return '';
|
|
234
|
+
}
|
|
235
|
+
class AXEAiFormbuilderValidateLayoutJsonForAiCommand {
|
|
236
|
+
async execute(input) {
|
|
237
|
+
const raw = resolveValidateLayoutJsonString(input?.json);
|
|
238
|
+
if (!raw) {
|
|
239
|
+
return {
|
|
240
|
+
success: true,
|
|
241
|
+
kind: 'object',
|
|
242
|
+
data: { valid: false, errors: ['Missing json string.'] },
|
|
243
|
+
message: { text: 'Missing json string.' },
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const stripped = stripJsonFences(raw);
|
|
247
|
+
let parsed;
|
|
248
|
+
try {
|
|
249
|
+
parsed = JSON.parse(stripped);
|
|
250
|
+
}
|
|
251
|
+
catch (e) {
|
|
252
|
+
const msg = e instanceof Error ? e.message : 'Invalid JSON';
|
|
253
|
+
return { success: true, kind: 'object',
|
|
254
|
+
data: {
|
|
255
|
+
valid: false,
|
|
256
|
+
errors: [`JSON parse error: ${msg}`],
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
const errors = [];
|
|
261
|
+
validateWidgetNodeShape(parsed, '$', errors);
|
|
262
|
+
const valid = errors.length === 0;
|
|
263
|
+
if (!valid) {
|
|
264
|
+
return { success: true, kind: 'object',
|
|
265
|
+
data: { valid: false, errors },
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
const normalizedJson = JSON.stringify(parsed);
|
|
269
|
+
return { success: true, kind: 'object',
|
|
270
|
+
data: {
|
|
271
|
+
valid: true,
|
|
272
|
+
errors: [],
|
|
273
|
+
normalizedJson,
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEAiFormbuilderValidateLayoutJsonForAiCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
278
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEAiFormbuilderValidateLayoutJsonForAiCommand, providedIn: 'root' }); }
|
|
279
|
+
}
|
|
280
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXEAiFormbuilderValidateLayoutJsonForAiCommand, decorators: [{
|
|
281
|
+
type: Injectable,
|
|
282
|
+
args: [{ providedIn: 'root' }]
|
|
283
|
+
}] });
|
|
284
|
+
|
|
285
|
+
var validateLayoutJsonForAi_command = /*#__PURE__*/Object.freeze({
|
|
286
|
+
__proto__: null,
|
|
287
|
+
AXEAiFormbuilderValidateLayoutJsonForAiCommand: AXEAiFormbuilderValidateLayoutJsonForAiCommand
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Build-time only. Do not import from Angular modules.
|
|
292
|
+
* Source: validate-layout-json-for-ai.command.ts — AXEAiFormbuilderValidateLayoutJsonForAiCommand.execute
|
|
293
|
+
*/
|
|
294
|
+
const axeAiFormbuilderValidateLayoutJsonForAiCommandDefinition = defineCommand({
|
|
295
|
+
key: 'AiFormbuilder:ValidateLayoutJsonForAi',
|
|
296
|
+
title: 'Validate widget layout JSON for AI (form template designer)',
|
|
297
|
+
description: 'Parses a JSON string and checks it is a single root AXPWidgetNode (object with string type, optional children/options). Rejects raw CSS/DOM-style keys. Returns validation errors and compact normalized JSON when valid — call before the layout specialist emits its final JSON-only reply.',
|
|
298
|
+
executionMode: 'frontend',
|
|
299
|
+
inputs: [
|
|
300
|
+
{
|
|
301
|
+
name: 'json',
|
|
302
|
+
title: 'Layout JSON string',
|
|
303
|
+
description: 'Stringified widget tree: one root object with "type" (registry name). Optional markdown/json fences are stripped.',
|
|
304
|
+
interface: { name: 'large-text-editor' },
|
|
305
|
+
validations: [{ rule: 'required' }],
|
|
306
|
+
},
|
|
307
|
+
],
|
|
308
|
+
outcomes: {
|
|
309
|
+
mode: 'static',
|
|
310
|
+
values: ['success', 'failure'],
|
|
311
|
+
},
|
|
312
|
+
ai: {
|
|
313
|
+
shortDescription: 'Validate specialist JSON is parseable and shaped like AXPWidgetNode before returning it to chat.',
|
|
314
|
+
tags: ['ai-formbuilder', 'layout', 'ai', 'validation'],
|
|
315
|
+
},
|
|
316
|
+
capabilities: ['ai'],
|
|
317
|
+
categories: [AXP_COMMAND_DEFINITION_CATEGORY_AI_TOOLS],
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Generated bundle index. Do not edit.
|
|
322
|
+
*/
|
|
323
|
+
|
|
324
|
+
export { AXEAIFormBuilderExtensionModule, AXEAiFormbuilderDesignerAiAssistService, AXEAiFormbuilderDesignerRootMenuHookProvider, AXEAiFormbuilderValidateLayoutJsonForAiCommand, AXE_AI_FORMBUILDER_DESIGNER_DRAFT_ENTITY_ID, AXE_AI_FORMBUILDER_DESIGNER_ENTITY_TYPE, axeAiFormbuilderValidateLayoutJsonForAiCommandDefinition };
|
|
325
|
+
//# sourceMappingURL=acorex-platform-extension-ai-formbuilder-client.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acorex-platform-extension-ai-formbuilder-client.mjs","sources":["../../../../libs/extensions/ai/formbuilder/client/src/lib/ai-formbuilder-designer-entity-chat.constants.ts","../../../../libs/extensions/ai/formbuilder/client/src/lib/ai-formbuilder-designer-ai-assist.service.ts","../../../../libs/extensions/ai/formbuilder/client/src/lib/ai-formbuilder-designer-root-menu.hook.ts","../../../../libs/extensions/ai/formbuilder/client/src/lib/output-contract-transcript-segment.formbuilder.provider.ts","../../../../libs/extensions/ai/formbuilder/client/src/lib/ai-formbuilder-extention.module.ts","../../../../libs/extensions/ai/formbuilder/client/src/lib/commands/validate-layout-json-for-ai.command.ts","../../../../libs/extensions/ai/formbuilder/client/src/lib/commands/validate-layout-json-for-ai.command.definition.ts","../../../../libs/extensions/ai/formbuilder/client/src/acorex-platform-extension-ai-formbuilder-client.ts"],"sourcesContent":["//#region ---- Form designer entity chat ----\n\n/** Entity type for form-template designer mini chats (`FormTemplateManagement.Template`). */\nexport const AXE_AI_FORMBUILDER_DESIGNER_ENTITY_TYPE = 'FormTemplateManagement.Template';\n\n/** Fallback entity id when the designer has no persisted template id yet. */\nexport const AXE_AI_FORMBUILDER_DESIGNER_DRAFT_ENTITY_ID = 'draft';\n\n//#endregion\n","//#region ---- Imports ----\n\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { AXMMiniChatPanelService } from '@acorex-platform/module-conversation-client';\nimport type { AXPDesignerService } from '@acorex-platform/framework-client/layout/designer';\nimport { inject, Injectable } from '@angular/core';\nimport {\n AXE_AI_FORMBUILDER_DESIGNER_DRAFT_ENTITY_ID,\n AXE_AI_FORMBUILDER_DESIGNER_ENTITY_TYPE,\n} from './ai-formbuilder-designer-entity-chat.constants';\n\n//#endregion\n\n//#region ---- Service ----\n\n/**\n * Form-template designer AI assist entry point: opens the entity-scoped mini chat panel\n * bound to the current template (`FormTemplateManagement.Template` + template id).\n *\n * Layout generation from chat responses is handled separately in the conversation layer.\n */\n@Injectable()\nexport class AXEAiFormbuilderDesignerAiAssistService {\n //#region ---- Services & Dependencies ----\n\n private readonly miniChatPanel = inject(AXMMiniChatPanelService);\n private readonly translationService = inject(AXTranslationService);\n\n //#endregion\n\n //#region ---- Public API ----\n\n /**\n * Opens (or toggles) the mini chat panel for the designer's current template entity.\n */\n async runFromDesigner(designer: unknown): Promise<void> {\n const svc = designer as AXPDesignerService;\n const entityId = svc.templateId()?.trim() || AXE_AI_FORMBUILDER_DESIGNER_DRAFT_ENTITY_ID;\n const title = await this.translationService.translateAsync('@form-template-management:designerAi.dialog-title');\n\n this.miniChatPanel.toggle({\n entityId,\n entityType: AXE_AI_FORMBUILDER_DESIGNER_ENTITY_TYPE,\n title,\n showInfoBar: false,\n showComposer: true,\n });\n }\n\n //#endregion\n\n //#region ---- Utility Methods ----\n\n //#endregion\n}\n\n//#endregion\n","import { AXPDistributedEventListenerProvider } from '@acorex-platform/framework-client/core';\nimport {\n AXPLayoutDesignerHeaderMenuHookKeys,\n type AXPLayoutDesignerHeaderMenuRootPayload,\n} from '@acorex-platform/framework-client/layout/designer';\nimport { inject } from '@angular/core';\nimport { AXEAiFormbuilderDesignerAiAssistService } from './ai-formbuilder-designer-ai-assist.service';\n\n//#region ---- Formbuilder designer header root menu ----\n\n/** Registers the layout designer header root-menu entry for AI assist (wand icon). */\nexport const AXEAiFormbuilderDesignerRootMenuHookProvider: AXPDistributedEventListenerProvider<\n AXPLayoutDesignerHeaderMenuRootPayload,\n AXPLayoutDesignerHeaderMenuRootPayload\n> = {\n key: AXPLayoutDesignerHeaderMenuHookKeys.root,\n priority: 40,\n execute: (payload: AXPLayoutDesignerHeaderMenuRootPayload) => {\n const assist = inject(AXEAiFormbuilderDesignerAiAssistService);\n\n payload.items.push({\n id: 'extensions-ai-formbuilder-layout-assist',\n priority: 20,\n labelKey: 'AI Assist',\n iconClass: 'fa-solid fa-wand-magic-sparkles',\n run: () => {\n void assist.runFromDesigner(payload.designer);\n },\n });\n return payload;\n },\n};\n\n//#endregion\n","//#region ---- Imports ----\n\nimport type {\n AXPOutputContractTranscriptSegmentDefinition,\n AXPOutputContractTranscriptSegmentProvider,\n} from '@acorex-platform/framework-client/common';\n\n//#endregion\n\n//#region ---- Formbuilder node segment preset ----\n\nconst FORM_BUILDER_NODE_SEGMENT: AXPOutputContractTranscriptSegmentDefinition = {\n name: 'node',\n title: '@ai-management:agents.entities.agent.fields.output-contract.transcript-segment.options.node',\n applicableKinds: ['object'],\n contract: {\n kind: 'object',\n transcriptSegment: 'node',\n validationCommandName: 'AiFormbuilder:ValidateLayoutJsonForAi',\n structuredRetries: 3,\n schemaSummary:\n 'Chat UI: block-layout or table-layout root with mode edit/view. Form Template designer: document-layout → page-layout → fieldset/flex/grid. No raw CSS keys.',\n },\n};\n\n/**\n * Enriches the built-in `node` transcript segment with formbuilder validation and schema hints.\n */\nexport class AXPAiFormbuilderOutputContractTranscriptSegmentProvider\n implements AXPOutputContractTranscriptSegmentProvider\n{\n provide(): AXPOutputContractTranscriptSegmentDefinition[] {\n return [FORM_BUILDER_NODE_SEGMENT];\n }\n}\n\n//#endregion\n","//#region ---- Imports ----\n\nimport { NgModule } from '@angular/core';\nimport { AXMPlatformManagementModule } from '@acorex-platform/module-platform-management-client';\nimport { AXP_OUTPUT_CONTRACT_TRANSCRIPT_SEGMENT_PROVIDER } from '@acorex-platform/framework-client/common';\nimport { AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER } from '@acorex-platform/framework-client/core';\nimport { provideCommandSetups } from '@acorex-platform/framework-client/runtime';\nimport { AXEAiFormbuilderDesignerAiAssistService } from './ai-formbuilder-designer-ai-assist.service';\nimport { AXEAiFormbuilderDesignerRootMenuHookProvider } from './ai-formbuilder-designer-root-menu.hook';\nimport { AXPAiFormbuilderOutputContractTranscriptSegmentProvider } from './output-contract-transcript-segment.formbuilder.provider';\n\n//#endregion\n\n//#region ---- Module ----\n\n@NgModule({\n imports: [AXMPlatformManagementModule],\n providers: [\n AXEAiFormbuilderDesignerAiAssistService,\n provideCommandSetups([\n {\n key: 'AiFormbuilder:ValidateLayoutJsonForAi',\n command: () =>\n import('./commands/validate-layout-json-for-ai.command').then(\n (c) => c.AXEAiFormbuilderValidateLayoutJsonForAiCommand,\n ),\n },\n ]),\n {\n provide: AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER,\n multi: true,\n useValue: AXEAiFormbuilderDesignerRootMenuHookProvider,\n },\n {\n provide: AXP_OUTPUT_CONTRACT_TRANSCRIPT_SEGMENT_PROVIDER,\n useClass: AXPAiFormbuilderOutputContractTranscriptSegmentProvider,\n multi: true,\n },\n ],\n})\nexport class AXEAIFormBuilderExtensionModule { }\n\n//#endregion\n","import { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport { AXPRuntimeCommandResult, type AXPWidgetNode } from '@acorex-platform/framework-shared/core';\n\nimport { Injectable } from '@angular/core';\n\n//#region ---- Types ----\n\n/** Result payload for {@link AXEAiFormbuilderValidateLayoutJsonForAiCommand}. */\nexport interface AXEAiFormbuilderValidateLayoutJsonForAiCommandData {\n /** True when the payload is valid JSON and matches the minimal AXPWidgetNode shape. */\n valid: boolean;\n /** Human-readable issues; empty when valid. */\n errors: string[];\n /**\n * Compact canonical JSON for the validated root (only when valid).\n * The specialist may paste this verbatim as its final reply.\n */\n normalizedJson?: string;\n}\n\n//#endregion\n\n//#region ---- Validation helpers ----\n\nconst MAX_ERRORS = 48;\n\n/** Keys that must not appear on widget nodes — styling belongs in widget options, not DOM/CSS. */\nconst FORBIDDEN_LAYOUT_KEYS = new Set([\n 'style',\n 'styles',\n 'css',\n 'class',\n 'className',\n 'classList',\n 'innerHTML',\n 'dataset',\n]);\n\nfunction stripJsonFences(raw: string): string {\n const t = raw.trim();\n const fence = /^```(?:json)?\\s*\\r?\\n?([\\s\\S]*?)\\r?\\n?```\\s*$/i.exec(t);\n return fence ? fence[1].trim() : t;\n}\n\nfunction validateWidgetNodeShape(value: unknown, jsonPath: string, errors: string[]): void {\n if (errors.length >= MAX_ERRORS) {\n return;\n }\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n errors.push(`${jsonPath}: expected an object (AXPWidgetNode)`);\n return;\n }\n const o = value as Record<string, unknown>;\n const t = o['type'];\n if (typeof t !== 'string' || !t.trim()) {\n errors.push(`${jsonPath}: property \"type\" must be a non-empty string (widget registry name)`);\n }\n if (t === 'node' && 'content' in o) {\n errors.push(\n `${jsonPath}: do not use the chat envelope { \"type\":\"node\", \"content\":... }; output the inner widget root only.`,\n );\n }\n for (const key of FORBIDDEN_LAYOUT_KEYS) {\n if (key in o) {\n errors.push(\n `${jsonPath}: \"${key}\" is not allowed on AXPWidgetNode — map styling to widget options (e.g. flex-layout, grid-layout, button-action look/color, fieldset-layout), not raw CSS.`,\n );\n if (errors.length >= MAX_ERRORS) {\n return;\n }\n }\n }\n if ('options' in o && o['options'] != null && typeof o['options'] !== 'object') {\n errors.push(`${jsonPath}.options must be a plain object when present`);\n }\n if ('children' in o && o['children'] != null) {\n if (!Array.isArray(o['children'])) {\n errors.push(`${jsonPath}.children must be an array`);\n return;\n }\n for (let i = 0; i < o['children'].length; i++) {\n validateWidgetNodeShape(o['children'][i], `${jsonPath}.children[${i}]`, errors);\n if (errors.length >= MAX_ERRORS) {\n return;\n }\n }\n }\n}\n\n//#endregion\n\n//#region ---- Command input resolution ----\n\n/**\n * AI chat normalizes tool args by parsing JSON-like strings into objects. For this command the\n * `json` field may therefore arrive as a string **or** as an already-parsed widget root object.\n */\nfunction resolveValidateLayoutJsonString(json: unknown): string {\n if (typeof json === 'string') {\n return json.trim();\n }\n if (json !== null && json !== undefined && typeof json === 'object') {\n try {\n return JSON.stringify(json);\n } catch {\n return '';\n }\n }\n return '';\n}\n\n//#endregion\n\n//#region ---- Command ----\n\nexport interface AXEAiFormbuilderValidateLayoutJsonForAiCommandInput {\n /**\n * Stringified root `AXPWidgetNode`, or a plain object after AI tool-arg normalization\n * (nested JSON strings are auto-parsed before `execute`).\n */\n json: string | unknown;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class AXEAiFormbuilderValidateLayoutJsonForAiCommand\n implements\n AXPCommand<AXEAiFormbuilderValidateLayoutJsonForAiCommandInput, AXEAiFormbuilderValidateLayoutJsonForAiCommandData>\n{\n async execute(input: AXEAiFormbuilderValidateLayoutJsonForAiCommandInput): AXPCommandExecuteResultPromise<AXEAiFormbuilderValidateLayoutJsonForAiCommandData> {\n const raw = resolveValidateLayoutJsonString(input?.json);\n if (!raw) {\n return {\n success: true,\n kind: 'object',\n data: { valid: false, errors: ['Missing json string.'] },\n message: { text: 'Missing json string.' },\n };\n }\n const stripped = stripJsonFences(raw);\n let parsed: unknown;\n try {\n parsed = JSON.parse(stripped) as unknown;\n } catch (e) {\n const msg = e instanceof Error ? e.message : 'Invalid JSON';\n return { success: true, kind: 'object',\n data: {\n valid: false,\n errors: [`JSON parse error: ${msg}`],\n },\n };\n }\n const errors: string[] = [];\n validateWidgetNodeShape(parsed, '$', errors);\n const valid = errors.length === 0;\n if (!valid) {\n return { success: true, kind: 'object',\n data: { valid: false, errors },\n };\n }\n const normalizedJson = JSON.stringify(parsed as AXPWidgetNode);\n return { success: true, kind: 'object',\n data: {\n valid: true,\n errors: [],\n normalizedJson,\n },\n };\n }\n}\n\n//#endregion\n","/**\n * Build-time only. Do not import from Angular modules.\n * Source: validate-layout-json-for-ai.command.ts — AXEAiFormbuilderValidateLayoutJsonForAiCommand.execute\n */\n\nimport { AXP_COMMAND_DEFINITION_CATEGORY_AI_TOOLS, defineCommand } from '@acorex-platform/framework-shared/runtime';\nexport const axeAiFormbuilderValidateLayoutJsonForAiCommandDefinition = defineCommand({\n key: 'AiFormbuilder:ValidateLayoutJsonForAi',\n title: 'Validate widget layout JSON for AI (form template designer)',\n description:\n 'Parses a JSON string and checks it is a single root AXPWidgetNode (object with string type, optional children/options). Rejects raw CSS/DOM-style keys. Returns validation errors and compact normalized JSON when valid — call before the layout specialist emits its final JSON-only reply.',\n executionMode: 'frontend',\n inputs: [\n {\n name: 'json',\n title: 'Layout JSON string',\n description:\n 'Stringified widget tree: one root object with \"type\" (registry name). Optional markdown/json fences are stripped.',\n interface: { name: 'large-text-editor' },\n validations: [{ rule: 'required' }],\n },\n ],\n outcomes: {\n mode: 'static',\n values: ['success', 'failure'],\n },\n ai: {\n shortDescription:\n 'Validate specialist JSON is parseable and shaped like AXPWidgetNode before returning it to chat.',\n tags: ['ai-formbuilder', 'layout', 'ai', 'validation'],\n },\n capabilities: ['ai'],\n categories: [AXP_COMMAND_DEFINITION_CATEGORY_AI_TOOLS],\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@acorex-platform/extension-ai-formbuilder-client",
|
|
3
|
+
"version": "0.0.21",
|
|
4
|
+
"sideEffects": false,
|
|
5
|
+
"peerDependencies": {
|
|
6
|
+
"@angular/common": "^21.0.0",
|
|
7
|
+
"@angular/core": "^21.0.0"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"tslib": "^2.3.0"
|
|
11
|
+
},
|
|
12
|
+
"module": "fesm2022/acorex-platform-extension-ai-formbuilder-client.mjs",
|
|
13
|
+
"typings": "types/acorex-platform-extension-ai-formbuilder-client.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
"./package.json": {
|
|
16
|
+
"default": "./package.json"
|
|
17
|
+
},
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./types/acorex-platform-extension-ai-formbuilder-client.d.ts",
|
|
20
|
+
"default": "./fesm2022/acorex-platform-extension-ai-formbuilder-client.mjs"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"type": "module"
|
|
24
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import * as i1 from '@acorex-platform/module-platform-management-client';
|
|
3
|
+
import { AXPDistributedEventListenerProvider } from '@acorex-platform/framework-client/core';
|
|
4
|
+
import { AXPLayoutDesignerHeaderMenuRootPayload } from '@acorex-platform/framework-client/layout/designer';
|
|
5
|
+
import { AXPCommand, AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';
|
|
6
|
+
import * as _acorex_platform_framework_shared_core from '@acorex-platform/framework-shared/core';
|
|
7
|
+
|
|
8
|
+
/** Entity type for form-template designer mini chats (`FormTemplateManagement.Template`). */
|
|
9
|
+
declare const AXE_AI_FORMBUILDER_DESIGNER_ENTITY_TYPE = "FormTemplateManagement.Template";
|
|
10
|
+
/** Fallback entity id when the designer has no persisted template id yet. */
|
|
11
|
+
declare const AXE_AI_FORMBUILDER_DESIGNER_DRAFT_ENTITY_ID = "draft";
|
|
12
|
+
|
|
13
|
+
declare class AXEAIFormBuilderExtensionModule {
|
|
14
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AXEAIFormBuilderExtensionModule, never>;
|
|
15
|
+
static ɵmod: i0.ɵɵNgModuleDeclaration<AXEAIFormBuilderExtensionModule, never, [typeof i1.AXMPlatformManagementModule], never>;
|
|
16
|
+
static ɵinj: i0.ɵɵInjectorDeclaration<AXEAIFormBuilderExtensionModule>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Form-template designer AI assist entry point: opens the entity-scoped mini chat panel
|
|
21
|
+
* bound to the current template (`FormTemplateManagement.Template` + template id).
|
|
22
|
+
*
|
|
23
|
+
* Layout generation from chat responses is handled separately in the conversation layer.
|
|
24
|
+
*/
|
|
25
|
+
declare class AXEAiFormbuilderDesignerAiAssistService {
|
|
26
|
+
private readonly miniChatPanel;
|
|
27
|
+
private readonly translationService;
|
|
28
|
+
/**
|
|
29
|
+
* Opens (or toggles) the mini chat panel for the designer's current template entity.
|
|
30
|
+
*/
|
|
31
|
+
runFromDesigner(designer: unknown): Promise<void>;
|
|
32
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AXEAiFormbuilderDesignerAiAssistService, never>;
|
|
33
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<AXEAiFormbuilderDesignerAiAssistService>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Registers the layout designer header root-menu entry for AI assist (wand icon). */
|
|
37
|
+
declare const AXEAiFormbuilderDesignerRootMenuHookProvider: AXPDistributedEventListenerProvider<AXPLayoutDesignerHeaderMenuRootPayload, AXPLayoutDesignerHeaderMenuRootPayload>;
|
|
38
|
+
|
|
39
|
+
/** Result payload for {@link AXEAiFormbuilderValidateLayoutJsonForAiCommand}. */
|
|
40
|
+
interface AXEAiFormbuilderValidateLayoutJsonForAiCommandData {
|
|
41
|
+
/** True when the payload is valid JSON and matches the minimal AXPWidgetNode shape. */
|
|
42
|
+
valid: boolean;
|
|
43
|
+
/** Human-readable issues; empty when valid. */
|
|
44
|
+
errors: string[];
|
|
45
|
+
/**
|
|
46
|
+
* Compact canonical JSON for the validated root (only when valid).
|
|
47
|
+
* The specialist may paste this verbatim as its final reply.
|
|
48
|
+
*/
|
|
49
|
+
normalizedJson?: string;
|
|
50
|
+
}
|
|
51
|
+
interface AXEAiFormbuilderValidateLayoutJsonForAiCommandInput {
|
|
52
|
+
/**
|
|
53
|
+
* Stringified root `AXPWidgetNode`, or a plain object after AI tool-arg normalization
|
|
54
|
+
* (nested JSON strings are auto-parsed before `execute`).
|
|
55
|
+
*/
|
|
56
|
+
json: string | unknown;
|
|
57
|
+
}
|
|
58
|
+
declare class AXEAiFormbuilderValidateLayoutJsonForAiCommand implements AXPCommand<AXEAiFormbuilderValidateLayoutJsonForAiCommandInput, AXEAiFormbuilderValidateLayoutJsonForAiCommandData> {
|
|
59
|
+
execute(input: AXEAiFormbuilderValidateLayoutJsonForAiCommandInput): AXPCommandExecuteResultPromise<AXEAiFormbuilderValidateLayoutJsonForAiCommandData>;
|
|
60
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AXEAiFormbuilderValidateLayoutJsonForAiCommand, never>;
|
|
61
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<AXEAiFormbuilderValidateLayoutJsonForAiCommand>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Build-time only. Do not import from Angular modules.
|
|
66
|
+
* Source: validate-layout-json-for-ai.command.ts — AXEAiFormbuilderValidateLayoutJsonForAiCommand.execute
|
|
67
|
+
*/
|
|
68
|
+
declare const axeAiFormbuilderValidateLayoutJsonForAiCommandDefinition: {
|
|
69
|
+
key: string;
|
|
70
|
+
title: string;
|
|
71
|
+
description: string;
|
|
72
|
+
executionMode: "frontend";
|
|
73
|
+
inputs: {
|
|
74
|
+
name: string;
|
|
75
|
+
title: string;
|
|
76
|
+
description: string;
|
|
77
|
+
interface: {
|
|
78
|
+
name: string;
|
|
79
|
+
};
|
|
80
|
+
validations: {
|
|
81
|
+
rule: string;
|
|
82
|
+
}[];
|
|
83
|
+
}[];
|
|
84
|
+
outcomes: {
|
|
85
|
+
mode: "static";
|
|
86
|
+
values: string[];
|
|
87
|
+
};
|
|
88
|
+
ai: {
|
|
89
|
+
shortDescription: string;
|
|
90
|
+
tags: string[];
|
|
91
|
+
};
|
|
92
|
+
capabilities: "ai"[];
|
|
93
|
+
categories: _acorex_platform_framework_shared_core.AXPDefinitionCategory[];
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export { AXEAIFormBuilderExtensionModule, AXEAiFormbuilderDesignerAiAssistService, AXEAiFormbuilderDesignerRootMenuHookProvider, AXEAiFormbuilderValidateLayoutJsonForAiCommand, AXE_AI_FORMBUILDER_DESIGNER_DRAFT_ENTITY_ID, AXE_AI_FORMBUILDER_DESIGNER_ENTITY_TYPE, axeAiFormbuilderValidateLayoutJsonForAiCommandDefinition };
|
|
97
|
+
export type { AXEAiFormbuilderValidateLayoutJsonForAiCommandData, AXEAiFormbuilderValidateLayoutJsonForAiCommandInput };
|