@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.
Files changed (113) hide show
  1. package/README.md +71 -11
  2. package/dist/{authoring-references-X6uRaWuf.mjs → authoring-references-DYuOAdVx.mjs} +26 -2
  3. package/dist/authoring-references-DYuOAdVx.mjs.map +1 -0
  4. package/dist/{capabilities-B6tvE7fK.mjs → capabilities-DZ0a_o2y.mjs} +2 -2
  5. package/dist/{capabilities-B6tvE7fK.mjs.map → capabilities-DZ0a_o2y.mjs.map} +1 -1
  6. package/dist/{capabilities-DvSKtjAw.d.mts → capabilities-DlC1l6qy.d.mts} +4 -1
  7. package/dist/capabilities-DlC1l6qy.d.mts.map +1 -0
  8. package/dist/capabilities-default.d.mts +1 -1
  9. package/dist/capabilities-default.d.mts.map +1 -1
  10. package/dist/capabilities-default.mjs +6 -3
  11. package/dist/capabilities-default.mjs.map +1 -1
  12. package/dist/{constants-Jw0k8ojS.d.mts → constants-56jf_4ls.d.mts} +36 -9
  13. package/dist/constants-56jf_4ls.d.mts.map +1 -0
  14. package/dist/{controller-proxy-BRDusFiO.d.mts → controller-proxy-2VH0b_5E.d.mts} +29 -4
  15. package/dist/controller-proxy-2VH0b_5E.d.mts.map +1 -0
  16. package/dist/{controller-proxy-Duxo2IFE.mjs → controller-proxy-ClsY4lFI.mjs} +74 -5
  17. package/dist/controller-proxy-ClsY4lFI.mjs.map +1 -0
  18. package/dist/{digest-BsoVq49o.d.mts → digest-BvXpeWcR.d.mts} +2 -2
  19. package/dist/{digest-BsoVq49o.d.mts.map → digest-BvXpeWcR.d.mts.map} +1 -1
  20. package/dist/digest.d.mts +1 -1
  21. package/dist/{engine-sPvuixWg.mjs → engine-DQrCO_ur.mjs} +392 -50
  22. package/dist/engine-DQrCO_ur.mjs.map +1 -0
  23. package/dist/engine.d.mts +2 -2
  24. package/dist/engine.mjs +2 -2
  25. package/dist/{index-MpEMQzTm.d.mts → index-B_x2IYi7.d.mts} +5 -1
  26. package/dist/index-B_x2IYi7.d.mts.map +1 -0
  27. package/dist/{index-BWNHkpkh.d.mts → index-C_x686M7.d.mts} +27 -5
  28. package/dist/index-C_x686M7.d.mts.map +1 -0
  29. package/dist/{index-TFtvBiSQ.d.mts → index-DVxVyhAu.d.mts} +31 -9
  30. package/dist/index-DVxVyhAu.d.mts.map +1 -0
  31. package/dist/{index-CUqbBjkc.d.mts → index-DZ6KBwVR.d.mts} +16 -3
  32. package/dist/index-DZ6KBwVR.d.mts.map +1 -0
  33. package/dist/{memory-thread-repository-CJkkVE2-.mjs → memory-thread-repository-Cm1BJyRw.mjs} +110 -41
  34. package/dist/memory-thread-repository-Cm1BJyRw.mjs.map +1 -0
  35. package/dist/{protocol-DV0ka9WT.mjs → protocol-7EEgcYja.mjs} +70 -97
  36. package/dist/protocol-7EEgcYja.mjs.map +1 -0
  37. package/dist/protocol.d.mts +3 -3
  38. package/dist/protocol.mjs +2 -2
  39. package/dist/{react-VuYe-cPh.mjs → react-B_5smfiK.mjs} +145 -38
  40. package/dist/react-B_5smfiK.mjs.map +1 -0
  41. package/dist/react-integration.d.mts +2 -2
  42. package/dist/react-integration.mjs +2 -2
  43. package/dist/react.d.mts +3 -3
  44. package/dist/react.mjs +3 -3
  45. package/dist/references/assistant-operations.md +6 -0
  46. package/dist/references/core-rules.md +6 -0
  47. package/dist/references/embedded-forms.md +21 -14
  48. package/dist/references/expressions.md +3 -0
  49. package/dist/references/item-types.md +37 -10
  50. package/dist/references/source-material-surveys.md +9 -1
  51. package/dist/references/survey-data-model.md +13 -0
  52. package/dist/request-context-BDBw4-Gw.mjs +79 -0
  53. package/dist/request-context-BDBw4-Gw.mjs.map +1 -0
  54. package/dist/request-guardrails-h4t6u8mP.mjs +129 -0
  55. package/dist/request-guardrails-h4t6u8mP.mjs.map +1 -0
  56. package/dist/server-agent.d.mts +6 -2
  57. package/dist/server-agent.d.mts.map +1 -1
  58. package/dist/server-agent.mjs +39 -24
  59. package/dist/server-agent.mjs.map +1 -1
  60. package/dist/server-runtime.d.mts +21 -5
  61. package/dist/server-runtime.d.mts.map +1 -1
  62. package/dist/server-runtime.mjs +98 -32
  63. package/dist/server-runtime.mjs.map +1 -1
  64. package/dist/server-tasks.d.mts +2 -78
  65. package/dist/server-tasks.mjs +103 -46
  66. package/dist/server-tasks.mjs.map +1 -1
  67. package/dist/server-tools.d.mts +1 -1
  68. package/dist/server-tools.mjs +1 -1
  69. package/dist/server.d.mts +89 -21
  70. package/dist/server.d.mts.map +1 -1
  71. package/dist/server.mjs +136 -5
  72. package/dist/server.mjs.map +1 -0
  73. package/dist/storage-postgres.d.mts +12 -2
  74. package/dist/storage-postgres.d.mts.map +1 -1
  75. package/dist/storage-postgres.mjs +11 -6
  76. package/dist/storage-postgres.mjs.map +1 -1
  77. package/dist/tasks-COQnhSeT.d.mts +140 -0
  78. package/dist/tasks-COQnhSeT.d.mts.map +1 -0
  79. package/dist/{thread-documents-DamIq9Od.d.mts → thread-documents-BlxNjc7S.d.mts} +21 -5
  80. package/dist/thread-documents-BlxNjc7S.d.mts.map +1 -0
  81. package/dist/{thread-handlers-DpynUc64.d.mts → thread-handlers-l79JBl5m.d.mts} +38 -5
  82. package/dist/thread-handlers-l79JBl5m.d.mts.map +1 -0
  83. package/dist/{tools-Hz2p7vyv.mjs → tools-DDXaJ8Za.mjs} +257 -38
  84. package/dist/tools-DDXaJ8Za.mjs.map +1 -0
  85. package/dist/ui.d.mts +5 -3
  86. package/dist/ui.d.mts.map +1 -1
  87. package/dist/ui.mjs +91 -12
  88. package/dist/ui.mjs.map +1 -1
  89. package/docs/integration.md +234 -0
  90. package/package.json +9 -7
  91. package/dist/authoring-references-Cy8J-DWt.d.mts +0 -48
  92. package/dist/authoring-references-Cy8J-DWt.d.mts.map +0 -1
  93. package/dist/authoring-references-X6uRaWuf.mjs.map +0 -1
  94. package/dist/capabilities-DvSKtjAw.d.mts.map +0 -1
  95. package/dist/constants-Jw0k8ojS.d.mts.map +0 -1
  96. package/dist/controller-proxy-BRDusFiO.d.mts.map +0 -1
  97. package/dist/controller-proxy-Duxo2IFE.mjs.map +0 -1
  98. package/dist/engine-sPvuixWg.mjs.map +0 -1
  99. package/dist/index-BWNHkpkh.d.mts.map +0 -1
  100. package/dist/index-CUqbBjkc.d.mts.map +0 -1
  101. package/dist/index-MpEMQzTm.d.mts.map +0 -1
  102. package/dist/index-TFtvBiSQ.d.mts.map +0 -1
  103. package/dist/memory-thread-repository-CJkkVE2-.mjs.map +0 -1
  104. package/dist/protocol-DV0ka9WT.mjs.map +0 -1
  105. package/dist/react-VuYe-cPh.mjs.map +0 -1
  106. package/dist/request-context-jcmXT_Q2.mjs +0 -44
  107. package/dist/request-context-jcmXT_Q2.mjs.map +0 -1
  108. package/dist/request-guardrails-C59IWnH8.mjs +0 -73
  109. package/dist/request-guardrails-C59IWnH8.mjs.map +0 -1
  110. package/dist/server-tasks.d.mts.map +0 -1
  111. package/dist/thread-documents-DamIq9Od.d.mts.map +0 -1
  112. package/dist/thread-handlers-DpynUc64.d.mts.map +0 -1
  113. package/dist/tools-Hz2p7vyv.mjs.map +0 -1
@@ -0,0 +1,234 @@
1
+ # Real-host integration
2
+
3
+ This guide is the production integration contract for
4
+ `@case-framework/survey-assistant`. The package remains an embedded Mastra
5
+ runtime: the host owns authentication, survey persistence, route files,
6
+ storage credentials, logs, and deployment policy.
7
+
8
+ ## Compatibility and release gate
9
+
10
+ - Node.js 20 or newer and standard Web `Request`/`Response` route handlers.
11
+ - React and React DOM 19.2 or newer for `/react` and `/ui`.
12
+ - `@case-framework/survey-core` 0.4.2 or newer within the 0.4 line; the
13
+ assistant uses its browser-safe `editor/colors` entry.
14
+ - Install peer versions compatible with the ranges in `package.json`; do not
15
+ mix a newer package with stale generated declarations.
16
+ - Run `pnpm --filter @case-framework/survey-assistant check:release` before
17
+ publishing. It includes typecheck, every entry build, import-boundary checks,
18
+ unit tests, and the clean Next host fixture.
19
+
20
+ Import UI CSS once in the host root:
21
+
22
+ ```ts
23
+ import "@case-framework/survey-assistant/ui.css";
24
+ ```
25
+
26
+ ## 1. Construct storage, runtime, and Mastra
27
+
28
+ Parse an injected environment and keep the result as server-only configuration:
29
+
30
+ ```ts
31
+ import { Mastra } from "@mastra/core/mastra";
32
+ import {
33
+ createSurveyAssistantRuntime,
34
+ parseSurveyAssistantEnvironment,
35
+ } from "@case-framework/survey-assistant/server/runtime";
36
+ import { createSurveyAssistantPostgresRuntime } from "@case-framework/survey-assistant/storage/postgres";
37
+
38
+ const config = parseSurveyAssistantEnvironment(process.env);
39
+ const assistant = createSurveyAssistantRuntime(config);
40
+ const postgres = createSurveyAssistantPostgresRuntime({
41
+ store: { id: "survey-assistant", connectionString: process.env.DATABASE_URL! },
42
+ });
43
+ const mastra = new Mastra({
44
+ agents: assistant.agents,
45
+ gateways: assistant.gateways,
46
+ storage: postgres.storage,
47
+ });
48
+ ```
49
+
50
+ Required provider/storage variables depend on the selected provider. The common
51
+ settings are:
52
+
53
+ ```dotenv
54
+ SURVEY_ASSISTANT_ENABLED=true
55
+ SURVEY_ASSISTANT_PROVIDER=openai
56
+ SURVEY_ASSISTANT_MODEL=gpt-5.4-nano
57
+ # Optional: pin one-shot editor tasks to a separate model.
58
+ # SURVEY_ASSISTANT_TASK_MODEL=gpt-5.4-nano
59
+ # Optional: use a separate model for memory observation and reflection.
60
+ # SURVEY_ASSISTANT_MEMORY_MODEL=gpt-5.4-nano
61
+ OPENAI_API_KEY=...
62
+ DATABASE_URL=...
63
+ ```
64
+
65
+ One deployment uses one provider. `SURVEY_ASSISTANT_MODEL`,
66
+ `SURVEY_ASSISTANT_MODELS`, `SURVEY_ASSISTANT_TASK_MODEL`, and
67
+ `SURVEY_ASSISTANT_MEMORY_MODEL` therefore contain bare model or Azure deployment
68
+ ids, not `provider/model` strings. Provider-prefixed values fail at startup.
69
+
70
+ `SURVEY_ASSISTANT_MODEL` is the default chat model and
71
+ `SURVEY_ASSISTANT_MODELS` is the server-owned chat picker allowlist. When
72
+ `SURVEY_ASSISTANT_TASK_MODEL` is omitted, one-shot tasks follow the
73
+ server-authorized chat selection; setting it pins all built-in tasks to that
74
+ model. The memory model is fixed per runtime and defaults to the configured chat
75
+ default. It is shared by Mastra's Observer and Reflector.
76
+
77
+ This same-provider rule applies to the standard runtime. Hosts that genuinely
78
+ need custom dynamic or cross-provider model routing can compose the exported
79
+ low-level Agent and handler factories instead.
80
+
81
+ Optional operational settings have useful defaults:
82
+
83
+ ```dotenv
84
+ SURVEY_ASSISTANT_MAX_CONCURRENT_REQUESTS=4
85
+ SURVEY_ASSISTANT_MAX_DURATION_MS=180000
86
+ SURVEY_ASSISTANT_MAX_STEPS=48
87
+ SURVEY_ASSISTANT_SEND_REASONING=true
88
+ SURVEY_ASSISTANT_MEMORY_ENABLED=true
89
+ # Optional request policy overrides:
90
+ SURVEY_ASSISTANT_MAX_REQUEST_BYTES=20971520
91
+ SURVEY_ASSISTANT_MAX_ATTACHMENTS=4
92
+ SURVEY_ASSISTANT_MAX_ATTACHMENT_BYTES=5242880
93
+ SURVEY_ASSISTANT_MAX_TOTAL_ATTACHMENT_BYTES=12582912
94
+ SURVEY_ASSISTANT_MAX_TEXT_PART_CHARS=64000
95
+ ```
96
+
97
+ Explicit malformed booleans, enums, or positive integers fail at startup.
98
+ `readinessError` reports missing credentials/storage without exposing them.
99
+
100
+ ## 2. Create one survey lifecycle
101
+
102
+ Create this once on the server, next to the runtime:
103
+
104
+ ```ts
105
+ import {
106
+ createSurveyAssistantSurveyLifecycle,
107
+ SURVEY_ASSISTANT_AGENT_ID,
108
+ } from "@case-framework/survey-assistant/server";
109
+
110
+ const lifecycle = createSurveyAssistantSurveyLifecycle({
111
+ scopeMetadata: { appId: "case-survey-mode", deploymentId: "production" },
112
+ getThreadApi: (surveyId) => `/api/surveys/${encodeURIComponent(surveyId)}/assistant/threads`,
113
+ threadDocuments: postgres.threadDocuments,
114
+ getMemory: async () => {
115
+ const memory = await mastra.getAgent(SURVEY_ASSISTANT_AGENT_ID).getMemory();
116
+ if (!memory) throw new Error("Survey assistant memory is unavailable.");
117
+ return memory;
118
+ },
119
+ });
120
+ ```
121
+
122
+ For every request, the host must first authenticate the user, authorize access
123
+ to the route's survey, and reject activity while that survey is being deleted.
124
+ Only then call:
125
+
126
+ ```ts
127
+ const scoped = lifecycle.forSurvey(survey.id, user.id);
128
+ ```
129
+
130
+ Browser `resourceId`, `surveyId`, and `threadId` values are untrusted matching
131
+ inputs. `scoped.authorizeChat` verifies all three against stored thread
132
+ ownership. `scoped.authorizeTask` verifies task scope. Thread routes use
133
+ `scoped.threadIdentity`.
134
+
135
+ ## 3. Register handlers
136
+
137
+ ```ts
138
+ const handlers = assistant.createHandlers({
139
+ mastra,
140
+ threadDocuments: postgres.threadDocuments,
141
+ authorize: {
142
+ chat: async (input) => (await getScopedSurvey(input.request)).authorizeChat(input),
143
+ task: async (input) => (await getScopedSurvey(input.request)).authorizeTask(input),
144
+ thread: async (request) => (await getScopedSurvey(request)).threadIdentity,
145
+ model: async (request) => {
146
+ await getScopedSurvey(request);
147
+ },
148
+ },
149
+ chat: {
150
+ onStreamError: (error, context) => logger.error({ error, ...context }),
151
+ onTurnMetrics: (event) => metrics.recordAssistantTurn(event),
152
+ },
153
+ });
154
+ ```
155
+
156
+ Expose `handlers.chat`, `handlers.task`, `handlers.models`, and the five thread
157
+ methods from host routes. Keep authentication middleware in front of them.
158
+ Unknown provider and storage errors are deliberately generic on the wire; log
159
+ the original error through the hooks.
160
+
161
+ The built-in limiter is process-local protection against accidental bursts.
162
+ Multi-instance deployments should also enforce user/tenant quotas at the edge
163
+ or in the host authorization layer.
164
+
165
+ ## 4. Wire the editor and panel
166
+
167
+ Use the same trusted scope for the panel and bounded editor tasks:
168
+
169
+ ```tsx
170
+ const assistant = useSurveyEditorAssistantIntegration({
171
+ resourceId: user.id,
172
+ surveyId,
173
+ taskApi: "/api/survey-assistant/tasks",
174
+ });
175
+
176
+ <ConnectedSurveyAssistantPanel
177
+ {...panelProps}
178
+ api="/api/survey-assistant/chat"
179
+ applyPolicy="auto"
180
+ controller={assistant.controller}
181
+ onSettleApply={persistAndAuditAssistantApply}
182
+ />;
183
+ ```
184
+
185
+ `applyPolicy` is required because immediate apply, review, and denial are
186
+ material host decisions. For a real editing host, `onSettleApply` should save
187
+ the already-applied editor state and durable audit receipts. The session remains
188
+ active until it resolves and writes its settled document baseline only after
189
+ success. If it rejects, reconcile or reload the editor state in host code; the
190
+ package cannot roll back host persistence.
191
+
192
+ Use `"review"` with `onReviewChangeSets`. The callback may keep a host approval
193
+ dialog open asynchronously; resolve `true` to apply the exact authorized change
194
+ sets through the normal controller and settlement path, or `false` to leave the
195
+ editor unchanged. A missing or failed review adapter fails the turn instead of
196
+ silently discarding a requested approval. Use `"deny"` for read-only
197
+ deployments. These policies do not remove inspection, chat, tasks, or
198
+ attachments.
199
+
200
+ ## Attachments
201
+
202
+ Uploads remain enabled by default for PDF, GIF, JPEG, PNG, and WebP. The server
203
+ checks request size, count, per-file and total bytes, filename controls, data
204
+ URL/media-type agreement, and common file signatures before provider use.
205
+
206
+ Passing `threadDocuments` enables persistence and safe replay in later turns.
207
+ Passing `false` to the lifecycle means only persistence/replay is disabled;
208
+ current-turn uploads still work. The Postgres repository defaults to 100 stored
209
+ files and 200 MiB per thread, independently from the stricter per-request
210
+ defaults. Both storage limits are configurable when constructing the repository
211
+ or Postgres runtime.
212
+
213
+ For higher-risk deployments, add malware scanning before the route or in a
214
+ host-owned repository wrapper. Never render attachment bytes as executable
215
+ HTML, and keep provider/storage retention in the host privacy policy.
216
+
217
+ ## Cleanup and acceptance
218
+
219
+ Block new activity before deletion, then call `lifecycle.deleteSurvey(surveyId)`
220
+ from an idempotent job. Use `scoped.deleteThreads()` for one user's survey
221
+ chats and `lifecycle.deleteResource(userId)` for account deletion. Provider
222
+ retention, logs, backups, and imported survey assets remain host concerns.
223
+
224
+ Before enabling a real host, verify:
225
+
226
+ - cross-user and cross-survey thread/task requests return not-found or denied;
227
+ - a request abort stops chat and task generation;
228
+ - apply settlement failure does not advance the settled baseline;
229
+ - attachments work in the current turn and replay only within their owner
230
+ thread;
231
+ - request/deadline/concurrency limits produce controlled errors;
232
+ - logs contain resource, survey, thread/turn or task identity without prompts,
233
+ attachment bytes, credentials, or raw provider responses;
234
+ - cleanup is retry-safe and removes thread documents before survey deletion.
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@case-framework/survey-assistant",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Shared protocol, engine, and runtime for the CASE survey assistant.",
5
5
  "license": "ISC",
6
6
  "files": [
7
7
  "dist",
8
+ "docs",
8
9
  "ui.css.d.ts"
9
10
  ],
10
11
  "type": "module",
@@ -96,7 +97,7 @@
96
97
  "tw-animate-css": "^1.4.0",
97
98
  "use-stick-to-bottom": "^1.1.6",
98
99
  "zod": "^4.3.6",
99
- "@case-framework/ui-localization": "0.2.0"
100
+ "@case-framework/ui-localization": "0.2.1"
100
101
  },
101
102
  "devDependencies": {
102
103
  "@ai-sdk/react": "^4.0.10",
@@ -116,18 +117,18 @@
116
117
  "tsdown": "^0.21.10",
117
118
  "typescript": "^6.0.3",
118
119
  "vite": "^8.0.10",
119
- "@case-framework/survey-core": "0.4.2"
120
+ "@case-framework/survey-core": "0.5.0"
120
121
  },
121
122
  "peerDependencies": {
122
123
  "@ai-sdk/react": "^4.0.10",
123
- "@case-framework/survey-core": "^0.4.1",
124
+ "@case-framework/survey-core": "^0.4.2",
124
125
  "@mastra/ai-sdk": "^1.6.0",
125
126
  "@mastra/core": "^1.47.0",
126
127
  "@mastra/memory": "^1.21.2",
127
128
  "@mastra/pg": "^1.14.2",
128
129
  "ai": "^7.0.15",
129
- "react": ">=18.2.0",
130
- "react-dom": ">=18.2.0"
130
+ "react": ">=19.2.0",
131
+ "react-dom": ">=19.2.0"
131
132
  },
132
133
  "peerDependenciesMeta": {
133
134
  "@mastra/ai-sdk": {
@@ -161,6 +162,7 @@
161
162
  "typecheck": "tsc --noEmit",
162
163
  "check:imports": "node scripts/check-protocol-imports.mjs",
163
164
  "check:next-host": "node scripts/check-next-host-fixture.mjs",
164
- "check": "pnpm typecheck && pnpm build && pnpm check:imports && pnpm test"
165
+ "check": "pnpm typecheck && pnpm build && pnpm check:imports && pnpm test",
166
+ "check:release": "pnpm check && pnpm check:next-host"
165
167
  }
166
168
  }
@@ -1,48 +0,0 @@
1
- //#region src/server/authoring-references.d.ts
2
- declare const surveyAuthoringReferenceTopics: readonly ["core-rules", "survey-data-model", "source-material-surveys", "localization", "rich-text-content", "item-types", "embedded-forms", "expressions", "assistant-operations", "survey-quality"];
3
- type SurveyAuthoringReferenceTopic = (typeof surveyAuthoringReferenceTopics)[number];
4
- declare const surveyAuthoringReferences: {
5
- readonly "core-rules": {
6
- readonly title: "Core authoring rules";
7
- readonly content: string;
8
- };
9
- readonly "survey-data-model": {
10
- readonly title: "Survey data model";
11
- readonly content: string;
12
- };
13
- readonly "source-material-surveys": {
14
- readonly title: "Source-material survey implementation";
15
- readonly content: string;
16
- };
17
- readonly localization: {
18
- readonly title: "Survey localization";
19
- readonly content: string;
20
- };
21
- readonly "rich-text-content": {
22
- readonly title: "Rich text content";
23
- readonly content: string;
24
- };
25
- readonly "item-types": {
26
- readonly title: "Item types";
27
- readonly content: string;
28
- };
29
- readonly "embedded-forms": {
30
- readonly title: "Choice option embedded forms";
31
- readonly content: string;
32
- };
33
- readonly expressions: {
34
- readonly title: "Expressions";
35
- readonly content: string;
36
- };
37
- readonly "assistant-operations": {
38
- readonly title: "Assistant operations";
39
- readonly content: string;
40
- };
41
- readonly "survey-quality": {
42
- readonly title: "Survey quality review";
43
- readonly content: string;
44
- };
45
- };
46
- //#endregion
47
- export { surveyAuthoringReferenceTopics as n, surveyAuthoringReferences as r, SurveyAuthoringReferenceTopic as t };
48
- //# sourceMappingURL=authoring-references-Cy8J-DWt.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"authoring-references-Cy8J-DWt.d.mts","names":[],"sources":["../src/server/authoring-references.ts"],"mappings":";cAMa,8BAAA;AAAA,KAaD,6BAAA,WAAwC,8BAAA;AAAA,cAEvC,yBAAA;EAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"authoring-references-X6uRaWuf.mjs","names":[],"sources":["../../../node_modules/.pnpm/tsdown@0.21.10_synckit@0.11.12_typescript@6.0.3/node_modules/tsdown/esm-shims.js","../src/server/authoring-references.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import { readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\nconst loadReference = (fileName: string) =>\n readFileSync(resolve(__dirname, \"references\", fileName), \"utf8\").trim();\n\nexport const surveyAuthoringReferenceTopics = [\n \"core-rules\",\n \"survey-data-model\",\n \"source-material-surveys\",\n \"localization\",\n \"rich-text-content\",\n \"item-types\",\n \"embedded-forms\",\n \"expressions\",\n \"assistant-operations\",\n \"survey-quality\",\n] as const;\n\nexport type SurveyAuthoringReferenceTopic = (typeof surveyAuthoringReferenceTopics)[number];\n\nexport const surveyAuthoringReferences = {\n \"core-rules\": {\n title: \"Core authoring rules\",\n content: loadReference(\"core-rules.md\"),\n },\n \"survey-data-model\": {\n title: \"Survey data model\",\n content: loadReference(\"survey-data-model.md\"),\n },\n \"source-material-surveys\": {\n title: \"Source-material survey implementation\",\n content: loadReference(\"source-material-surveys.md\"),\n },\n localization: {\n title: \"Survey localization\",\n content: loadReference(\"localization.md\"),\n },\n \"rich-text-content\": {\n title: \"Rich text content\",\n content: loadReference(\"rich-text-content.md\"),\n },\n \"item-types\": {\n title: \"Item types\",\n content: loadReference(\"item-types.md\"),\n },\n \"embedded-forms\": {\n title: \"Choice option embedded forms\",\n content: loadReference(\"embedded-forms.md\"),\n },\n expressions: {\n title: \"Expressions\",\n content: loadReference(\"expressions.md\"),\n },\n \"assistant-operations\": {\n title: \"Assistant operations\",\n content: loadReference(\"assistant-operations.md\"),\n },\n \"survey-quality\": {\n title: \"Survey quality review\",\n content: loadReference(\"survey-quality.md\"),\n },\n} as const satisfies Record<SurveyAuthoringReferenceTopic, { title: string; content: string }>;\n"],"x_google_ignoreList":[0],"mappings":";;;;AAIA,MAAM,oBAAoB,cAAc,OAAO,KAAK,IAAI;AACxD,MAAM,mBAAmB,KAAK,QAAQ,aAAa,CAAC;AAEpD,MAAa,YAA4B,4BAAY;;;ACJrD,MAAM,iBAAiB,aACrB,aAAa,QAAQ,WAAW,cAAc,SAAS,EAAE,OAAO,CAAC,MAAM;AAEzE,MAAa,iCAAiC;CAC5C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAID,MAAa,4BAA4B;CACvC,cAAc;EACZ,OAAO;EACP,SAAS,cAAc,gBAAgB;EACxC;CACD,qBAAqB;EACnB,OAAO;EACP,SAAS,cAAc,uBAAuB;EAC/C;CACD,2BAA2B;EACzB,OAAO;EACP,SAAS,cAAc,6BAA6B;EACrD;CACD,cAAc;EACZ,OAAO;EACP,SAAS,cAAc,kBAAkB;EAC1C;CACD,qBAAqB;EACnB,OAAO;EACP,SAAS,cAAc,uBAAuB;EAC/C;CACD,cAAc;EACZ,OAAO;EACP,SAAS,cAAc,gBAAgB;EACxC;CACD,kBAAkB;EAChB,OAAO;EACP,SAAS,cAAc,oBAAoB;EAC5C;CACD,aAAa;EACX,OAAO;EACP,SAAS,cAAc,iBAAiB;EACzC;CACD,wBAAwB;EACtB,OAAO;EACP,SAAS,cAAc,0BAA0B;EAClD;CACD,kBAAkB;EAChB,OAAO;EACP,SAAS,cAAc,oBAAoB;EAC5C;CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"capabilities-DvSKtjAw.d.mts","names":[],"sources":["../src/protocol/capabilities.ts"],"mappings":";;;cAGa,6BAAA,EAA6B,CAAA,CAAA,OAAA;;;;;cAM7B,6BAAA,EAA6B,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;cAS7B,2BAAA,EAA2B,CAAA,CAAA,SAAA;;;;cAK3B,4BAAA,EAA4B,CAAA,CAAA,SAAA;;;cAI5B,+BAAA,EAA+B,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAc/B,uCAAA,EAAuC,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAKxC,uBAAA,GAA0B,CAAA,CAAE,KAAA,QAAa,6BAAA;AAAA,KACzC,uBAAA,GAA0B,CAAA,CAAE,KAAA,QAAa,6BAAA;AAAA,KACzC,qBAAA,GAAwB,CAAA,CAAE,KAAA,QAAa,2BAAA;AAAA,KACvC,sBAAA,GAAyB,CAAA,CAAE,KAAA,QAAa,4BAAA;AAAA,KACxC,yBAAA,GAA4B,CAAA,CAAE,KAAA,QAAa,+BAAA;AAAA,KAC3C,iCAAA,GAAoC,CAAA,CAAE,KAAA,QACzC,uCAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants-Jw0k8ojS.d.mts","names":[],"sources":["../src/server/request-context.ts","../src/server/constants.ts"],"mappings":";;;;;;UAkBiB,gCAAA;EACf,IAAA;AAAA;AAAA,UAGe,8BAAA;EACf,SAAA;EACA,UAAA;EACA,QAAA;AAAA;AAAA,UAGe,6BAAA;EACf,EAAA;EACA,KAAA;AAAA;AAAA,KAGU,6BAAA;AAAA,UAEK,6BAAA;EACf,UAAA,EAAY,gCAAA;EACZ,MAAA;EACA,eAAA,EAAiB,mBAAA;EACjB,QAAA,EAAU,8BAAA;EACV,uBAAA;EACA,kBAAA;EACA,WAAA;EACA,kBAAA;EACA,gBAAA;EACA,cAAA,GAAiB,6BAAA;EACjB,aAAA,GAAgB,4BAAA;EAChB,gBAAA,GAAmB,sBAAA;EACnB,gBAAA,GAAmB,8BAAA;EACnB,gBAAA,GAAmB,+BAAA;EACnB,cAAA,GAAiB,6BAAA;AAAA;AAAA,cAGN,4BAAA,GAAgC,KAAA,cAAiB,sBAAA;AAAA,cAQjD,kCAAA;EAAsC,eAAA;EAAA,QAAA;EAAA,QAAA;EAAA,cAAA;EAAA,mBAAA;EAAA,gBAAA;EAAA,gBAAA;EAAA;AAAA;EAUjD,eAAA,EAAiB,mBAAA;EACjB,QAAA,EAAU,8BAAA;EACV,QAAA,EAAU,sBAAA;EACV,cAAA,GAAiB,6BAAA;EACjB,mBAAA,GAAsB,4BAAA;EACtB,gBAAA,GAAmB,+BAAA;EACnB,gBAAA,GAAmB,8BAAA;EACnB,cAAA,GAAiB,6BAAA;AAAA,MACf,cAAA,CAAe,6BAAA;AAAA,cAmCN,+BAAA,GACX,cAAA,EAAgB,cAAA,CAAe,6BAAA;;;;;;cCnHpB,yBAAA;AAAA,cACA,8BAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"controller-proxy-BRDusFiO.d.mts","names":[],"sources":["../src/react/task-client.ts","../src/react/controller.ts","../src/react/controller-proxy.ts"],"mappings":";;;UAeiB,gCAAA;EACf,GAAA;EACA,UAAA;AAAA;AAAA,UAGe,mCAAA;EACf,IAAA,GAAO,iCAAA;EACP,OAAA;EACA,MAAA,GAAS,WAAA;AAAA;AAAA,UAGM,yBAAA;EACf,cAAA,CACE,KAAA,EAAO,kCAAA,EACP,OAAA,EAAS,0BAAA,EACT,OAAA,GAAU,mCAAA,GACT,OAAA,CAAQ,mCAAA;EACX,gBAAA,CACE,KAAA,EAAO,oCAAA,EACP,OAAA,EAAS,0BAAA,EACT,OAAA,GAAU,mCAAA,GACT,OAAA,CAAQ,qCAAA;EACX,gBAAA,CACE,KAAA,EAAO,oCAAA,EACP,OAAA,EAAS,0BAAA,EACT,OAAA,GAAU,mCAAA,GACT,OAAA,CAAQ,qCAAA;AAAA;AAAA,UAGI,yCAAA;EACf,IAAA,GAAO,iCAAA;EACP,MAAA,GAAS,WAAA;AAAA;AAAA,UAGM,uCAAA;EACf,UAAA;AAAA;AAAA,UAGe,2BAAA;EACf,cAAA,CACE,KAAA,EAAO,kCAAA,EACP,OAAA,EAAS,0BAAA,EACT,OAAA,GAAU,yCAAA,EACV,KAAA,GAAQ,uCAAA,GACP,OAAA,CAAQ,mCAAA;EACX,gBAAA,CACE,KAAA,EAAO,oCAAA,EACP,OAAA,EAAS,0BAAA,EACT,OAAA,GAAU,yCAAA,EACV,KAAA,GAAQ,uCAAA,GACP,OAAA,CAAQ,qCAAA;EACX,gBAAA,CACE,KAAA,EAAO,oCAAA,EACP,OAAA,EAAS,0BAAA,EACT,OAAA,GAAU,yCAAA,EACV,KAAA,GAAQ,uCAAA,GACP,OAAA,CAAQ,qCAAA;AAAA;AAAA,cAGA,+BAAA;EAAmC,GAAA;EAAA;AAAA,IAG7C,gCAAA,KAAwC,yBAAA;AAAA,cA4C9B,iCAAA,GACX,OAAA,GAAS,gCAAA,KACR,2BAAA;;;UCpHc,yBAAA;EACf,WAAA,IAAe,uBAAA;EACf,oBAAA,EAAsB,MAAA,EAAQ,eAAA,GAAkB,iBAAA;EAChD,qBAAA,EAAuB,OAAA,EAAS,eAAA,KAAoB,sBAAA;AAAA;;;UCPrC,2CAAA;EACf,eAAA;AAAA;AAAA,UAGe,+BAAA;EACf,UAAA,EAAY,yBAAA;EACZ,aAAA,CAAc,UAAA,EAAY,yBAAA;AAAA;AAAA,cAWf,oCAAA,GACX,aAAA,QAAqB,yBAAA;EACrB;AAAA,IAEG,2CAAA,KACF,yBAAA;AAAA,cAUU,qCAAA,GACX,OAAA,GAAU,2CAAA,KACT,+BAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"controller-proxy-Duxo2IFE.mjs","names":[],"sources":["../src/react/client-error.ts","../src/react/task-client.ts","../src/react/controller-proxy.ts"],"sourcesContent":["import { parseSurveyAssistantError, type SurveyAssistantErrorCode } from \"../protocol\";\n\nexport class SurveyAssistantClientError extends Error {\n readonly code: SurveyAssistantErrorCode;\n\n constructor(code: SurveyAssistantErrorCode, message: string) {\n super(message);\n this.name = \"SurveyAssistantClientError\";\n this.code = code;\n }\n}\n\nexport const readSurveyAssistantJson = async (\n response: Response,\n fallback = \"The assistant request could not be completed.\",\n) => {\n const body = await response.json().catch(() => ({}));\n if (!response.ok) {\n const detail = typeof body?.error === \"string\" ? body.error : fallback;\n const parsed = parseSurveyAssistantError(\n typeof body?.code === \"string\" ? { code: body.code, detail } : detail,\n );\n throw new SurveyAssistantClientError(parsed.code, parsed.detail ?? detail);\n }\n return body;\n};\n","import {\n surveyAssistantSuggestItemKeyResultSchema,\n surveyAssistantSuggestItemLabelResultSchema,\n surveyAssistantTranslateContentResultSchema,\n type SurveyAssistantSuggestItemKeyInput,\n type SurveyAssistantSuggestItemKeyResult,\n type SurveyAssistantSuggestItemLabelInput,\n type SurveyAssistantSuggestItemLabelResult,\n type SurveyAssistantTaskContext,\n type SurveyAssistantTaskInvocationMode,\n type SurveyAssistantTranslateContentInput,\n type SurveyAssistantTranslateContentResult,\n} from \"../protocol\";\nimport { readSurveyAssistantJson } from \"./client-error\";\n\nexport interface SurveyAssistantTaskClientOptions {\n api?: string;\n getModelId?: () => string | undefined;\n}\n\nexport interface SurveyAssistantTaskExecutionOptions {\n mode?: SurveyAssistantTaskInvocationMode;\n modelId?: string;\n signal?: AbortSignal;\n}\n\nexport interface SurveyAssistantTaskClient {\n suggestItemKey(\n input: SurveyAssistantSuggestItemKeyInput,\n context: SurveyAssistantTaskContext,\n options?: SurveyAssistantTaskExecutionOptions,\n ): Promise<SurveyAssistantSuggestItemKeyResult>;\n suggestItemLabel(\n input: SurveyAssistantSuggestItemLabelInput,\n context: SurveyAssistantTaskContext,\n options?: SurveyAssistantTaskExecutionOptions,\n ): Promise<SurveyAssistantSuggestItemLabelResult>;\n translateContent(\n input: SurveyAssistantTranslateContentInput,\n context: SurveyAssistantTaskContext,\n options?: SurveyAssistantTaskExecutionOptions,\n ): Promise<SurveyAssistantTranslateContentResult>;\n}\n\nexport interface SurveyAssistantTaskExecutorRequestOptions {\n mode?: SurveyAssistantTaskInvocationMode;\n signal?: AbortSignal;\n}\n\nexport interface SurveyAssistantTaskExecutorCacheContext {\n cacheScope?: string;\n}\n\nexport interface SurveyAssistantTaskExecutor {\n suggestItemKey(\n input: SurveyAssistantSuggestItemKeyInput,\n context: SurveyAssistantTaskContext,\n options?: SurveyAssistantTaskExecutorRequestOptions,\n cache?: SurveyAssistantTaskExecutorCacheContext,\n ): Promise<SurveyAssistantSuggestItemKeyResult>;\n suggestItemLabel(\n input: SurveyAssistantSuggestItemLabelInput,\n context: SurveyAssistantTaskContext,\n options?: SurveyAssistantTaskExecutorRequestOptions,\n cache?: SurveyAssistantTaskExecutorCacheContext,\n ): Promise<SurveyAssistantSuggestItemLabelResult>;\n translateContent(\n input: SurveyAssistantTranslateContentInput,\n context: SurveyAssistantTaskContext,\n options?: SurveyAssistantTaskExecutorRequestOptions,\n cache?: SurveyAssistantTaskExecutorCacheContext,\n ): Promise<SurveyAssistantTranslateContentResult>;\n}\n\nexport const createSurveyAssistantTaskClient = ({\n api = \"/api/survey-assistant/tasks\",\n getModelId,\n}: SurveyAssistantTaskClientOptions = {}): SurveyAssistantTaskClient => {\n const run = async (\n taskId: \"suggest-item-key\" | \"suggest-item-label\" | \"translate-content\",\n input: unknown,\n context: SurveyAssistantTaskContext,\n options?: SurveyAssistantTaskExecutionOptions,\n ) => {\n const modelId = options?.modelId ?? getModelId?.();\n return readSurveyAssistantJson(\n await fetch(api, {\n body: JSON.stringify({\n taskId,\n input,\n context,\n ...(options?.mode ? { mode: options.mode } : {}),\n ...(modelId ? { modelId } : {}),\n }),\n headers: { \"content-type\": \"application/json\" },\n method: \"POST\",\n signal: options?.signal,\n }),\n \"The survey assistant task could not be completed.\",\n );\n };\n\n return {\n async suggestItemKey(input, context, options) {\n return surveyAssistantSuggestItemKeyResultSchema.parse(\n await run(\"suggest-item-key\", input, context, options),\n );\n },\n async suggestItemLabel(input, context, options) {\n return surveyAssistantSuggestItemLabelResultSchema.parse(\n await run(\"suggest-item-label\", input, context, options),\n );\n },\n async translateContent(input, context, options) {\n return surveyAssistantTranslateContentResultSchema.parse(\n await run(\"translate-content\", input, context, options),\n );\n },\n };\n};\n\nexport const createSurveyAssistantTaskExecutor = (\n options: SurveyAssistantTaskClientOptions = {},\n): SurveyAssistantTaskExecutor => {\n const client = createSurveyAssistantTaskClient(options);\n const executionOptions = (\n request?: SurveyAssistantTaskExecutorRequestOptions,\n cache?: SurveyAssistantTaskExecutorCacheContext,\n ): SurveyAssistantTaskExecutionOptions => ({\n mode: request?.mode,\n modelId: cache?.cacheScope,\n signal: request?.signal,\n });\n\n return {\n suggestItemKey: (input, context, request, cache) =>\n client.suggestItemKey(input, context, executionOptions(request, cache)),\n suggestItemLabel: (input, context, request, cache) =>\n client.suggestItemLabel(input, context, executionOptions(request, cache)),\n translateContent: (input, context, request, cache) =>\n client.translateContent(input, context, executionOptions(request, cache)),\n };\n};\n","import type { SurveyApplyResult, SurveyBatchApplyResult, SurveyChangeSet } from \"../protocol\";\nimport type { SurveyAssistantController } from \"./controller\";\n\nexport interface CreateSurveyAssistantControllerProxyOptions {\n notReadyMessage?: string;\n}\n\nexport interface SurveyAssistantControllerBridge {\n controller: SurveyAssistantController;\n setController(controller: SurveyAssistantController | null | undefined): void;\n}\n\nconst failedResult = (change: SurveyChangeSet, message: string): SurveyApplyResult => ({\n status: \"failed\",\n changeId: change.id,\n summary: change.summary,\n message,\n appliedOperations: 0,\n});\n\nexport const createSurveyAssistantControllerProxy = (\n getController: () => SurveyAssistantController | null | undefined,\n {\n notReadyMessage = \"The survey editor is not ready.\",\n }: CreateSurveyAssistantControllerProxyOptions = {},\n): SurveyAssistantController => ({\n getSnapshot: () => getController()?.getSnapshot() ?? null,\n applyAssistantChange: (change) =>\n getController()?.applyAssistantChange?.(change) ?? failedResult(change, notReadyMessage),\n applyAssistantChanges: (changes): SurveyBatchApplyResult =>\n getController()?.applyAssistantChanges?.(changes) ?? {\n results: changes.map((change) => failedResult(change, notReadyMessage)),\n },\n});\n\nexport const createSurveyAssistantControllerBridge = (\n options?: CreateSurveyAssistantControllerProxyOptions,\n): SurveyAssistantControllerBridge => {\n let currentController: SurveyAssistantController | null | undefined;\n return {\n controller: createSurveyAssistantControllerProxy(() => currentController, options),\n setController(controller) {\n currentController = controller;\n },\n };\n};\n"],"mappings":";;AAEA,IAAa,6BAAb,cAAgD,MAAM;CACpD;CAEA,YAAY,MAAgC,SAAiB;AAC3D,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,OAAK,OAAO;;;AAIhB,MAAa,0BAA0B,OACrC,UACA,WAAW,oDACR;CACH,MAAM,OAAO,MAAM,SAAS,MAAM,CAAC,aAAa,EAAE,EAAE;AACpD,KAAI,CAAC,SAAS,IAAI;EAChB,MAAM,SAAS,OAAO,MAAM,UAAU,WAAW,KAAK,QAAQ;EAC9D,MAAM,SAAS,0BACb,OAAO,MAAM,SAAS,WAAW;GAAE,MAAM,KAAK;GAAM;GAAQ,GAAG,OAChE;AACD,QAAM,IAAI,2BAA2B,OAAO,MAAM,OAAO,UAAU,OAAO;;AAE5E,QAAO;;;;ACkDT,MAAa,mCAAmC,EAC9C,MAAM,+BACN,eACoC,EAAE,KAAgC;CACtE,MAAM,MAAM,OACV,QACA,OACA,SACA,YACG;EACH,MAAM,UAAU,SAAS,WAAW,cAAc;AAClD,SAAO,wBACL,MAAM,MAAM,KAAK;GACf,MAAM,KAAK,UAAU;IACnB;IACA;IACA;IACA,GAAI,SAAS,OAAO,EAAE,MAAM,QAAQ,MAAM,GAAG,EAAE;IAC/C,GAAI,UAAU,EAAE,SAAS,GAAG,EAAE;IAC/B,CAAC;GACF,SAAS,EAAE,gBAAgB,oBAAoB;GAC/C,QAAQ;GACR,QAAQ,SAAS;GAClB,CAAC,EACF,oDACD;;AAGH,QAAO;EACL,MAAM,eAAe,OAAO,SAAS,SAAS;AAC5C,UAAO,0CAA0C,MAC/C,MAAM,IAAI,oBAAoB,OAAO,SAAS,QAAQ,CACvD;;EAEH,MAAM,iBAAiB,OAAO,SAAS,SAAS;AAC9C,UAAO,4CAA4C,MACjD,MAAM,IAAI,sBAAsB,OAAO,SAAS,QAAQ,CACzD;;EAEH,MAAM,iBAAiB,OAAO,SAAS,SAAS;AAC9C,UAAO,4CAA4C,MACjD,MAAM,IAAI,qBAAqB,OAAO,SAAS,QAAQ,CACxD;;EAEJ;;AAGH,MAAa,qCACX,UAA4C,EAAE,KACd;CAChC,MAAM,SAAS,gCAAgC,QAAQ;CACvD,MAAM,oBACJ,SACA,WACyC;EACzC,MAAM,SAAS;EACf,SAAS,OAAO;EAChB,QAAQ,SAAS;EAClB;AAED,QAAO;EACL,iBAAiB,OAAO,SAAS,SAAS,UACxC,OAAO,eAAe,OAAO,SAAS,iBAAiB,SAAS,MAAM,CAAC;EACzE,mBAAmB,OAAO,SAAS,SAAS,UAC1C,OAAO,iBAAiB,OAAO,SAAS,iBAAiB,SAAS,MAAM,CAAC;EAC3E,mBAAmB,OAAO,SAAS,SAAS,UAC1C,OAAO,iBAAiB,OAAO,SAAS,iBAAiB,SAAS,MAAM,CAAC;EAC5E;;;;ACjIH,MAAM,gBAAgB,QAAyB,aAAwC;CACrF,QAAQ;CACR,UAAU,OAAO;CACjB,SAAS,OAAO;CAChB;CACA,mBAAmB;CACpB;AAED,MAAa,wCACX,eACA,EACE,kBAAkB,sCAC6B,EAAE,MACpB;CAC/B,mBAAmB,eAAe,EAAE,aAAa,IAAI;CACrD,uBAAuB,WACrB,eAAe,EAAE,uBAAuB,OAAO,IAAI,aAAa,QAAQ,gBAAgB;CAC1F,wBAAwB,YACtB,eAAe,EAAE,wBAAwB,QAAQ,IAAI,EACnD,SAAS,QAAQ,KAAK,WAAW,aAAa,QAAQ,gBAAgB,CAAC,EACxE;CACJ;AAED,MAAa,yCACX,YACoC;CACpC,IAAI;AACJ,QAAO;EACL,YAAY,2CAA2C,mBAAmB,QAAQ;EAClF,cAAc,YAAY;AACxB,uBAAoB;;EAEvB"}