@case-framework/survey-assistant 0.1.0 → 0.2.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/README.md +71 -11
- package/dist/{authoring-references-X6uRaWuf.mjs → authoring-references-DYuOAdVx.mjs} +26 -2
- package/dist/authoring-references-DYuOAdVx.mjs.map +1 -0
- package/dist/{capabilities-B6tvE7fK.mjs → capabilities-DZ0a_o2y.mjs} +2 -2
- package/dist/{capabilities-B6tvE7fK.mjs.map → capabilities-DZ0a_o2y.mjs.map} +1 -1
- package/dist/{capabilities-DvSKtjAw.d.mts → capabilities-DlC1l6qy.d.mts} +4 -1
- package/dist/capabilities-DlC1l6qy.d.mts.map +1 -0
- package/dist/capabilities-default.d.mts +1 -1
- package/dist/capabilities-default.d.mts.map +1 -1
- package/dist/capabilities-default.mjs +6 -3
- package/dist/capabilities-default.mjs.map +1 -1
- package/dist/{constants-Jw0k8ojS.d.mts → constants-56jf_4ls.d.mts} +36 -9
- package/dist/constants-56jf_4ls.d.mts.map +1 -0
- package/dist/{controller-proxy-BRDusFiO.d.mts → controller-proxy-2VH0b_5E.d.mts} +29 -4
- package/dist/controller-proxy-2VH0b_5E.d.mts.map +1 -0
- package/dist/{controller-proxy-Duxo2IFE.mjs → controller-proxy-ClsY4lFI.mjs} +74 -5
- package/dist/controller-proxy-ClsY4lFI.mjs.map +1 -0
- package/dist/{digest-BsoVq49o.d.mts → digest-BvXpeWcR.d.mts} +2 -2
- package/dist/{digest-BsoVq49o.d.mts.map → digest-BvXpeWcR.d.mts.map} +1 -1
- package/dist/digest.d.mts +1 -1
- package/dist/{engine-sPvuixWg.mjs → engine-DQrCO_ur.mjs} +392 -50
- package/dist/engine-DQrCO_ur.mjs.map +1 -0
- package/dist/engine.d.mts +2 -2
- package/dist/engine.mjs +2 -2
- package/dist/{index-MpEMQzTm.d.mts → index-B_x2IYi7.d.mts} +5 -1
- package/dist/index-B_x2IYi7.d.mts.map +1 -0
- package/dist/{index-BWNHkpkh.d.mts → index-C_x686M7.d.mts} +27 -5
- package/dist/index-C_x686M7.d.mts.map +1 -0
- package/dist/{index-TFtvBiSQ.d.mts → index-DVxVyhAu.d.mts} +31 -9
- package/dist/index-DVxVyhAu.d.mts.map +1 -0
- package/dist/{index-CUqbBjkc.d.mts → index-DZ6KBwVR.d.mts} +16 -3
- package/dist/index-DZ6KBwVR.d.mts.map +1 -0
- package/dist/{memory-thread-repository-CJkkVE2-.mjs → memory-thread-repository-Cm1BJyRw.mjs} +110 -41
- package/dist/memory-thread-repository-Cm1BJyRw.mjs.map +1 -0
- package/dist/{protocol-DV0ka9WT.mjs → protocol-7EEgcYja.mjs} +70 -97
- package/dist/protocol-7EEgcYja.mjs.map +1 -0
- package/dist/protocol.d.mts +3 -3
- package/dist/protocol.mjs +2 -2
- package/dist/{react-VuYe-cPh.mjs → react-B_5smfiK.mjs} +145 -38
- package/dist/react-B_5smfiK.mjs.map +1 -0
- package/dist/react-integration.d.mts +2 -2
- package/dist/react-integration.mjs +2 -2
- package/dist/react.d.mts +3 -3
- package/dist/react.mjs +3 -3
- package/dist/references/assistant-operations.md +6 -0
- package/dist/references/core-rules.md +6 -0
- package/dist/references/embedded-forms.md +21 -14
- package/dist/references/expressions.md +3 -0
- package/dist/references/item-types.md +37 -10
- package/dist/references/source-material-surveys.md +9 -1
- package/dist/references/survey-data-model.md +13 -0
- package/dist/request-context-BDBw4-Gw.mjs +79 -0
- package/dist/request-context-BDBw4-Gw.mjs.map +1 -0
- package/dist/request-guardrails-h4t6u8mP.mjs +129 -0
- package/dist/request-guardrails-h4t6u8mP.mjs.map +1 -0
- package/dist/server-agent.d.mts +6 -2
- package/dist/server-agent.d.mts.map +1 -1
- package/dist/server-agent.mjs +39 -24
- package/dist/server-agent.mjs.map +1 -1
- package/dist/server-runtime.d.mts +21 -5
- package/dist/server-runtime.d.mts.map +1 -1
- package/dist/server-runtime.mjs +98 -32
- package/dist/server-runtime.mjs.map +1 -1
- package/dist/server-tasks.d.mts +2 -78
- package/dist/server-tasks.mjs +103 -46
- package/dist/server-tasks.mjs.map +1 -1
- package/dist/server-tools.d.mts +1 -1
- package/dist/server-tools.mjs +1 -1
- package/dist/server.d.mts +89 -21
- package/dist/server.d.mts.map +1 -1
- package/dist/server.mjs +136 -5
- package/dist/server.mjs.map +1 -0
- package/dist/storage-postgres.d.mts +12 -2
- package/dist/storage-postgres.d.mts.map +1 -1
- package/dist/storage-postgres.mjs +11 -6
- package/dist/storage-postgres.mjs.map +1 -1
- package/dist/tasks-COQnhSeT.d.mts +140 -0
- package/dist/tasks-COQnhSeT.d.mts.map +1 -0
- package/dist/{thread-documents-DamIq9Od.d.mts → thread-documents-BlxNjc7S.d.mts} +21 -5
- package/dist/thread-documents-BlxNjc7S.d.mts.map +1 -0
- package/dist/{thread-handlers-DpynUc64.d.mts → thread-handlers-l79JBl5m.d.mts} +38 -5
- package/dist/thread-handlers-l79JBl5m.d.mts.map +1 -0
- package/dist/{tools-Hz2p7vyv.mjs → tools-DDXaJ8Za.mjs} +257 -38
- package/dist/tools-DDXaJ8Za.mjs.map +1 -0
- package/dist/ui.d.mts +5 -3
- package/dist/ui.d.mts.map +1 -1
- package/dist/ui.mjs +91 -12
- package/dist/ui.mjs.map +1 -1
- package/docs/integration.md +234 -0
- package/package.json +9 -7
- package/dist/authoring-references-Cy8J-DWt.d.mts +0 -48
- package/dist/authoring-references-Cy8J-DWt.d.mts.map +0 -1
- package/dist/authoring-references-X6uRaWuf.mjs.map +0 -1
- package/dist/capabilities-DvSKtjAw.d.mts.map +0 -1
- package/dist/constants-Jw0k8ojS.d.mts.map +0 -1
- package/dist/controller-proxy-BRDusFiO.d.mts.map +0 -1
- package/dist/controller-proxy-Duxo2IFE.mjs.map +0 -1
- package/dist/engine-sPvuixWg.mjs.map +0 -1
- package/dist/index-BWNHkpkh.d.mts.map +0 -1
- package/dist/index-CUqbBjkc.d.mts.map +0 -1
- package/dist/index-MpEMQzTm.d.mts.map +0 -1
- package/dist/index-TFtvBiSQ.d.mts.map +0 -1
- package/dist/memory-thread-repository-CJkkVE2-.mjs.map +0 -1
- package/dist/protocol-DV0ka9WT.mjs.map +0 -1
- package/dist/react-VuYe-cPh.mjs.map +0 -1
- package/dist/request-context-jcmXT_Q2.mjs +0 -44
- package/dist/request-context-jcmXT_Q2.mjs.map +0 -1
- package/dist/request-guardrails-C59IWnH8.mjs +0 -73
- package/dist/request-guardrails-C59IWnH8.mjs.map +0 -1
- package/dist/server-tasks.d.mts.map +0 -1
- package/dist/thread-documents-DamIq9Od.d.mts.map +0 -1
- package/dist/thread-handlers-DpynUc64.d.mts.map +0 -1
- package/dist/tools-Hz2p7vyv.mjs.map +0 -1
|
@@ -21,13 +21,14 @@ Use a group when its children form a meaningful, independently managed section o
|
|
|
21
21
|
## Editor Presentation
|
|
22
22
|
|
|
23
23
|
Every item has three distinct naming/presentation surfaces:
|
|
24
|
+
|
|
24
25
|
- `key`: stable coding key used in expressions and response paths. Change it with `update-item-key`.
|
|
25
26
|
- `metadata.itemLabel`: internal editor label, not shown to respondents. Change it with `update-item-label`.
|
|
26
27
|
- `metadata.editorItemColor`: editor-only color swatch, not shown to respondents. Change it with `update-item-color`.
|
|
27
28
|
|
|
28
29
|
Across editor views, an unqualified request for labels on one or more items/questions means `metadata.itemLabel`, including the visible \"Add label...\" editor control. It does not mean respondent-facing question titles, option labels, or form-field labels unless the user says so. Do not ask for clarification when the requested item set is clear; inspect/search to resolve that set when needed. Clarify only if the request explicitly spans multiple label surfaces.
|
|
29
30
|
|
|
30
|
-
`update-item-color.color` must be one of the editor palette values
|
|
31
|
+
`update-item-color.color` must be one of the editor palette values provided in the `survey_change` tool contract. Use it only when the user asks for editor organization or color; it must not be used to imply respondent-facing meaning.
|
|
31
32
|
|
|
32
33
|
## page-break
|
|
33
34
|
|
|
@@ -50,14 +51,13 @@ Interactive choice question:
|
|
|
50
51
|
"id": "<itemId>",
|
|
51
52
|
"maxSelection": 1,
|
|
52
53
|
"shuffleOptions": false,
|
|
53
|
-
"options": [
|
|
54
|
-
{ "id": "fuji", "key": "FUJI" }
|
|
55
|
-
]
|
|
54
|
+
"options": [{ "id": "fuji", "key": "FUJI" }]
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
57
|
```
|
|
59
58
|
|
|
60
59
|
Choice conventions:
|
|
60
|
+
|
|
61
61
|
- `maxSelection: 1` means single select.
|
|
62
62
|
- `maxSelection: null` means multiple select with no cap.
|
|
63
63
|
- `maxSelection: n` means multiple select capped at n selections.
|
|
@@ -71,10 +71,15 @@ Choice conventions:
|
|
|
71
71
|
- Do not use provider-specific label metadata such as `labelKey`. CASE resolves every respondent-visible option label from `options.<optionId>.label` translations.
|
|
72
72
|
- CASE choice options do not currently have a separate visible option-description field. If source material has an option-specific parenthetical/note, include it in the option label or move it to nearby question content. The `survey_change` normalizer preserves shorthand `option.note`, `option.description`, `option.helpText`, and `option.footnoteMarker` by folding them into the label translation.
|
|
73
73
|
- If an option has an embedded form, do not duplicate trailing completion words in both the option label and field label. The normalizer strips trailing `, namelijk`, `, please specify`, `, specify`, `, explain`, and `, toelichting` from embedded-form option labels before validation.
|
|
74
|
-
- The main response slot is `<itemId>...get...<config.id
|
|
74
|
+
- The main response slot is `<itemId>...get...<config.id>`. For a new choice item, always set
|
|
75
|
+
`config.id` to the exact same value as `item.id`; do not invent a second semantic name from the
|
|
76
|
+
question wording and do not add ordering suffixes such as `q1`. The choice response-slot ID has no
|
|
77
|
+
direct editor control and expressions refer to it exactly, so changing it later requires updating
|
|
78
|
+
every reference in the same change.
|
|
75
79
|
- Single select returns `reference`; multiple select returns `reference[]`.
|
|
76
80
|
|
|
77
81
|
Embedded option forms:
|
|
82
|
+
|
|
78
83
|
- There is no `allowOther` flag in the current choice item model. Do not use `allowOther` to create free-text "Other" inputs.
|
|
79
84
|
- CRITICAL — exact key name: the field on the option object is `embeddedForm` (singular, one object). It is NEVER `embeddedForms` (plural) and NEVER an array. The option's recognized keys are only: `id`, `key`, `label`, `hasDisplayCondition`, `embeddedFormItemId`, `embeddedForm`. Any other key (including a typo'd/pluralized `embeddedForms`) is silently dropped during validation — no error is raised, the field simply never appears, and you must not report the change as successful if you are not certain you used the exact singular key.
|
|
80
85
|
- CRITICAL — exact shape: `embeddedForm` fields are never listed directly as `embeddedForm.fields`. They must be nested inside `embeddedForm.fieldGroups`, an array of groups, each with its own `fields` array: `{ "id": "...", "fieldGroups": [ { "id": "...", "fields": [ { "id": "...", "type": "input", "controller": { "type": "input", ... } } ] } ] }`. A top-level `fields` array with no `fieldGroups` wrapper will not render anything.
|
|
@@ -84,8 +89,8 @@ Embedded option forms:
|
|
|
84
89
|
- The embedded form renders only while that option is selected. When the option is deselected, existing embedded responses are cleared after user confirmation.
|
|
85
90
|
- Embedded form translation keys are prefixed with `embeddedForms.<optionId>`; for example `embeddedForms.other.fields.other_text.label`. Note this translation content-key prefix IS plural (`embeddedForms`) even though the config field on the option is singular (`embeddedForm`) — these are two different things; do not confuse them.
|
|
86
91
|
- Embedded form response slots are `embedded.<optionId>.<fieldKey>`; for example `embedded.other.other_text`.
|
|
87
|
-
- Use `create-item` with embedded form config and matching translations when creating a new choice item. For an existing choice option,
|
|
88
|
-
- MANDATORY: every embedded form field needs a matching `embeddedForms.<optionId>.fields.<fieldId>.label` translation entry
|
|
92
|
+
- Use `create-item` with embedded form config and matching translations when creating a new choice item. For an existing choice option, inspect its exact item and option ids and use `set-embedded-form`; its relative form translations are prefixed automatically. If the option is also new, put `add-choice-option` with an explicit id immediately before `set-embedded-form` in the same proposal.
|
|
93
|
+
- MANDATORY: every embedded form field needs a matching `embeddedForms.<optionId>.fields.<fieldId>.label` translation entry when it is introduced. There is no fallback/derived label text — a field without this translation renders its raw key to respondents.
|
|
89
94
|
|
|
90
95
|
Example "Other, please specify" option:
|
|
91
96
|
|
|
@@ -116,6 +121,7 @@ Example "Other, please specify" option:
|
|
|
116
121
|
```
|
|
117
122
|
|
|
118
123
|
Matching translation keys on the choice item:
|
|
124
|
+
|
|
119
125
|
- `options.other.label`: "Other"
|
|
120
126
|
- `embeddedForms.other.fields.other_text.label`: "Please specify"
|
|
121
127
|
- Optional placeholder: `embeddedForms.other.fields.other_text.placeholder`
|
|
@@ -180,7 +186,11 @@ One `create-item` operation carries the whole item plus every translation it nee
|
|
|
180
186
|
{ "locale": "en", "contentKey": "options.strawberry.label", "plainText": "Strawberry" },
|
|
181
187
|
{ "locale": "en", "contentKey": "options.blueberry.label", "plainText": "Blueberry" },
|
|
182
188
|
{ "locale": "en", "contentKey": "options.other.label", "plainText": "Other" },
|
|
183
|
-
{
|
|
189
|
+
{
|
|
190
|
+
"locale": "en",
|
|
191
|
+
"contentKey": "embeddedForms.other.fields.other_text.label",
|
|
192
|
+
"plainText": "Please specify"
|
|
193
|
+
}
|
|
184
194
|
]
|
|
185
195
|
}
|
|
186
196
|
```
|
|
@@ -211,7 +221,11 @@ Use `maxSelection: null` for "select all that apply" / checkbox-style questions:
|
|
|
211
221
|
}
|
|
212
222
|
},
|
|
213
223
|
"translations": [
|
|
214
|
-
{
|
|
224
|
+
{
|
|
225
|
+
"locale": "en",
|
|
226
|
+
"contentKey": "title",
|
|
227
|
+
"plainText": "Which industries have you worked in? Select all that apply."
|
|
228
|
+
},
|
|
215
229
|
{ "locale": "en", "contentKey": "options.healthcare.label", "plainText": "Healthcare" },
|
|
216
230
|
{ "locale": "en", "contentKey": "options.education.label", "plainText": "Education" },
|
|
217
231
|
{ "locale": "en", "contentKey": "options.food_service.label", "plainText": "Food service" }
|
|
@@ -242,9 +256,10 @@ Interactive form question:
|
|
|
242
256
|
CRITICAL — the item's `config` object has exactly two meaningful keys: `id` and `fieldGroups`. `fieldGroups` sits directly on `config` — never nest it under another wrapper, and never put a top-level `fields` array directly on `config` (fields must be inside a `fieldGroups` entry). Fields need at least one non-empty `fieldGroups` entry with an actual `fields` array to be useful; an empty `fieldGroups: [{ "fields": [] }]` is only a starting scaffold, not a finished item.
|
|
243
257
|
|
|
244
258
|
Field group config:
|
|
259
|
+
|
|
245
260
|
- `id`: stable group id.
|
|
246
261
|
- `hasDisplayCondition`: optional boolean used by the editor to mark groups that participate in branching/display logic.
|
|
247
|
-
- `layout`: column counts by container breakpoint, using
|
|
262
|
+
- `layout`: column counts by container breakpoint, using integers 1 through 4. These are grid column counts, not field spans; use 1 at every breakpoint for a lone full-width field.
|
|
248
263
|
|
|
249
264
|
Example field group layout:
|
|
250
265
|
|
|
@@ -258,6 +273,7 @@ Example field group layout:
|
|
|
258
273
|
```
|
|
259
274
|
|
|
260
275
|
Field group translations:
|
|
276
|
+
|
|
261
277
|
- `fieldGroups.<groupId>.title`
|
|
262
278
|
- `fieldGroups.<groupId>.description`
|
|
263
279
|
|
|
@@ -274,7 +290,16 @@ Field shape:
|
|
|
274
290
|
}
|
|
275
291
|
```
|
|
276
292
|
|
|
293
|
+
`key` is the field's exact response-slot identifier. Choose a stable coding key for the field's
|
|
294
|
+
role within this form item. Do not copy the question wording, duplicate context already present in
|
|
295
|
+
the item key, or add ordering suffixes such as `q1`. For a single-field form, concise keys such as
|
|
296
|
+
`response`, `selection`, `value`, or `other_text` are often appropriate. Keys only need to be unique
|
|
297
|
+
within the form item, so the same general key can be reused in another item. A user can edit the
|
|
298
|
+
field key in the form editor, but changing it also changes the response-slot identifier; any
|
|
299
|
+
expressions that use the old slot must be updated in the same change.
|
|
300
|
+
|
|
277
301
|
Field types and default controllers:
|
|
302
|
+
|
|
278
303
|
- `input`: `{ "type": "input", "inputMode": "text" }`
|
|
279
304
|
- `textarea`: `{ "type": "textarea", "rows": 3 }`
|
|
280
305
|
- `number`: `{ "type": "number", "step": 1 }`
|
|
@@ -284,6 +309,7 @@ Field types and default controllers:
|
|
|
284
309
|
- `slider`: `{ "type": "slider", "min": 0, "max": 100, "step": 1, "defaultValue": 50, "showValue": true }`
|
|
285
310
|
|
|
286
311
|
Supported controller properties by type:
|
|
312
|
+
|
|
287
313
|
- `input`: `placeholder`, `inputMode`, `autocomplete`
|
|
288
314
|
- `textarea`: `placeholder`, `rows`
|
|
289
315
|
- `number`: `placeholder`, `step`, `unit`, `defaultValue`
|
|
@@ -302,6 +328,7 @@ Visible select-option labels do NOT live in the controller config. They live in
|
|
|
302
328
|
If a select controller option has `id: "minder_7_dagen", value: "minder_7_dagen"`, the visible Dutch label still needs a separate translation such as `fields.<fieldId>.options.minder_7_dagen.label`: "minder dan 7 dagen". Without this translation, respondents see the raw key/value in the dropdown.
|
|
303
329
|
|
|
304
330
|
Field translation keys:
|
|
331
|
+
|
|
305
332
|
- `fields.<fieldId>.label`
|
|
306
333
|
- `fields.<fieldId>.description`
|
|
307
334
|
- `fields.<fieldId>.error`
|
|
@@ -28,6 +28,10 @@ Use this reference when the user asks to implement, recreate, convert, import, o
|
|
|
28
28
|
- Map supported item types directly. Use `choiceItem` for single choice, multiple choice, and scale-like questions until a dedicated scale item exists.
|
|
29
29
|
- For scale questions, create an ordered `choiceItem` with stable option ids/keys and labels that preserve the endpoints and intermediate labels. Include the scale instruction in `subtitle` or `topContent` when it is not part of the actual question.
|
|
30
30
|
- Use `formItem` for grouped personal data, tables of fields, repeated short inputs, dates, numbers, contact details, or unsupported compound controls.
|
|
31
|
+
- Prefer the supported semantic field type for the respondent value instead of copying the paper
|
|
32
|
+
form's box layout. Use one `datepicker` with mode `year-month-day` for an ordinary full calendar
|
|
33
|
+
date; use separate day/month/year fields only when the source measures those components
|
|
34
|
+
independently or the user requests literal paper-form reproduction.
|
|
31
35
|
- Use choice option embedded forms for choices that include an open field, such as "Other, specify", "Yes, explain", or an option-specific quantity/date/text input.
|
|
32
36
|
- Preserve option-level parenthetical instructions, side notes, and footnote markers. If the current choice option UI has no separate option-description surface, fold short option notes into the visible option label, for example `Uitgenodigde persoon zelf (zie hiervoor de naam op de brief en/of geboortedatum op de voorkant van de vragenlijst)`, and keep markers such as `Iemand anders*`.
|
|
33
37
|
- For sentence-completion options with an embedded input, put the completion cue on the embedded field label, not twice. Source text like `Iemand anders*, namelijk ____`, `Andere bedrijfstak, namelijk ____`, or `Other, please specify ____` should become option label `Iemand anders*` / `Andere bedrijfstak` / `Other` and embedded field label `Namelijk` / `Please specify`.
|
|
@@ -53,7 +57,11 @@ Use this reference when the user asks to implement, recreate, convert, import, o
|
|
|
53
57
|
|
|
54
58
|
## Workflow
|
|
55
59
|
|
|
56
|
-
- For complex source implementation, load
|
|
60
|
+
- For complex source implementation, load this source-material reference once, then load item-types
|
|
61
|
+
with the specific `itemType` needed for the current chunk and assistant-operations for unfamiliar
|
|
62
|
+
operation shapes. Do not load the combined item-types reference merely because a source contains
|
|
63
|
+
several types. Load rich-text-content before formatted info items and expressions before complex
|
|
64
|
+
branching.
|
|
57
65
|
- Use survey_inspect for the root group and long-survey insertion points. Use full outline paging or children lookup; do not guess append indexes from truncated context.
|
|
58
66
|
- Before calling survey_change for a source-derived chunk, do a quick fidelity pass against the source: every question title, option label, option parenthetical, blank/input, section heading, footnote marker, and footnote text in that chunk should either be represented digitally or intentionally omitted as print-only/admin material.
|
|
59
67
|
- If the fidelity pass finds missing details, fix the operations before calling survey_change. Do not knowingly leave cleanup for the user when the source gives enough information to implement it now.
|
|
@@ -44,6 +44,19 @@ Conventions:
|
|
|
44
44
|
- `key` is the coding key shown in fullKey paths. Sibling keys must be unique and use letters, numbers, underscores, or hyphens.
|
|
45
45
|
- `itemType` must exist in the current editor registry.
|
|
46
46
|
|
|
47
|
+
Identifier rules apply to every built-in and custom item type:
|
|
48
|
+
- Keep inspected identifiers byte-for-byte exact when displaying, explaining, comparing, or
|
|
49
|
+
reusing them. Do not replace separators, split camelCase, change capitalization, or substitute
|
|
50
|
+
visible labels.
|
|
51
|
+
- Choose new ids and keys for stable data roles, not the current wording or position. Avoid names
|
|
52
|
+
such as `question_about_apples` or suffixes such as `q1`; labels and question text can change
|
|
53
|
+
without changing durable identities.
|
|
54
|
+
- Do not silently derive one configured identifier from another. If a required identifier is
|
|
55
|
+
omitted and a typed operation generates it, inspect the result before using it in another
|
|
56
|
+
reference.
|
|
57
|
+
- Custom item response slots come from that item's registered capability. Preserve their exact
|
|
58
|
+
slot ids just like built-in slots.
|
|
59
|
+
|
|
47
60
|
Optional fields:
|
|
48
61
|
- `metadata`: string map. `metadata.itemLabel` is the internal editor label, not respondent-visible text. `metadata.editorItemColor` stores the editor item color as a hex string such as `#0369a1`.
|
|
49
62
|
- `config`: item-type-specific configuration. Many item types need config; simple structural/content items can be sparse.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { B as surveyDocumentVersionSchema, L as surveyAssistantSnapshotPayloadSchema } from "./protocol-7EEgcYja.mjs";
|
|
2
|
+
import { Q as createSurveyAssistantEngineContext } from "./engine-DQrCO_ur.mjs";
|
|
3
|
+
import { defaultSurveyAssistantCapabilitySet } from "./capabilities-default.mjs";
|
|
4
|
+
import { MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY, RequestContext } from "@mastra/core/request-context";
|
|
5
|
+
//#region src/server/request-context.ts
|
|
6
|
+
const parseSurveyAssistantSnapshot = (value) => {
|
|
7
|
+
if (value === void 0 || value === null) return null;
|
|
8
|
+
return surveyAssistantSnapshotPayloadSchema.parse(value);
|
|
9
|
+
};
|
|
10
|
+
const parseSurveyAssistantPreviousSettledVersion = (value) => {
|
|
11
|
+
if (value === void 0 || value === null) return null;
|
|
12
|
+
return surveyDocumentVersionSchema.parse(value);
|
|
13
|
+
};
|
|
14
|
+
const deriveSurveyAssistantDocumentTransition = ({ current, previous }) => {
|
|
15
|
+
if (!current) return void 0;
|
|
16
|
+
if (!previous) return { status: "no-baseline" };
|
|
17
|
+
const previousHistoryIndex = previous.historyIndex;
|
|
18
|
+
const currentHistoryIndex = current.version.historyIndex;
|
|
19
|
+
if (previous.sessionId !== current.version.sessionId) return {
|
|
20
|
+
status: "session-changed",
|
|
21
|
+
previousHistoryIndex,
|
|
22
|
+
currentHistoryIndex
|
|
23
|
+
};
|
|
24
|
+
const capabilitiesChanged = previous.capabilityDigest !== current.version.capabilityDigest;
|
|
25
|
+
if (previous.contentHash === current.version.contentHash) return {
|
|
26
|
+
status: "unchanged",
|
|
27
|
+
previousHistoryIndex,
|
|
28
|
+
currentHistoryIndex,
|
|
29
|
+
capabilitiesChanged
|
|
30
|
+
};
|
|
31
|
+
const historyDirection = currentHistoryIndex > previousHistoryIndex ? "forward" : currentHistoryIndex < previousHistoryIndex ? "backward" : "same-index";
|
|
32
|
+
return {
|
|
33
|
+
status: "changed",
|
|
34
|
+
previousHistoryIndex,
|
|
35
|
+
currentHistoryIndex,
|
|
36
|
+
historyDirection,
|
|
37
|
+
recordedSources: historyDirection === "forward" ? [...new Set((current.ui.history?.recent ?? []).filter((entry) => entry.index > previousHistoryIndex && entry.index <= currentHistoryIndex).flatMap((entry) => entry.source ? [entry.source] : []))] : [],
|
|
38
|
+
capabilitiesChanged
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
const buildSurveyAssistantRequestContext = ({ changeCollector, identity, snapshot, previousSettledVersion = null, trustedCapabilities = defaultSurveyAssistantCapabilitySet, attachmentAccess, modelAttachments = [], modelSelection }) => {
|
|
42
|
+
const requestContext = new RequestContext();
|
|
43
|
+
requestContext.set("invocation", { kind: "chat" });
|
|
44
|
+
requestContext.set("turnId", changeCollector.turnId);
|
|
45
|
+
requestContext.set("changeCollector", changeCollector);
|
|
46
|
+
requestContext.set("identity", identity);
|
|
47
|
+
if (identity.authority === "authenticated-host") {
|
|
48
|
+
requestContext.set("authenticatedResourceId", identity.resourceId);
|
|
49
|
+
requestContext.set("authorizedThreadId", identity.threadId);
|
|
50
|
+
}
|
|
51
|
+
requestContext.set(MASTRA_RESOURCE_ID_KEY, identity.resourceId);
|
|
52
|
+
requestContext.set(MASTRA_THREAD_ID_KEY, identity.threadId);
|
|
53
|
+
const documentTransition = deriveSurveyAssistantDocumentTransition({
|
|
54
|
+
current: snapshot,
|
|
55
|
+
previous: previousSettledVersion
|
|
56
|
+
});
|
|
57
|
+
if (documentTransition) requestContext.set("documentTransition", documentTransition);
|
|
58
|
+
if (attachmentAccess && attachmentAccess.documents.length > 0) requestContext.set("attachmentAccess", attachmentAccess);
|
|
59
|
+
if (modelAttachments.length > 0) requestContext.set("modelAttachments", modelAttachments);
|
|
60
|
+
if (modelSelection) requestContext.set("modelSelection", modelSelection);
|
|
61
|
+
if (!snapshot) return requestContext;
|
|
62
|
+
const engineContext = createSurveyAssistantEngineContext(snapshot, trustedCapabilities);
|
|
63
|
+
requestContext.set("documentSnapshot", snapshot);
|
|
64
|
+
requestContext.set("engineContext", engineContext);
|
|
65
|
+
return requestContext;
|
|
66
|
+
};
|
|
67
|
+
const requireSurveyAssistantTurnState = (requestContext) => {
|
|
68
|
+
const turnId = requestContext?.get("turnId");
|
|
69
|
+
const changeCollector = requestContext?.get("changeCollector");
|
|
70
|
+
if (!turnId || !changeCollector || changeCollector.turnId !== turnId) throw new Error("Survey assistant turn context is unavailable or inconsistent.");
|
|
71
|
+
return {
|
|
72
|
+
turnId,
|
|
73
|
+
changeCollector
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
//#endregion
|
|
77
|
+
export { requireSurveyAssistantTurnState as a, parseSurveyAssistantSnapshot as i, deriveSurveyAssistantDocumentTransition as n, parseSurveyAssistantPreviousSettledVersion as r, buildSurveyAssistantRequestContext as t };
|
|
78
|
+
|
|
79
|
+
//# sourceMappingURL=request-context-BDBw4-Gw.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-context-BDBw4-Gw.mjs","names":[],"sources":["../src/server/request-context.ts"],"sourcesContent":["import {\n MASTRA_RESOURCE_ID_KEY,\n MASTRA_THREAD_ID_KEY,\n RequestContext,\n} from \"@mastra/core/request-context\";\nimport {\n surveyAssistantSnapshotPayloadSchema,\n surveyDocumentVersionSchema,\n type SurveyDocumentSnapshot,\n type SurveyDocumentVersion,\n} from \"../protocol\";\nimport {\n createSurveyAssistantEngineContext,\n TurnChangeCollector,\n type SurveyAssistantCapabilitySet,\n type SurveyAssistantEngineContext,\n} from \"../engine\";\nimport { defaultSurveyAssistantCapabilitySet } from \"../capabilities/default\";\nimport type {\n SurveyAssistantAttachmentAccess,\n SurveyAssistantModelAttachment,\n} from \"./thread-documents\";\n\nexport interface SurveyAssistantInvocationContext {\n kind: \"chat\";\n}\n\nexport interface SurveyAssistantIdentityContext {\n authority: \"experimental-client-request\" | \"authenticated-host\";\n resourceId: string;\n surveyId?: string;\n threadId: string;\n}\n\nexport interface SurveyAssistantModelSelection {\n id: string;\n model: string;\n}\n\nexport type SurveyAssistantDocumentTransition =\n | { status: \"no-baseline\" }\n | {\n status: \"session-changed\";\n previousHistoryIndex: number;\n currentHistoryIndex: number;\n }\n | {\n status: \"unchanged\";\n previousHistoryIndex: number;\n currentHistoryIndex: number;\n capabilitiesChanged: boolean;\n }\n | {\n status: \"changed\";\n previousHistoryIndex: number;\n currentHistoryIndex: number;\n historyDirection: \"backward\" | \"forward\" | \"same-index\";\n recordedSources: Array<\"user\" | \"system\" | \"assistant\">;\n capabilitiesChanged: boolean;\n };\n\nexport interface SurveyAssistantRequestContext {\n invocation: SurveyAssistantInvocationContext;\n turnId: string;\n changeCollector: TurnChangeCollector;\n identity: SurveyAssistantIdentityContext;\n authenticatedResourceId?: string;\n authorizedThreadId?: string;\n applyPolicy?: \"auto\" | \"review\" | \"deny\";\n mastra__resourceId?: string;\n mastra__threadId?: string;\n documentTransition?: SurveyAssistantDocumentTransition;\n engineContext?: SurveyAssistantEngineContext;\n documentSnapshot?: SurveyDocumentSnapshot;\n modelAttachments?: SurveyAssistantModelAttachment[];\n attachmentAccess?: SurveyAssistantAttachmentAccess;\n modelSelection?: SurveyAssistantModelSelection;\n}\n\nexport const parseSurveyAssistantSnapshot = (value: unknown): SurveyDocumentSnapshot | null => {\n if (value === undefined || value === null) {\n return null;\n }\n\n return surveyAssistantSnapshotPayloadSchema.parse(value);\n};\n\nexport const parseSurveyAssistantPreviousSettledVersion = (\n value: unknown,\n): SurveyDocumentVersion | null => {\n if (value === undefined || value === null) {\n return null;\n }\n\n return surveyDocumentVersionSchema.parse(value);\n};\n\nexport const deriveSurveyAssistantDocumentTransition = ({\n current,\n previous,\n}: {\n current: SurveyDocumentSnapshot | null;\n previous: SurveyDocumentVersion | null;\n}): SurveyAssistantDocumentTransition | undefined => {\n if (!current) return undefined;\n if (!previous) return { status: \"no-baseline\" };\n\n const previousHistoryIndex = previous.historyIndex;\n const currentHistoryIndex = current.version.historyIndex;\n if (previous.sessionId !== current.version.sessionId) {\n return {\n status: \"session-changed\",\n previousHistoryIndex,\n currentHistoryIndex,\n };\n }\n\n const capabilitiesChanged = previous.capabilityDigest !== current.version.capabilityDigest;\n if (previous.contentHash === current.version.contentHash) {\n return {\n status: \"unchanged\",\n previousHistoryIndex,\n currentHistoryIndex,\n capabilitiesChanged,\n };\n }\n\n const historyDirection =\n currentHistoryIndex > previousHistoryIndex\n ? \"forward\"\n : currentHistoryIndex < previousHistoryIndex\n ? \"backward\"\n : \"same-index\";\n const recordedSources =\n historyDirection === \"forward\"\n ? [\n ...new Set(\n (current.ui.history?.recent ?? [])\n .filter(\n (entry) => entry.index > previousHistoryIndex && entry.index <= currentHistoryIndex,\n )\n .flatMap((entry) => (entry.source ? [entry.source] : [])),\n ),\n ]\n : [];\n\n return {\n status: \"changed\",\n previousHistoryIndex,\n currentHistoryIndex,\n historyDirection,\n recordedSources,\n capabilitiesChanged,\n };\n};\n\nexport const buildSurveyAssistantRequestContext = ({\n changeCollector,\n identity,\n snapshot,\n previousSettledVersion = null,\n trustedCapabilities = defaultSurveyAssistantCapabilitySet,\n attachmentAccess,\n modelAttachments = [],\n modelSelection,\n}: {\n changeCollector: TurnChangeCollector;\n identity: SurveyAssistantIdentityContext;\n snapshot: SurveyDocumentSnapshot | null;\n previousSettledVersion?: SurveyDocumentVersion | null;\n trustedCapabilities?: SurveyAssistantCapabilitySet;\n attachmentAccess?: SurveyAssistantAttachmentAccess;\n modelAttachments?: SurveyAssistantModelAttachment[];\n modelSelection?: SurveyAssistantModelSelection;\n}): RequestContext<SurveyAssistantRequestContext> => {\n const requestContext = new RequestContext<SurveyAssistantRequestContext>();\n\n requestContext.set(\"invocation\", { kind: \"chat\" });\n requestContext.set(\"turnId\", changeCollector.turnId);\n requestContext.set(\"changeCollector\", changeCollector);\n requestContext.set(\"identity\", identity);\n if (identity.authority === \"authenticated-host\") {\n requestContext.set(\"authenticatedResourceId\", identity.resourceId);\n requestContext.set(\"authorizedThreadId\", identity.threadId);\n }\n requestContext.set(MASTRA_RESOURCE_ID_KEY, identity.resourceId);\n requestContext.set(MASTRA_THREAD_ID_KEY, identity.threadId);\n const documentTransition = deriveSurveyAssistantDocumentTransition({\n current: snapshot,\n previous: previousSettledVersion,\n });\n if (documentTransition) {\n requestContext.set(\"documentTransition\", documentTransition);\n }\n if (attachmentAccess && attachmentAccess.documents.length > 0) {\n requestContext.set(\"attachmentAccess\", attachmentAccess);\n }\n if (modelAttachments.length > 0) {\n requestContext.set(\"modelAttachments\", modelAttachments);\n }\n if (modelSelection) {\n requestContext.set(\"modelSelection\", modelSelection);\n }\n\n if (!snapshot) {\n return requestContext;\n }\n\n const engineContext = createSurveyAssistantEngineContext(snapshot, trustedCapabilities);\n requestContext.set(\"documentSnapshot\", snapshot);\n requestContext.set(\"engineContext\", engineContext);\n\n return requestContext;\n};\n\nexport const requireSurveyAssistantTurnState = (\n requestContext: RequestContext<SurveyAssistantRequestContext> | undefined,\n) => {\n const turnId = requestContext?.get(\"turnId\");\n const changeCollector = requestContext?.get(\"changeCollector\");\n if (!turnId || !changeCollector || changeCollector.turnId !== turnId) {\n throw new Error(\"Survey assistant turn context is unavailable or inconsistent.\");\n }\n\n return { turnId, changeCollector };\n};\n"],"mappings":";;;;;AA+EA,MAAa,gCAAgC,UAAkD;AAC7F,KAAI,UAAU,KAAA,KAAa,UAAU,KACnC,QAAO;AAGT,QAAO,qCAAqC,MAAM,MAAM;;AAG1D,MAAa,8CACX,UACiC;AACjC,KAAI,UAAU,KAAA,KAAa,UAAU,KACnC,QAAO;AAGT,QAAO,4BAA4B,MAAM,MAAM;;AAGjD,MAAa,2CAA2C,EACtD,SACA,eAImD;AACnD,KAAI,CAAC,QAAS,QAAO,KAAA;AACrB,KAAI,CAAC,SAAU,QAAO,EAAE,QAAQ,eAAe;CAE/C,MAAM,uBAAuB,SAAS;CACtC,MAAM,sBAAsB,QAAQ,QAAQ;AAC5C,KAAI,SAAS,cAAc,QAAQ,QAAQ,UACzC,QAAO;EACL,QAAQ;EACR;EACA;EACD;CAGH,MAAM,sBAAsB,SAAS,qBAAqB,QAAQ,QAAQ;AAC1E,KAAI,SAAS,gBAAgB,QAAQ,QAAQ,YAC3C,QAAO;EACL,QAAQ;EACR;EACA;EACA;EACD;CAGH,MAAM,mBACJ,sBAAsB,uBAClB,YACA,sBAAsB,uBACpB,aACA;AAcR,QAAO;EACL,QAAQ;EACR;EACA;EACA;EACA,iBAjBA,qBAAqB,YACjB,CACE,GAAG,IAAI,KACJ,QAAQ,GAAG,SAAS,UAAU,EAAE,EAC9B,QACE,UAAU,MAAM,QAAQ,wBAAwB,MAAM,SAAS,oBACjE,CACA,SAAS,UAAW,MAAM,SAAS,CAAC,MAAM,OAAO,GAAG,EAAE,CAAE,CAC5D,CACF,GACD,EAAE;EAQN;EACD;;AAGH,MAAa,sCAAsC,EACjD,iBACA,UACA,UACA,yBAAyB,MACzB,sBAAsB,qCACtB,kBACA,mBAAmB,EAAE,EACrB,qBAUmD;CACnD,MAAM,iBAAiB,IAAI,gBAA+C;AAE1E,gBAAe,IAAI,cAAc,EAAE,MAAM,QAAQ,CAAC;AAClD,gBAAe,IAAI,UAAU,gBAAgB,OAAO;AACpD,gBAAe,IAAI,mBAAmB,gBAAgB;AACtD,gBAAe,IAAI,YAAY,SAAS;AACxC,KAAI,SAAS,cAAc,sBAAsB;AAC/C,iBAAe,IAAI,2BAA2B,SAAS,WAAW;AAClE,iBAAe,IAAI,sBAAsB,SAAS,SAAS;;AAE7D,gBAAe,IAAI,wBAAwB,SAAS,WAAW;AAC/D,gBAAe,IAAI,sBAAsB,SAAS,SAAS;CAC3D,MAAM,qBAAqB,wCAAwC;EACjE,SAAS;EACT,UAAU;EACX,CAAC;AACF,KAAI,mBACF,gBAAe,IAAI,sBAAsB,mBAAmB;AAE9D,KAAI,oBAAoB,iBAAiB,UAAU,SAAS,EAC1D,gBAAe,IAAI,oBAAoB,iBAAiB;AAE1D,KAAI,iBAAiB,SAAS,EAC5B,gBAAe,IAAI,oBAAoB,iBAAiB;AAE1D,KAAI,eACF,gBAAe,IAAI,kBAAkB,eAAe;AAGtD,KAAI,CAAC,SACH,QAAO;CAGT,MAAM,gBAAgB,mCAAmC,UAAU,oBAAoB;AACvF,gBAAe,IAAI,oBAAoB,SAAS;AAChD,gBAAe,IAAI,iBAAiB,cAAc;AAElD,QAAO;;AAGT,MAAa,mCACX,mBACG;CACH,MAAM,SAAS,gBAAgB,IAAI,SAAS;CAC5C,MAAM,kBAAkB,gBAAgB,IAAI,kBAAkB;AAC9D,KAAI,CAAC,UAAU,CAAC,mBAAmB,gBAAgB,WAAW,OAC5D,OAAM,IAAI,MAAM,gEAAgE;AAGlF,QAAO;EAAE;EAAQ;EAAiB"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
//#region src/server/request-guardrails.ts
|
|
2
|
+
const SURVEY_ASSISTANT_MAX_REQUEST_BYTES = 20 * 1024 * 1024;
|
|
3
|
+
const SURVEY_ASSISTANT_MAX_MESSAGES = 32;
|
|
4
|
+
const SURVEY_ASSISTANT_MAX_ATTACHMENTS = 4;
|
|
5
|
+
const SURVEY_ASSISTANT_MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
|
|
6
|
+
const SURVEY_ASSISTANT_MAX_TOTAL_ATTACHMENT_BYTES = 12 * 1024 * 1024;
|
|
7
|
+
const SURVEY_ASSISTANT_MAX_TEXT_PART_CHARS = 64e3;
|
|
8
|
+
const SURVEY_ASSISTANT_MAX_ATTACHMENT_NAME_CHARS = 255;
|
|
9
|
+
const SURVEY_ASSISTANT_ACCEPTED_ATTACHMENT_TYPES = new Set([
|
|
10
|
+
"application/pdf",
|
|
11
|
+
"image/gif",
|
|
12
|
+
"image/jpeg",
|
|
13
|
+
"image/png",
|
|
14
|
+
"image/webp"
|
|
15
|
+
]);
|
|
16
|
+
const SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS = Object.freeze({
|
|
17
|
+
acceptedAttachmentTypes: SURVEY_ASSISTANT_ACCEPTED_ATTACHMENT_TYPES,
|
|
18
|
+
maxAttachmentBytes: SURVEY_ASSISTANT_MAX_ATTACHMENT_BYTES,
|
|
19
|
+
maxAttachmentNameChars: 255,
|
|
20
|
+
maxAttachments: 4,
|
|
21
|
+
maxMessages: 32,
|
|
22
|
+
maxRequestBytes: SURVEY_ASSISTANT_MAX_REQUEST_BYTES,
|
|
23
|
+
maxTextPartChars: SURVEY_ASSISTANT_MAX_TEXT_PART_CHARS,
|
|
24
|
+
maxTotalAttachmentBytes: SURVEY_ASSISTANT_MAX_TOTAL_ATTACHMENT_BYTES
|
|
25
|
+
});
|
|
26
|
+
var SurveyAssistantRequestError = class extends Error {
|
|
27
|
+
status;
|
|
28
|
+
constructor(message, status = 400) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = "SurveyAssistantRequestError";
|
|
31
|
+
this.status = status;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const attachmentSignatures = {
|
|
35
|
+
"application/pdf": (bytes) => bytes[0] === 37 && bytes[1] === 80 && bytes[2] === 68 && bytes[3] === 70,
|
|
36
|
+
"image/gif": (bytes) => String.fromCharCode(...bytes.slice(0, 6)) === "GIF87a" || String.fromCharCode(...bytes.slice(0, 6)) === "GIF89a",
|
|
37
|
+
"image/jpeg": (bytes) => bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255,
|
|
38
|
+
"image/png": (bytes) => [
|
|
39
|
+
137,
|
|
40
|
+
80,
|
|
41
|
+
78,
|
|
42
|
+
71,
|
|
43
|
+
13,
|
|
44
|
+
10,
|
|
45
|
+
26,
|
|
46
|
+
10
|
|
47
|
+
].every((value, index) => bytes[index] === value),
|
|
48
|
+
"image/webp": (bytes) => String.fromCharCode(...bytes.slice(0, 4)) === "RIFF" && String.fromCharCode(...bytes.slice(8, 12)) === "WEBP"
|
|
49
|
+
};
|
|
50
|
+
const decodeBase64Prefix = (payload) => {
|
|
51
|
+
try {
|
|
52
|
+
const binary = atob(payload.slice(0, 24));
|
|
53
|
+
return Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
54
|
+
} catch {
|
|
55
|
+
throw new SurveyAssistantRequestError("The survey assistant attachment is malformed.");
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const getDataUrlBytes = (url, expectedMediaType) => {
|
|
59
|
+
const match = /^data:([^;,]+);base64,([A-Za-z0-9+/]*={0,2})$/.exec(url);
|
|
60
|
+
if (!match) throw new SurveyAssistantRequestError("Attachments must be base64 data URLs.");
|
|
61
|
+
if (match[1]?.toLowerCase() !== expectedMediaType.toLowerCase()) throw new SurveyAssistantRequestError("Attachment media type does not match its data URL.");
|
|
62
|
+
const payload = match[2] ?? "";
|
|
63
|
+
const signatureMatches = attachmentSignatures[expectedMediaType.toLowerCase()];
|
|
64
|
+
if (signatureMatches && !signatureMatches(decodeBase64Prefix(payload))) throw new SurveyAssistantRequestError("Attachment content does not match its declared media type.");
|
|
65
|
+
const padding = payload.endsWith("==") ? 2 : payload.endsWith("=") ? 1 : 0;
|
|
66
|
+
return Math.max(0, Math.floor(payload.length * 3 / 4) - padding);
|
|
67
|
+
};
|
|
68
|
+
const validateSurveyAssistantMessages = (value, limits = SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS) => {
|
|
69
|
+
if (!Array.isArray(value) || value.length === 0) throw new SurveyAssistantRequestError("A survey assistant message is required.");
|
|
70
|
+
if (value.length > limits.maxMessages) throw new SurveyAssistantRequestError("The survey assistant request contains too many messages.");
|
|
71
|
+
if (value.length !== 1 || value[0]?.role !== "user") throw new SurveyAssistantRequestError("The survey assistant request must contain only the current user message.");
|
|
72
|
+
let attachmentCount = 0;
|
|
73
|
+
let totalAttachmentBytes = 0;
|
|
74
|
+
for (const message of value) {
|
|
75
|
+
if (!message || typeof message !== "object" || !Array.isArray(message.parts)) throw new SurveyAssistantRequestError("The survey assistant messages are malformed.");
|
|
76
|
+
for (const part of message.parts) {
|
|
77
|
+
if (!part || typeof part !== "object" || typeof part.type !== "string") throw new SurveyAssistantRequestError("A survey assistant message part is malformed.");
|
|
78
|
+
if (part.type === "text") {
|
|
79
|
+
if (typeof part.text !== "string") throw new SurveyAssistantRequestError("A survey assistant text part is malformed.");
|
|
80
|
+
if (part.text.length > limits.maxTextPartChars) throw new SurveyAssistantRequestError("A survey assistant message is too long.");
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (part.type !== "file") throw new SurveyAssistantRequestError("The survey assistant message part is not supported.");
|
|
84
|
+
attachmentCount += 1;
|
|
85
|
+
if (attachmentCount > limits.maxAttachments) throw new SurveyAssistantRequestError("The survey assistant request has too many attachments.");
|
|
86
|
+
if (typeof part.mediaType !== "string" || !limits.acceptedAttachmentTypes.has(part.mediaType.toLowerCase())) throw new SurveyAssistantRequestError("The survey assistant attachment type is not supported.");
|
|
87
|
+
if (typeof part.url !== "string") throw new SurveyAssistantRequestError("The survey assistant attachment is malformed.");
|
|
88
|
+
if (part.filename !== void 0 && (typeof part.filename !== "string" || part.filename.length > limits.maxAttachmentNameChars || /[\u0000-\u001f\u007f]/.test(part.filename))) throw new SurveyAssistantRequestError("The survey assistant attachment name is invalid.");
|
|
89
|
+
const bytes = getDataUrlBytes(part.url, part.mediaType);
|
|
90
|
+
if (bytes > limits.maxAttachmentBytes) throw new SurveyAssistantRequestError("A survey assistant attachment is too large.");
|
|
91
|
+
totalAttachmentBytes += bytes;
|
|
92
|
+
if (totalAttachmentBytes > limits.maxTotalAttachmentBytes) throw new SurveyAssistantRequestError("The survey assistant attachments are too large in total.");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return value;
|
|
96
|
+
};
|
|
97
|
+
const readSurveyAssistantRequestJson = async (request, maxRequestBytes = SURVEY_ASSISTANT_MAX_REQUEST_BYTES) => {
|
|
98
|
+
const declaredLength = Number(request.headers.get("content-length"));
|
|
99
|
+
if (Number.isFinite(declaredLength) && declaredLength > maxRequestBytes) throw new SurveyAssistantRequestError("The survey assistant request is too large.", 413);
|
|
100
|
+
const reader = request.body?.getReader();
|
|
101
|
+
const chunks = [];
|
|
102
|
+
let totalBytes = 0;
|
|
103
|
+
if (reader) while (true) {
|
|
104
|
+
const { done, value } = await reader.read();
|
|
105
|
+
if (done) break;
|
|
106
|
+
totalBytes += value.byteLength;
|
|
107
|
+
if (totalBytes > maxRequestBytes) {
|
|
108
|
+
await reader.cancel();
|
|
109
|
+
throw new SurveyAssistantRequestError("The survey assistant request is too large.", 413);
|
|
110
|
+
}
|
|
111
|
+
chunks.push(value);
|
|
112
|
+
}
|
|
113
|
+
const bytes = new Uint8Array(totalBytes);
|
|
114
|
+
let offset = 0;
|
|
115
|
+
for (const chunk of chunks) {
|
|
116
|
+
bytes.set(chunk, offset);
|
|
117
|
+
offset += chunk.byteLength;
|
|
118
|
+
}
|
|
119
|
+
const text = new TextDecoder().decode(bytes);
|
|
120
|
+
try {
|
|
121
|
+
return JSON.parse(text);
|
|
122
|
+
} catch {
|
|
123
|
+
throw new SurveyAssistantRequestError("The survey assistant request is not valid JSON.");
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
//#endregion
|
|
127
|
+
export { SURVEY_ASSISTANT_MAX_ATTACHMENT_NAME_CHARS as a, SURVEY_ASSISTANT_MAX_TEXT_PART_CHARS as c, readSurveyAssistantRequestJson as d, validateSurveyAssistantMessages as f, SURVEY_ASSISTANT_MAX_ATTACHMENT_BYTES as i, SURVEY_ASSISTANT_MAX_TOTAL_ATTACHMENT_BYTES as l, SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS as n, SURVEY_ASSISTANT_MAX_MESSAGES as o, SURVEY_ASSISTANT_MAX_ATTACHMENTS as r, SURVEY_ASSISTANT_MAX_REQUEST_BYTES as s, SURVEY_ASSISTANT_ACCEPTED_ATTACHMENT_TYPES as t, SurveyAssistantRequestError as u };
|
|
128
|
+
|
|
129
|
+
//# sourceMappingURL=request-guardrails-h4t6u8mP.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-guardrails-h4t6u8mP.mjs","names":[],"sources":["../src/server/request-guardrails.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\n\nexport const SURVEY_ASSISTANT_MAX_REQUEST_BYTES = 20 * 1024 * 1024;\nexport const SURVEY_ASSISTANT_MAX_MESSAGES = 32;\nexport const SURVEY_ASSISTANT_MAX_ATTACHMENTS = 4;\nexport const SURVEY_ASSISTANT_MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;\nexport const SURVEY_ASSISTANT_MAX_TOTAL_ATTACHMENT_BYTES = 12 * 1024 * 1024;\nexport const SURVEY_ASSISTANT_MAX_TEXT_PART_CHARS = 64_000;\nexport const SURVEY_ASSISTANT_MAX_ATTACHMENT_NAME_CHARS = 255;\n\nexport const SURVEY_ASSISTANT_ACCEPTED_ATTACHMENT_TYPES = new Set<string>([\n \"application/pdf\",\n \"image/gif\",\n \"image/jpeg\",\n \"image/png\",\n \"image/webp\",\n]);\n\nexport interface SurveyAssistantRequestLimits {\n acceptedAttachmentTypes: ReadonlySet<string>;\n maxAttachmentBytes: number;\n maxAttachmentNameChars: number;\n maxAttachments: number;\n maxMessages: number;\n maxRequestBytes: number;\n maxTextPartChars: number;\n maxTotalAttachmentBytes: number;\n}\n\nexport const SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS: SurveyAssistantRequestLimits = Object.freeze({\n acceptedAttachmentTypes: SURVEY_ASSISTANT_ACCEPTED_ATTACHMENT_TYPES,\n maxAttachmentBytes: SURVEY_ASSISTANT_MAX_ATTACHMENT_BYTES,\n maxAttachmentNameChars: SURVEY_ASSISTANT_MAX_ATTACHMENT_NAME_CHARS,\n maxAttachments: SURVEY_ASSISTANT_MAX_ATTACHMENTS,\n maxMessages: SURVEY_ASSISTANT_MAX_MESSAGES,\n maxRequestBytes: SURVEY_ASSISTANT_MAX_REQUEST_BYTES,\n maxTextPartChars: SURVEY_ASSISTANT_MAX_TEXT_PART_CHARS,\n maxTotalAttachmentBytes: SURVEY_ASSISTANT_MAX_TOTAL_ATTACHMENT_BYTES,\n});\n\nexport class SurveyAssistantRequestError extends Error {\n readonly status: number;\n\n constructor(message: string, status = 400) {\n super(message);\n this.name = \"SurveyAssistantRequestError\";\n this.status = status;\n }\n}\n\nconst attachmentSignatures: Record<string, (bytes: Uint8Array) => boolean> = {\n \"application/pdf\": (bytes) =>\n bytes[0] === 0x25 && bytes[1] === 0x50 && bytes[2] === 0x44 && bytes[3] === 0x46,\n \"image/gif\": (bytes) =>\n String.fromCharCode(...bytes.slice(0, 6)) === \"GIF87a\" ||\n String.fromCharCode(...bytes.slice(0, 6)) === \"GIF89a\",\n \"image/jpeg\": (bytes) => bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff,\n \"image/png\": (bytes) =>\n [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a].every(\n (value, index) => bytes[index] === value,\n ),\n \"image/webp\": (bytes) =>\n String.fromCharCode(...bytes.slice(0, 4)) === \"RIFF\" &&\n String.fromCharCode(...bytes.slice(8, 12)) === \"WEBP\",\n};\n\nconst decodeBase64Prefix = (payload: string) => {\n try {\n const binary = atob(payload.slice(0, 24));\n return Uint8Array.from(binary, (character) => character.charCodeAt(0));\n } catch {\n throw new SurveyAssistantRequestError(\"The survey assistant attachment is malformed.\");\n }\n};\n\nconst getDataUrlBytes = (url: string, expectedMediaType: string): number => {\n const match = /^data:([^;,]+);base64,([A-Za-z0-9+/]*={0,2})$/.exec(url);\n if (!match) {\n throw new SurveyAssistantRequestError(\"Attachments must be base64 data URLs.\");\n }\n if (match[1]?.toLowerCase() !== expectedMediaType.toLowerCase()) {\n throw new SurveyAssistantRequestError(\"Attachment media type does not match its data URL.\");\n }\n\n const payload = match[2] ?? \"\";\n const signatureMatches = attachmentSignatures[expectedMediaType.toLowerCase()];\n if (signatureMatches && !signatureMatches(decodeBase64Prefix(payload))) {\n throw new SurveyAssistantRequestError(\n \"Attachment content does not match its declared media type.\",\n );\n }\n const padding = payload.endsWith(\"==\") ? 2 : payload.endsWith(\"=\") ? 1 : 0;\n return Math.max(0, Math.floor((payload.length * 3) / 4) - padding);\n};\n\nexport const validateSurveyAssistantMessages = (\n value: unknown,\n limits: SurveyAssistantRequestLimits = SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS,\n): UIMessage[] => {\n if (!Array.isArray(value) || value.length === 0) {\n throw new SurveyAssistantRequestError(\"A survey assistant message is required.\");\n }\n if (value.length > limits.maxMessages) {\n throw new SurveyAssistantRequestError(\n \"The survey assistant request contains too many messages.\",\n );\n }\n if (value.length !== 1 || value[0]?.role !== \"user\") {\n throw new SurveyAssistantRequestError(\n \"The survey assistant request must contain only the current user message.\",\n );\n }\n\n let attachmentCount = 0;\n let totalAttachmentBytes = 0;\n for (const message of value) {\n if (!message || typeof message !== \"object\" || !Array.isArray(message.parts)) {\n throw new SurveyAssistantRequestError(\"The survey assistant messages are malformed.\");\n }\n\n for (const part of message.parts) {\n if (!part || typeof part !== \"object\" || typeof part.type !== \"string\") {\n throw new SurveyAssistantRequestError(\"A survey assistant message part is malformed.\");\n }\n if (part.type === \"text\") {\n if (typeof part.text !== \"string\") {\n throw new SurveyAssistantRequestError(\"A survey assistant text part is malformed.\");\n }\n if (part.text.length > limits.maxTextPartChars) {\n throw new SurveyAssistantRequestError(\"A survey assistant message is too long.\");\n }\n continue;\n }\n if (part.type !== \"file\") {\n throw new SurveyAssistantRequestError(\n \"The survey assistant message part is not supported.\",\n );\n }\n\n attachmentCount += 1;\n if (attachmentCount > limits.maxAttachments) {\n throw new SurveyAssistantRequestError(\n \"The survey assistant request has too many attachments.\",\n );\n }\n if (\n typeof part.mediaType !== \"string\" ||\n !limits.acceptedAttachmentTypes.has(part.mediaType.toLowerCase())\n ) {\n throw new SurveyAssistantRequestError(\n \"The survey assistant attachment type is not supported.\",\n );\n }\n if (typeof part.url !== \"string\") {\n throw new SurveyAssistantRequestError(\"The survey assistant attachment is malformed.\");\n }\n if (\n part.filename !== undefined &&\n (typeof part.filename !== \"string\" ||\n part.filename.length > limits.maxAttachmentNameChars ||\n /[\\u0000-\\u001f\\u007f]/.test(part.filename))\n ) {\n throw new SurveyAssistantRequestError(\"The survey assistant attachment name is invalid.\");\n }\n\n const bytes = getDataUrlBytes(part.url, part.mediaType);\n if (bytes > limits.maxAttachmentBytes) {\n throw new SurveyAssistantRequestError(\"A survey assistant attachment is too large.\");\n }\n totalAttachmentBytes += bytes;\n if (totalAttachmentBytes > limits.maxTotalAttachmentBytes) {\n throw new SurveyAssistantRequestError(\n \"The survey assistant attachments are too large in total.\",\n );\n }\n }\n }\n\n return value as UIMessage[];\n};\n\nexport const readSurveyAssistantRequestJson = async (\n request: Request,\n maxRequestBytes = SURVEY_ASSISTANT_MAX_REQUEST_BYTES,\n): Promise<unknown> => {\n const declaredLength = Number(request.headers.get(\"content-length\"));\n if (Number.isFinite(declaredLength) && declaredLength > maxRequestBytes) {\n throw new SurveyAssistantRequestError(\"The survey assistant request is too large.\", 413);\n }\n\n const reader = request.body?.getReader();\n const chunks: Uint8Array[] = [];\n let totalBytes = 0;\n if (reader) {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n totalBytes += value.byteLength;\n if (totalBytes > maxRequestBytes) {\n await reader.cancel();\n throw new SurveyAssistantRequestError(\"The survey assistant request is too large.\", 413);\n }\n chunks.push(value);\n }\n }\n const bytes = new Uint8Array(totalBytes);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n const text = new TextDecoder().decode(bytes);\n\n try {\n return JSON.parse(text) as unknown;\n } catch {\n throw new SurveyAssistantRequestError(\"The survey assistant request is not valid JSON.\");\n }\n};\n"],"mappings":"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"}
|
package/dist/server-agent.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as surveyAssistantTools } from "./index-
|
|
1
|
+
import { o as SurveyAssistantRequestContext, t as SURVEY_ASSISTANT_AGENT_ID } from "./constants-56jf_4ls.mjs";
|
|
2
|
+
import { n as surveyAssistantTools } from "./index-B_x2IYi7.mjs";
|
|
3
3
|
import * as _$_mastra_core_agent0 from "@mastra/core/agent";
|
|
4
4
|
import { Agent, AgentConfig } from "@mastra/core/agent";
|
|
5
5
|
import { Memory } from "@mastra/memory";
|
|
@@ -77,6 +77,8 @@ declare const createSurveyAssistantAgent: ({
|
|
|
77
77
|
survey_authoring_reference: _$_mastra_core_tools0.Tool<{
|
|
78
78
|
topic: string;
|
|
79
79
|
itemType?: string | undefined;
|
|
80
|
+
operationKind?: string | undefined;
|
|
81
|
+
detail?: "full" | "compact" | undefined;
|
|
80
82
|
reason?: string | undefined;
|
|
81
83
|
}, {
|
|
82
84
|
ok: boolean;
|
|
@@ -84,6 +86,8 @@ declare const createSurveyAssistantAgent: ({
|
|
|
84
86
|
title: string;
|
|
85
87
|
content: string;
|
|
86
88
|
itemType?: string | undefined;
|
|
89
|
+
operationKind?: string | undefined;
|
|
90
|
+
detail?: "full" | "compact" | undefined;
|
|
87
91
|
}, unknown, unknown, _$_mastra_core_tools0.ToolExecutionContext<unknown, unknown, unknown>, "survey_authoring_reference", unknown>;
|
|
88
92
|
survey_expression: _$_mastra_core_tools0.Tool<{
|
|
89
93
|
action: "context" | "prepare";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-agent.d.mts","names":[],"sources":["../src/server/agent.ts"],"mappings":";;;;;;;;;cAuBa,wCAAA,EAA0C,cAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"server-agent.d.mts","names":[],"sources":["../src/server/agent.ts"],"mappings":";;;;;;;;;cAuBa,wCAAA,EAA0C,cAAA;AAAA,KAqPlD,0BAAA,GAA6B,WAAA,QACzB,yBAAA,SACA,oBAAA,aAEP,6BAAA;AAAA,KAGG,4BAAA,GAA+B,WAAA,CAClC,WAAA,CAAY,qBAAA,QAA6B,MAAA;AAAA,KAyC/B,yCAAA,GAA4C,OAAA,CACtD,4BAAA;AAAA,KAIG,8CAAA,GAAiD,OAAA,CACpD,IAAA,CAAK,yCAAA;EAEL,KAAA,EAAO,WAAA,CAAY,yCAAA;AAAA;AAAA,cAGR,8CAAA;EAAA;;;;cAMA,+CAAA;EAAmD,KAAA;EAAA,WAAA;EAAA,UAAA;EAAA,GAAA;AAAA,GAK7D,8CAAA,KAAiD,yCAAA;AAAA,UAkCnC,iCAAA;EACf,KAAA,EAAO,0BAAA;EACP,MAAA,GAAS,0BAAA;EACT,mBAAA,GAAsB,yCAAA;AAAA;AAAA,cAGX,0BAAA;EAA8B,MAAA;EAAA,KAAA;EAAA;AAAA,GAIxC,iCAAA,KAAiC,KAAA,2BAAA,QAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAAA,qBAAA,CAAA,oBAAA"}
|