@leanmcp/elicitation 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +564 -0
- package/dist/index.d.mts +345 -0
- package/dist/index.d.ts +345 -0
- package/dist/index.js +700 -0
- package/dist/index.mjs +665 -0
- package/package.json +58 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Elicitation request structure following MCP spec
|
|
3
|
+
*/
|
|
4
|
+
interface ElicitationRequest {
|
|
5
|
+
type: 'elicitation';
|
|
6
|
+
title: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
fields: ElicitationField[];
|
|
9
|
+
metadata?: {
|
|
10
|
+
stepNumber?: number;
|
|
11
|
+
totalSteps?: number;
|
|
12
|
+
previousValues?: Record<string, any>;
|
|
13
|
+
[key: string]: any;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Individual field in elicitation form
|
|
18
|
+
*/
|
|
19
|
+
interface ElicitationField {
|
|
20
|
+
name: string;
|
|
21
|
+
label: string;
|
|
22
|
+
type: 'text' | 'number' | 'boolean' | 'select' | 'multiselect' | 'date' | 'email' | 'url' | 'textarea';
|
|
23
|
+
description?: string;
|
|
24
|
+
required?: boolean;
|
|
25
|
+
defaultValue?: any;
|
|
26
|
+
options?: Array<{
|
|
27
|
+
label: string;
|
|
28
|
+
value: any;
|
|
29
|
+
}>;
|
|
30
|
+
validation?: FieldValidation;
|
|
31
|
+
placeholder?: string;
|
|
32
|
+
helpText?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Field validation rules
|
|
36
|
+
*/
|
|
37
|
+
interface FieldValidation {
|
|
38
|
+
min?: number;
|
|
39
|
+
max?: number;
|
|
40
|
+
minLength?: number;
|
|
41
|
+
maxLength?: number;
|
|
42
|
+
pattern?: string;
|
|
43
|
+
customValidator?: (value: any) => boolean | string;
|
|
44
|
+
errorMessage?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Elicitation response from user
|
|
48
|
+
*/
|
|
49
|
+
interface ElicitationResponse {
|
|
50
|
+
values: Record<string, any>;
|
|
51
|
+
metadata?: Record<string, any>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Strategy configuration
|
|
55
|
+
*/
|
|
56
|
+
interface ElicitationStrategyConfig {
|
|
57
|
+
strategy: 'form' | 'conversational' | 'multi-step';
|
|
58
|
+
onComplete?: (values: Record<string, any>) => void;
|
|
59
|
+
onValidationError?: (errors: ValidationError[]) => void;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Validation error
|
|
63
|
+
*/
|
|
64
|
+
interface ValidationError {
|
|
65
|
+
field: string;
|
|
66
|
+
message: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Elicitation configuration for decorator
|
|
70
|
+
*/
|
|
71
|
+
interface ElicitationConfig {
|
|
72
|
+
strategy?: 'form' | 'conversational' | 'multi-step';
|
|
73
|
+
title?: string;
|
|
74
|
+
description?: string;
|
|
75
|
+
fields?: ElicitationField[];
|
|
76
|
+
condition?: (args: any) => boolean;
|
|
77
|
+
builder?: (context: ElicitationContext) => ElicitationRequest | ElicitationStep[];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Context passed to elicitation builder
|
|
81
|
+
*/
|
|
82
|
+
interface ElicitationContext {
|
|
83
|
+
args: any;
|
|
84
|
+
meta?: any;
|
|
85
|
+
previousAttempts?: number;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Multi-step elicitation step
|
|
89
|
+
*/
|
|
90
|
+
interface ElicitationStep {
|
|
91
|
+
title: string;
|
|
92
|
+
description?: string;
|
|
93
|
+
fields: ElicitationField[];
|
|
94
|
+
condition?: (previousValues: Record<string, any>) => boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Elicitation error
|
|
98
|
+
*/
|
|
99
|
+
declare class ElicitationError extends Error {
|
|
100
|
+
code: string;
|
|
101
|
+
details?: any | undefined;
|
|
102
|
+
constructor(message: string, code: string, details?: any | undefined);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Check if method arguments are missing required fields
|
|
107
|
+
*/
|
|
108
|
+
declare function checkMissingFields(args: any, config: ElicitationConfig): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Decorator to mark a method as requiring elicitation
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* // Simple form elicitation
|
|
114
|
+
* @Tool({ description: 'Create Slack channel' })
|
|
115
|
+
* @Elicitation({
|
|
116
|
+
* title: 'Create Channel',
|
|
117
|
+
* fields: [
|
|
118
|
+
* { name: 'channelName', label: 'Channel Name', type: 'text', required: true },
|
|
119
|
+
* { name: 'isPrivate', label: 'Private Channel', type: 'boolean', defaultValue: false }
|
|
120
|
+
* ]
|
|
121
|
+
* })
|
|
122
|
+
* async createChannel(args: CreateChannelInput) {
|
|
123
|
+
* // Method receives complete args after elicitation
|
|
124
|
+
* }
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* // Conditional elicitation
|
|
128
|
+
* @Tool({ description: 'Send message' })
|
|
129
|
+
* @Elicitation({
|
|
130
|
+
* condition: (args) => !args.channelId,
|
|
131
|
+
* title: 'Select Channel',
|
|
132
|
+
* fields: [
|
|
133
|
+
* { name: 'channelId', label: 'Channel', type: 'select', required: true }
|
|
134
|
+
* ]
|
|
135
|
+
* })
|
|
136
|
+
* async sendMessage(args: SendMessageInput) {
|
|
137
|
+
* // Only elicits if channelId is missing
|
|
138
|
+
* }
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* // Multi-step elicitation
|
|
142
|
+
* @Tool({ description: 'Deploy app' })
|
|
143
|
+
* @Elicitation({
|
|
144
|
+
* strategy: 'multi-step',
|
|
145
|
+
* builder: () => [
|
|
146
|
+
* {
|
|
147
|
+
* title: 'Step 1: Environment',
|
|
148
|
+
* fields: [{ name: 'env', label: 'Environment', type: 'select', required: true }]
|
|
149
|
+
* },
|
|
150
|
+
* {
|
|
151
|
+
* title: 'Step 2: Config',
|
|
152
|
+
* fields: [{ name: 'replicas', label: 'Replicas', type: 'number', defaultValue: 3 }]
|
|
153
|
+
* }
|
|
154
|
+
* ]
|
|
155
|
+
* })
|
|
156
|
+
* async deployApp(args: DeployConfig) {
|
|
157
|
+
* // Implementation
|
|
158
|
+
* }
|
|
159
|
+
*/
|
|
160
|
+
declare function Elicitation(config: ElicitationConfig): MethodDecorator;
|
|
161
|
+
/**
|
|
162
|
+
* Check if a method requires elicitation
|
|
163
|
+
*/
|
|
164
|
+
declare function isElicitationEnabled(method: Function): boolean;
|
|
165
|
+
/**
|
|
166
|
+
* Get elicitation configuration for a method
|
|
167
|
+
*/
|
|
168
|
+
declare function getElicitationConfig(method: Function): ElicitationConfig | undefined;
|
|
169
|
+
/**
|
|
170
|
+
* Get elicitation strategy type for a method
|
|
171
|
+
*/
|
|
172
|
+
declare function getElicitationStrategy(method: Function): string | undefined;
|
|
173
|
+
/**
|
|
174
|
+
* Build elicitation request from method metadata
|
|
175
|
+
*/
|
|
176
|
+
declare function buildElicitationRequest(method: Function, args: any, meta?: any): ElicitationRequest | null;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Base class for elicitation strategies
|
|
180
|
+
* Extend this class to implement custom elicitation strategies
|
|
181
|
+
*/
|
|
182
|
+
declare abstract class ElicitationStrategyBase {
|
|
183
|
+
/**
|
|
184
|
+
* Build an elicitation request from configuration and context
|
|
185
|
+
*/
|
|
186
|
+
abstract buildRequest(config: ElicitationConfig, context: ElicitationContext): ElicitationRequest;
|
|
187
|
+
/**
|
|
188
|
+
* Validate user response against field definitions
|
|
189
|
+
*/
|
|
190
|
+
validateResponse(response: ElicitationResponse, fields: ElicitationField[]): ValidationError[];
|
|
191
|
+
/**
|
|
192
|
+
* Validate field type
|
|
193
|
+
*/
|
|
194
|
+
protected validateFieldType(value: any, field: ElicitationField): ValidationError | null;
|
|
195
|
+
/**
|
|
196
|
+
* Validate field against validation rules
|
|
197
|
+
*/
|
|
198
|
+
protected validateField(value: any, field: ElicitationField): ValidationError | null;
|
|
199
|
+
/**
|
|
200
|
+
* Merge elicited values with original arguments
|
|
201
|
+
*/
|
|
202
|
+
mergeWithArgs(originalArgs: any, elicitedValues: Record<string, any>): any;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Form-based elicitation strategy
|
|
207
|
+
* Presents all fields at once in a single form
|
|
208
|
+
*/
|
|
209
|
+
declare class FormElicitationStrategy extends ElicitationStrategyBase {
|
|
210
|
+
buildRequest(config: ElicitationConfig, context: ElicitationContext): ElicitationRequest;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Multi-step elicitation strategy
|
|
215
|
+
* Breaks elicitation into multiple sequential steps
|
|
216
|
+
*/
|
|
217
|
+
declare class MultiStepElicitationStrategy extends ElicitationStrategyBase {
|
|
218
|
+
private steps;
|
|
219
|
+
private currentStep;
|
|
220
|
+
private accumulatedValues;
|
|
221
|
+
constructor(steps: ElicitationStep[]);
|
|
222
|
+
buildRequest(config: ElicitationConfig, context: ElicitationContext): ElicitationRequest;
|
|
223
|
+
/**
|
|
224
|
+
* Check if there are more steps
|
|
225
|
+
*/
|
|
226
|
+
hasNextStep(): boolean;
|
|
227
|
+
/**
|
|
228
|
+
* Move to next step and accumulate values
|
|
229
|
+
*/
|
|
230
|
+
nextStep(values: Record<string, any>): void;
|
|
231
|
+
/**
|
|
232
|
+
* Get all accumulated values
|
|
233
|
+
*/
|
|
234
|
+
getAccumulatedValues(): Record<string, any>;
|
|
235
|
+
/**
|
|
236
|
+
* Reset to first step
|
|
237
|
+
*/
|
|
238
|
+
reset(): void;
|
|
239
|
+
/**
|
|
240
|
+
* Override merge to include all accumulated values
|
|
241
|
+
*/
|
|
242
|
+
mergeWithArgs(originalArgs: any, elicitedValues: Record<string, any>): any;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Fluent builder for creating elicitation forms
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* const config = new ElicitationFormBuilder()
|
|
250
|
+
* .title('Create Slack Channel')
|
|
251
|
+
* .description('Please provide channel details')
|
|
252
|
+
* .addTextField('channelName', 'Channel Name', { required: true })
|
|
253
|
+
* .addBooleanField('isPrivate', 'Private Channel', { defaultValue: false })
|
|
254
|
+
* .addSelectField('team', 'Team', [
|
|
255
|
+
* { label: 'Engineering', value: 'eng' },
|
|
256
|
+
* { label: 'Marketing', value: 'mkt' }
|
|
257
|
+
* ])
|
|
258
|
+
* .build();
|
|
259
|
+
*/
|
|
260
|
+
declare class ElicitationFormBuilder {
|
|
261
|
+
private fields;
|
|
262
|
+
private config;
|
|
263
|
+
/**
|
|
264
|
+
* Set the form title
|
|
265
|
+
*/
|
|
266
|
+
title(title: string): this;
|
|
267
|
+
/**
|
|
268
|
+
* Set the form description
|
|
269
|
+
*/
|
|
270
|
+
description(description: string): this;
|
|
271
|
+
/**
|
|
272
|
+
* Set a condition for when elicitation should occur
|
|
273
|
+
*/
|
|
274
|
+
condition(condition: (args: any) => boolean): this;
|
|
275
|
+
/**
|
|
276
|
+
* Add a text field
|
|
277
|
+
*/
|
|
278
|
+
addTextField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
279
|
+
/**
|
|
280
|
+
* Add a textarea field
|
|
281
|
+
*/
|
|
282
|
+
addTextAreaField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
283
|
+
/**
|
|
284
|
+
* Add a number field
|
|
285
|
+
*/
|
|
286
|
+
addNumberField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
287
|
+
/**
|
|
288
|
+
* Add a boolean field (checkbox)
|
|
289
|
+
*/
|
|
290
|
+
addBooleanField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
291
|
+
/**
|
|
292
|
+
* Add a select field (dropdown)
|
|
293
|
+
*/
|
|
294
|
+
addSelectField(name: string, label: string, options: Array<{
|
|
295
|
+
label: string;
|
|
296
|
+
value: any;
|
|
297
|
+
}>, fieldOptions?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type' | 'options'>>): this;
|
|
298
|
+
/**
|
|
299
|
+
* Add a multi-select field
|
|
300
|
+
*/
|
|
301
|
+
addMultiSelectField(name: string, label: string, options: Array<{
|
|
302
|
+
label: string;
|
|
303
|
+
value: any;
|
|
304
|
+
}>, fieldOptions?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type' | 'options'>>): this;
|
|
305
|
+
/**
|
|
306
|
+
* Add an email field
|
|
307
|
+
*/
|
|
308
|
+
addEmailField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
309
|
+
/**
|
|
310
|
+
* Add a URL field
|
|
311
|
+
*/
|
|
312
|
+
addUrlField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
313
|
+
/**
|
|
314
|
+
* Add a date field
|
|
315
|
+
*/
|
|
316
|
+
addDateField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
317
|
+
/**
|
|
318
|
+
* Add a custom field with full control
|
|
319
|
+
*/
|
|
320
|
+
addCustomField(field: ElicitationField): this;
|
|
321
|
+
/**
|
|
322
|
+
* Build the final configuration
|
|
323
|
+
*/
|
|
324
|
+
build(): ElicitationConfig;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Helper function to create validation rules
|
|
328
|
+
*/
|
|
329
|
+
declare class ValidationBuilder {
|
|
330
|
+
private validation;
|
|
331
|
+
min(min: number): this;
|
|
332
|
+
max(max: number): this;
|
|
333
|
+
minLength(minLength: number): this;
|
|
334
|
+
maxLength(maxLength: number): this;
|
|
335
|
+
pattern(pattern: string): this;
|
|
336
|
+
customValidator(validator: (value: any) => boolean | string): this;
|
|
337
|
+
errorMessage(message: string): this;
|
|
338
|
+
build(): FieldValidation;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Helper to create validation rules
|
|
342
|
+
*/
|
|
343
|
+
declare function validation(): ValidationBuilder;
|
|
344
|
+
|
|
345
|
+
export { Elicitation, type ElicitationConfig, type ElicitationContext, ElicitationError, type ElicitationField, ElicitationFormBuilder, type ElicitationRequest, type ElicitationResponse, type ElicitationStep, ElicitationStrategyBase, type ElicitationStrategyConfig, type FieldValidation, FormElicitationStrategy, MultiStepElicitationStrategy, ValidationBuilder, type ValidationError, buildElicitationRequest, checkMissingFields, getElicitationConfig, getElicitationStrategy, isElicitationEnabled, validation };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Elicitation request structure following MCP spec
|
|
3
|
+
*/
|
|
4
|
+
interface ElicitationRequest {
|
|
5
|
+
type: 'elicitation';
|
|
6
|
+
title: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
fields: ElicitationField[];
|
|
9
|
+
metadata?: {
|
|
10
|
+
stepNumber?: number;
|
|
11
|
+
totalSteps?: number;
|
|
12
|
+
previousValues?: Record<string, any>;
|
|
13
|
+
[key: string]: any;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Individual field in elicitation form
|
|
18
|
+
*/
|
|
19
|
+
interface ElicitationField {
|
|
20
|
+
name: string;
|
|
21
|
+
label: string;
|
|
22
|
+
type: 'text' | 'number' | 'boolean' | 'select' | 'multiselect' | 'date' | 'email' | 'url' | 'textarea';
|
|
23
|
+
description?: string;
|
|
24
|
+
required?: boolean;
|
|
25
|
+
defaultValue?: any;
|
|
26
|
+
options?: Array<{
|
|
27
|
+
label: string;
|
|
28
|
+
value: any;
|
|
29
|
+
}>;
|
|
30
|
+
validation?: FieldValidation;
|
|
31
|
+
placeholder?: string;
|
|
32
|
+
helpText?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Field validation rules
|
|
36
|
+
*/
|
|
37
|
+
interface FieldValidation {
|
|
38
|
+
min?: number;
|
|
39
|
+
max?: number;
|
|
40
|
+
minLength?: number;
|
|
41
|
+
maxLength?: number;
|
|
42
|
+
pattern?: string;
|
|
43
|
+
customValidator?: (value: any) => boolean | string;
|
|
44
|
+
errorMessage?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Elicitation response from user
|
|
48
|
+
*/
|
|
49
|
+
interface ElicitationResponse {
|
|
50
|
+
values: Record<string, any>;
|
|
51
|
+
metadata?: Record<string, any>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Strategy configuration
|
|
55
|
+
*/
|
|
56
|
+
interface ElicitationStrategyConfig {
|
|
57
|
+
strategy: 'form' | 'conversational' | 'multi-step';
|
|
58
|
+
onComplete?: (values: Record<string, any>) => void;
|
|
59
|
+
onValidationError?: (errors: ValidationError[]) => void;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Validation error
|
|
63
|
+
*/
|
|
64
|
+
interface ValidationError {
|
|
65
|
+
field: string;
|
|
66
|
+
message: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Elicitation configuration for decorator
|
|
70
|
+
*/
|
|
71
|
+
interface ElicitationConfig {
|
|
72
|
+
strategy?: 'form' | 'conversational' | 'multi-step';
|
|
73
|
+
title?: string;
|
|
74
|
+
description?: string;
|
|
75
|
+
fields?: ElicitationField[];
|
|
76
|
+
condition?: (args: any) => boolean;
|
|
77
|
+
builder?: (context: ElicitationContext) => ElicitationRequest | ElicitationStep[];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Context passed to elicitation builder
|
|
81
|
+
*/
|
|
82
|
+
interface ElicitationContext {
|
|
83
|
+
args: any;
|
|
84
|
+
meta?: any;
|
|
85
|
+
previousAttempts?: number;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Multi-step elicitation step
|
|
89
|
+
*/
|
|
90
|
+
interface ElicitationStep {
|
|
91
|
+
title: string;
|
|
92
|
+
description?: string;
|
|
93
|
+
fields: ElicitationField[];
|
|
94
|
+
condition?: (previousValues: Record<string, any>) => boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Elicitation error
|
|
98
|
+
*/
|
|
99
|
+
declare class ElicitationError extends Error {
|
|
100
|
+
code: string;
|
|
101
|
+
details?: any | undefined;
|
|
102
|
+
constructor(message: string, code: string, details?: any | undefined);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Check if method arguments are missing required fields
|
|
107
|
+
*/
|
|
108
|
+
declare function checkMissingFields(args: any, config: ElicitationConfig): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Decorator to mark a method as requiring elicitation
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* // Simple form elicitation
|
|
114
|
+
* @Tool({ description: 'Create Slack channel' })
|
|
115
|
+
* @Elicitation({
|
|
116
|
+
* title: 'Create Channel',
|
|
117
|
+
* fields: [
|
|
118
|
+
* { name: 'channelName', label: 'Channel Name', type: 'text', required: true },
|
|
119
|
+
* { name: 'isPrivate', label: 'Private Channel', type: 'boolean', defaultValue: false }
|
|
120
|
+
* ]
|
|
121
|
+
* })
|
|
122
|
+
* async createChannel(args: CreateChannelInput) {
|
|
123
|
+
* // Method receives complete args after elicitation
|
|
124
|
+
* }
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* // Conditional elicitation
|
|
128
|
+
* @Tool({ description: 'Send message' })
|
|
129
|
+
* @Elicitation({
|
|
130
|
+
* condition: (args) => !args.channelId,
|
|
131
|
+
* title: 'Select Channel',
|
|
132
|
+
* fields: [
|
|
133
|
+
* { name: 'channelId', label: 'Channel', type: 'select', required: true }
|
|
134
|
+
* ]
|
|
135
|
+
* })
|
|
136
|
+
* async sendMessage(args: SendMessageInput) {
|
|
137
|
+
* // Only elicits if channelId is missing
|
|
138
|
+
* }
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* // Multi-step elicitation
|
|
142
|
+
* @Tool({ description: 'Deploy app' })
|
|
143
|
+
* @Elicitation({
|
|
144
|
+
* strategy: 'multi-step',
|
|
145
|
+
* builder: () => [
|
|
146
|
+
* {
|
|
147
|
+
* title: 'Step 1: Environment',
|
|
148
|
+
* fields: [{ name: 'env', label: 'Environment', type: 'select', required: true }]
|
|
149
|
+
* },
|
|
150
|
+
* {
|
|
151
|
+
* title: 'Step 2: Config',
|
|
152
|
+
* fields: [{ name: 'replicas', label: 'Replicas', type: 'number', defaultValue: 3 }]
|
|
153
|
+
* }
|
|
154
|
+
* ]
|
|
155
|
+
* })
|
|
156
|
+
* async deployApp(args: DeployConfig) {
|
|
157
|
+
* // Implementation
|
|
158
|
+
* }
|
|
159
|
+
*/
|
|
160
|
+
declare function Elicitation(config: ElicitationConfig): MethodDecorator;
|
|
161
|
+
/**
|
|
162
|
+
* Check if a method requires elicitation
|
|
163
|
+
*/
|
|
164
|
+
declare function isElicitationEnabled(method: Function): boolean;
|
|
165
|
+
/**
|
|
166
|
+
* Get elicitation configuration for a method
|
|
167
|
+
*/
|
|
168
|
+
declare function getElicitationConfig(method: Function): ElicitationConfig | undefined;
|
|
169
|
+
/**
|
|
170
|
+
* Get elicitation strategy type for a method
|
|
171
|
+
*/
|
|
172
|
+
declare function getElicitationStrategy(method: Function): string | undefined;
|
|
173
|
+
/**
|
|
174
|
+
* Build elicitation request from method metadata
|
|
175
|
+
*/
|
|
176
|
+
declare function buildElicitationRequest(method: Function, args: any, meta?: any): ElicitationRequest | null;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Base class for elicitation strategies
|
|
180
|
+
* Extend this class to implement custom elicitation strategies
|
|
181
|
+
*/
|
|
182
|
+
declare abstract class ElicitationStrategyBase {
|
|
183
|
+
/**
|
|
184
|
+
* Build an elicitation request from configuration and context
|
|
185
|
+
*/
|
|
186
|
+
abstract buildRequest(config: ElicitationConfig, context: ElicitationContext): ElicitationRequest;
|
|
187
|
+
/**
|
|
188
|
+
* Validate user response against field definitions
|
|
189
|
+
*/
|
|
190
|
+
validateResponse(response: ElicitationResponse, fields: ElicitationField[]): ValidationError[];
|
|
191
|
+
/**
|
|
192
|
+
* Validate field type
|
|
193
|
+
*/
|
|
194
|
+
protected validateFieldType(value: any, field: ElicitationField): ValidationError | null;
|
|
195
|
+
/**
|
|
196
|
+
* Validate field against validation rules
|
|
197
|
+
*/
|
|
198
|
+
protected validateField(value: any, field: ElicitationField): ValidationError | null;
|
|
199
|
+
/**
|
|
200
|
+
* Merge elicited values with original arguments
|
|
201
|
+
*/
|
|
202
|
+
mergeWithArgs(originalArgs: any, elicitedValues: Record<string, any>): any;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Form-based elicitation strategy
|
|
207
|
+
* Presents all fields at once in a single form
|
|
208
|
+
*/
|
|
209
|
+
declare class FormElicitationStrategy extends ElicitationStrategyBase {
|
|
210
|
+
buildRequest(config: ElicitationConfig, context: ElicitationContext): ElicitationRequest;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Multi-step elicitation strategy
|
|
215
|
+
* Breaks elicitation into multiple sequential steps
|
|
216
|
+
*/
|
|
217
|
+
declare class MultiStepElicitationStrategy extends ElicitationStrategyBase {
|
|
218
|
+
private steps;
|
|
219
|
+
private currentStep;
|
|
220
|
+
private accumulatedValues;
|
|
221
|
+
constructor(steps: ElicitationStep[]);
|
|
222
|
+
buildRequest(config: ElicitationConfig, context: ElicitationContext): ElicitationRequest;
|
|
223
|
+
/**
|
|
224
|
+
* Check if there are more steps
|
|
225
|
+
*/
|
|
226
|
+
hasNextStep(): boolean;
|
|
227
|
+
/**
|
|
228
|
+
* Move to next step and accumulate values
|
|
229
|
+
*/
|
|
230
|
+
nextStep(values: Record<string, any>): void;
|
|
231
|
+
/**
|
|
232
|
+
* Get all accumulated values
|
|
233
|
+
*/
|
|
234
|
+
getAccumulatedValues(): Record<string, any>;
|
|
235
|
+
/**
|
|
236
|
+
* Reset to first step
|
|
237
|
+
*/
|
|
238
|
+
reset(): void;
|
|
239
|
+
/**
|
|
240
|
+
* Override merge to include all accumulated values
|
|
241
|
+
*/
|
|
242
|
+
mergeWithArgs(originalArgs: any, elicitedValues: Record<string, any>): any;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Fluent builder for creating elicitation forms
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* const config = new ElicitationFormBuilder()
|
|
250
|
+
* .title('Create Slack Channel')
|
|
251
|
+
* .description('Please provide channel details')
|
|
252
|
+
* .addTextField('channelName', 'Channel Name', { required: true })
|
|
253
|
+
* .addBooleanField('isPrivate', 'Private Channel', { defaultValue: false })
|
|
254
|
+
* .addSelectField('team', 'Team', [
|
|
255
|
+
* { label: 'Engineering', value: 'eng' },
|
|
256
|
+
* { label: 'Marketing', value: 'mkt' }
|
|
257
|
+
* ])
|
|
258
|
+
* .build();
|
|
259
|
+
*/
|
|
260
|
+
declare class ElicitationFormBuilder {
|
|
261
|
+
private fields;
|
|
262
|
+
private config;
|
|
263
|
+
/**
|
|
264
|
+
* Set the form title
|
|
265
|
+
*/
|
|
266
|
+
title(title: string): this;
|
|
267
|
+
/**
|
|
268
|
+
* Set the form description
|
|
269
|
+
*/
|
|
270
|
+
description(description: string): this;
|
|
271
|
+
/**
|
|
272
|
+
* Set a condition for when elicitation should occur
|
|
273
|
+
*/
|
|
274
|
+
condition(condition: (args: any) => boolean): this;
|
|
275
|
+
/**
|
|
276
|
+
* Add a text field
|
|
277
|
+
*/
|
|
278
|
+
addTextField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
279
|
+
/**
|
|
280
|
+
* Add a textarea field
|
|
281
|
+
*/
|
|
282
|
+
addTextAreaField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
283
|
+
/**
|
|
284
|
+
* Add a number field
|
|
285
|
+
*/
|
|
286
|
+
addNumberField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
287
|
+
/**
|
|
288
|
+
* Add a boolean field (checkbox)
|
|
289
|
+
*/
|
|
290
|
+
addBooleanField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
291
|
+
/**
|
|
292
|
+
* Add a select field (dropdown)
|
|
293
|
+
*/
|
|
294
|
+
addSelectField(name: string, label: string, options: Array<{
|
|
295
|
+
label: string;
|
|
296
|
+
value: any;
|
|
297
|
+
}>, fieldOptions?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type' | 'options'>>): this;
|
|
298
|
+
/**
|
|
299
|
+
* Add a multi-select field
|
|
300
|
+
*/
|
|
301
|
+
addMultiSelectField(name: string, label: string, options: Array<{
|
|
302
|
+
label: string;
|
|
303
|
+
value: any;
|
|
304
|
+
}>, fieldOptions?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type' | 'options'>>): this;
|
|
305
|
+
/**
|
|
306
|
+
* Add an email field
|
|
307
|
+
*/
|
|
308
|
+
addEmailField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
309
|
+
/**
|
|
310
|
+
* Add a URL field
|
|
311
|
+
*/
|
|
312
|
+
addUrlField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
313
|
+
/**
|
|
314
|
+
* Add a date field
|
|
315
|
+
*/
|
|
316
|
+
addDateField(name: string, label: string, options?: Partial<Omit<ElicitationField, 'name' | 'label' | 'type'>>): this;
|
|
317
|
+
/**
|
|
318
|
+
* Add a custom field with full control
|
|
319
|
+
*/
|
|
320
|
+
addCustomField(field: ElicitationField): this;
|
|
321
|
+
/**
|
|
322
|
+
* Build the final configuration
|
|
323
|
+
*/
|
|
324
|
+
build(): ElicitationConfig;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Helper function to create validation rules
|
|
328
|
+
*/
|
|
329
|
+
declare class ValidationBuilder {
|
|
330
|
+
private validation;
|
|
331
|
+
min(min: number): this;
|
|
332
|
+
max(max: number): this;
|
|
333
|
+
minLength(minLength: number): this;
|
|
334
|
+
maxLength(maxLength: number): this;
|
|
335
|
+
pattern(pattern: string): this;
|
|
336
|
+
customValidator(validator: (value: any) => boolean | string): this;
|
|
337
|
+
errorMessage(message: string): this;
|
|
338
|
+
build(): FieldValidation;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Helper to create validation rules
|
|
342
|
+
*/
|
|
343
|
+
declare function validation(): ValidationBuilder;
|
|
344
|
+
|
|
345
|
+
export { Elicitation, type ElicitationConfig, type ElicitationContext, ElicitationError, type ElicitationField, ElicitationFormBuilder, type ElicitationRequest, type ElicitationResponse, type ElicitationStep, ElicitationStrategyBase, type ElicitationStrategyConfig, type FieldValidation, FormElicitationStrategy, MultiStepElicitationStrategy, ValidationBuilder, type ValidationError, buildElicitationRequest, checkMissingFields, getElicitationConfig, getElicitationStrategy, isElicitationEnabled, validation };
|