@case-framework/survey-assistant 0.3.0 → 0.5.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 (79) hide show
  1. package/README.md +20 -4
  2. package/dist/capabilities-default.d.mts +1 -1
  3. package/dist/capabilities-default.mjs +1 -1
  4. package/dist/{constants-DrGZXtQf.d.mts → constants-DbrJxxOh.d.mts} +5 -2
  5. package/dist/constants-DbrJxxOh.d.mts.map +1 -0
  6. package/dist/{controller-proxy-DmBdzqKs.d.mts → controller-proxy-BdKF2yrq.d.mts} +2 -2
  7. package/dist/{controller-proxy-DmBdzqKs.d.mts.map → controller-proxy-BdKF2yrq.d.mts.map} +1 -1
  8. package/dist/{controller-proxy-CpkQRezb.mjs → controller-proxy-jWIPOZAv.mjs} +17 -8
  9. package/dist/controller-proxy-jWIPOZAv.mjs.map +1 -0
  10. package/dist/{engine-CWTuN3o2.mjs → engine-DcSdLRle.mjs} +172 -12
  11. package/dist/engine-DcSdLRle.mjs.map +1 -0
  12. package/dist/engine.d.mts +2 -2
  13. package/dist/engine.mjs +3 -3
  14. package/dist/{form-authoring-DCd9XfXf.mjs → form-authoring-BQh40yDb.mjs} +2 -2
  15. package/dist/{form-authoring-DCd9XfXf.mjs.map → form-authoring-BQh40yDb.mjs.map} +1 -1
  16. package/dist/{index-D4OitUg4.d.mts → index-BApnIiCI.d.mts} +7 -4
  17. package/dist/index-BApnIiCI.d.mts.map +1 -0
  18. package/dist/{index-Bo4dHAo8.d.mts → index-Da_Hb9-1.d.mts} +28 -4
  19. package/dist/index-Da_Hb9-1.d.mts.map +1 -0
  20. package/dist/{index-DZk20e3k.d.mts → index-DhNQKOwr.d.mts} +9 -5
  21. package/dist/index-DhNQKOwr.d.mts.map +1 -0
  22. package/dist/{index-Dxgg0-D_.d.mts → index-dV6df0W3.d.mts} +11 -5
  23. package/dist/index-dV6df0W3.d.mts.map +1 -0
  24. package/dist/{memory-thread-repository-acbz6HZJ.mjs → memory-thread-repository-CvYZwni6.mjs} +87 -28
  25. package/dist/memory-thread-repository-CvYZwni6.mjs.map +1 -0
  26. package/dist/{protocol-DATvkr1S.mjs → protocol-DJUP4gc0.mjs} +10 -4
  27. package/dist/protocol-DJUP4gc0.mjs.map +1 -0
  28. package/dist/protocol.d.mts +1 -1
  29. package/dist/protocol.mjs +1 -1
  30. package/dist/{react-Br5YE8H-.mjs → react-CY6N7lVi.mjs} +25 -5
  31. package/dist/react-CY6N7lVi.mjs.map +1 -0
  32. package/dist/react-integration.d.mts +1 -1
  33. package/dist/react-integration.mjs +1 -1
  34. package/dist/react.d.mts +2 -2
  35. package/dist/react.mjs +2 -2
  36. package/dist/{request-context-BEjnaaFr.mjs → request-context-D1sC54ZA.mjs} +3 -3
  37. package/dist/request-context-D1sC54ZA.mjs.map +1 -0
  38. package/dist/server-agent.d.mts +8 -6
  39. package/dist/server-agent.d.mts.map +1 -1
  40. package/dist/server-agent.mjs +4 -3
  41. package/dist/server-agent.mjs.map +1 -1
  42. package/dist/server-runtime.d.mts +354 -7
  43. package/dist/server-runtime.d.mts.map +1 -1
  44. package/dist/server-runtime.mjs +361 -24
  45. package/dist/server-runtime.mjs.map +1 -1
  46. package/dist/server-tasks.d.mts +1 -1
  47. package/dist/server-tasks.mjs +5 -4
  48. package/dist/server-tasks.mjs.map +1 -1
  49. package/dist/server-tools.d.mts +1 -1
  50. package/dist/server-tools.mjs +1 -1
  51. package/dist/server.d.mts +7 -7
  52. package/dist/server.d.mts.map +1 -1
  53. package/dist/server.mjs +2 -2
  54. package/dist/storage-postgres.mjs +3 -0
  55. package/dist/storage-postgres.mjs.map +1 -1
  56. package/dist/{tasks-DQgL449A.d.mts → tasks-CCtxjhwh.d.mts} +3 -3
  57. package/dist/{tasks-DQgL449A.d.mts.map → tasks-CCtxjhwh.d.mts.map} +1 -1
  58. package/dist/{thread-handlers-CeYl45xG.d.mts → thread-handlers-Bt9cDo-F.d.mts} +21 -6
  59. package/dist/{thread-handlers-CeYl45xG.d.mts.map → thread-handlers-Bt9cDo-F.d.mts.map} +1 -1
  60. package/dist/{tools-Dg9HZrYU.mjs → tools-3tq-XqI0.mjs} +31 -6
  61. package/dist/{tools-Dg9HZrYU.mjs.map → tools-3tq-XqI0.mjs.map} +1 -1
  62. package/dist/ui.css +1 -1
  63. package/dist/ui.d.mts +3 -3
  64. package/dist/ui.d.mts.map +1 -1
  65. package/dist/ui.mjs +438 -140
  66. package/dist/ui.mjs.map +1 -1
  67. package/docs/integration.md +113 -58
  68. package/package.json +3 -3
  69. package/dist/constants-DrGZXtQf.d.mts.map +0 -1
  70. package/dist/controller-proxy-CpkQRezb.mjs.map +0 -1
  71. package/dist/engine-CWTuN3o2.mjs.map +0 -1
  72. package/dist/index-Bo4dHAo8.d.mts.map +0 -1
  73. package/dist/index-D4OitUg4.d.mts.map +0 -1
  74. package/dist/index-DZk20e3k.d.mts.map +0 -1
  75. package/dist/index-Dxgg0-D_.d.mts.map +0 -1
  76. package/dist/memory-thread-repository-acbz6HZJ.mjs.map +0 -1
  77. package/dist/protocol-DATvkr1S.mjs.map +0 -1
  78. package/dist/react-Br5YE8H-.mjs.map +0 -1
  79. package/dist/request-context-BEjnaaFr.mjs.map +0 -1
@@ -1,11 +1,122 @@
1
1
  import { n as SURVEY_ASSISTANT_TASK_AGENT_ID, t as SURVEY_ASSISTANT_AGENT_ID } from "./constants-CFUWrRtl.mjs";
2
2
  import { n as SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS } from "./request-guardrails-h4t6u8mP.mjs";
3
- import { i as createSurveyAssistantChatHandler, n as createSurveyAssistantThreadHandlers, r as SurveyAssistantAuthorizationError, t as createMastraMemoryThreadRepository } from "./memory-thread-repository-acbz6HZJ.mjs";
4
- import { t as SURVEY_ASSISTANT_TOOL_IDS } from "./tools-Dg9HZrYU.mjs";
3
+ import { i as createSurveyAssistantChatHandler, n as createSurveyAssistantThreadHandlers, r as SurveyAssistantAuthorizationError, t as createMastraMemoryThreadRepository } from "./memory-thread-repository-CvYZwni6.mjs";
4
+ import { t as SURVEY_ASSISTANT_TOOL_IDS } from "./tools-3tq-XqI0.mjs";
5
5
  import { SURVEY_ASSISTANT_OBSERVATIONAL_MEMORY_DEFAULTS, createSurveyAssistantAgent, createSurveyAssistantObservationalMemoryOptions } from "./server-agent.mjs";
6
6
  import { createSurveyAssistantTaskAgent, createSurveyAssistantTaskHandler } from "./server-tasks.mjs";
7
+ import { z } from "zod";
7
8
  import { AzureOpenAIGateway } from "@mastra/core/llm";
8
9
  //#region src/server/runtime-config.ts
10
+ const ENVIRONMENT_VARIABLE_NAME = /^[A-Z_][A-Z0-9_]*$/;
11
+ const modelRoleSchema = z.enum([
12
+ "chat-default",
13
+ "chat-picker",
14
+ "memory",
15
+ "task-default"
16
+ ]);
17
+ const providerModelOptionsSchema = z.object({
18
+ parallelToolCalls: z.boolean().optional(),
19
+ promptCacheKey: z.string().trim().min(1).optional(),
20
+ promptCacheRetention: z.enum(["in_memory", "24h"]).optional(),
21
+ reasoningEffort: z.string().trim().min(1).optional(),
22
+ reasoningSummary: z.enum([
23
+ "auto",
24
+ "concise",
25
+ "detailed",
26
+ "off",
27
+ "none"
28
+ ]).optional(),
29
+ serviceTier: z.enum([
30
+ "auto",
31
+ "flex",
32
+ "priority",
33
+ "default"
34
+ ]).optional(),
35
+ textVerbosity: z.enum([
36
+ "low",
37
+ "medium",
38
+ "high"
39
+ ]).optional()
40
+ }).strict();
41
+ const configuredModelSchema = z.object({
42
+ id: z.string().trim().min(1).max(240),
43
+ label: z.string().trim().min(1).max(240).optional(),
44
+ upstreamModel: z.string().trim().min(1).max(240).optional(),
45
+ roles: z.array(modelRoleSchema).min(1),
46
+ options: providerModelOptionsSchema.optional()
47
+ }).strict().superRefine(({ roles }, context) => {
48
+ if (new Set(roles).size !== roles.length) context.addIssue({
49
+ code: "custom",
50
+ message: "Model roles must be unique."
51
+ });
52
+ });
53
+ const providerBaseShape = {
54
+ apiKeyEnv: z.string().regex(ENVIRONMENT_VARIABLE_NAME).optional(),
55
+ models: z.array(configuredModelSchema).min(1),
56
+ options: providerModelOptionsSchema.optional()
57
+ };
58
+ const providerSchema = z.discriminatedUnion("type", [
59
+ z.object({
60
+ ...providerBaseShape,
61
+ type: z.literal("openai"),
62
+ apiKeyEnv: z.string().regex(ENVIRONMENT_VARIABLE_NAME)
63
+ }).strict(),
64
+ z.object({
65
+ ...providerBaseShape,
66
+ type: z.literal("mistral"),
67
+ apiKeyEnv: z.string().regex(ENVIRONMENT_VARIABLE_NAME)
68
+ }).strict(),
69
+ z.object({
70
+ ...providerBaseShape,
71
+ type: z.literal("lmstudio"),
72
+ baseUrl: z.string().url().default("http://127.0.0.1:1234/v1"),
73
+ apiKeyOptional: z.boolean().default(true)
74
+ }).strict(),
75
+ z.object({
76
+ ...providerBaseShape,
77
+ type: z.literal("azure-openai"),
78
+ apiKeyEnv: z.string().regex(ENVIRONMENT_VARIABLE_NAME),
79
+ apiVersion: z.enum(["v1", "preview"]).default("v1"),
80
+ discoverModels: z.boolean().default(false),
81
+ resourceName: z.string().trim().min(1),
82
+ management: z.object({
83
+ tenantId: z.string().trim().min(1),
84
+ clientId: z.string().trim().min(1),
85
+ clientSecretEnv: z.string().regex(ENVIRONMENT_VARIABLE_NAME),
86
+ subscriptionId: z.string().trim().min(1),
87
+ resourceGroup: z.string().trim().min(1)
88
+ }).strict().optional()
89
+ }).strict()
90
+ ]);
91
+ const surveyAssistantConfigurationDocumentSchema = z.object({
92
+ version: z.literal(1),
93
+ activeProvider: z.string().trim().min(1),
94
+ enabled: z.boolean().optional(),
95
+ providers: z.record(z.string().trim().min(1), providerSchema),
96
+ execution: z.object({
97
+ firstResponseTimeoutMs: z.number().int().positive().optional(),
98
+ idleTimeoutMs: z.number().int().positive().optional(),
99
+ maxConcurrentRequests: z.number().int().positive().optional(),
100
+ maxDurationMs: z.number().int().positive().optional(),
101
+ maxSteps: z.number().int().positive().optional(),
102
+ sendReasoning: z.boolean().optional()
103
+ }).strict().optional(),
104
+ memory: z.object({
105
+ enabled: z.boolean().optional(),
106
+ bufferOnIdle: z.boolean().optional(),
107
+ messageTokens: z.number().int().positive().optional(),
108
+ observationTokens: z.number().int().positive().optional(),
109
+ temporalMarkers: z.boolean().optional()
110
+ }).strict().optional(),
111
+ modelCatalogTtlMs: z.number().int().positive().optional(),
112
+ requestLimits: z.object({
113
+ maxAttachmentBytes: z.number().int().positive().optional(),
114
+ maxAttachments: z.number().int().positive().optional(),
115
+ maxRequestBytes: z.number().int().positive().optional(),
116
+ maxTextPartChars: z.number().int().positive().optional(),
117
+ maxTotalAttachmentBytes: z.number().int().positive().optional()
118
+ }).strict().optional()
119
+ }).strict();
9
120
  const DEFAULT_MAX_STEPS = 48;
10
121
  const HARD_MAX_STEPS = 64;
11
122
  const DEFAULT_FIRST_RESPONSE_TIMEOUT_MS = 900 * 1e3;
@@ -45,6 +156,62 @@ const getOptionalSameProviderModelId = (env, name, options) => {
45
156
  return value ? getSameProviderModelId(value, name, options) : void 0;
46
157
  };
47
158
  const resolveSurveyAssistantProviderOptionsKey = (provider) => provider === "azure-openai" ? "azure" : provider;
159
+ const createProviderOptions = (provider, options, sendReasoning) => {
160
+ const providerOptionsKey = resolveSurveyAssistantProviderOptionsKey(provider);
161
+ const reasoningSummary = options?.reasoningSummary === "off" || options?.reasoningSummary === "none" ? void 0 : options?.reasoningSummary;
162
+ const reasoningEffort = options?.reasoningEffort === "default" || options?.reasoningEffort === "provider-default" ? void 0 : options?.reasoningEffort;
163
+ const resolved = {
164
+ parallelToolCalls: options?.parallelToolCalls ?? false,
165
+ ...reasoningEffort ? { reasoningEffort } : {},
166
+ ...options?.promptCacheKey ? { promptCacheKey: options.promptCacheKey } : {},
167
+ ...options?.promptCacheRetention ? { promptCacheRetention: options.promptCacheRetention } : {},
168
+ ...sendReasoning && reasoningSummary ? { reasoningSummary } : {},
169
+ ...options?.serviceTier ? { serviceTier: options.serviceTier } : {},
170
+ ...options?.textVerbosity ? { textVerbosity: options.textVerbosity } : {}
171
+ };
172
+ return { [providerOptionsKey]: resolved };
173
+ };
174
+ const getConfiguredEnabledOverride = (env) => {
175
+ const value = getValue(env, "SURVEY_ASSISTANT_ENABLED");
176
+ if (value !== void 0 && value !== "true" && value !== "false") throw new Error("SURVEY_ASSISTANT_ENABLED must be \"true\" or \"false\".");
177
+ return value === void 0 ? void 0 : value === "true";
178
+ };
179
+ const isSurveyAssistantExplicitlyDisabled = (input, env) => {
180
+ const environmentOverride = getConfiguredEnabledOverride(env);
181
+ if (environmentOverride !== void 0) return !environmentOverride;
182
+ return typeof input === "object" && input !== null && "enabled" in input && input.enabled === false;
183
+ };
184
+ const createDisabledSurveyAssistantRuntimeConfig = () => {
185
+ const disabledModelId = "survey-assistant-disabled";
186
+ return {
187
+ provider: "openai",
188
+ defaultModelId: disabledModelId,
189
+ memoryModelId: disabledModelId,
190
+ modelIds: [disabledModelId],
191
+ models: [{
192
+ id: disabledModelId,
193
+ label: "Survey assistant disabled",
194
+ upstreamModelId: disabledModelId
195
+ }],
196
+ modelCatalogTtlMs: DEFAULT_CATALOG_TTL_MS,
197
+ enabled: false,
198
+ readinessError: null,
199
+ requestLimits: { ...SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS },
200
+ execution: {
201
+ firstResponseTimeoutMs: DEFAULT_FIRST_RESPONSE_TIMEOUT_MS,
202
+ idleTimeoutMs: DEFAULT_IDLE_TIMEOUT_MS,
203
+ maxConcurrentRequests: 4,
204
+ maxDurationMs: DEFAULT_MAX_DURATION_MS,
205
+ maxSteps: DEFAULT_MAX_STEPS,
206
+ sendReasoning: false
207
+ },
208
+ observationalMemory: false
209
+ };
210
+ };
211
+ const resolveConfiguredEnabled = (env, configured, requireExperimentalIdentityOptIn) => {
212
+ const environmentOverride = getConfiguredEnabledOverride(env);
213
+ return (environmentOverride !== void 0 ? environmentOverride : configured ?? env.NODE_ENV === "development") && (!requireExperimentalIdentityOptIn || env.NODE_ENV === "development" || getBoolean(env, "SURVEY_ASSISTANT_ALLOW_EXPERIMENTAL_IDENTITY", false));
214
+ };
48
215
  const parseProvider = (env, fallback) => {
49
216
  const value = getValue(env, "SURVEY_ASSISTANT_PROVIDER")?.toLowerCase();
50
217
  if (value === "azure" || value === "azure-openai") return "azure-openai";
@@ -75,7 +242,142 @@ const getReadinessError = ({ azure, env, modelWasConfigured, provider, requireSt
75
242
  }
76
243
  return null;
77
244
  };
245
+ const parseSurveyAssistantConfigurationDocument = (input, env, { requireExperimentalIdentityOptIn = false, requireStorage = true } = {}) => {
246
+ if (isSurveyAssistantExplicitlyDisabled(input, env)) return createDisabledSurveyAssistantRuntimeConfig();
247
+ const document = surveyAssistantConfigurationDocumentSchema.parse(input);
248
+ const activeProvider = document.providers[document.activeProvider];
249
+ if (!activeProvider) throw new Error(`activeProvider references unknown provider "${document.activeProvider}".`);
250
+ const memoryEnabled = document.memory?.enabled ?? true;
251
+ for (const [providerName, configuredProvider] of Object.entries(document.providers)) {
252
+ const duplicateModelId = configuredProvider.models.find((model, index, models) => models.findIndex((candidate) => candidate.id === model.id) !== index)?.id;
253
+ if (duplicateModelId) throw new Error(`Provider "${providerName}" contains duplicate model id "${duplicateModelId}".`);
254
+ const modelsForProviderRole = (role) => configuredProvider.models.filter((model) => model.roles.includes(role));
255
+ const providerChatDefaults = modelsForProviderRole("chat-default");
256
+ const providerChatModels = modelsForProviderRole("chat-picker");
257
+ const providerTaskDefaults = modelsForProviderRole("task-default");
258
+ const providerMemoryModels = modelsForProviderRole("memory");
259
+ if (providerChatDefaults.length !== 1) throw new Error(`Provider "${providerName}" must configure exactly one chat-default model.`);
260
+ if (!providerChatDefaults[0].roles.includes("chat-picker")) throw new Error(`The chat-default model for provider "${providerName}" must also have the chat-picker role.`);
261
+ if (providerChatModels.length === 0) throw new Error(`Provider "${providerName}" must configure a chat-picker model.`);
262
+ if (providerTaskDefaults.length > 1) throw new Error(`Provider "${providerName}" may configure at most one task-default model.`);
263
+ if (providerMemoryModels.length > 1 || memoryEnabled && providerMemoryModels.length !== 1) throw new Error(memoryEnabled ? `Provider "${providerName}" must configure exactly one memory model when memory is enabled.` : `Provider "${providerName}" may configure at most one memory model.`);
264
+ if (configuredProvider.type === "lmstudio" && !configuredProvider.apiKeyOptional && !configuredProvider.apiKeyEnv) throw new Error(`Provider "${providerName}" must configure apiKeyEnv when apiKeyOptional is false.`);
265
+ const validateOptions = (options, location) => {
266
+ if (!options) return;
267
+ if (configuredProvider.type !== "openai" && configuredProvider.type !== "azure-openai" && (options.promptCacheKey || options.promptCacheRetention || options.reasoningSummary || options.textVerbosity)) throw new Error(`${location} contains options unsupported by ${configuredProvider.type}.`);
268
+ if (configuredProvider.type !== "openai" && options.serviceTier) throw new Error(`${location} contains serviceTier, which is only supported by openai.`);
269
+ };
270
+ validateOptions(configuredProvider.options, `Provider "${providerName}"`);
271
+ for (const model of configuredProvider.models) {
272
+ const upstreamModelId = model.upstreamModel ?? model.id;
273
+ if (configuredProvider.type !== "lmstudio" && upstreamModelId.includes("/")) throw new Error(`Model "${model.id}" must use an upstreamModel without a provider prefix for ${configuredProvider.type}.`);
274
+ validateOptions(model.options, `Model "${model.id}" in provider "${providerName}"`);
275
+ }
276
+ }
277
+ const modelsForRole = (role) => activeProvider.models.filter((model) => model.roles.includes(role));
278
+ const chatDefaults = modelsForRole("chat-default");
279
+ const chatModels = modelsForRole("chat-picker");
280
+ const taskDefaults = modelsForRole("task-default");
281
+ const memoryModels = modelsForRole("memory");
282
+ const provider = activeProvider.type;
283
+ const sendReasoning = document.execution?.sendReasoning ?? true;
284
+ const providerDefaults = {
285
+ parallelToolCalls: false,
286
+ ...provider === "openai" || provider === "azure-openai" ? {
287
+ reasoningEffort: "low",
288
+ reasoningSummary: "detailed",
289
+ promptCacheKey: "survey-assistant-chat-v21"
290
+ } : provider === "mistral" ? { reasoningEffort: "none" } : {},
291
+ ...activeProvider.options
292
+ };
293
+ const models = activeProvider.models.map((model) => ({
294
+ id: model.id,
295
+ label: model.label ?? model.id,
296
+ upstreamModelId: model.upstreamModel ?? model.id,
297
+ providerOptions: createProviderOptions(provider, {
298
+ ...providerDefaults,
299
+ ...model.options
300
+ }, sendReasoning)
301
+ }));
302
+ const configuredModel = (id) => models.find((model) => model.id === id);
303
+ const defaultModelId = chatDefaults[0].id;
304
+ const memoryModelId = (memoryModels[0] ?? chatDefaults[0]).id;
305
+ const taskModelId = taskDefaults[0]?.id;
306
+ const providerApiKey = activeProvider.apiKeyEnv ? getValue(env, activeProvider.apiKeyEnv) : void 0;
307
+ const memoryModel = configuredModel(memoryModelId);
308
+ const memoryModelConfig = provider === "lmstudio" ? {
309
+ providerId: "lmstudio",
310
+ modelId: memoryModel.upstreamModelId,
311
+ url: activeProvider.baseUrl,
312
+ ...providerApiKey ? { apiKey: providerApiKey } : {}
313
+ } : provider === "azure-openai" ? `${provider}/${memoryModel.upstreamModelId}` : {
314
+ id: `${provider}/${memoryModel.upstreamModelId}`,
315
+ ...providerApiKey ? { apiKey: providerApiKey } : {}
316
+ };
317
+ const azure = provider === "azure-openai" ? {
318
+ resourceName: activeProvider.resourceName,
319
+ apiKey: providerApiKey,
320
+ apiVersion: activeProvider.apiVersion,
321
+ discoverModels: activeProvider.discoverModels,
322
+ management: activeProvider.management ? {
323
+ tenantId: activeProvider.management.tenantId,
324
+ clientId: activeProvider.management.clientId,
325
+ clientSecret: getValue(env, activeProvider.management.clientSecretEnv) ?? "",
326
+ subscriptionId: activeProvider.management.subscriptionId,
327
+ resourceGroup: activeProvider.management.resourceGroup
328
+ } : void 0
329
+ } : void 0;
330
+ const lmstudio = provider === "lmstudio" ? {
331
+ baseUrl: activeProvider.baseUrl,
332
+ ...providerApiKey ? { apiKey: providerApiKey } : {}
333
+ } : void 0;
334
+ const missingProviderSecret = activeProvider.apiKeyEnv && !providerApiKey && !(provider === "lmstudio" && activeProvider.apiKeyOptional);
335
+ const missingManagementSecret = provider === "azure-openai" && activeProvider.discoverModels && (!activeProvider.management || !azure?.management?.clientSecret);
336
+ const readinessError = requireStorage && !getValue(env, "SURVEY_ASSISTANT_DATABASE_URL") && !getValue(env, "DATABASE_URL") ? "Survey assistant storage is not configured." : missingProviderSecret ? `The provider credential ${activeProvider.apiKeyEnv} is not configured for the survey assistant.` : missingManagementSecret ? "Azure deployment discovery requires complete management configuration and credentials." : null;
337
+ const configuredMaxSteps = document.execution?.maxSteps ?? DEFAULT_MAX_STEPS;
338
+ return {
339
+ provider,
340
+ providerApiKey,
341
+ defaultModelId,
342
+ memoryModelId,
343
+ taskModelId,
344
+ modelIds: chatModels.map((model) => model.id),
345
+ models,
346
+ modelCatalogTtlMs: document.modelCatalogTtlMs ?? DEFAULT_CATALOG_TTL_MS,
347
+ azure,
348
+ lmstudio,
349
+ enabled: resolveConfiguredEnabled(env, document.enabled, requireExperimentalIdentityOptIn),
350
+ readinessError,
351
+ requestLimits: {
352
+ maxAttachmentBytes: document.requestLimits?.maxAttachmentBytes ?? SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxAttachmentBytes,
353
+ maxAttachments: document.requestLimits?.maxAttachments ?? SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxAttachments,
354
+ maxRequestBytes: document.requestLimits?.maxRequestBytes ?? SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxRequestBytes,
355
+ maxTextPartChars: document.requestLimits?.maxTextPartChars ?? SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxTextPartChars,
356
+ maxTotalAttachmentBytes: document.requestLimits?.maxTotalAttachmentBytes ?? SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxTotalAttachmentBytes
357
+ },
358
+ execution: {
359
+ firstResponseTimeoutMs: document.execution?.firstResponseTimeoutMs ?? DEFAULT_FIRST_RESPONSE_TIMEOUT_MS,
360
+ idleTimeoutMs: document.execution?.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS,
361
+ maxConcurrentRequests: document.execution?.maxConcurrentRequests ?? 4,
362
+ maxDurationMs: document.execution?.maxDurationMs ?? DEFAULT_MAX_DURATION_MS,
363
+ maxSteps: Math.min(configuredMaxSteps, HARD_MAX_STEPS),
364
+ providerOptions: configuredModel(defaultModelId).providerOptions,
365
+ sendReasoning
366
+ },
367
+ observationalMemory: memoryEnabled ? createSurveyAssistantObservationalMemoryOptions({
368
+ model: memoryModelConfig,
369
+ temporalMarkers: document.memory?.temporalMarkers ?? false,
370
+ observation: {
371
+ messageTokens: document.memory?.messageTokens ?? SURVEY_ASSISTANT_OBSERVATIONAL_MEMORY_DEFAULTS.messageTokens,
372
+ bufferOnIdle: document.memory?.bufferOnIdle ?? false,
373
+ observeAttachments: false
374
+ },
375
+ reflection: { observationTokens: document.memory?.observationTokens ?? SURVEY_ASSISTANT_OBSERVATIONAL_MEMORY_DEFAULTS.observationTokens }
376
+ }) : false
377
+ };
378
+ };
78
379
  const parseSurveyAssistantEnvironment = (env, { defaultLmStudioModel, defaultMistralModel = "mistral-medium-latest", defaultOpenAIModel = "gpt-5.4-nano", defaultProvider = "openai", requireExperimentalIdentityOptIn = false, requireStorage = true } = {}) => {
380
+ if (getConfiguredEnabledOverride(env) === false) return createDisabledSurveyAssistantRuntimeConfig();
79
381
  const provider = parseProvider(env, defaultProvider);
80
382
  const modelIdOptions = { allowNestedId: provider === "lmstudio" };
81
383
  const configuredModelId = getOptionalSameProviderModelId(env, "SURVEY_ASSISTANT_MODEL", modelIdOptions);
@@ -122,7 +424,7 @@ const parseSurveyAssistantEnvironment = (env, { defaultLmStudioModel, defaultMis
122
424
  const azure = provider === "azure-openai" ? {
123
425
  resourceName: getValue(env, "AZURE_RESOURCE_NAME"),
124
426
  apiKey: getValue(env, "AZURE_API_KEY"),
125
- apiVersion: getValue(env, "SURVEY_ASSISTANT_AZURE_API_VERSION") ?? "v1",
427
+ apiVersion: getEnum(env, "SURVEY_ASSISTANT_AZURE_API_VERSION", ["v1", "preview"]) ?? "v1",
126
428
  discoverModels: getBoolean(env, "SURVEY_ASSISTANT_AZURE_DISCOVER_MODELS", false),
127
429
  management: parseAzureManagement(env)
128
430
  } : void 0;
@@ -130,8 +432,14 @@ const parseSurveyAssistantEnvironment = (env, { defaultLmStudioModel, defaultMis
130
432
  baseUrl: getValue(env, "SURVEY_ASSISTANT_LMSTUDIO_BASE_URL") ?? "http://127.0.0.1:1234/v1",
131
433
  apiKey: getValue(env, "SURVEY_ASSISTANT_LMSTUDIO_API_KEY")
132
434
  } : void 0;
435
+ const providerApiKey = provider === "openai" ? getValue(env, "OPENAI_API_KEY") : provider === "mistral" ? getValue(env, "MISTRAL_API_KEY") : provider === "lmstudio" ? getValue(env, "SURVEY_ASSISTANT_LMSTUDIO_API_KEY") : getValue(env, "AZURE_API_KEY");
133
436
  const memoryModelId = getOptionalSameProviderModelId(env, "SURVEY_ASSISTANT_MEMORY_MODEL", modelIdOptions) ?? defaultModelId;
134
- const memoryModel = `${provider}/${memoryModelId}`;
437
+ const memoryModel = provider === "lmstudio" ? {
438
+ providerId: "lmstudio",
439
+ modelId: memoryModelId,
440
+ url: lmstudio.baseUrl,
441
+ ...providerApiKey ? { apiKey: providerApiKey } : {}
442
+ } : provider === "azure-openai" ? `${provider}/${memoryModelId}` : `${provider}/${memoryModelId}`;
135
443
  const observationalMemory = getBoolean(env, "SURVEY_ASSISTANT_MEMORY_ENABLED", true) ? createSurveyAssistantObservationalMemoryOptions({
136
444
  model: memoryModel,
137
445
  temporalMarkers: getBoolean(env, "SURVEY_ASSISTANT_MEMORY_TEMPORAL_MARKERS", false),
@@ -143,14 +451,22 @@ const parseSurveyAssistantEnvironment = (env, { defaultLmStudioModel, defaultMis
143
451
  reflection: { observationTokens: getPositiveNumber(env, "SURVEY_ASSISTANT_MEMORY_OBSERVATION_TOKENS", SURVEY_ASSISTANT_OBSERVATIONAL_MEMORY_DEFAULTS.observationTokens) }
144
452
  }) : false;
145
453
  const configuredMaxSteps = getPositiveNumber(env, "SURVEY_ASSISTANT_MAX_STEPS", DEFAULT_MAX_STEPS);
146
- const enabledSetting = getValue(env, "SURVEY_ASSISTANT_ENABLED")?.toLowerCase();
147
- if (enabledSetting !== void 0 && enabledSetting !== "true" && enabledSetting !== "false") throw new Error("SURVEY_ASSISTANT_ENABLED must be \"true\" or \"false\".");
148
- const enabled = enabledSetting === "false" ? false : enabledSetting === "true" ? !requireExperimentalIdentityOptIn || env.NODE_ENV === "development" || getBoolean(env, "SURVEY_ASSISTANT_ALLOW_EXPERIMENTAL_IDENTITY", false) : env.NODE_ENV === "development";
454
+ const enabled = resolveConfiguredEnabled(env, void 0, requireExperimentalIdentityOptIn);
149
455
  return {
150
456
  provider,
151
457
  defaultModelId,
152
458
  memoryModelId,
153
459
  modelIds,
460
+ models: [...new Set([
461
+ ...modelIds,
462
+ ...taskModelId ? [taskModelId] : [],
463
+ memoryModelId
464
+ ])].map((id) => ({
465
+ id,
466
+ label: id,
467
+ upstreamModelId: id,
468
+ providerOptions
469
+ })),
154
470
  modelCatalogTtlMs: getPositiveNumber(env, "SURVEY_ASSISTANT_MODEL_CATALOG_TTL_MS", DEFAULT_CATALOG_TTL_MS),
155
471
  azure,
156
472
  lmstudio,
@@ -185,18 +501,30 @@ const parseSurveyAssistantEnvironment = (env, { defaultLmStudioModel, defaultMis
185
501
  //#endregion
186
502
  //#region src/server/runtime.ts
187
503
  const createSurveyAssistantModelRouter = (config) => {
504
+ const configuredModels = new Map(config.models?.map((model) => [model.id, model]));
505
+ const getConfiguredModel = (modelId) => configuredModels.get(modelId) ?? {
506
+ id: modelId,
507
+ label: modelId,
508
+ upstreamModelId: modelId,
509
+ providerOptions: config.execution.providerOptions
510
+ };
188
511
  const toProviderModel = (modelId, configName) => {
512
+ const upstreamModelId = getConfiguredModel(modelId).upstreamModelId;
189
513
  if (config.provider === "lmstudio") {
190
514
  if (!config.lmstudio) throw new Error("LM Studio configuration is missing for the lmstudio provider.");
191
515
  return {
192
516
  providerId: "lmstudio",
193
- modelId,
517
+ modelId: upstreamModelId,
194
518
  url: config.lmstudio.baseUrl,
195
519
  ...config.lmstudio.apiKey ? { apiKey: config.lmstudio.apiKey } : {}
196
520
  };
197
521
  }
198
- if (modelId.includes("/")) throw new Error(`${configName} must be a model or deployment id without a provider prefix. All survey assistant models use the configured provider.`);
199
- return `${config.provider}/${modelId}`;
522
+ if (upstreamModelId.includes("/")) throw new Error(`${configName} must be a model or deployment id without a provider prefix. All survey assistant models use the configured provider.`);
523
+ const id = `${config.provider}/${upstreamModelId}`;
524
+ return config.providerApiKey && config.provider !== "azure-openai" ? {
525
+ id,
526
+ apiKey: config.providerApiKey
527
+ } : id;
200
528
  };
201
529
  const defaultModel = toProviderModel(config.defaultModelId, "defaultModelId");
202
530
  const chatModelIds = config.modelIds.map((modelId) => {
@@ -207,13 +535,13 @@ const createSurveyAssistantModelRouter = (config) => {
207
535
  const taskModel = config.taskModelId ? toProviderModel(config.taskModelId, "taskModelId") : void 0;
208
536
  const memoryModel = toProviderModel(config.memoryModelId, "memoryModelId");
209
537
  if (config.observationalMemory !== false) {
210
- const configuredMemoryModel = `${config.provider}/${config.memoryModelId}`;
211
- if (typeof config.observationalMemory.model !== "string" || config.observationalMemory.model !== configuredMemoryModel || config.observationalMemory.observation?.model !== void 0 || config.observationalMemory.reflection?.model !== void 0) throw new Error("The standard runtime requires observationalMemory to use memoryModelId for both observation and reflection. Use the low-level Agent factory for custom memory model routing.");
538
+ const configuredMemoryModel = toProviderModel(config.memoryModelId, "memoryModelId");
539
+ if (JSON.stringify(config.observationalMemory.model) !== JSON.stringify(configuredMemoryModel) || config.observationalMemory.observation?.model !== void 0 || config.observationalMemory.reflection?.model !== void 0) throw new Error("The standard runtime requires observationalMemory to use memoryModelId for both observation and reflection. Use the low-level Agent factory for custom memory model routing.");
212
540
  }
213
541
  const deploymentIds = [...new Set([
214
- ...chatModelIds,
215
- ...config.taskModelId ? [config.taskModelId] : [],
216
- config.memoryModelId
542
+ ...chatModelIds.map((id) => getConfiguredModel(id).upstreamModelId),
543
+ ...config.taskModelId ? [getConfiguredModel(config.taskModelId).upstreamModelId] : [],
544
+ getConfiguredModel(config.memoryModelId).upstreamModelId
217
545
  ])];
218
546
  const azureGateway = config.azure ? new AzureOpenAIGateway({
219
547
  resourceName: config.azure.resourceName ?? "",
@@ -228,14 +556,18 @@ const createSurveyAssistantModelRouter = (config) => {
228
556
  let ids = chatModelIds;
229
557
  if (azureGateway && config.azure?.discoverModels) try {
230
558
  const providers = await azureGateway.fetchProviders();
231
- ids = [...new Set([...chatModelIds, ...providers["azure-openai"]?.models ?? []])];
559
+ const configuredUpstreamIds = new Set(chatModelIds.map((id) => getConfiguredModel(id).upstreamModelId));
560
+ const discoveredIds = (providers["azure-openai"]?.models ?? []).filter((id) => !configuredUpstreamIds.has(id));
561
+ ids = [...new Set([...chatModelIds, ...discoveredIds])];
232
562
  } catch {}
233
563
  const value = {
234
564
  defaultModelId: config.defaultModelId,
235
- models: ids.map((id) => ({
236
- id,
237
- label: id
238
- }))
565
+ models: ids.map((id) => {
566
+ return {
567
+ id,
568
+ label: getConfiguredModel(id).label
569
+ };
570
+ })
239
571
  };
240
572
  cachedCatalog = {
241
573
  expiresAt: Date.now() + config.modelCatalogTtlMs,
@@ -248,7 +580,9 @@ const createSurveyAssistantModelRouter = (config) => {
248
580
  const id = requestedModelId ?? catalog.defaultModelId;
249
581
  return catalog.models.some((model) => model.id === id) ? {
250
582
  id,
251
- model: toProviderModel(id, "requestedModelId")
583
+ model: toProviderModel(id, "requestedModelId"),
584
+ providerName: config.provider,
585
+ ...getConfiguredModel(id).providerOptions ? { providerOptions: getConfiguredModel(id).providerOptions } : {}
252
586
  } : null;
253
587
  };
254
588
  return {
@@ -261,7 +595,9 @@ const createSurveyAssistantModelRouter = (config) => {
261
595
  resolveModel: async ({ requestedModelId }) => resolveRequestedModel(requestedModelId),
262
596
  resolveTaskModel: async ({ requestedModelId }) => config.taskModelId ? {
263
597
  id: config.taskModelId,
264
- model: taskModel
598
+ model: taskModel,
599
+ providerName: config.provider,
600
+ ...getConfiguredModel(config.taskModelId).providerOptions ? { providerOptions: getConfiguredModel(config.taskModelId).providerOptions } : {}
265
601
  } : resolveRequestedModel(requestedModelId),
266
602
  taskModel
267
603
  };
@@ -287,7 +623,7 @@ const createSurveyAssistantRuntimeComponents = (config) => {
287
623
  };
288
624
  };
289
625
  const resolveMastra = async (mastra) => typeof mastra === "function" ? mastra() : mastra;
290
- const createSurveyAssistantRuntimeHandlers = ({ authorize, chat = {}, config, mastra, modelRouter, task = {}, threadDocuments }) => {
626
+ const createSurveyAssistantRuntimeHandlers = ({ authorize, chat = {}, config, mastra, modelRouter, task = {}, threads: threadOptions = {}, threadDocuments }) => {
291
627
  const isEnabled = chat.isEnabled ?? (() => config.enabled);
292
628
  const getReadinessError = chat.getReadinessError ?? (() => config.readinessError);
293
629
  const chatHandler = createSurveyAssistantChatHandler({
@@ -334,6 +670,7 @@ const createSurveyAssistantRuntimeHandlers = ({ authorize, chat = {}, config, ma
334
670
  if (!config.enabled) throw new SurveyAssistantAuthorizationError("Survey assistant is disabled.", 404);
335
671
  return authorize.thread(request);
336
672
  },
673
+ ...threadOptions,
337
674
  repository: createMastraMemoryThreadRepository({
338
675
  getMemory,
339
676
  threadDocuments
@@ -385,6 +722,6 @@ const createSurveyAssistantRuntime = (config, runtimeOptions = {}) => {
385
722
  };
386
723
  };
387
724
  //#endregion
388
- export { createSurveyAssistantModelRouter, createSurveyAssistantRuntime, createSurveyAssistantRuntimeComponents, createSurveyAssistantRuntimeHandlers, parseSurveyAssistantEnvironment, resolveSurveyAssistantProviderOptionsKey };
725
+ export { createSurveyAssistantModelRouter, createSurveyAssistantRuntime, createSurveyAssistantRuntimeComponents, createSurveyAssistantRuntimeHandlers, parseSurveyAssistantConfigurationDocument, parseSurveyAssistantEnvironment, resolveSurveyAssistantProviderOptionsKey, surveyAssistantConfigurationDocumentSchema };
389
726
 
390
727
  //# sourceMappingURL=server-runtime.mjs.map