@elizaos/plugin-form 2.0.0-alpha.1 → 2.0.0-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/chunk-4B5QLNVA.js +187 -0
  2. package/dist/chunk-ARWZY3NX.js +284 -0
  3. package/dist/chunk-R4VBS2YK.js +1597 -0
  4. package/dist/chunk-TBCL2ILB.js +172 -0
  5. package/dist/chunk-WY4WK3HD.js +57 -0
  6. package/dist/chunk-XHECCAUT.js +544 -0
  7. package/dist/chunk-YTWANJ3R.js +64 -0
  8. package/dist/context-MHPFYZZ2.js +9 -0
  9. package/dist/extractor-UWASKXKD.js +11 -0
  10. package/dist/index.d.ts +3057 -19
  11. package/dist/index.js +428 -2826
  12. package/dist/restore-S7JLME4H.js +9 -0
  13. package/dist/service-TCCXKV3T.js +7 -0
  14. package/package.json +33 -23
  15. package/LICENSE +0 -21
  16. package/README.md +0 -846
  17. package/dist/actions/restore.d.ts +0 -62
  18. package/dist/actions/restore.d.ts.map +0 -1
  19. package/dist/builder.d.ts +0 -320
  20. package/dist/builder.d.ts.map +0 -1
  21. package/dist/builtins.d.ts +0 -128
  22. package/dist/builtins.d.ts.map +0 -1
  23. package/dist/defaults.d.ts +0 -95
  24. package/dist/defaults.d.ts.map +0 -1
  25. package/dist/evaluators/extractor.d.ts +0 -91
  26. package/dist/evaluators/extractor.d.ts.map +0 -1
  27. package/dist/extraction.d.ts +0 -105
  28. package/dist/extraction.d.ts.map +0 -1
  29. package/dist/index.d.ts.map +0 -1
  30. package/dist/index.js.map +0 -30
  31. package/dist/intent.d.ts +0 -116
  32. package/dist/intent.d.ts.map +0 -1
  33. package/dist/providers/context.d.ts +0 -69
  34. package/dist/providers/context.d.ts.map +0 -1
  35. package/dist/service.d.ts +0 -417
  36. package/dist/service.d.ts.map +0 -1
  37. package/dist/storage.d.ts +0 -228
  38. package/dist/storage.d.ts.map +0 -1
  39. package/dist/tasks/nudge.d.ts +0 -89
  40. package/dist/tasks/nudge.d.ts.map +0 -1
  41. package/dist/template.d.ts +0 -10
  42. package/dist/template.d.ts.map +0 -1
  43. package/dist/ttl.d.ts +0 -144
  44. package/dist/ttl.d.ts.map +0 -1
  45. package/dist/types.d.ts +0 -1214
  46. package/dist/types.d.ts.map +0 -1
  47. package/dist/validation.d.ts +0 -156
  48. package/dist/validation.d.ts.map +0 -1
@@ -0,0 +1,544 @@
1
+ import {
2
+ getTypeHandler,
3
+ parseValue,
4
+ validateField
5
+ } from "./chunk-ARWZY3NX.js";
6
+ import {
7
+ quickIntentDetect
8
+ } from "./chunk-YTWANJ3R.js";
9
+ import {
10
+ buildTemplateValues,
11
+ resolveControlTemplates
12
+ } from "./chunk-WY4WK3HD.js";
13
+
14
+ // src/evaluators/extractor.ts
15
+ import { logger } from "@elizaos/core";
16
+
17
+ // src/extraction.ts
18
+ import { ModelType, parseKeyValueXml } from "@elizaos/core";
19
+ async function llmIntentAndExtract(runtime, text, form, controls, templateValues) {
20
+ const resolvedControls = templateValues ? controls.map((control) => resolveControlTemplates(control, templateValues)) : controls;
21
+ const fieldsDescription = resolvedControls.filter((c) => !c.hidden).map((c) => {
22
+ const handler = getTypeHandler(c.type);
23
+ const typeHint = handler?.extractionPrompt || c.type;
24
+ const hints = c.extractHints?.join(", ") || "";
25
+ const options = c.options?.map((o) => o.value).join(", ") || "";
26
+ return `- ${c.key} (${c.label}): ${c.description || typeHint}${hints ? ` [hints: ${hints}]` : ""}${options ? ` [options: ${options}]` : ""}`;
27
+ }).join("\n");
28
+ const prompt = `You are extracting structured data from a user's natural language message.
29
+
30
+ FORM: ${form.name}
31
+ ${form.description ? `DESCRIPTION: ${form.description}` : ""}
32
+
33
+ FIELDS TO EXTRACT:
34
+ ${fieldsDescription}
35
+
36
+ USER MESSAGE:
37
+ "${text}"
38
+
39
+ INSTRUCTIONS:
40
+ 1. Determine the user's intent:
41
+ - fill_form: They are providing information for form fields
42
+ - submit: They want to submit/complete the form ("done", "submit", "finish", "that's all")
43
+ - stash: They want to save for later ("save for later", "pause", "hold on")
44
+ - restore: They want to resume a saved form ("resume", "continue", "pick up where")
45
+ - cancel: They want to cancel ("cancel", "abort", "nevermind", "forget it")
46
+ - undo: They want to undo last change ("undo", "go back", "wait no")
47
+ - skip: They want to skip current field ("skip", "pass", "don't know")
48
+ - explain: They want explanation ("why?", "what's that for?")
49
+ - example: They want an example ("example?", "like what?")
50
+ - progress: They want progress update ("how far?", "status")
51
+ - autofill: They want to use saved values ("same as last time")
52
+ - other: None of the above
53
+
54
+ 2. For fill_form intent, extract all field values mentioned.
55
+ - For each extracted value, provide a confidence score (0.0-1.0)
56
+ - Note if this appears to be a correction to a previous value
57
+
58
+ Respond using TOON like this:
59
+ intent: fill_form, submit, stash, restore, cancel, undo, skip, explain, example, progress, autofill, or other
60
+ extractions[N]{key,value,confidence,reasoning,is_correction}:
61
+ field_key,extracted_value,0.9,why this value,false
62
+
63
+ Example:
64
+ intent: fill_form
65
+ extractions[2]{key,value,confidence,reasoning,is_correction}:
66
+ name,Jane Doe,0.95,User said their name is Jane,false
67
+ email,jane@example.com,0.9,Email mentioned in message,false
68
+
69
+ IMPORTANT: Your response must ONLY contain the TOON document above. No preamble or explanation.`;
70
+ try {
71
+ const response = await runtime.useModel(ModelType.TEXT_SMALL, {
72
+ prompt,
73
+ temperature: 0.1
74
+ });
75
+ const parsed = parseExtractionResponse(response);
76
+ for (const extraction of parsed.extractions) {
77
+ const control = resolvedControls.find((c) => c.key === extraction.field);
78
+ if (control) {
79
+ if (typeof extraction.value === "string") {
80
+ extraction.value = parseValue(extraction.value, control);
81
+ }
82
+ const validation = validateField(extraction.value, control);
83
+ if (!validation.valid) {
84
+ extraction.confidence = Math.min(extraction.confidence, 0.3);
85
+ extraction.reasoning = `${extraction.reasoning || ""} (Validation failed: ${validation.error})`;
86
+ }
87
+ }
88
+ }
89
+ if (form.debug) {
90
+ runtime.logger.debug("[FormExtraction] LLM extraction result:", JSON.stringify(parsed));
91
+ }
92
+ return parsed;
93
+ } catch (error) {
94
+ runtime.logger.error("[FormExtraction] LLM extraction failed:", String(error));
95
+ return { intent: "other", extractions: [] };
96
+ }
97
+ }
98
+ function parseExtractionResponse(response) {
99
+ const result = {
100
+ intent: "other",
101
+ extractions: []
102
+ };
103
+ try {
104
+ const parsed = parseKeyValueXml(response);
105
+ if (parsed) {
106
+ const intentStr = parsed.intent?.toLowerCase() ?? "other";
107
+ result.intent = isValidIntent(intentStr) ? intentStr : "other";
108
+ if (parsed.extractions) {
109
+ const fields = Array.isArray(parsed.extractions) ? parsed.extractions : parsed.extractions.field ? Array.isArray(parsed.extractions.field) ? parsed.extractions.field : [parsed.extractions.field] : [];
110
+ for (const field of fields) {
111
+ if (field?.key) {
112
+ const extraction = {
113
+ field: String(field.key),
114
+ value: field.value ?? null,
115
+ confidence: parseFloat(String(field.confidence ?? "")) || 0.5,
116
+ reasoning: field.reasoning ? String(field.reasoning) : void 0,
117
+ isCorrection: field.is_correction === "true" || field.is_correction === true
118
+ };
119
+ result.extractions.push(extraction);
120
+ }
121
+ }
122
+ }
123
+ }
124
+ } catch (_error) {
125
+ const intentMatch = response.match(/<intent>([^<]+)<\/intent>/);
126
+ if (intentMatch) {
127
+ const intentStr = intentMatch[1].toLowerCase().trim();
128
+ result.intent = isValidIntent(intentStr) ? intentStr : "other";
129
+ }
130
+ const fieldMatches = response.matchAll(
131
+ /<field>\s*<key>([^<]+)<\/key>\s*<value>([^<]*)<\/value>\s*<confidence>([^<]+)<\/confidence>/g
132
+ );
133
+ for (const match of fieldMatches) {
134
+ result.extractions.push({
135
+ field: match[1].trim(),
136
+ value: match[2].trim(),
137
+ confidence: parseFloat(match[3]) || 0.5
138
+ });
139
+ }
140
+ }
141
+ return result;
142
+ }
143
+ function isValidIntent(str) {
144
+ const validIntents = [
145
+ "fill_form",
146
+ "submit",
147
+ "stash",
148
+ "restore",
149
+ "cancel",
150
+ "undo",
151
+ "skip",
152
+ "explain",
153
+ "example",
154
+ "progress",
155
+ "autofill",
156
+ "other"
157
+ ];
158
+ return validIntents.includes(str);
159
+ }
160
+ async function extractSingleField(runtime, text, control, debug, templateValues) {
161
+ const resolvedControl = templateValues ? resolveControlTemplates(control, templateValues) : control;
162
+ const handler = getTypeHandler(resolvedControl.type);
163
+ const typeHint = handler?.extractionPrompt || resolvedControl.type;
164
+ const prompt = `Extract the ${resolvedControl.label} (${typeHint}) from this message:
165
+
166
+ "${text}"
167
+
168
+ ${resolvedControl.description ? `Context: ${resolvedControl.description}` : ""}
169
+ ${resolvedControl.extractHints?.length ? `Look for: ${resolvedControl.extractHints.join(", ")}` : ""}
170
+ ${resolvedControl.options?.length ? `Valid options: ${resolvedControl.options.map((o) => o.value).join(", ")}` : ""}
171
+ ${resolvedControl.example ? `Example: ${resolvedControl.example}` : ""}
172
+
173
+ Respond using TOON like this:
174
+ found: true or false
175
+ value: extracted value or empty if not found
176
+ confidence: 0.0 to 1.0
177
+ reasoning: brief explanation
178
+
179
+ IMPORTANT: Your response must ONLY contain the TOON document above. No preamble or explanation.`;
180
+ try {
181
+ const response = await runtime.useModel(ModelType.TEXT_SMALL, {
182
+ prompt,
183
+ temperature: 0.1
184
+ });
185
+ const parsed = parseKeyValueXml(response);
186
+ const found = parsed?.found === true || parsed?.found === "true";
187
+ if (found) {
188
+ let value = parsed.value;
189
+ if (typeof value === "string") {
190
+ value = parseValue(value, resolvedControl);
191
+ }
192
+ const confidence = typeof parsed?.confidence === "number" ? parsed.confidence : parseFloat(String(parsed?.confidence ?? ""));
193
+ const result = {
194
+ field: resolvedControl.key,
195
+ value: value ?? null,
196
+ confidence: Number.isFinite(confidence) ? confidence : 0.5,
197
+ reasoning: parsed.reasoning ? String(parsed.reasoning) : void 0
198
+ };
199
+ if (debug) {
200
+ runtime.logger.debug("[FormExtraction] Single field extraction:", JSON.stringify(result));
201
+ }
202
+ return result;
203
+ }
204
+ return null;
205
+ } catch (error) {
206
+ runtime.logger.error("[FormExtraction] Single field extraction failed:", String(error));
207
+ return null;
208
+ }
209
+ }
210
+ async function detectCorrection(runtime, text, currentValues, controls, templateValues) {
211
+ const resolvedControls = templateValues ? controls.map((control) => resolveControlTemplates(control, templateValues)) : controls;
212
+ const currentValuesStr = resolvedControls.filter((c) => currentValues[c.key] !== void 0).map((c) => `- ${c.label}: ${currentValues[c.key]}`).join("\n");
213
+ if (!currentValuesStr) {
214
+ return [];
215
+ }
216
+ const prompt = `Is the user correcting any of these previously provided values?
217
+
218
+ Current values:
219
+ ${currentValuesStr}
220
+
221
+ User message:
222
+ "${text}"
223
+
224
+ If they are correcting a value, extract the new value. Otherwise respond with no corrections.
225
+
226
+ Respond using TOON like this:
227
+ has_correction: true or false
228
+ corrections[N]{field,old_value,new_value,confidence}:
229
+ field_label,previous value,corrected value,0.9
230
+
231
+ If no corrections:
232
+ has_correction: false
233
+
234
+ IMPORTANT: Your response must ONLY contain the TOON document above. No preamble or explanation.`;
235
+ try {
236
+ const response = await runtime.useModel(ModelType.TEXT_SMALL, {
237
+ prompt,
238
+ temperature: 0.1
239
+ });
240
+ const parsed = parseKeyValueXml(response);
241
+ const hasCorrection = parsed?.has_correction === true || parsed?.has_correction === "true";
242
+ if (parsed && hasCorrection && parsed.corrections) {
243
+ const corrections = [];
244
+ const correctionList = Array.isArray(parsed.corrections) ? parsed.corrections : parsed.corrections.correction ? Array.isArray(parsed.corrections.correction) ? parsed.corrections.correction : [parsed.corrections.correction] : [];
245
+ for (const correction of correctionList) {
246
+ const fieldName = correction.field ? String(correction.field) : "";
247
+ const control = resolvedControls.find(
248
+ (c) => c.label.toLowerCase() === fieldName.toLowerCase() || c.key.toLowerCase() === fieldName.toLowerCase()
249
+ );
250
+ if (control) {
251
+ let value = correction.new_value;
252
+ if (typeof value === "string") {
253
+ value = parseValue(value, control);
254
+ }
255
+ const confidence = typeof correction.confidence === "number" ? correction.confidence : parseFloat(String(correction.confidence ?? ""));
256
+ const extraction = {
257
+ field: control.key,
258
+ value: value ?? null,
259
+ confidence: Number.isFinite(confidence) ? confidence : 0.8,
260
+ isCorrection: true
261
+ };
262
+ corrections.push(extraction);
263
+ }
264
+ }
265
+ return corrections;
266
+ }
267
+ return [];
268
+ } catch (error) {
269
+ runtime.logger.error("[FormExtraction] Correction detection failed:", String(error));
270
+ return [];
271
+ }
272
+ }
273
+
274
+ // src/evaluators/extractor.ts
275
+ var formEvaluator = {
276
+ name: "form_evaluator",
277
+ description: "Extracts form fields and handles form intents from user messages",
278
+ similes: ["FORM_EXTRACTION", "FORM_HANDLER"],
279
+ examples: [],
280
+ // No examples needed for evaluators
281
+ /**
282
+ * Validate: Should this evaluator run?
283
+ *
284
+ * Only runs if there's an active form session OR stashed sessions
285
+ * (to handle restore intent).
286
+ *
287
+ * WHY check stashed:
288
+ * - User might say "resume my form"
289
+ * - Need to detect restore intent even without active session
290
+ * - Note: Actual restore is handled by FORM_RESTORE action
291
+ *
292
+ * @returns true if evaluator should run
293
+ */
294
+ validate: async (runtime, message, _state) => {
295
+ try {
296
+ const formService = runtime.getService("FORM");
297
+ if (!formService) return false;
298
+ const entityId = message.entityId;
299
+ const roomId = message.roomId;
300
+ if (!entityId || !roomId) return false;
301
+ const session = await formService.getActiveSession(entityId, roomId);
302
+ const stashed = await formService.getStashedSessions(entityId);
303
+ return session !== null || stashed.length > 0;
304
+ } catch (error) {
305
+ logger.error("[FormEvaluator] Validation error:", String(error));
306
+ return false;
307
+ }
308
+ },
309
+ /**
310
+ * Handler: Process the message and update form state.
311
+ *
312
+ * This is the main logic loop:
313
+ * 1. Try fast-path intent detection
314
+ * 2. Fall back to LLM if no match
315
+ * 3. Handle the detected intent
316
+ * 4. Process any field extractions
317
+ *
318
+ * @param runtime - Agent runtime for service access
319
+ * @param message - The user message to process
320
+ * @param state - Current agent state (optional)
321
+ */
322
+ handler: async (runtime, message, _state) => {
323
+ try {
324
+ const formService = runtime.getService("FORM");
325
+ if (!formService) return void 0;
326
+ const entityId = message.entityId;
327
+ const roomId = message.roomId;
328
+ const text = message.content?.text || "";
329
+ if (!entityId || !roomId) return void 0;
330
+ if (!text.trim()) return void 0;
331
+ let session = await formService.getActiveSession(entityId, roomId);
332
+ let intent = quickIntentDetect(text);
333
+ let extractions = [];
334
+ if (intent === "restore" && !session) {
335
+ logger.debug("[FormEvaluator] Restore intent detected, deferring to action");
336
+ return void 0;
337
+ }
338
+ if (!session) {
339
+ return void 0;
340
+ }
341
+ const form = formService.getForm(session.formId);
342
+ if (!form) {
343
+ logger.warn("[FormEvaluator] Form not found for session:", session.formId);
344
+ return void 0;
345
+ }
346
+ const templateValues = buildTemplateValues(session);
347
+ if (!intent) {
348
+ const result = await llmIntentAndExtract(
349
+ runtime,
350
+ text,
351
+ form,
352
+ form.controls,
353
+ templateValues
354
+ );
355
+ intent = result.intent;
356
+ extractions = result.extractions;
357
+ if (form.debug) {
358
+ logger.debug(
359
+ "[FormEvaluator] LLM extraction result:",
360
+ JSON.stringify({ intent, extractions })
361
+ );
362
+ }
363
+ }
364
+ switch (intent) {
365
+ // --- Lifecycle Intents ---
366
+ case "submit":
367
+ await handleSubmit(formService, session, entityId);
368
+ break;
369
+ case "stash":
370
+ await formService.stash(session.id, entityId);
371
+ break;
372
+ case "cancel":
373
+ await formService.cancel(session.id, entityId);
374
+ break;
375
+ // --- UX Intents ---
376
+ case "undo":
377
+ await handleUndo(formService, session, entityId, form);
378
+ break;
379
+ case "skip":
380
+ await handleSkip(formService, session, entityId, form);
381
+ break;
382
+ case "autofill":
383
+ await formService.applyAutofill(session);
384
+ break;
385
+ // --- Info Intents ---
386
+ // These don't change state - the provider gives context for response
387
+ case "explain":
388
+ case "example":
389
+ case "progress":
390
+ logger.debug(`[FormEvaluator] Info intent: ${intent}`);
391
+ break;
392
+ // --- Special Cases ---
393
+ case "restore":
394
+ logger.debug("[FormEvaluator] Restore intent - deferring to action");
395
+ break;
396
+ default:
397
+ await processExtractions(
398
+ runtime,
399
+ formService,
400
+ session,
401
+ form,
402
+ entityId,
403
+ extractions,
404
+ message.id
405
+ );
406
+ break;
407
+ }
408
+ session = await formService.getActiveSession(entityId, roomId);
409
+ if (session) {
410
+ session.lastMessageId = message.id;
411
+ await formService.saveSession(session);
412
+ }
413
+ } catch (error) {
414
+ logger.error("[FormEvaluator] Handler error:", String(error));
415
+ return void 0;
416
+ }
417
+ return void 0;
418
+ }
419
+ };
420
+ async function processExtractions(runtime, formService, session, form, entityId, extractions, messageId) {
421
+ const updatedParents = /* @__PURE__ */ new Set();
422
+ for (const extraction of extractions) {
423
+ if (extraction.field.includes(".")) {
424
+ const [parentKey, subKey] = extraction.field.split(".");
425
+ await formService.updateSubField(
426
+ session.id,
427
+ entityId,
428
+ parentKey,
429
+ subKey,
430
+ extraction.value,
431
+ extraction.confidence,
432
+ messageId
433
+ );
434
+ await emitEvent(runtime, "FORM_SUBFIELD_UPDATED", {
435
+ sessionId: session.id,
436
+ parentField: parentKey,
437
+ subField: subKey,
438
+ value: extraction.value,
439
+ confidence: extraction.confidence
440
+ });
441
+ updatedParents.add(parentKey);
442
+ if (form.debug) {
443
+ logger.debug(`[FormEvaluator] Updated subfield ${parentKey}.${subKey}`);
444
+ }
445
+ } else {
446
+ await formService.updateField(
447
+ session.id,
448
+ entityId,
449
+ extraction.field,
450
+ extraction.value,
451
+ extraction.confidence,
452
+ extraction.isCorrection ? "correction" : "extraction",
453
+ messageId
454
+ );
455
+ await emitEvent(runtime, "FORM_FIELD_EXTRACTED", {
456
+ sessionId: session.id,
457
+ field: extraction.field,
458
+ value: extraction.value,
459
+ confidence: extraction.confidence
460
+ });
461
+ if (form.debug) {
462
+ logger.debug(`[FormEvaluator] Updated field ${extraction.field}`);
463
+ }
464
+ }
465
+ }
466
+ for (const parentKey of updatedParents) {
467
+ await checkAndActivateExternalField(runtime, formService, session, form, entityId, parentKey);
468
+ }
469
+ }
470
+ async function checkAndActivateExternalField(runtime, formService, session, form, entityId, field) {
471
+ const freshSession = await formService.getActiveSession(entityId, session.roomId);
472
+ if (!freshSession) return;
473
+ if (!formService.isExternalType(form.controls.find((c) => c.key === field)?.type || "")) {
474
+ return;
475
+ }
476
+ if (!formService.areSubFieldsFilled(freshSession, field)) {
477
+ return;
478
+ }
479
+ const subValues = formService.getSubFieldValues(freshSession, field);
480
+ await emitEvent(runtime, "FORM_SUBCONTROLS_FILLED", {
481
+ sessionId: session.id,
482
+ field,
483
+ subValues
484
+ });
485
+ logger.debug(`[FormEvaluator] All subcontrols filled for ${field}, activating...`);
486
+ try {
487
+ const activation = await formService.activateExternalField(session.id, entityId, field);
488
+ const activationPayload = JSON.parse(JSON.stringify(activation));
489
+ await emitEvent(runtime, "FORM_EXTERNAL_ACTIVATED", {
490
+ sessionId: session.id,
491
+ field,
492
+ activation: activationPayload
493
+ });
494
+ logger.info(`[FormEvaluator] Activated external field ${field}: ${activation.instructions}`);
495
+ } catch (error) {
496
+ logger.error(`[FormEvaluator] Failed to activate external field ${field}:`, String(error));
497
+ }
498
+ }
499
+ async function emitEvent(runtime, eventType, payload) {
500
+ try {
501
+ if (typeof runtime.emitEvent === "function") {
502
+ const eventPayload = { runtime, ...payload };
503
+ await runtime.emitEvent(eventType, eventPayload);
504
+ }
505
+ } catch (error) {
506
+ logger.debug(`[FormEvaluator] Event emission (${eventType}):`, String(error));
507
+ }
508
+ }
509
+ async function handleSubmit(formService, session, entityId) {
510
+ try {
511
+ await formService.submit(session.id, entityId);
512
+ } catch (error) {
513
+ logger.debug("[FormEvaluator] Submit failed:", String(error));
514
+ }
515
+ }
516
+ async function handleUndo(formService, session, entityId, form) {
517
+ if (!form.ux?.allowUndo) {
518
+ return;
519
+ }
520
+ const result = await formService.undoLastChange(session.id, entityId);
521
+ if (result) {
522
+ logger.debug("[FormEvaluator] Undid field:", result.field);
523
+ }
524
+ }
525
+ async function handleSkip(formService, session, entityId, form) {
526
+ if (!form.ux?.allowSkip) {
527
+ return;
528
+ }
529
+ if (session.lastAskedField) {
530
+ const skipped = await formService.skipField(session.id, entityId, session.lastAskedField);
531
+ if (skipped) {
532
+ logger.debug("[FormEvaluator] Skipped field:", session.lastAskedField);
533
+ }
534
+ }
535
+ }
536
+ var extractor_default = formEvaluator;
537
+
538
+ export {
539
+ llmIntentAndExtract,
540
+ extractSingleField,
541
+ detectCorrection,
542
+ formEvaluator,
543
+ extractor_default
544
+ };
@@ -0,0 +1,64 @@
1
+ // src/intent.ts
2
+ function quickIntentDetect(text) {
3
+ const lower = text.toLowerCase().trim();
4
+ if (lower.length < 2) {
5
+ return null;
6
+ }
7
+ if (/\b(resume|continue|pick up where|go back to|get back to)\b/.test(lower)) {
8
+ return "restore";
9
+ }
10
+ if (/\b(submit|done|finish|send it|that'?s all|i'?m done|complete|all set)\b/.test(lower)) {
11
+ return "submit";
12
+ }
13
+ if (/\b(save|stash|later|hold on|pause|save for later|come back|save this)\b/.test(lower)) {
14
+ if (!/\b(save and submit|save and send)\b/.test(lower)) {
15
+ return "stash";
16
+ }
17
+ }
18
+ if (/\b(cancel|abort|nevermind|never mind|forget it|stop|quit|exit)\b/.test(lower)) {
19
+ return "cancel";
20
+ }
21
+ if (/\b(undo|go back|wait no|change that|oops|that'?s wrong|wrong|not right)\b/.test(lower)) {
22
+ return "undo";
23
+ }
24
+ if (/\b(skip|pass|don'?t know|next one|next|don'?t have|no idea)\b/.test(lower)) {
25
+ if (!/\bskip to\b/.test(lower)) {
26
+ return "skip";
27
+ }
28
+ }
29
+ if (/\b(why|what'?s that for|explain|what do you mean|what is|purpose|reason)\b\??$/i.test(lower)) {
30
+ return "explain";
31
+ }
32
+ if (/^why\??$/i.test(lower)) {
33
+ return "explain";
34
+ }
35
+ if (/\b(example|like what|show me|such as|for instance|sample)\b\??$/i.test(lower)) {
36
+ return "example";
37
+ }
38
+ if (/^(example|e\.?g\.?)\??$/i.test(lower)) {
39
+ return "example";
40
+ }
41
+ if (/\b(how far|how many left|progress|status|how much more|where are we)\b/.test(lower)) {
42
+ return "progress";
43
+ }
44
+ if (/\b(same as|last time|use my usual|like before|previous|from before)\b/.test(lower)) {
45
+ return "autofill";
46
+ }
47
+ return null;
48
+ }
49
+ function isLifecycleIntent(intent) {
50
+ return ["submit", "stash", "restore", "cancel"].includes(intent);
51
+ }
52
+ function isUXIntent(intent) {
53
+ return ["undo", "skip", "explain", "example", "progress", "autofill"].includes(intent);
54
+ }
55
+ function hasDataToExtract(intent) {
56
+ return intent === "fill_form" || intent === "other";
57
+ }
58
+
59
+ export {
60
+ quickIntentDetect,
61
+ isLifecycleIntent,
62
+ isUXIntent,
63
+ hasDataToExtract
64
+ };
@@ -0,0 +1,9 @@
1
+ import {
2
+ context_default,
3
+ formContextProvider
4
+ } from "./chunk-4B5QLNVA.js";
5
+ import "./chunk-WY4WK3HD.js";
6
+ export {
7
+ context_default as default,
8
+ formContextProvider
9
+ };
@@ -0,0 +1,11 @@
1
+ import {
2
+ extractor_default,
3
+ formEvaluator
4
+ } from "./chunk-XHECCAUT.js";
5
+ import "./chunk-ARWZY3NX.js";
6
+ import "./chunk-YTWANJ3R.js";
7
+ import "./chunk-WY4WK3HD.js";
8
+ export {
9
+ extractor_default as default,
10
+ formEvaluator
11
+ };