flowquery 1.0.8 → 1.0.10
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/dist/flowquery.min.js +1 -1
- package/dist/parsing/functions/function_factory.d.ts +2 -0
- package/dist/parsing/functions/function_factory.d.ts.map +1 -1
- package/dist/parsing/functions/function_factory.js +2 -0
- package/dist/parsing/functions/function_factory.js.map +1 -1
- package/dist/parsing/functions/keys.d.ts +7 -0
- package/dist/parsing/functions/keys.d.ts.map +1 -0
- package/dist/parsing/functions/keys.js +42 -0
- package/dist/parsing/functions/keys.js.map +1 -0
- package/dist/parsing/functions/type.d.ts +7 -0
- package/dist/parsing/functions/type.d.ts.map +1 -0
- package/dist/parsing/functions/type.js +49 -0
- package/dist/parsing/functions/type.js.map +1 -0
- package/docs/flowquery.min.js +1 -1
- package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
- package/misc/apps/RAG/package.json +3 -1
- package/misc/apps/RAG/src/components/AdaptiveCardRenderer.css +172 -0
- package/misc/apps/RAG/src/components/AdaptiveCardRenderer.tsx +312 -0
- package/misc/apps/RAG/src/components/ChatContainer.tsx +159 -112
- package/misc/apps/RAG/src/components/ChatInput.tsx +58 -44
- package/misc/apps/RAG/src/components/ChatMessage.tsx +186 -101
- package/misc/apps/RAG/src/components/FlowQueryAgent.ts +50 -6
- package/misc/apps/RAG/src/components/FlowQueryRunner.css +9 -0
- package/misc/apps/RAG/src/components/FlowQueryRunner.tsx +44 -5
- package/misc/apps/RAG/src/components/index.ts +4 -0
- package/misc/apps/RAG/src/plugins/index.ts +6 -4
- package/misc/apps/RAG/src/plugins/loaders/CatFacts.ts +1 -2
- package/misc/apps/RAG/src/plugins/loaders/FetchJson.ts +1 -2
- package/misc/apps/RAG/src/plugins/loaders/Form.ts +578 -0
- package/misc/apps/RAG/src/plugins/loaders/Llm.ts +1 -2
- package/misc/apps/RAG/src/plugins/loaders/MockData.ts +2 -4
- package/misc/apps/RAG/src/plugins/loaders/Table.ts +271 -0
- package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +12 -0
- package/package.json +1 -1
- package/src/parsing/functions/function_factory.ts +2 -0
- package/src/parsing/functions/keys.ts +31 -0
- package/src/parsing/functions/type.ts +39 -0
- package/tests/compute/runner.test.ts +8 -0
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Form loader plugin - transforms configuration into Adaptive Card form format.
|
|
3
|
+
*
|
|
4
|
+
* Adaptive Cards are platform-agnostic UI snippets that can be rendered in
|
|
5
|
+
* Microsoft Teams, Outlook, Windows, and other applications.
|
|
6
|
+
*
|
|
7
|
+
* This loader creates customizable forms with various input types including:
|
|
8
|
+
* - Text inputs (single and multi-line)
|
|
9
|
+
* - Number inputs
|
|
10
|
+
* - Date and time pickers
|
|
11
|
+
* - Dropdown/choice sets
|
|
12
|
+
* - Toggle switches
|
|
13
|
+
* - Choice sets (radio buttons, checkboxes)
|
|
14
|
+
*
|
|
15
|
+
* Usage in FlowQuery:
|
|
16
|
+
* // Create a simple contact form:
|
|
17
|
+
* LOAD JSON FROM form('Contact Us', [
|
|
18
|
+
* { id: 'name', type: 'text', label: 'Your Name', required: true },
|
|
19
|
+
* { id: 'email', type: 'text', label: 'Email', placeholder: 'you@example.com' },
|
|
20
|
+
* { id: 'message', type: 'textarea', label: 'Message' }
|
|
21
|
+
* ]) AS form
|
|
22
|
+
* RETURN form
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { FunctionDef } from 'flowquery/extensibility';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Interface for Adaptive Card structure
|
|
29
|
+
*/
|
|
30
|
+
interface AdaptiveCard {
|
|
31
|
+
type: 'AdaptiveCard';
|
|
32
|
+
$schema: string;
|
|
33
|
+
version: string;
|
|
34
|
+
body: AdaptiveCardElement[];
|
|
35
|
+
actions?: AdaptiveCardAction[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface AdaptiveCardElement {
|
|
39
|
+
type: string;
|
|
40
|
+
[key: string]: any;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface AdaptiveCardAction {
|
|
44
|
+
type: string;
|
|
45
|
+
title: string;
|
|
46
|
+
[key: string]: any;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Input field configuration
|
|
51
|
+
*/
|
|
52
|
+
interface FormFieldConfig {
|
|
53
|
+
/** Unique identifier for the field */
|
|
54
|
+
id: string;
|
|
55
|
+
/** Input type: text, textarea, number, date, time, datetime, toggle, dropdown, radio, checkbox */
|
|
56
|
+
type: 'text' | 'textarea' | 'number' | 'date' | 'time' | 'datetime' | 'toggle' | 'dropdown' | 'radio' | 'checkbox';
|
|
57
|
+
/** Display label for the field */
|
|
58
|
+
label: string;
|
|
59
|
+
/** Placeholder text for input fields */
|
|
60
|
+
placeholder?: string;
|
|
61
|
+
/** Default value */
|
|
62
|
+
defaultValue?: any;
|
|
63
|
+
/** Whether the field is required */
|
|
64
|
+
required?: boolean;
|
|
65
|
+
/** Choices for dropdown/radio/checkbox types */
|
|
66
|
+
choices?: Array<{ title: string; value: string }> | string[];
|
|
67
|
+
/** Minimum value for number inputs */
|
|
68
|
+
min?: number;
|
|
69
|
+
/** Maximum value for number inputs */
|
|
70
|
+
max?: number;
|
|
71
|
+
/** Regex pattern for validation (displayed in error message) */
|
|
72
|
+
pattern?: string;
|
|
73
|
+
/** Error message for validation */
|
|
74
|
+
errorMessage?: string;
|
|
75
|
+
/** Toggle title (for toggle type) */
|
|
76
|
+
toggleTitle?: string;
|
|
77
|
+
/** Whether the field is read-only */
|
|
78
|
+
readOnly?: boolean;
|
|
79
|
+
/** Separator before this field */
|
|
80
|
+
separator?: boolean;
|
|
81
|
+
/** Field width: auto, stretch, or weighted value */
|
|
82
|
+
width?: 'auto' | 'stretch' | number;
|
|
83
|
+
/** Custom style for the label */
|
|
84
|
+
labelStyle?: 'default' | 'heading';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Form configuration options
|
|
89
|
+
*/
|
|
90
|
+
interface FormConfig {
|
|
91
|
+
/** Form title */
|
|
92
|
+
title?: string;
|
|
93
|
+
/** Form description/subtitle */
|
|
94
|
+
description?: string;
|
|
95
|
+
/** Submit button configuration */
|
|
96
|
+
submitButton?: {
|
|
97
|
+
title?: string;
|
|
98
|
+
style?: 'default' | 'positive' | 'destructive';
|
|
99
|
+
/** Action URL for form submission */
|
|
100
|
+
url?: string;
|
|
101
|
+
/** Action type: submit, openUrl, or custom */
|
|
102
|
+
actionType?: 'submit' | 'openUrl' | 'showCard';
|
|
103
|
+
};
|
|
104
|
+
/** Additional action buttons */
|
|
105
|
+
additionalActions?: Array<{
|
|
106
|
+
title: string;
|
|
107
|
+
type: 'submit' | 'openUrl' | 'showCard';
|
|
108
|
+
url?: string;
|
|
109
|
+
style?: 'default' | 'positive' | 'destructive';
|
|
110
|
+
data?: any;
|
|
111
|
+
}>;
|
|
112
|
+
/** Card background style */
|
|
113
|
+
style?: 'default' | 'emphasis' | 'good' | 'attention' | 'warning' | 'accent';
|
|
114
|
+
/** Whether to show a reset/clear button */
|
|
115
|
+
showResetButton?: boolean;
|
|
116
|
+
/** Card schema version */
|
|
117
|
+
version?: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Form loader - creates customizable Adaptive Card forms.
|
|
122
|
+
*/
|
|
123
|
+
@FunctionDef({
|
|
124
|
+
description: 'Creates a customizable Adaptive Card form with various input types',
|
|
125
|
+
category: 'async',
|
|
126
|
+
parameters: [
|
|
127
|
+
{
|
|
128
|
+
name: 'title',
|
|
129
|
+
description: 'Form title displayed at the top',
|
|
130
|
+
type: 'string',
|
|
131
|
+
required: true
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: 'fields',
|
|
135
|
+
description: 'Array of field configurations defining the form inputs',
|
|
136
|
+
type: 'array',
|
|
137
|
+
required: true
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: 'config',
|
|
141
|
+
description: 'Optional form configuration (submit button, additional actions, styling)',
|
|
142
|
+
type: 'object',
|
|
143
|
+
required: false
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
output: {
|
|
147
|
+
description: 'Adaptive Card JSON object with form elements',
|
|
148
|
+
type: 'object',
|
|
149
|
+
properties: {
|
|
150
|
+
type: { description: 'Always "AdaptiveCard"', type: 'string' },
|
|
151
|
+
$schema: { description: 'Adaptive Card schema URL', type: 'string' },
|
|
152
|
+
version: { description: 'Adaptive Card version', type: 'string' },
|
|
153
|
+
body: { description: 'Card body elements including form inputs', type: 'array' },
|
|
154
|
+
actions: { description: 'Card actions (submit, cancel, etc.)', type: 'array' }
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
examples: [
|
|
158
|
+
"LOAD JSON FROM form('Contact Form', [{ id: 'name', type: 'text', label: 'Name', required: true }, { id: 'email', type: 'text', label: 'Email' }]) AS form RETURN form",
|
|
159
|
+
"LOAD JSON FROM form('Survey', [{ id: 'rating', type: 'dropdown', label: 'Rating', choices: ['1', '2', '3', '4', '5'] }, { id: 'subscribe', type: 'toggle', label: 'Subscribe', toggleTitle: 'Yes, send me updates' }], { submitButton: { title: 'Submit Survey', style: 'positive' } }) AS form RETURN form"
|
|
160
|
+
]
|
|
161
|
+
})
|
|
162
|
+
export class FormLoader {
|
|
163
|
+
/**
|
|
164
|
+
* Creates an Adaptive Card form with the specified fields and configuration.
|
|
165
|
+
*
|
|
166
|
+
* @param title - Form title
|
|
167
|
+
* @param fields - Array of field configurations
|
|
168
|
+
* @param config - Optional form configuration
|
|
169
|
+
*/
|
|
170
|
+
async *fetch(
|
|
171
|
+
title: string,
|
|
172
|
+
fields: FormFieldConfig[],
|
|
173
|
+
config?: FormConfig
|
|
174
|
+
): AsyncGenerator<AdaptiveCard, void, unknown> {
|
|
175
|
+
const card = this.createFormCard(title, fields, config || {});
|
|
176
|
+
yield card;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Creates the Adaptive Card with form elements.
|
|
181
|
+
*/
|
|
182
|
+
private createFormCard(
|
|
183
|
+
title: string,
|
|
184
|
+
fields: FormFieldConfig[],
|
|
185
|
+
config: FormConfig
|
|
186
|
+
): AdaptiveCard {
|
|
187
|
+
const card: AdaptiveCard = {
|
|
188
|
+
type: 'AdaptiveCard',
|
|
189
|
+
$schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
|
|
190
|
+
version: config.version || '1.5',
|
|
191
|
+
body: [],
|
|
192
|
+
actions: []
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
// Add container with optional background style
|
|
196
|
+
const container: AdaptiveCardElement = {
|
|
197
|
+
type: 'Container',
|
|
198
|
+
style: config.style || 'default',
|
|
199
|
+
items: []
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// Add title
|
|
203
|
+
container.items.push({
|
|
204
|
+
type: 'TextBlock',
|
|
205
|
+
text: title,
|
|
206
|
+
weight: 'Bolder',
|
|
207
|
+
size: 'Large',
|
|
208
|
+
wrap: true
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// Add description if provided
|
|
212
|
+
if (config.description) {
|
|
213
|
+
container.items.push({
|
|
214
|
+
type: 'TextBlock',
|
|
215
|
+
text: config.description,
|
|
216
|
+
isSubtle: true,
|
|
217
|
+
wrap: true,
|
|
218
|
+
spacing: 'Small'
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Add separator after header
|
|
223
|
+
container.items.push({
|
|
224
|
+
type: 'TextBlock',
|
|
225
|
+
text: ' ',
|
|
226
|
+
separator: true,
|
|
227
|
+
spacing: 'Medium'
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Add form fields
|
|
231
|
+
for (const field of fields) {
|
|
232
|
+
const fieldElements = this.createFieldElements(field);
|
|
233
|
+
container.items.push(...fieldElements);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
card.body.push(container);
|
|
237
|
+
|
|
238
|
+
// Add actions
|
|
239
|
+
card.actions = this.createActions(config);
|
|
240
|
+
|
|
241
|
+
return card;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Creates the elements for a single form field (label + input).
|
|
246
|
+
*/
|
|
247
|
+
private createFieldElements(field: FormFieldConfig): AdaptiveCardElement[] {
|
|
248
|
+
const elements: AdaptiveCardElement[] = [];
|
|
249
|
+
|
|
250
|
+
// Add label
|
|
251
|
+
const labelText = field.required ? `${field.label} *` : field.label;
|
|
252
|
+
elements.push({
|
|
253
|
+
type: 'TextBlock',
|
|
254
|
+
text: labelText,
|
|
255
|
+
weight: field.labelStyle === 'heading' ? 'Bolder' : 'Default',
|
|
256
|
+
wrap: true,
|
|
257
|
+
separator: field.separator || false,
|
|
258
|
+
spacing: field.separator ? 'Large' : 'Default'
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// Add input based on type
|
|
262
|
+
const inputElement = this.createInputElement(field);
|
|
263
|
+
elements.push(inputElement);
|
|
264
|
+
|
|
265
|
+
return elements;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Creates the appropriate input element based on field type.
|
|
270
|
+
*/
|
|
271
|
+
private createInputElement(field: FormFieldConfig): AdaptiveCardElement {
|
|
272
|
+
switch (field.type) {
|
|
273
|
+
case 'text':
|
|
274
|
+
return this.createTextInput(field, false);
|
|
275
|
+
|
|
276
|
+
case 'textarea':
|
|
277
|
+
return this.createTextInput(field, true);
|
|
278
|
+
|
|
279
|
+
case 'number':
|
|
280
|
+
return this.createNumberInput(field);
|
|
281
|
+
|
|
282
|
+
case 'date':
|
|
283
|
+
return this.createDateInput(field);
|
|
284
|
+
|
|
285
|
+
case 'time':
|
|
286
|
+
return this.createTimeInput(field);
|
|
287
|
+
|
|
288
|
+
case 'datetime':
|
|
289
|
+
return this.createDateTimeInputs(field);
|
|
290
|
+
|
|
291
|
+
case 'toggle':
|
|
292
|
+
return this.createToggleInput(field);
|
|
293
|
+
|
|
294
|
+
case 'dropdown':
|
|
295
|
+
return this.createChoiceSet(field, 'compact');
|
|
296
|
+
|
|
297
|
+
case 'radio':
|
|
298
|
+
return this.createChoiceSet(field, 'expanded');
|
|
299
|
+
|
|
300
|
+
case 'checkbox':
|
|
301
|
+
return this.createChoiceSet(field, 'expanded', true);
|
|
302
|
+
|
|
303
|
+
default:
|
|
304
|
+
return this.createTextInput(field, false);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Creates a text input element.
|
|
310
|
+
*/
|
|
311
|
+
private createTextInput(field: FormFieldConfig, isMultiLine: boolean): AdaptiveCardElement {
|
|
312
|
+
const input: AdaptiveCardElement = {
|
|
313
|
+
type: 'Input.Text',
|
|
314
|
+
id: field.id,
|
|
315
|
+
placeholder: field.placeholder || '',
|
|
316
|
+
isMultiline: isMultiLine,
|
|
317
|
+
isRequired: field.required || false
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
if (field.defaultValue !== undefined) {
|
|
321
|
+
input.value = String(field.defaultValue);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (field.pattern) {
|
|
325
|
+
input.regex = field.pattern;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (field.errorMessage) {
|
|
329
|
+
input.errorMessage = field.errorMessage;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (isMultiLine) {
|
|
333
|
+
input.style = 'text';
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return input;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Creates a number input element.
|
|
341
|
+
*/
|
|
342
|
+
private createNumberInput(field: FormFieldConfig): AdaptiveCardElement {
|
|
343
|
+
const input: AdaptiveCardElement = {
|
|
344
|
+
type: 'Input.Number',
|
|
345
|
+
id: field.id,
|
|
346
|
+
placeholder: field.placeholder || '',
|
|
347
|
+
isRequired: field.required || false
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
if (field.defaultValue !== undefined) {
|
|
351
|
+
input.value = Number(field.defaultValue);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (field.min !== undefined) {
|
|
355
|
+
input.min = field.min;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (field.max !== undefined) {
|
|
359
|
+
input.max = field.max;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (field.errorMessage) {
|
|
363
|
+
input.errorMessage = field.errorMessage;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
return input;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Creates a date input element.
|
|
371
|
+
*/
|
|
372
|
+
private createDateInput(field: FormFieldConfig): AdaptiveCardElement {
|
|
373
|
+
const input: AdaptiveCardElement = {
|
|
374
|
+
type: 'Input.Date',
|
|
375
|
+
id: field.id,
|
|
376
|
+
isRequired: field.required || false
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
if (field.defaultValue !== undefined) {
|
|
380
|
+
input.value = String(field.defaultValue);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (field.placeholder) {
|
|
384
|
+
input.placeholder = field.placeholder;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return input;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Creates a time input element.
|
|
392
|
+
*/
|
|
393
|
+
private createTimeInput(field: FormFieldConfig): AdaptiveCardElement {
|
|
394
|
+
const input: AdaptiveCardElement = {
|
|
395
|
+
type: 'Input.Time',
|
|
396
|
+
id: field.id,
|
|
397
|
+
isRequired: field.required || false
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
if (field.defaultValue !== undefined) {
|
|
401
|
+
input.value = String(field.defaultValue);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (field.placeholder) {
|
|
405
|
+
input.placeholder = field.placeholder;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return input;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Creates date and time inputs in a column set for datetime fields.
|
|
413
|
+
*/
|
|
414
|
+
private createDateTimeInputs(field: FormFieldConfig): AdaptiveCardElement {
|
|
415
|
+
const dateValue = field.defaultValue ? String(field.defaultValue).split('T')[0] : undefined;
|
|
416
|
+
const timeValue = field.defaultValue ? String(field.defaultValue).split('T')[1]?.substring(0, 5) : undefined;
|
|
417
|
+
|
|
418
|
+
return {
|
|
419
|
+
type: 'ColumnSet',
|
|
420
|
+
columns: [
|
|
421
|
+
{
|
|
422
|
+
type: 'Column',
|
|
423
|
+
width: 'stretch',
|
|
424
|
+
items: [{
|
|
425
|
+
type: 'Input.Date',
|
|
426
|
+
id: `${field.id}_date`,
|
|
427
|
+
isRequired: field.required || false,
|
|
428
|
+
value: dateValue
|
|
429
|
+
}]
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
type: 'Column',
|
|
433
|
+
width: 'stretch',
|
|
434
|
+
items: [{
|
|
435
|
+
type: 'Input.Time',
|
|
436
|
+
id: `${field.id}_time`,
|
|
437
|
+
isRequired: field.required || false,
|
|
438
|
+
value: timeValue
|
|
439
|
+
}]
|
|
440
|
+
}
|
|
441
|
+
]
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Creates a toggle input element.
|
|
447
|
+
*/
|
|
448
|
+
private createToggleInput(field: FormFieldConfig): AdaptiveCardElement {
|
|
449
|
+
const input: AdaptiveCardElement = {
|
|
450
|
+
type: 'Input.Toggle',
|
|
451
|
+
id: field.id,
|
|
452
|
+
title: field.toggleTitle || field.label,
|
|
453
|
+
valueOn: 'true',
|
|
454
|
+
valueOff: 'false',
|
|
455
|
+
isRequired: field.required || false
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
if (field.defaultValue !== undefined) {
|
|
459
|
+
input.value = field.defaultValue ? 'true' : 'false';
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
return input;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Creates a choice set (dropdown, radio, or checkbox).
|
|
467
|
+
*/
|
|
468
|
+
private createChoiceSet(
|
|
469
|
+
field: FormFieldConfig,
|
|
470
|
+
style: 'compact' | 'expanded',
|
|
471
|
+
isMultiSelect: boolean = false
|
|
472
|
+
): AdaptiveCardElement {
|
|
473
|
+
const choices = this.normalizeChoices(field.choices || []);
|
|
474
|
+
|
|
475
|
+
const input: AdaptiveCardElement = {
|
|
476
|
+
type: 'Input.ChoiceSet',
|
|
477
|
+
id: field.id,
|
|
478
|
+
style: style,
|
|
479
|
+
isMultiSelect: isMultiSelect,
|
|
480
|
+
isRequired: field.required || false,
|
|
481
|
+
choices: choices
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
if (field.defaultValue !== undefined) {
|
|
485
|
+
input.value = String(field.defaultValue);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
if (field.placeholder && style === 'compact') {
|
|
489
|
+
input.placeholder = field.placeholder;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return input;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Normalizes choices to the expected format.
|
|
497
|
+
*/
|
|
498
|
+
private normalizeChoices(choices: Array<{ title: string; value: string }> | string[]): Array<{ title: string; value: string }> {
|
|
499
|
+
return choices.map(choice => {
|
|
500
|
+
if (typeof choice === 'string') {
|
|
501
|
+
return { title: choice, value: choice };
|
|
502
|
+
}
|
|
503
|
+
return choice;
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* Creates the action buttons for the form.
|
|
509
|
+
*/
|
|
510
|
+
private createActions(config: FormConfig): AdaptiveCardAction[] {
|
|
511
|
+
const actions: AdaptiveCardAction[] = [];
|
|
512
|
+
|
|
513
|
+
// Add submit button
|
|
514
|
+
const submitConfig = config.submitButton || {};
|
|
515
|
+
const submitAction: AdaptiveCardAction = {
|
|
516
|
+
type: this.getActionType(submitConfig.actionType || 'submit'),
|
|
517
|
+
title: submitConfig.title || 'Submit',
|
|
518
|
+
style: submitConfig.style || 'positive'
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
if (submitConfig.actionType === 'openUrl' && submitConfig.url) {
|
|
522
|
+
submitAction.url = submitConfig.url;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
actions.push(submitAction);
|
|
526
|
+
|
|
527
|
+
// Add reset button if requested
|
|
528
|
+
if (config.showResetButton) {
|
|
529
|
+
actions.push({
|
|
530
|
+
type: 'Action.Submit',
|
|
531
|
+
title: 'Reset',
|
|
532
|
+
style: 'default',
|
|
533
|
+
data: { action: 'reset' }
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Add additional actions
|
|
538
|
+
if (config.additionalActions) {
|
|
539
|
+
for (const actionConfig of config.additionalActions) {
|
|
540
|
+
const action: AdaptiveCardAction = {
|
|
541
|
+
type: this.getActionType(actionConfig.type),
|
|
542
|
+
title: actionConfig.title,
|
|
543
|
+
style: actionConfig.style || 'default'
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
if (actionConfig.type === 'openUrl' && actionConfig.url) {
|
|
547
|
+
action.url = actionConfig.url;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
if (actionConfig.data) {
|
|
551
|
+
action.data = actionConfig.data;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
actions.push(action);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
return actions;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Gets the Adaptive Card action type string.
|
|
563
|
+
*/
|
|
564
|
+
private getActionType(type: string): string {
|
|
565
|
+
switch (type) {
|
|
566
|
+
case 'submit':
|
|
567
|
+
return 'Action.Submit';
|
|
568
|
+
case 'openUrl':
|
|
569
|
+
return 'Action.OpenUrl';
|
|
570
|
+
case 'showCard':
|
|
571
|
+
return 'Action.ShowCard';
|
|
572
|
+
default:
|
|
573
|
+
return 'Action.Submit';
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
export { FormLoader as default };
|
|
@@ -81,9 +81,8 @@ export interface LlmResponse {
|
|
|
81
81
|
* LLM Loader class - calls OpenAI-compatible APIs for chat completions.
|
|
82
82
|
*/
|
|
83
83
|
@FunctionDef({
|
|
84
|
-
isAsyncProvider: true,
|
|
85
84
|
description: 'Calls OpenAI-compatible chat completion APIs. Supports GPT models and any OpenAI-compatible endpoint.',
|
|
86
|
-
category: '
|
|
85
|
+
category: 'async',
|
|
87
86
|
parameters: [
|
|
88
87
|
{
|
|
89
88
|
name: 'prompt',
|
|
@@ -12,9 +12,8 @@ import { FunctionDef } from 'flowquery/extensibility';
|
|
|
12
12
|
* MockUsers loader class - generates mock user data for testing.
|
|
13
13
|
*/
|
|
14
14
|
@FunctionDef({
|
|
15
|
-
isAsyncProvider: true,
|
|
16
15
|
description: 'Generates mock user data for testing purposes',
|
|
17
|
-
category: '
|
|
16
|
+
category: 'async',
|
|
18
17
|
parameters: [
|
|
19
18
|
{
|
|
20
19
|
name: 'count',
|
|
@@ -81,9 +80,8 @@ export class MockUsersLoader {
|
|
|
81
80
|
* MockProducts loader class - generates mock product data for testing.
|
|
82
81
|
*/
|
|
83
82
|
@FunctionDef({
|
|
84
|
-
isAsyncProvider: true,
|
|
85
83
|
description: 'Generates mock product data for testing purposes',
|
|
86
|
-
category: '
|
|
84
|
+
category: 'async',
|
|
87
85
|
parameters: [
|
|
88
86
|
{
|
|
89
87
|
name: 'count',
|