@elizaos/plugin-form 2.0.0-alpha.3 → 2.0.0-alpha.4
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/index.d.ts +2 -174
- package/dist/{node/index.node.js → index.js} +463 -373
- package/dist/index.js.map +30 -0
- package/package.json +4 -2
- package/dist/actions/restore.d.ts +0 -62
- package/dist/actions/restore.d.ts.map +0 -1
- package/dist/builder.d.ts +0 -320
- package/dist/builder.d.ts.map +0 -1
- package/dist/builtins.d.ts +0 -128
- package/dist/builtins.d.ts.map +0 -1
- package/dist/defaults.d.ts +0 -95
- package/dist/defaults.d.ts.map +0 -1
- package/dist/evaluators/extractor.d.ts +0 -91
- package/dist/evaluators/extractor.d.ts.map +0 -1
- package/dist/extraction.d.ts +0 -105
- package/dist/extraction.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/intent.d.ts +0 -116
- package/dist/intent.d.ts.map +0 -1
- package/dist/node/index.node.js.map +0 -29
- package/dist/providers/context.d.ts +0 -69
- package/dist/providers/context.d.ts.map +0 -1
- package/dist/service.d.ts +0 -407
- package/dist/service.d.ts.map +0 -1
- package/dist/storage.d.ts +0 -228
- package/dist/storage.d.ts.map +0 -1
- package/dist/tasks/nudge.d.ts +0 -89
- package/dist/tasks/nudge.d.ts.map +0 -1
- package/dist/template.d.ts +0 -10
- package/dist/template.d.ts.map +0 -1
- package/dist/ttl.d.ts +0 -144
- package/dist/ttl.d.ts.map +0 -1
- package/dist/types.d.ts +0 -1186
- package/dist/types.d.ts.map +0 -1
- package/dist/validation.d.ts +0 -177
- package/dist/validation.d.ts.map +0 -1
|
@@ -105,7 +105,7 @@ var init_builtins = __esm(() => {
|
|
|
105
105
|
return { valid: true };
|
|
106
106
|
}
|
|
107
107
|
const num = typeof value === "number" ? value : parseFloat(String(value));
|
|
108
|
-
if (isNaN(num)) {
|
|
108
|
+
if (Number.isNaN(num)) {
|
|
109
109
|
return { valid: false, error: "Must be a valid number" };
|
|
110
110
|
}
|
|
111
111
|
if (control.min !== undefined && num < control.min) {
|
|
@@ -124,7 +124,7 @@ var init_builtins = __esm(() => {
|
|
|
124
124
|
if (value === null || value === undefined)
|
|
125
125
|
return "";
|
|
126
126
|
const num = typeof value === "number" ? value : parseFloat(String(value));
|
|
127
|
-
if (isNaN(num))
|
|
127
|
+
if (Number.isNaN(num))
|
|
128
128
|
return String(value);
|
|
129
129
|
return num.toLocaleString();
|
|
130
130
|
},
|
|
@@ -218,14 +218,14 @@ var init_builtins = __esm(() => {
|
|
|
218
218
|
return { valid: false, error: "Must be in YYYY-MM-DD format" };
|
|
219
219
|
}
|
|
220
220
|
const date = new Date(str);
|
|
221
|
-
if (isNaN(date.getTime())) {
|
|
221
|
+
if (Number.isNaN(date.getTime())) {
|
|
222
222
|
return { valid: false, error: "Invalid date" };
|
|
223
223
|
}
|
|
224
224
|
return { valid: true };
|
|
225
225
|
},
|
|
226
226
|
parse: (value) => {
|
|
227
227
|
const date = new Date(value);
|
|
228
|
-
if (!isNaN(date.getTime())) {
|
|
228
|
+
if (!Number.isNaN(date.getTime())) {
|
|
229
229
|
return date.toISOString().split("T")[0];
|
|
230
230
|
}
|
|
231
231
|
return value.trim();
|
|
@@ -234,7 +234,7 @@ var init_builtins = __esm(() => {
|
|
|
234
234
|
if (!value)
|
|
235
235
|
return "";
|
|
236
236
|
const date = new Date(String(value));
|
|
237
|
-
if (isNaN(date.getTime()))
|
|
237
|
+
if (Number.isNaN(date.getTime()))
|
|
238
238
|
return String(value);
|
|
239
239
|
return date.toLocaleDateString();
|
|
240
240
|
},
|
|
@@ -243,7 +243,7 @@ var init_builtins = __esm(() => {
|
|
|
243
243
|
fileType = {
|
|
244
244
|
id: "file",
|
|
245
245
|
builtin: true,
|
|
246
|
-
validate: (value,
|
|
246
|
+
validate: (value, _control) => {
|
|
247
247
|
if (value === null || value === undefined) {
|
|
248
248
|
return { valid: true };
|
|
249
249
|
}
|
|
@@ -319,7 +319,6 @@ function validateField(value, control) {
|
|
|
319
319
|
return validateSelect(value, control);
|
|
320
320
|
case "file":
|
|
321
321
|
return validateFile(value, control);
|
|
322
|
-
case "text":
|
|
323
322
|
default:
|
|
324
323
|
return validateText(value, control);
|
|
325
324
|
}
|
|
@@ -370,7 +369,7 @@ function validateEmail(value, control) {
|
|
|
370
369
|
}
|
|
371
370
|
function validateNumber(value, control) {
|
|
372
371
|
const numValue = typeof value === "number" ? value : parseFloat(String(value).replace(/[,$]/g, ""));
|
|
373
|
-
if (isNaN(numValue)) {
|
|
372
|
+
if (Number.isNaN(numValue)) {
|
|
374
373
|
return {
|
|
375
374
|
valid: false,
|
|
376
375
|
error: `${control.label || control.key} must be a number`
|
|
@@ -414,7 +413,7 @@ function validateDate(value, control) {
|
|
|
414
413
|
error: `${control.label || control.key} must be a valid date`
|
|
415
414
|
};
|
|
416
415
|
}
|
|
417
|
-
if (isNaN(dateValue.getTime())) {
|
|
416
|
+
if (Number.isNaN(dateValue.getTime())) {
|
|
418
417
|
return {
|
|
419
418
|
valid: false,
|
|
420
419
|
error: `${control.label || control.key} must be a valid date`
|
|
@@ -515,9 +514,6 @@ function parseValue(value, control) {
|
|
|
515
514
|
const timestamp = Date.parse(value);
|
|
516
515
|
return Number.isFinite(timestamp) ? new Date(timestamp).toISOString() : value;
|
|
517
516
|
}
|
|
518
|
-
case "text":
|
|
519
|
-
case "email":
|
|
520
|
-
case "select":
|
|
521
517
|
default:
|
|
522
518
|
return value;
|
|
523
519
|
}
|
|
@@ -616,20 +612,13 @@ function isLifecycleIntent(intent) {
|
|
|
616
612
|
return ["submit", "stash", "restore", "cancel"].includes(intent);
|
|
617
613
|
}
|
|
618
614
|
function isUXIntent(intent) {
|
|
619
|
-
return [
|
|
620
|
-
"undo",
|
|
621
|
-
"skip",
|
|
622
|
-
"explain",
|
|
623
|
-
"example",
|
|
624
|
-
"progress",
|
|
625
|
-
"autofill"
|
|
626
|
-
].includes(intent);
|
|
615
|
+
return ["undo", "skip", "explain", "example", "progress", "autofill"].includes(intent);
|
|
627
616
|
}
|
|
628
617
|
function hasDataToExtract(intent) {
|
|
629
618
|
return intent === "fill_form" || intent === "other";
|
|
630
619
|
}
|
|
631
620
|
|
|
632
|
-
//
|
|
621
|
+
// node_modules/uuid/dist-node/stringify.js
|
|
633
622
|
function unsafeStringify(arr, offset = 0) {
|
|
634
623
|
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
635
624
|
}
|
|
@@ -641,8 +630,8 @@ var init_stringify = __esm(() => {
|
|
|
641
630
|
}
|
|
642
631
|
});
|
|
643
632
|
|
|
644
|
-
//
|
|
645
|
-
import { randomFillSync } from "crypto";
|
|
633
|
+
// node_modules/uuid/dist-node/rng.js
|
|
634
|
+
import { randomFillSync } from "node:crypto";
|
|
646
635
|
function rng() {
|
|
647
636
|
if (poolPtr > rnds8Pool.length - 16) {
|
|
648
637
|
randomFillSync(rnds8Pool);
|
|
@@ -656,18 +645,15 @@ var init_rng = __esm(() => {
|
|
|
656
645
|
poolPtr = rnds8Pool.length;
|
|
657
646
|
});
|
|
658
647
|
|
|
659
|
-
//
|
|
660
|
-
import { randomUUID } from "crypto";
|
|
648
|
+
// node_modules/uuid/dist-node/native.js
|
|
649
|
+
import { randomUUID } from "node:crypto";
|
|
661
650
|
var native_default;
|
|
662
651
|
var init_native = __esm(() => {
|
|
663
652
|
native_default = { randomUUID };
|
|
664
653
|
});
|
|
665
654
|
|
|
666
|
-
//
|
|
667
|
-
function
|
|
668
|
-
if (native_default.randomUUID && !buf && !options) {
|
|
669
|
-
return native_default.randomUUID();
|
|
670
|
-
}
|
|
655
|
+
// node_modules/uuid/dist-node/v4.js
|
|
656
|
+
function _v4(options, buf, offset) {
|
|
671
657
|
options = options || {};
|
|
672
658
|
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
673
659
|
if (rnds.length < 16) {
|
|
@@ -687,6 +673,12 @@ function v4(options, buf, offset) {
|
|
|
687
673
|
}
|
|
688
674
|
return unsafeStringify(rnds);
|
|
689
675
|
}
|
|
676
|
+
function v4(options, buf, offset) {
|
|
677
|
+
if (native_default.randomUUID && !buf && !options) {
|
|
678
|
+
return native_default.randomUUID();
|
|
679
|
+
}
|
|
680
|
+
return _v4(options, buf, offset);
|
|
681
|
+
}
|
|
690
682
|
var v4_default;
|
|
691
683
|
var init_v4 = __esm(() => {
|
|
692
684
|
init_native();
|
|
@@ -695,8 +687,8 @@ var init_v4 = __esm(() => {
|
|
|
695
687
|
v4_default = v4;
|
|
696
688
|
});
|
|
697
689
|
|
|
698
|
-
//
|
|
699
|
-
var
|
|
690
|
+
// node_modules/uuid/dist-node/index.js
|
|
691
|
+
var init_dist_node = __esm(() => {
|
|
700
692
|
init_v4();
|
|
701
693
|
});
|
|
702
694
|
|
|
@@ -868,7 +860,7 @@ var isRecord = (value) => typeof value === "object" && value !== null && !Array.
|
|
|
868
860
|
return typeof data.formId === "string" && typeof data.updatedAt === "number" && typeof data.values === "object";
|
|
869
861
|
};
|
|
870
862
|
var init_storage = __esm(() => {
|
|
871
|
-
|
|
863
|
+
init_dist_node();
|
|
872
864
|
init_types();
|
|
873
865
|
});
|
|
874
866
|
|
|
@@ -1037,7 +1029,7 @@ function parseExtractionResponse(response) {
|
|
|
1037
1029
|
}
|
|
1038
1030
|
}
|
|
1039
1031
|
}
|
|
1040
|
-
} catch (
|
|
1032
|
+
} catch (_error) {
|
|
1041
1033
|
const intentMatch = response.match(/<intent>([^<]+)<\/intent>/);
|
|
1042
1034
|
if (intentMatch) {
|
|
1043
1035
|
const intentStr = intentMatch[1].toLowerCase().trim();
|
|
@@ -1187,9 +1179,8 @@ Respond in XML:
|
|
|
1187
1179
|
}
|
|
1188
1180
|
}
|
|
1189
1181
|
var init_extraction = __esm(() => {
|
|
1190
|
-
init_validation();
|
|
1191
|
-
init_validation();
|
|
1192
1182
|
init_template();
|
|
1183
|
+
init_validation();
|
|
1193
1184
|
});
|
|
1194
1185
|
|
|
1195
1186
|
// src/service.ts
|
|
@@ -1198,19 +1189,19 @@ __export(exports_service, {
|
|
|
1198
1189
|
FormService: () => FormService
|
|
1199
1190
|
});
|
|
1200
1191
|
import {
|
|
1201
|
-
|
|
1202
|
-
|
|
1192
|
+
logger,
|
|
1193
|
+
Service
|
|
1203
1194
|
} from "@elizaos/core";
|
|
1204
1195
|
function prettify3(key) {
|
|
1205
1196
|
return key.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
1206
1197
|
}
|
|
1207
1198
|
var FormService;
|
|
1208
1199
|
var init_service = __esm(() => {
|
|
1209
|
-
|
|
1210
|
-
|
|
1200
|
+
init_dist_node();
|
|
1201
|
+
init_builtins();
|
|
1211
1202
|
init_storage();
|
|
1203
|
+
init_types();
|
|
1212
1204
|
init_validation();
|
|
1213
|
-
init_builtins();
|
|
1214
1205
|
FormService = class FormService extends Service {
|
|
1215
1206
|
static serviceType = "FORM";
|
|
1216
1207
|
capabilityDescription = "Manages conversational forms for data collection";
|
|
@@ -1251,6 +1242,13 @@ var init_service = __esm(() => {
|
|
|
1251
1242
|
listForms() {
|
|
1252
1243
|
return Array.from(this.forms.values());
|
|
1253
1244
|
}
|
|
1245
|
+
registerType(type, handler) {
|
|
1246
|
+
registerTypeHandler(type, handler);
|
|
1247
|
+
logger.debug(`[FormService] Registered type handler: ${type}`);
|
|
1248
|
+
}
|
|
1249
|
+
getTypeHandler(type) {
|
|
1250
|
+
return getTypeHandler(type);
|
|
1251
|
+
}
|
|
1254
1252
|
registerControlType(type, options) {
|
|
1255
1253
|
const existing = this.controlTypes.get(type.id);
|
|
1256
1254
|
if (existing) {
|
|
@@ -1679,7 +1677,7 @@ var init_service = __esm(() => {
|
|
|
1679
1677
|
value,
|
|
1680
1678
|
externalData
|
|
1681
1679
|
});
|
|
1682
|
-
} catch (
|
|
1680
|
+
} catch (_error) {
|
|
1683
1681
|
logger.debug(`[FormService] No event handler for FORM_FIELD_CONFIRMED`);
|
|
1684
1682
|
}
|
|
1685
1683
|
logger.info(`[FormService] Confirmed external field ${field}`);
|
|
@@ -1722,7 +1720,7 @@ var init_service = __esm(() => {
|
|
|
1722
1720
|
field,
|
|
1723
1721
|
reason
|
|
1724
1722
|
});
|
|
1725
|
-
} catch (
|
|
1723
|
+
} catch (_error) {
|
|
1726
1724
|
logger.debug(`[FormService] No event handler for FORM_FIELD_CANCELLED`);
|
|
1727
1725
|
}
|
|
1728
1726
|
logger.info(`[FormService] Cancelled external field ${field}: ${reason}`);
|
|
@@ -2039,218 +2037,159 @@ var init_service = __esm(() => {
|
|
|
2039
2037
|
};
|
|
2040
2038
|
});
|
|
2041
2039
|
|
|
2042
|
-
// src/
|
|
2043
|
-
var
|
|
2044
|
-
__export(
|
|
2045
|
-
|
|
2046
|
-
default: () =>
|
|
2040
|
+
// src/actions/restore.ts
|
|
2041
|
+
var exports_restore = {};
|
|
2042
|
+
__export(exports_restore, {
|
|
2043
|
+
formRestoreAction: () => formRestoreAction,
|
|
2044
|
+
default: () => restore_default
|
|
2047
2045
|
});
|
|
2048
|
-
import {
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2046
|
+
import {
|
|
2047
|
+
logger as logger2
|
|
2048
|
+
} from "@elizaos/core";
|
|
2049
|
+
var formRestoreAction, restore_default;
|
|
2050
|
+
var init_restore = __esm(() => {
|
|
2051
|
+
formRestoreAction = {
|
|
2052
|
+
name: "FORM_RESTORE",
|
|
2053
|
+
similes: ["RESUME_FORM", "CONTINUE_FORM"],
|
|
2054
|
+
description: "Restore a previously stashed form session",
|
|
2055
|
+
validate: async (runtime, message, _state) => {
|
|
2056
2056
|
try {
|
|
2057
|
+
const text = message.content?.text || "";
|
|
2058
|
+
const intent = quickIntentDetect(text);
|
|
2059
|
+
if (intent !== "restore") {
|
|
2060
|
+
return false;
|
|
2061
|
+
}
|
|
2057
2062
|
const formService = runtime.getService("FORM");
|
|
2058
2063
|
if (!formService) {
|
|
2059
|
-
return
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
+
return false;
|
|
2065
|
+
}
|
|
2066
|
+
const entityId = message.entityId;
|
|
2067
|
+
if (!entityId)
|
|
2068
|
+
return false;
|
|
2069
|
+
const stashed = await formService.getStashedSessions(entityId);
|
|
2070
|
+
return stashed.length > 0;
|
|
2071
|
+
} catch (error) {
|
|
2072
|
+
logger2.error("[FormRestoreAction] Validation error:", String(error));
|
|
2073
|
+
return false;
|
|
2074
|
+
}
|
|
2075
|
+
},
|
|
2076
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
2077
|
+
try {
|
|
2078
|
+
const formService = runtime.getService("FORM");
|
|
2079
|
+
if (!formService) {
|
|
2080
|
+
await callback?.({
|
|
2081
|
+
text: "Sorry, I couldn't find the form service."
|
|
2082
|
+
});
|
|
2083
|
+
return { success: false };
|
|
2064
2084
|
}
|
|
2065
2085
|
const entityId = message.entityId;
|
|
2066
2086
|
const roomId = message.roomId;
|
|
2067
2087
|
if (!entityId || !roomId) {
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2088
|
+
await callback?.({
|
|
2089
|
+
text: "Sorry, I couldn't identify you."
|
|
2090
|
+
});
|
|
2091
|
+
return { success: false };
|
|
2092
|
+
}
|
|
2093
|
+
const existing = await formService.getActiveSession(entityId, roomId);
|
|
2094
|
+
if (existing) {
|
|
2095
|
+
const form2 = formService.getForm(existing.formId);
|
|
2096
|
+
await callback?.({
|
|
2097
|
+
text: `You already have an active form: "${form2?.name || existing.formId}". Would you like to continue with that one, or should I save it and restore your other form?`
|
|
2098
|
+
});
|
|
2099
|
+
return { success: false };
|
|
2073
2100
|
}
|
|
2074
|
-
const session = await formService.getActiveSession(entityId, roomId);
|
|
2075
2101
|
const stashed = await formService.getStashedSessions(entityId);
|
|
2076
|
-
if (
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
};
|
|
2102
|
+
if (stashed.length === 0) {
|
|
2103
|
+
await callback?.({
|
|
2104
|
+
text: "You don't have any saved forms to resume."
|
|
2105
|
+
});
|
|
2106
|
+
return { success: false };
|
|
2082
2107
|
}
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
...contextState,
|
|
2092
|
-
filledFields: contextState.filledFields.map((field) => ({
|
|
2093
|
-
...field,
|
|
2094
|
-
label: resolveText(field.label) ?? field.label
|
|
2095
|
-
})),
|
|
2096
|
-
missingRequired: contextState.missingRequired.map((field) => ({
|
|
2097
|
-
...field,
|
|
2098
|
-
label: resolveText(field.label) ?? field.label,
|
|
2099
|
-
description: resolveText(field.description),
|
|
2100
|
-
askPrompt: resolveText(field.askPrompt)
|
|
2101
|
-
})),
|
|
2102
|
-
uncertainFields: contextState.uncertainFields.map((field) => ({
|
|
2103
|
-
...field,
|
|
2104
|
-
label: resolveText(field.label) ?? field.label
|
|
2105
|
-
})),
|
|
2106
|
-
nextField: contextState.nextField ? resolveControlTemplates(contextState.nextField, templateValues) : null
|
|
2107
|
-
};
|
|
2108
|
-
contextText = `# Active Form: ${form?.name || session.formId}
|
|
2109
|
-
|
|
2110
|
-
`;
|
|
2111
|
-
contextText += `Progress: ${contextState.progress}%
|
|
2108
|
+
const sessionToRestore = stashed.sort((a, b) => b.updatedAt - a.updatedAt)[0];
|
|
2109
|
+
const session = await formService.restore(sessionToRestore.id, entityId);
|
|
2110
|
+
const form = formService.getForm(session.formId);
|
|
2111
|
+
const context = formService.getSessionContext(session);
|
|
2112
|
+
let responseText = `I've restored your "${form?.name || session.formId}" form. `;
|
|
2113
|
+
responseText += `You're ${context.progress}% complete. `;
|
|
2114
|
+
if (context.filledFields.length > 0) {
|
|
2115
|
+
responseText += `
|
|
2112
2116
|
|
|
2117
|
+
Here's what I have so far:
|
|
2113
2118
|
`;
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
`;
|
|
2117
|
-
for (const field of contextState.filledFields) {
|
|
2118
|
-
contextText += `- ${field.label}: ${field.displayValue}
|
|
2119
|
-
`;
|
|
2120
|
-
}
|
|
2121
|
-
contextText += `
|
|
2119
|
+
for (const field of context.filledFields) {
|
|
2120
|
+
responseText += `• ${field.label}: ${field.displayValue}
|
|
2122
2121
|
`;
|
|
2123
2122
|
}
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
`;
|
|
2130
|
-
}
|
|
2131
|
-
contextText += `
|
|
2132
|
-
`;
|
|
2123
|
+
}
|
|
2124
|
+
if (context.nextField) {
|
|
2125
|
+
responseText += `
|
|
2126
|
+
Let's continue with ${context.nextField.label}.`;
|
|
2127
|
+
if (context.nextField.askPrompt) {
|
|
2128
|
+
responseText += ` ${context.nextField.askPrompt}`;
|
|
2133
2129
|
}
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2130
|
+
} else if (context.status === "ready") {
|
|
2131
|
+
responseText += `
|
|
2132
|
+
Everything looks complete! Ready to submit?`;
|
|
2133
|
+
}
|
|
2134
|
+
await callback?.({
|
|
2135
|
+
text: responseText
|
|
2136
|
+
});
|
|
2137
|
+
return {
|
|
2138
|
+
success: true,
|
|
2139
|
+
data: {
|
|
2140
|
+
sessionId: session.id,
|
|
2141
|
+
formId: session.formId,
|
|
2142
|
+
progress: context.progress
|
|
2143
2143
|
}
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2144
|
+
};
|
|
2145
|
+
} catch (error) {
|
|
2146
|
+
logger2.error("[FormRestoreAction] Handler error:", String(error));
|
|
2147
|
+
await callback?.({
|
|
2148
|
+
text: "Sorry, I couldn't restore your form. Please try again."
|
|
2149
|
+
});
|
|
2150
|
+
return { success: false };
|
|
2151
|
+
}
|
|
2152
|
+
},
|
|
2153
|
+
examples: [
|
|
2154
|
+
[
|
|
2155
|
+
{
|
|
2156
|
+
name: "{{user1}}",
|
|
2157
|
+
content: { text: "Resume my form" }
|
|
2158
|
+
},
|
|
2159
|
+
{
|
|
2160
|
+
name: "{{agentName}}",
|
|
2161
|
+
content: {
|
|
2162
|
+
text: "I've restored your form. Let's continue where you left off."
|
|
2160
2163
|
}
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
contextText += `Ask user to confirm: "I understood your ${uncertain.label} as '${uncertain.value}'. Is that correct?"
|
|
2173
|
-
`;
|
|
2174
|
-
} else if (contextState.nextField) {
|
|
2175
|
-
const next = contextState.nextField;
|
|
2176
|
-
const prompt = next.askPrompt || `Ask for their ${next.label}`;
|
|
2177
|
-
contextText += `Next: ${prompt}
|
|
2178
|
-
`;
|
|
2179
|
-
if (next.example) {
|
|
2180
|
-
contextText += `Example: "${next.example}"
|
|
2181
|
-
`;
|
|
2182
|
-
}
|
|
2183
|
-
} else if (contextState.status === "ready") {
|
|
2184
|
-
contextText += `All fields collected! Nudge user to submit: "I have everything I need. Ready to submit?"
|
|
2185
|
-
`;
|
|
2164
|
+
}
|
|
2165
|
+
],
|
|
2166
|
+
[
|
|
2167
|
+
{
|
|
2168
|
+
name: "{{user1}}",
|
|
2169
|
+
content: { text: "Continue with my registration" }
|
|
2170
|
+
},
|
|
2171
|
+
{
|
|
2172
|
+
name: "{{agentName}}",
|
|
2173
|
+
content: {
|
|
2174
|
+
text: "I've restored your Registration form. You're 60% complete."
|
|
2186
2175
|
}
|
|
2187
|
-
contextText += `
|
|
2188
|
-
`;
|
|
2189
|
-
contextText += `## User Can Say
|
|
2190
|
-
`;
|
|
2191
|
-
contextText += `- Provide information for any field
|
|
2192
|
-
`;
|
|
2193
|
-
contextText += `- "undo" or "go back" to revert last change
|
|
2194
|
-
`;
|
|
2195
|
-
contextText += `- "skip" to skip optional fields
|
|
2196
|
-
`;
|
|
2197
|
-
contextText += `- "why?" to get explanation about a field
|
|
2198
|
-
`;
|
|
2199
|
-
contextText += `- "how far?" to check progress
|
|
2200
|
-
`;
|
|
2201
|
-
contextText += `- "submit" or "done" when ready
|
|
2202
|
-
`;
|
|
2203
|
-
contextText += `- "save for later" to stash the form
|
|
2204
|
-
`;
|
|
2205
|
-
contextText += `- "cancel" to abandon the form
|
|
2206
|
-
`;
|
|
2207
|
-
} else {
|
|
2208
|
-
contextState = {
|
|
2209
|
-
hasActiveForm: false,
|
|
2210
|
-
progress: 0,
|
|
2211
|
-
filledFields: [],
|
|
2212
|
-
missingRequired: [],
|
|
2213
|
-
uncertainFields: [],
|
|
2214
|
-
nextField: null,
|
|
2215
|
-
stashedCount: stashed.length,
|
|
2216
|
-
pendingExternalFields: []
|
|
2217
|
-
};
|
|
2218
2176
|
}
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
`;
|
|
2177
|
+
],
|
|
2178
|
+
[
|
|
2179
|
+
{
|
|
2180
|
+
name: "{{user1}}",
|
|
2181
|
+
content: { text: "Pick up where I left off" }
|
|
2182
|
+
},
|
|
2183
|
+
{
|
|
2184
|
+
name: "{{agentName}}",
|
|
2185
|
+
content: {
|
|
2186
|
+
text: "I've restored your form. Here's what you have so far..."
|
|
2230
2187
|
}
|
|
2231
2188
|
}
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
values: {
|
|
2235
|
-
formContext: contextText,
|
|
2236
|
-
hasActiveForm: String(contextState.hasActiveForm),
|
|
2237
|
-
formProgress: String(contextState.progress),
|
|
2238
|
-
formStatus: contextState.status || "",
|
|
2239
|
-
stashedCount: String(stashed.length)
|
|
2240
|
-
},
|
|
2241
|
-
text: contextText
|
|
2242
|
-
};
|
|
2243
|
-
} catch (error) {
|
|
2244
|
-
logger2.error("[FormContextProvider] Error:", String(error));
|
|
2245
|
-
return {
|
|
2246
|
-
data: { hasActiveForm: false, error: true },
|
|
2247
|
-
values: { formContext: "Error loading form context." },
|
|
2248
|
-
text: "Error loading form context."
|
|
2249
|
-
};
|
|
2250
|
-
}
|
|
2251
|
-
}
|
|
2189
|
+
]
|
|
2190
|
+
]
|
|
2252
2191
|
};
|
|
2253
|
-
|
|
2192
|
+
restore_default = formRestoreAction;
|
|
2254
2193
|
});
|
|
2255
2194
|
|
|
2256
2195
|
// src/evaluators/extractor.ts
|
|
@@ -2387,7 +2326,7 @@ var init_extractor = __esm(() => {
|
|
|
2387
2326
|
return false;
|
|
2388
2327
|
}
|
|
2389
2328
|
},
|
|
2390
|
-
handler: async (runtime, message,
|
|
2329
|
+
handler: async (runtime, message, _state) => {
|
|
2391
2330
|
try {
|
|
2392
2331
|
const formService = runtime.getService("FORM");
|
|
2393
2332
|
if (!formService)
|
|
@@ -2450,7 +2389,6 @@ var init_extractor = __esm(() => {
|
|
|
2450
2389
|
case "restore":
|
|
2451
2390
|
logger3.debug("[FormEvaluator] Restore intent - deferring to action");
|
|
2452
2391
|
break;
|
|
2453
|
-
case "fill_form":
|
|
2454
2392
|
default:
|
|
2455
2393
|
await processExtractions(runtime, formService, session, form, entityId, extractions, message.id);
|
|
2456
2394
|
break;
|
|
@@ -2470,165 +2408,223 @@ var init_extractor = __esm(() => {
|
|
|
2470
2408
|
extractor_default = formEvaluator;
|
|
2471
2409
|
});
|
|
2472
2410
|
|
|
2473
|
-
// src/
|
|
2474
|
-
var
|
|
2475
|
-
__export(
|
|
2476
|
-
|
|
2477
|
-
default: () =>
|
|
2411
|
+
// src/providers/context.ts
|
|
2412
|
+
var exports_context = {};
|
|
2413
|
+
__export(exports_context, {
|
|
2414
|
+
formContextProvider: () => formContextProvider,
|
|
2415
|
+
default: () => context_default
|
|
2478
2416
|
});
|
|
2479
|
-
import {
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
description: "Restore a previously stashed form session",
|
|
2488
|
-
validate: async (runtime, message, _state) => {
|
|
2489
|
-
try {
|
|
2490
|
-
const text = message.content?.text || "";
|
|
2491
|
-
const intent = quickIntentDetect(text);
|
|
2492
|
-
if (intent !== "restore") {
|
|
2493
|
-
return false;
|
|
2494
|
-
}
|
|
2495
|
-
const formService = runtime.getService("FORM");
|
|
2496
|
-
if (!formService) {
|
|
2497
|
-
return false;
|
|
2498
|
-
}
|
|
2499
|
-
const entityId = message.entityId;
|
|
2500
|
-
if (!entityId)
|
|
2501
|
-
return false;
|
|
2502
|
-
const stashed = await formService.getStashedSessions(entityId);
|
|
2503
|
-
return stashed.length > 0;
|
|
2504
|
-
} catch (error) {
|
|
2505
|
-
logger4.error("[FormRestoreAction] Validation error:", String(error));
|
|
2506
|
-
return false;
|
|
2507
|
-
}
|
|
2508
|
-
},
|
|
2509
|
-
handler: async (runtime, message, _state, _options, callback) => {
|
|
2417
|
+
import { logger as logger4 } from "@elizaos/core";
|
|
2418
|
+
var formContextProvider, context_default;
|
|
2419
|
+
var init_context = __esm(() => {
|
|
2420
|
+
init_template();
|
|
2421
|
+
formContextProvider = {
|
|
2422
|
+
name: "FORM_CONTEXT",
|
|
2423
|
+
description: "Provides context about active form sessions",
|
|
2424
|
+
get: async (runtime, message, _state) => {
|
|
2510
2425
|
try {
|
|
2511
2426
|
const formService = runtime.getService("FORM");
|
|
2512
2427
|
if (!formService) {
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2428
|
+
return {
|
|
2429
|
+
data: { hasActiveForm: false },
|
|
2430
|
+
values: { formContext: "" },
|
|
2431
|
+
text: ""
|
|
2432
|
+
};
|
|
2517
2433
|
}
|
|
2518
2434
|
const entityId = message.entityId;
|
|
2519
2435
|
const roomId = message.roomId;
|
|
2520
2436
|
if (!entityId || !roomId) {
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
const existing = await formService.getActiveSession(entityId, roomId);
|
|
2527
|
-
if (existing) {
|
|
2528
|
-
const form2 = formService.getForm(existing.formId);
|
|
2529
|
-
await callback?.({
|
|
2530
|
-
text: `You already have an active form: "${form2?.name || existing.formId}". Would you like to continue with that one, or should I save it and restore your other form?`
|
|
2531
|
-
});
|
|
2532
|
-
return { success: false };
|
|
2437
|
+
return {
|
|
2438
|
+
data: { hasActiveForm: false },
|
|
2439
|
+
values: { formContext: "" },
|
|
2440
|
+
text: ""
|
|
2441
|
+
};
|
|
2533
2442
|
}
|
|
2443
|
+
const session = await formService.getActiveSession(entityId, roomId);
|
|
2534
2444
|
const stashed = await formService.getStashedSessions(entityId);
|
|
2535
|
-
if (stashed.length === 0) {
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2445
|
+
if (!session && stashed.length === 0) {
|
|
2446
|
+
return {
|
|
2447
|
+
data: { hasActiveForm: false, stashedCount: 0 },
|
|
2448
|
+
values: { formContext: "" },
|
|
2449
|
+
text: ""
|
|
2450
|
+
};
|
|
2540
2451
|
}
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2452
|
+
let contextText = "";
|
|
2453
|
+
let contextState;
|
|
2454
|
+
if (session) {
|
|
2455
|
+
contextState = formService.getSessionContext(session);
|
|
2456
|
+
const form = formService.getForm(session.formId);
|
|
2457
|
+
const templateValues = buildTemplateValues(session);
|
|
2458
|
+
const resolveText = (value) => renderTemplate(value, templateValues);
|
|
2459
|
+
contextState = {
|
|
2460
|
+
...contextState,
|
|
2461
|
+
filledFields: contextState.filledFields.map((field) => ({
|
|
2462
|
+
...field,
|
|
2463
|
+
label: resolveText(field.label) ?? field.label
|
|
2464
|
+
})),
|
|
2465
|
+
missingRequired: contextState.missingRequired.map((field) => ({
|
|
2466
|
+
...field,
|
|
2467
|
+
label: resolveText(field.label) ?? field.label,
|
|
2468
|
+
description: resolveText(field.description),
|
|
2469
|
+
askPrompt: resolveText(field.askPrompt)
|
|
2470
|
+
})),
|
|
2471
|
+
uncertainFields: contextState.uncertainFields.map((field) => ({
|
|
2472
|
+
...field,
|
|
2473
|
+
label: resolveText(field.label) ?? field.label
|
|
2474
|
+
})),
|
|
2475
|
+
nextField: contextState.nextField ? resolveControlTemplates(contextState.nextField, templateValues) : null
|
|
2476
|
+
};
|
|
2477
|
+
contextText = `# Active Form: ${form?.name || session.formId}
|
|
2549
2478
|
|
|
2550
|
-
Here's what I have so far:
|
|
2551
2479
|
`;
|
|
2552
|
-
|
|
2553
|
-
|
|
2480
|
+
contextText += `Progress: ${contextState.progress}%
|
|
2481
|
+
|
|
2482
|
+
`;
|
|
2483
|
+
if (contextState.filledFields.length > 0) {
|
|
2484
|
+
contextText += `## Collected Information
|
|
2485
|
+
`;
|
|
2486
|
+
for (const field of contextState.filledFields) {
|
|
2487
|
+
contextText += `- ${field.label}: ${field.displayValue}
|
|
2488
|
+
`;
|
|
2489
|
+
}
|
|
2490
|
+
contextText += `
|
|
2554
2491
|
`;
|
|
2555
2492
|
}
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2493
|
+
if (contextState.missingRequired.length > 0) {
|
|
2494
|
+
contextText += `## Still Needed
|
|
2495
|
+
`;
|
|
2496
|
+
for (const field of contextState.missingRequired) {
|
|
2497
|
+
contextText += `- ${field.label}${field.description ? ` (${field.description})` : ""}
|
|
2498
|
+
`;
|
|
2499
|
+
}
|
|
2500
|
+
contextText += `
|
|
2501
|
+
`;
|
|
2562
2502
|
}
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
data: {
|
|
2573
|
-
sessionId: session.id,
|
|
2574
|
-
formId: session.formId,
|
|
2575
|
-
progress: context.progress
|
|
2503
|
+
if (contextState.uncertainFields.length > 0) {
|
|
2504
|
+
contextText += `## Needs Confirmation
|
|
2505
|
+
`;
|
|
2506
|
+
for (const field of contextState.uncertainFields) {
|
|
2507
|
+
contextText += `- ${field.label}: "${field.value}" (${Math.round(field.confidence * 100)}% confident)
|
|
2508
|
+
`;
|
|
2509
|
+
}
|
|
2510
|
+
contextText += `
|
|
2511
|
+
`;
|
|
2576
2512
|
}
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
name: "{{agentName}}",
|
|
2594
|
-
content: {
|
|
2595
|
-
text: "I've restored your form. Let's continue where you left off."
|
|
2513
|
+
if (contextState.pendingExternalFields.length > 0) {
|
|
2514
|
+
contextText += `## Waiting For External Action
|
|
2515
|
+
`;
|
|
2516
|
+
for (const field of contextState.pendingExternalFields) {
|
|
2517
|
+
const ageMs = Date.now() - field.activatedAt;
|
|
2518
|
+
const ageMin = Math.floor(ageMs / 60000);
|
|
2519
|
+
const ageText = ageMin < 1 ? "just now" : `${ageMin}m ago`;
|
|
2520
|
+
contextText += `- ${field.label}: ${field.instructions} (started ${ageText})
|
|
2521
|
+
`;
|
|
2522
|
+
if (field.address) {
|
|
2523
|
+
contextText += ` Address: ${field.address}
|
|
2524
|
+
`;
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
contextText += `
|
|
2528
|
+
`;
|
|
2596
2529
|
}
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2530
|
+
contextText += `## Agent Guidance
|
|
2531
|
+
`;
|
|
2532
|
+
if (contextState.pendingExternalFields.length > 0) {
|
|
2533
|
+
const pending = contextState.pendingExternalFields[0];
|
|
2534
|
+
contextText += `Waiting for external action. Remind user: "${pending.instructions}"
|
|
2535
|
+
`;
|
|
2536
|
+
} else if (contextState.pendingCancelConfirmation) {
|
|
2537
|
+
contextText += `User is trying to cancel. Confirm: "You've spent time on this. Are you sure you want to cancel?"
|
|
2538
|
+
`;
|
|
2539
|
+
} else if (contextState.uncertainFields.length > 0) {
|
|
2540
|
+
const uncertain = contextState.uncertainFields[0];
|
|
2541
|
+
contextText += `Ask user to confirm: "I understood your ${uncertain.label} as '${uncertain.value}'. Is that correct?"
|
|
2542
|
+
`;
|
|
2543
|
+
} else if (contextState.nextField) {
|
|
2544
|
+
const next = contextState.nextField;
|
|
2545
|
+
const prompt = next.askPrompt || `Ask for their ${next.label}`;
|
|
2546
|
+
contextText += `Next: ${prompt}
|
|
2547
|
+
`;
|
|
2548
|
+
if (next.example) {
|
|
2549
|
+
contextText += `Example: "${next.example}"
|
|
2550
|
+
`;
|
|
2551
|
+
}
|
|
2552
|
+
} else if (contextState.status === "ready") {
|
|
2553
|
+
contextText += `All fields collected! Nudge user to submit: "I have everything I need. Ready to submit?"
|
|
2554
|
+
`;
|
|
2608
2555
|
}
|
|
2556
|
+
contextText += `
|
|
2557
|
+
`;
|
|
2558
|
+
contextText += `## User Can Say
|
|
2559
|
+
`;
|
|
2560
|
+
contextText += `- Provide information for any field
|
|
2561
|
+
`;
|
|
2562
|
+
contextText += `- "undo" or "go back" to revert last change
|
|
2563
|
+
`;
|
|
2564
|
+
contextText += `- "skip" to skip optional fields
|
|
2565
|
+
`;
|
|
2566
|
+
contextText += `- "why?" to get explanation about a field
|
|
2567
|
+
`;
|
|
2568
|
+
contextText += `- "how far?" to check progress
|
|
2569
|
+
`;
|
|
2570
|
+
contextText += `- "submit" or "done" when ready
|
|
2571
|
+
`;
|
|
2572
|
+
contextText += `- "save for later" to stash the form
|
|
2573
|
+
`;
|
|
2574
|
+
contextText += `- "cancel" to abandon the form
|
|
2575
|
+
`;
|
|
2576
|
+
} else {
|
|
2577
|
+
contextState = {
|
|
2578
|
+
hasActiveForm: false,
|
|
2579
|
+
progress: 0,
|
|
2580
|
+
filledFields: [],
|
|
2581
|
+
missingRequired: [],
|
|
2582
|
+
uncertainFields: [],
|
|
2583
|
+
nextField: null,
|
|
2584
|
+
stashedCount: stashed.length,
|
|
2585
|
+
pendingExternalFields: []
|
|
2586
|
+
};
|
|
2609
2587
|
}
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2588
|
+
if (stashed.length > 0) {
|
|
2589
|
+
contextText += `
|
|
2590
|
+
## Saved Forms
|
|
2591
|
+
`;
|
|
2592
|
+
contextText += `User has ${stashed.length} saved form(s). They can say "resume" or "continue" to restore one.
|
|
2593
|
+
`;
|
|
2594
|
+
for (const s of stashed) {
|
|
2595
|
+
const form = formService.getForm(s.formId);
|
|
2596
|
+
const ctx = formService.getSessionContext(s);
|
|
2597
|
+
contextText += `- ${form?.name || s.formId} (${ctx.progress}% complete)
|
|
2598
|
+
`;
|
|
2620
2599
|
}
|
|
2621
2600
|
}
|
|
2622
|
-
|
|
2623
|
-
|
|
2601
|
+
return {
|
|
2602
|
+
data: JSON.parse(JSON.stringify(contextState)),
|
|
2603
|
+
values: {
|
|
2604
|
+
formContext: contextText,
|
|
2605
|
+
hasActiveForm: String(contextState.hasActiveForm),
|
|
2606
|
+
formProgress: String(contextState.progress),
|
|
2607
|
+
formStatus: contextState.status || "",
|
|
2608
|
+
stashedCount: String(stashed.length)
|
|
2609
|
+
},
|
|
2610
|
+
text: contextText
|
|
2611
|
+
};
|
|
2612
|
+
} catch (error) {
|
|
2613
|
+
logger4.error("[FormContextProvider] Error:", String(error));
|
|
2614
|
+
return {
|
|
2615
|
+
data: { hasActiveForm: false, error: true },
|
|
2616
|
+
values: { formContext: "Error loading form context." },
|
|
2617
|
+
text: "Error loading form context."
|
|
2618
|
+
};
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2624
2621
|
};
|
|
2625
|
-
|
|
2622
|
+
context_default = formContextProvider;
|
|
2626
2623
|
});
|
|
2627
2624
|
|
|
2628
|
-
//
|
|
2625
|
+
// index.ts
|
|
2629
2626
|
init_builtins();
|
|
2630
2627
|
init_validation();
|
|
2631
|
-
init_validation();
|
|
2632
2628
|
init_storage();
|
|
2633
2629
|
init_extraction();
|
|
2634
2630
|
init_types();
|
|
@@ -2953,7 +2949,7 @@ class FormBuilder {
|
|
|
2953
2949
|
}
|
|
2954
2950
|
control(builder) {
|
|
2955
2951
|
const ctrl = builder instanceof ControlBuilder ? builder.build() : builder;
|
|
2956
|
-
this.form.controls
|
|
2952
|
+
this.form.controls?.push(ctrl);
|
|
2957
2953
|
return this;
|
|
2958
2954
|
}
|
|
2959
2955
|
controls(...builders) {
|
|
@@ -3070,11 +3066,102 @@ function prettify2(key) {
|
|
|
3070
3066
|
return key.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
3071
3067
|
}
|
|
3072
3068
|
|
|
3073
|
-
//
|
|
3069
|
+
// index.ts
|
|
3074
3070
|
init_service();
|
|
3075
|
-
init_context();
|
|
3076
|
-
init_extractor();
|
|
3077
3071
|
init_restore();
|
|
3072
|
+
init_extractor();
|
|
3073
|
+
init_context();
|
|
3074
|
+
|
|
3075
|
+
// src/tasks/nudge.ts
|
|
3076
|
+
import { logger as logger5 } from "@elizaos/core";
|
|
3077
|
+
var formNudgeWorker = {
|
|
3078
|
+
name: "form_nudge_check",
|
|
3079
|
+
validate: async (_runtime, _message, _state) => {
|
|
3080
|
+
return true;
|
|
3081
|
+
},
|
|
3082
|
+
execute: async (runtime, _options, _task) => {
|
|
3083
|
+
try {
|
|
3084
|
+
const formService = runtime.getService("FORM");
|
|
3085
|
+
if (!formService) {
|
|
3086
|
+
logger5.debug("[FormNudge] Form service not available");
|
|
3087
|
+
return;
|
|
3088
|
+
}
|
|
3089
|
+
logger5.debug("[FormNudge] Nudge check cycle completed");
|
|
3090
|
+
} catch (error) {
|
|
3091
|
+
logger5.error("[FormNudge] Error during nudge check:", String(error));
|
|
3092
|
+
}
|
|
3093
|
+
}
|
|
3094
|
+
};
|
|
3095
|
+
async function processEntityNudges(runtime, entityId) {
|
|
3096
|
+
const formService = runtime.getService("FORM");
|
|
3097
|
+
if (!formService)
|
|
3098
|
+
return;
|
|
3099
|
+
const activeSessions = await formService.getAllActiveSessions(entityId);
|
|
3100
|
+
const stashedSessions = await formService.getStashedSessions(entityId);
|
|
3101
|
+
const allSessions = [...activeSessions, ...stashedSessions];
|
|
3102
|
+
const now = Date.now();
|
|
3103
|
+
const expirationWarningMs = 24 * 60 * 60 * 1000;
|
|
3104
|
+
for (const session of allSessions) {
|
|
3105
|
+
const form = formService.getForm(session.formId);
|
|
3106
|
+
if (session.expiresAt < now) {
|
|
3107
|
+
session.status = "expired";
|
|
3108
|
+
await formService.saveSession(session);
|
|
3109
|
+
if (form?.hooks?.onExpire) {
|
|
3110
|
+
const worker = runtime.getTaskWorker(form.hooks.onExpire);
|
|
3111
|
+
if (worker) {
|
|
3112
|
+
try {
|
|
3113
|
+
await worker.execute(runtime, { session, form }, {});
|
|
3114
|
+
} catch (error) {
|
|
3115
|
+
logger5.error("[FormNudge] onExpire hook failed:", String(error));
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
}
|
|
3119
|
+
logger5.debug(`[FormNudge] Session ${session.id} expired`);
|
|
3120
|
+
continue;
|
|
3121
|
+
}
|
|
3122
|
+
if (isExpiringSoon(session, expirationWarningMs) && !session.expirationWarned) {
|
|
3123
|
+
await sendExpirationWarning(runtime, session, form);
|
|
3124
|
+
session.expirationWarned = true;
|
|
3125
|
+
await formService.saveSession(session);
|
|
3126
|
+
continue;
|
|
3127
|
+
}
|
|
3128
|
+
if (session.status === "stashed" && shouldNudge(session, form)) {
|
|
3129
|
+
await sendNudge(runtime, session, form);
|
|
3130
|
+
session.nudgeCount = (session.nudgeCount || 0) + 1;
|
|
3131
|
+
session.lastNudgeAt = now;
|
|
3132
|
+
await formService.saveSession(session);
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
}
|
|
3136
|
+
async function sendNudge(runtime, session, form) {
|
|
3137
|
+
const message = form?.nudge?.message || `You have an unfinished "${form?.name || "form"}". Would you like to continue?`;
|
|
3138
|
+
try {
|
|
3139
|
+
if (typeof runtime.sendMessageToRoom === "function") {
|
|
3140
|
+
await runtime.sendMessageToRoom(session.roomId, {
|
|
3141
|
+
text: message
|
|
3142
|
+
});
|
|
3143
|
+
logger5.debug(`[FormNudge] Sent nudge for session in room ${session.roomId}`);
|
|
3144
|
+
}
|
|
3145
|
+
} catch (error) {
|
|
3146
|
+
logger5.error("[FormNudge] Failed to send nudge:", String(error));
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
async function sendExpirationWarning(runtime, session, form) {
|
|
3150
|
+
const remaining = formatTimeRemaining(session);
|
|
3151
|
+
const message = `Your "${form?.name || "form"}" form will expire in ${remaining}. Say "resume" to keep working on it.`;
|
|
3152
|
+
try {
|
|
3153
|
+
if (typeof runtime.sendMessageToRoom === "function") {
|
|
3154
|
+
await runtime.sendMessageToRoom(session.roomId, {
|
|
3155
|
+
text: message
|
|
3156
|
+
});
|
|
3157
|
+
logger5.debug(`[FormNudge] Sent expiration warning for session in room ${session.roomId}`);
|
|
3158
|
+
}
|
|
3159
|
+
} catch (error) {
|
|
3160
|
+
logger5.error("[FormNudge] Failed to send expiration warning:", String(error));
|
|
3161
|
+
}
|
|
3162
|
+
}
|
|
3163
|
+
|
|
3164
|
+
// index.ts
|
|
3078
3165
|
var formPlugin = {
|
|
3079
3166
|
name: "form",
|
|
3080
3167
|
description: "Agent-native conversational forms for data collection",
|
|
@@ -3143,7 +3230,7 @@ var formPlugin = {
|
|
|
3143
3230
|
}
|
|
3144
3231
|
]
|
|
3145
3232
|
};
|
|
3146
|
-
var
|
|
3233
|
+
var typescript_default = formPlugin;
|
|
3147
3234
|
export {
|
|
3148
3235
|
validateField,
|
|
3149
3236
|
shouldNudge,
|
|
@@ -3154,6 +3241,7 @@ export {
|
|
|
3154
3241
|
registerTypeHandler,
|
|
3155
3242
|
registerBuiltinTypes,
|
|
3156
3243
|
quickIntentDetect,
|
|
3244
|
+
processEntityNudges,
|
|
3157
3245
|
prettify,
|
|
3158
3246
|
parseValue,
|
|
3159
3247
|
matchesMimeType,
|
|
@@ -3176,12 +3264,13 @@ export {
|
|
|
3176
3264
|
formatEffort,
|
|
3177
3265
|
formRestoreAction,
|
|
3178
3266
|
formPlugin,
|
|
3267
|
+
formNudgeWorker,
|
|
3179
3268
|
formEvaluator,
|
|
3180
3269
|
formContextProvider,
|
|
3181
3270
|
extractSingleField,
|
|
3182
3271
|
detectCorrection,
|
|
3183
3272
|
deleteSession,
|
|
3184
|
-
|
|
3273
|
+
typescript_default as default,
|
|
3185
3274
|
clearTypeHandlers,
|
|
3186
3275
|
calculateTTL,
|
|
3187
3276
|
applyFormDefaults,
|
|
@@ -3200,4 +3289,5 @@ export {
|
|
|
3200
3289
|
BUILTIN_TYPES
|
|
3201
3290
|
};
|
|
3202
3291
|
|
|
3203
|
-
//# debugId=
|
|
3292
|
+
//# debugId=D9CCEBB86B648A7B64756E2164756E21
|
|
3293
|
+
//# sourceMappingURL=index.js.map
|