@case-framework/survey-assistant 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{authoring-references-DYuOAdVx.mjs → authoring-references-ChDTVnms.mjs} +8 -2
- package/dist/authoring-references-ChDTVnms.mjs.map +1 -0
- package/dist/{capabilities-DlC1l6qy.d.mts → capabilities-CnsVuJ1k.d.mts} +12 -4
- package/dist/capabilities-CnsVuJ1k.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 +38 -4
- package/dist/capabilities-default.mjs.map +1 -1
- package/dist/{constants-CgV4cTg5.d.mts → constants-BK1-g6pR.d.mts} +12 -7
- package/dist/constants-BK1-g6pR.d.mts.map +1 -0
- package/dist/{controller-proxy-BzpEOygv.d.mts → controller-proxy-CIDRd8Wu.d.mts} +2 -2
- package/dist/{controller-proxy-BzpEOygv.d.mts.map → controller-proxy-CIDRd8Wu.d.mts.map} +1 -1
- package/dist/{controller-proxy-0WJZUZYx.mjs → controller-proxy-DY36XFV3.mjs} +2 -2
- package/dist/{controller-proxy-0WJZUZYx.mjs.map → controller-proxy-DY36XFV3.mjs.map} +1 -1
- package/dist/{digest-BvXpeWcR.d.mts → digest-Dyjch_sC.d.mts} +2 -2
- package/dist/{digest-BvXpeWcR.d.mts.map → digest-Dyjch_sC.d.mts.map} +1 -1
- package/dist/digest.d.mts +1 -1
- package/dist/{engine-0AJrv0hI.mjs → engine-CWTuN3o2.mjs} +866 -663
- package/dist/engine-CWTuN3o2.mjs.map +1 -0
- package/dist/engine.d.mts +3 -3
- package/dist/engine.mjs +3 -3
- package/dist/fair-guidance-CEdJYccK.mjs +21 -0
- package/dist/fair-guidance-CEdJYccK.mjs.map +1 -0
- package/dist/form-authoring-DCd9XfXf.mjs +155 -0
- package/dist/form-authoring-DCd9XfXf.mjs.map +1 -0
- package/dist/{index-BUF-sE8j.d.mts → index-Bp5W_oPa.d.mts} +27 -7
- package/dist/index-Bp5W_oPa.d.mts.map +1 -0
- package/dist/{index-BdXb6jER.d.mts → index-CPOQgkTN.d.mts} +67 -6
- package/dist/index-CPOQgkTN.d.mts.map +1 -0
- package/dist/{index-BiTT71Xp.d.mts → index-EDL1V168.d.mts} +101 -7
- package/dist/{index-BiTT71Xp.d.mts.map → index-EDL1V168.d.mts.map} +1 -1
- package/dist/{index-BNdvGEaq.d.mts → index-SPHf3OoJ.d.mts} +9 -3
- package/dist/index-SPHf3OoJ.d.mts.map +1 -0
- package/dist/{memory-thread-repository-1ocPOda8.mjs → memory-thread-repository-acbz6HZJ.mjs} +181 -26
- package/dist/memory-thread-repository-acbz6HZJ.mjs.map +1 -0
- package/dist/{protocol-DpCYmCjr.mjs → protocol-DATvkr1S.mjs} +125 -6
- package/dist/protocol-DATvkr1S.mjs.map +1 -0
- package/dist/protocol.d.mts +3 -3
- package/dist/protocol.mjs +2 -2
- package/dist/{react-DXK5zWNo.mjs → react-3kSE6WtS.mjs} +127 -9
- package/dist/react-3kSE6WtS.mjs.map +1 -0
- package/dist/react-integration.d.mts +1 -1
- package/dist/react-integration.mjs +1 -1
- package/dist/react.d.mts +2 -2
- package/dist/react.mjs +2 -2
- package/dist/references/assistant-operations.md +13 -18
- package/dist/references/embedded-forms.md +41 -2
- package/dist/references/expressions.md +17 -9
- package/dist/references/fair-by-design.md +80 -0
- package/dist/references/item-types.md +19 -3
- package/dist/references/localization.md +7 -4
- package/dist/references/source-material-surveys.md +6 -4
- package/dist/{request-context-BBzU3VdG.mjs → request-context-BEjnaaFr.mjs} +10 -5
- package/dist/request-context-BEjnaaFr.mjs.map +1 -0
- package/dist/server-agent.d.mts +28 -8
- package/dist/server-agent.d.mts.map +1 -1
- package/dist/server-agent.mjs +70 -13
- package/dist/server-agent.mjs.map +1 -1
- package/dist/server-runtime.d.mts +22 -11
- package/dist/server-runtime.d.mts.map +1 -1
- package/dist/server-runtime.mjs +47 -19
- package/dist/server-runtime.mjs.map +1 -1
- package/dist/server-tasks.d.mts +1 -1
- package/dist/server-tasks.mjs +4 -3
- 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 +16 -7
- package/dist/server.d.mts.map +1 -1
- package/dist/server.mjs +4 -4
- package/dist/storage-postgres.d.mts +1 -1
- package/dist/{tasks-BuLnWrR4.d.mts → tasks-DIZgr4nD.d.mts} +8 -4
- package/dist/tasks-DIZgr4nD.d.mts.map +1 -0
- package/dist/{thread-documents-BlxNjc7S.d.mts → thread-documents-C3kf0Vds.d.mts} +1 -1
- package/dist/{thread-documents-BlxNjc7S.d.mts.map → thread-documents-C3kf0Vds.d.mts.map} +1 -1
- package/dist/{thread-handlers-6L8sAreR.d.mts → thread-handlers-DZ1WsorO.d.mts} +9 -4
- package/dist/thread-handlers-DZ1WsorO.d.mts.map +1 -0
- package/dist/{tools-wgLen05n.mjs → tools-GDd5_GUh.mjs} +403 -77
- package/dist/tools-GDd5_GUh.mjs.map +1 -0
- package/dist/ui.css +1 -1
- package/dist/ui.d.mts +3 -3
- package/dist/ui.d.mts.map +1 -1
- package/dist/ui.mjs +152 -36
- package/dist/ui.mjs.map +1 -1
- package/docs/integration.md +73 -5
- package/package.json +4 -4
- package/dist/authoring-references-DYuOAdVx.mjs.map +0 -1
- package/dist/capabilities-DKbNCnBf.mjs +0 -66
- package/dist/capabilities-DKbNCnBf.mjs.map +0 -1
- package/dist/capabilities-DlC1l6qy.d.mts.map +0 -1
- package/dist/constants-CgV4cTg5.d.mts.map +0 -1
- package/dist/engine-0AJrv0hI.mjs.map +0 -1
- package/dist/index-BNdvGEaq.d.mts.map +0 -1
- package/dist/index-BUF-sE8j.d.mts.map +0 -1
- package/dist/index-BdXb6jER.d.mts.map +0 -1
- package/dist/memory-thread-repository-1ocPOda8.mjs.map +0 -1
- package/dist/protocol-DpCYmCjr.mjs.map +0 -1
- package/dist/react-DXK5zWNo.mjs.map +0 -1
- package/dist/request-context-BBzU3VdG.mjs.map +0 -1
- package/dist/tasks-BuLnWrR4.d.mts.map +0 -1
- package/dist/thread-handlers-6L8sAreR.d.mts.map +0 -1
- package/dist/tools-wgLen05n.mjs.map +0 -1
package/dist/server-runtime.mjs
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
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-
|
|
4
|
-
import { t as SURVEY_ASSISTANT_TOOL_IDS } from "./tools-
|
|
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-GDd5_GUh.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
7
|
import { AzureOpenAIGateway } from "@mastra/core/llm";
|
|
8
8
|
//#region src/server/runtime-config.ts
|
|
9
9
|
const DEFAULT_MAX_STEPS = 48;
|
|
10
10
|
const HARD_MAX_STEPS = 64;
|
|
11
|
-
const
|
|
11
|
+
const DEFAULT_FIRST_RESPONSE_TIMEOUT_MS = 900 * 1e3;
|
|
12
|
+
const DEFAULT_IDLE_TIMEOUT_MS = 300 * 1e3;
|
|
13
|
+
const DEFAULT_MAX_DURATION_MS = 3600 * 1e3;
|
|
12
14
|
const DEFAULT_CATALOG_TTL_MS = 300 * 1e3;
|
|
13
15
|
const getValue = (env, name) => {
|
|
14
16
|
return env[name]?.trim() || void 0;
|
|
@@ -34,20 +36,20 @@ const getEnum = (env, name, values) => {
|
|
|
34
36
|
return value;
|
|
35
37
|
};
|
|
36
38
|
const getCommaSeparatedValues = (env, name) => [...new Set((getValue(env, name) ?? "").split(",").map((value) => value.trim()).filter(Boolean))];
|
|
37
|
-
const getSameProviderModelId = (value, name) => {
|
|
38
|
-
if (value.includes("/")) throw new Error(`${name} must be a model or deployment id without a provider prefix. All survey assistant models use SURVEY_ASSISTANT_PROVIDER.`);
|
|
39
|
+
const getSameProviderModelId = (value, name, { allowNestedId = false } = {}) => {
|
|
40
|
+
if (!allowNestedId && value.includes("/")) throw new Error(`${name} must be a model or deployment id without a provider prefix. All survey assistant models use SURVEY_ASSISTANT_PROVIDER.`);
|
|
39
41
|
return value;
|
|
40
42
|
};
|
|
41
|
-
const getOptionalSameProviderModelId = (env, name) => {
|
|
43
|
+
const getOptionalSameProviderModelId = (env, name, options) => {
|
|
42
44
|
const value = getValue(env, name);
|
|
43
|
-
return value ? getSameProviderModelId(value, name) : void 0;
|
|
45
|
+
return value ? getSameProviderModelId(value, name, options) : void 0;
|
|
44
46
|
};
|
|
45
47
|
const resolveSurveyAssistantProviderOptionsKey = (provider) => provider === "azure-openai" ? "azure" : provider;
|
|
46
48
|
const parseProvider = (env, fallback) => {
|
|
47
49
|
const value = getValue(env, "SURVEY_ASSISTANT_PROVIDER")?.toLowerCase();
|
|
48
50
|
if (value === "azure" || value === "azure-openai") return "azure-openai";
|
|
49
|
-
if (value === "openai" || value === "mistral") return value;
|
|
50
|
-
if (value) throw new Error("SURVEY_ASSISTANT_PROVIDER must be one of: openai, mistral, azure-openai.");
|
|
51
|
+
if (value === "lmstudio" || value === "openai" || value === "mistral") return value;
|
|
52
|
+
if (value) throw new Error("SURVEY_ASSISTANT_PROVIDER must be one of: openai, mistral, lmstudio, azure-openai.");
|
|
51
53
|
return fallback;
|
|
52
54
|
};
|
|
53
55
|
const parseAzureManagement = (env) => {
|
|
@@ -73,12 +75,15 @@ const getReadinessError = ({ azure, env, modelWasConfigured, provider, requireSt
|
|
|
73
75
|
}
|
|
74
76
|
return null;
|
|
75
77
|
};
|
|
76
|
-
const parseSurveyAssistantEnvironment = (env, { defaultMistralModel = "mistral-medium-latest", defaultOpenAIModel = "gpt-5.4-nano", defaultProvider = "openai", requireExperimentalIdentityOptIn = false, requireStorage = true } = {}) => {
|
|
78
|
+
const parseSurveyAssistantEnvironment = (env, { defaultLmStudioModel, defaultMistralModel = "mistral-medium-latest", defaultOpenAIModel = "gpt-5.4-nano", defaultProvider = "openai", requireExperimentalIdentityOptIn = false, requireStorage = true } = {}) => {
|
|
77
79
|
const provider = parseProvider(env, defaultProvider);
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
const
|
|
80
|
+
const modelIdOptions = { allowNestedId: provider === "lmstudio" };
|
|
81
|
+
const configuredModelId = getOptionalSameProviderModelId(env, "SURVEY_ASSISTANT_MODEL", modelIdOptions);
|
|
82
|
+
if (provider === "lmstudio" && !configuredModelId && !defaultLmStudioModel) throw new Error("SURVEY_ASSISTANT_MODEL must be configured when SURVEY_ASSISTANT_PROVIDER is lmstudio.");
|
|
83
|
+
const defaultModelId = configuredModelId ?? getSameProviderModelId(provider === "lmstudio" ? defaultLmStudioModel : provider === "mistral" ? defaultMistralModel : defaultOpenAIModel, provider === "lmstudio" ? "defaultLmStudioModel" : provider === "mistral" ? "defaultMistralModel" : "defaultOpenAIModel", modelIdOptions);
|
|
84
|
+
const configuredModelIds = getCommaSeparatedValues(env, "SURVEY_ASSISTANT_MODELS").map((modelId) => getSameProviderModelId(modelId, "SURVEY_ASSISTANT_MODELS", modelIdOptions));
|
|
85
|
+
const modelIds = [...new Set(configuredModelIds.includes(defaultModelId) ? configuredModelIds : [defaultModelId, ...configuredModelIds])];
|
|
86
|
+
const taskModelId = getOptionalSameProviderModelId(env, "SURVEY_ASSISTANT_TASK_MODEL", modelIdOptions);
|
|
82
87
|
const sendReasoning = getBoolean(env, "SURVEY_ASSISTANT_SEND_REASONING", true);
|
|
83
88
|
const providerOptionsKey = resolveSurveyAssistantProviderOptionsKey(provider);
|
|
84
89
|
const reasoningEffort = getValue(env, `SURVEY_ASSISTANT_${providerOptionsKey.toUpperCase()}_REASONING_EFFORT`) ?? getValue(env, "SURVEY_ASSISTANT_REASONING_EFFORT") ?? (provider === "openai" || provider === "azure-openai" ? "low" : "none");
|
|
@@ -101,9 +106,9 @@ const parseSurveyAssistantEnvironment = (env, { defaultMistralModel = "mistral-m
|
|
|
101
106
|
"off",
|
|
102
107
|
"none"
|
|
103
108
|
]);
|
|
104
|
-
const reasoningSummary = reasoningSummaryValue === "off" || reasoningSummaryValue === "none" ? void 0 : reasoningSummaryValue ?? "
|
|
109
|
+
const reasoningSummary = reasoningSummaryValue === "off" || reasoningSummaryValue === "none" ? void 0 : reasoningSummaryValue ?? "detailed";
|
|
105
110
|
const resolvedReasoningEffort = reasoningEffort === "default" || reasoningEffort === "provider-default" ? void 0 : reasoningEffort;
|
|
106
|
-
const providerOptions = { [providerOptionsKey]: {
|
|
111
|
+
const providerOptions = provider === "lmstudio" ? void 0 : { [providerOptionsKey]: {
|
|
107
112
|
parallelToolCalls: false,
|
|
108
113
|
...resolvedReasoningEffort ? { reasoningEffort: resolvedReasoningEffort } : {},
|
|
109
114
|
...provider === "openai" || provider === "azure-openai" ? {
|
|
@@ -121,7 +126,11 @@ const parseSurveyAssistantEnvironment = (env, { defaultMistralModel = "mistral-m
|
|
|
121
126
|
discoverModels: getBoolean(env, "SURVEY_ASSISTANT_AZURE_DISCOVER_MODELS", false),
|
|
122
127
|
management: parseAzureManagement(env)
|
|
123
128
|
} : void 0;
|
|
124
|
-
const
|
|
129
|
+
const lmstudio = provider === "lmstudio" ? {
|
|
130
|
+
baseUrl: getValue(env, "SURVEY_ASSISTANT_LMSTUDIO_BASE_URL") ?? "http://127.0.0.1:1234/v1",
|
|
131
|
+
apiKey: getValue(env, "SURVEY_ASSISTANT_LMSTUDIO_API_KEY")
|
|
132
|
+
} : void 0;
|
|
133
|
+
const memoryModelId = getOptionalSameProviderModelId(env, "SURVEY_ASSISTANT_MEMORY_MODEL", modelIdOptions) ?? defaultModelId;
|
|
125
134
|
const memoryModel = `${provider}/${memoryModelId}`;
|
|
126
135
|
const observationalMemory = getBoolean(env, "SURVEY_ASSISTANT_MEMORY_ENABLED", true) ? createSurveyAssistantObservationalMemoryOptions({
|
|
127
136
|
model: memoryModel,
|
|
@@ -144,6 +153,7 @@ const parseSurveyAssistantEnvironment = (env, { defaultMistralModel = "mistral-m
|
|
|
144
153
|
modelIds,
|
|
145
154
|
modelCatalogTtlMs: getPositiveNumber(env, "SURVEY_ASSISTANT_MODEL_CATALOG_TTL_MS", DEFAULT_CATALOG_TTL_MS),
|
|
146
155
|
azure,
|
|
156
|
+
lmstudio,
|
|
147
157
|
enabled,
|
|
148
158
|
readinessError: getReadinessError({
|
|
149
159
|
azure,
|
|
@@ -160,6 +170,8 @@ const parseSurveyAssistantEnvironment = (env, { defaultMistralModel = "mistral-m
|
|
|
160
170
|
maxTotalAttachmentBytes: getPositiveNumber(env, "SURVEY_ASSISTANT_MAX_TOTAL_ATTACHMENT_BYTES", SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxTotalAttachmentBytes)
|
|
161
171
|
},
|
|
162
172
|
execution: {
|
|
173
|
+
firstResponseTimeoutMs: getPositiveNumber(env, "SURVEY_ASSISTANT_FIRST_RESPONSE_TIMEOUT_MS", DEFAULT_FIRST_RESPONSE_TIMEOUT_MS),
|
|
174
|
+
idleTimeoutMs: getPositiveNumber(env, "SURVEY_ASSISTANT_IDLE_TIMEOUT_MS", DEFAULT_IDLE_TIMEOUT_MS),
|
|
163
175
|
maxConcurrentRequests: getPositiveNumber(env, "SURVEY_ASSISTANT_MAX_CONCURRENT_REQUESTS", 4),
|
|
164
176
|
maxDurationMs: getPositiveNumber(env, "SURVEY_ASSISTANT_MAX_DURATION_MS", DEFAULT_MAX_DURATION_MS),
|
|
165
177
|
maxSteps: Math.min(configuredMaxSteps, HARD_MAX_STEPS),
|
|
@@ -174,6 +186,15 @@ const parseSurveyAssistantEnvironment = (env, { defaultMistralModel = "mistral-m
|
|
|
174
186
|
//#region src/server/runtime.ts
|
|
175
187
|
const createSurveyAssistantModelRouter = (config) => {
|
|
176
188
|
const toProviderModel = (modelId, configName) => {
|
|
189
|
+
if (config.provider === "lmstudio") {
|
|
190
|
+
if (!config.lmstudio) throw new Error("LM Studio configuration is missing for the lmstudio provider.");
|
|
191
|
+
return {
|
|
192
|
+
providerId: "lmstudio",
|
|
193
|
+
modelId,
|
|
194
|
+
url: config.lmstudio.baseUrl,
|
|
195
|
+
...config.lmstudio.apiKey ? { apiKey: config.lmstudio.apiKey } : {}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
177
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.`);
|
|
178
199
|
return `${config.provider}/${modelId}`;
|
|
179
200
|
};
|
|
@@ -186,7 +207,8 @@ const createSurveyAssistantModelRouter = (config) => {
|
|
|
186
207
|
const taskModel = config.taskModelId ? toProviderModel(config.taskModelId, "taskModelId") : void 0;
|
|
187
208
|
const memoryModel = toProviderModel(config.memoryModelId, "memoryModelId");
|
|
188
209
|
if (config.observationalMemory !== false) {
|
|
189
|
-
|
|
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.");
|
|
190
212
|
}
|
|
191
213
|
const deploymentIds = [...new Set([
|
|
192
214
|
...chatModelIds,
|
|
@@ -248,11 +270,15 @@ const createSurveyAssistantRuntimeComponents = (config) => {
|
|
|
248
270
|
const modelRouter = createSurveyAssistantModelRouter(config);
|
|
249
271
|
const chatModel = ({ requestContext }) => requestContext.get("modelSelection")?.model ?? modelRouter.defaultModel;
|
|
250
272
|
const taskModel = modelRouter.taskModel ?? chatModel;
|
|
273
|
+
const observationalMemory = config.provider === "lmstudio" && config.observationalMemory !== false ? {
|
|
274
|
+
...config.observationalMemory,
|
|
275
|
+
model: modelRouter.memoryModel
|
|
276
|
+
} : config.observationalMemory;
|
|
251
277
|
return {
|
|
252
278
|
agents: {
|
|
253
279
|
[SURVEY_ASSISTANT_AGENT_ID]: createSurveyAssistantAgent({
|
|
254
280
|
model: chatModel,
|
|
255
|
-
observationalMemory
|
|
281
|
+
observationalMemory
|
|
256
282
|
}),
|
|
257
283
|
[SURVEY_ASSISTANT_TASK_AGENT_ID]: createSurveyAssistantTaskAgent({ model: taskModel })
|
|
258
284
|
},
|
|
@@ -270,8 +296,10 @@ const createSurveyAssistantRuntimeHandlers = ({ authorize, chat = {}, config, ma
|
|
|
270
296
|
agentId: SURVEY_ASSISTANT_AGENT_ID,
|
|
271
297
|
activeTools: chat.activeTools ?? (config.observationalMemory === false ? SURVEY_ASSISTANT_TOOL_IDS : [...SURVEY_ASSISTANT_TOOL_IDS, "recall"]),
|
|
272
298
|
authorize: authorize.chat,
|
|
299
|
+
firstResponseTimeoutMs: chat.firstResponseTimeoutMs ?? config.execution.firstResponseTimeoutMs,
|
|
273
300
|
getReadinessError,
|
|
274
301
|
isEnabled,
|
|
302
|
+
idleTimeoutMs: chat.idleTimeoutMs ?? config.execution.idleTimeoutMs,
|
|
275
303
|
maxConcurrentRequests: chat.maxConcurrentRequests ?? config.execution.maxConcurrentRequests,
|
|
276
304
|
maxDurationMs: chat.maxDurationMs ?? config.execution.maxDurationMs,
|
|
277
305
|
maxSteps: chat.maxSteps ?? config.execution.maxSteps,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-runtime.mjs","names":[],"sources":["../src/server/runtime-config.ts","../src/server/runtime.ts"],"sourcesContent":["import type { AgentExecutionOptions } from \"@mastra/core/agent\";\nimport type { AzureOpenAIGatewayConfig } from \"@mastra/core/llm\";\nimport {\n createSurveyAssistantObservationalMemoryOptions,\n SURVEY_ASSISTANT_OBSERVATIONAL_MEMORY_DEFAULTS,\n type SurveyAssistantObservationalMemoryOptions,\n} from \"./agent\";\nimport {\n SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS,\n type SurveyAssistantRequestLimits,\n} from \"./request-guardrails\";\n\nexport type SurveyAssistantProvider = \"azure-openai\" | \"mistral\" | \"openai\";\nexport type SurveyAssistantProviderOptionsKey = \"azure\" | \"mistral\" | \"openai\";\n\nexport interface SurveyAssistantAzureConfig {\n apiKey?: string;\n apiVersion: string;\n discoverModels: boolean;\n management?: AzureOpenAIGatewayConfig[\"management\"];\n resourceName?: string;\n}\n\nexport interface SurveyAssistantExecutionConfig {\n maxConcurrentRequests: number;\n maxDurationMs: number;\n maxSteps: number;\n providerOptions?: AgentExecutionOptions[\"providerOptions\"];\n sendReasoning: boolean;\n}\n\nexport interface SurveyAssistantRuntimeConfig {\n azure?: SurveyAssistantAzureConfig;\n /** Default chat model and fallback for chat requests without a selection. */\n defaultModelId: string;\n enabled: boolean;\n /** Fixed same-provider model shared by memory observation and reflection. */\n memoryModelId: string;\n modelCatalogTtlMs: number;\n modelIds: string[];\n observationalMemory: SurveyAssistantObservationalMemoryOptions | false;\n provider: SurveyAssistantProvider;\n requestLimits: Pick<\n SurveyAssistantRequestLimits,\n | \"maxAttachmentBytes\"\n | \"maxAttachments\"\n | \"maxRequestBytes\"\n | \"maxTextPartChars\"\n | \"maxTotalAttachmentBytes\"\n >;\n readinessError: string | null;\n /**\n * Fixed model for one-shot tasks. When omitted, tasks follow the\n * server-authorized chat model selection.\n */\n taskModelId?: string;\n execution: SurveyAssistantExecutionConfig;\n}\n\nexport interface ParseSurveyAssistantEnvironmentOptions {\n defaultMistralModel?: string;\n defaultOpenAIModel?: string;\n defaultProvider?: SurveyAssistantProvider;\n requireExperimentalIdentityOptIn?: boolean;\n requireStorage?: boolean;\n}\n\ntype Environment = Record<string, string | undefined>;\n\nconst DEFAULT_MAX_STEPS = 48;\nconst HARD_MAX_STEPS = 64;\nconst DEFAULT_MAX_DURATION_MS = 3 * 60 * 1_000;\nconst DEFAULT_CATALOG_TTL_MS = 5 * 60 * 1_000;\n\nconst getValue = (env: Environment, name: string) => {\n const value = env[name]?.trim();\n return value || undefined;\n};\n\nconst getBoolean = (env: Environment, name: string, fallback: boolean) => {\n const value = getValue(env, name)?.toLowerCase();\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n if (value !== undefined) {\n throw new Error(`${name} must be \"true\" or \"false\".`);\n }\n return fallback;\n};\n\nconst getPositiveNumber = (env: Environment, name: string, fallback: number) => {\n const configured = getValue(env, name);\n if (configured === undefined) return fallback;\n const value = Number(configured);\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(`${name} must be a positive integer.`);\n }\n return value;\n};\n\nconst getEnum = <TValue extends string>(\n env: Environment,\n name: string,\n values: readonly TValue[],\n) => {\n const value = getValue(env, name);\n if (!value) return undefined;\n if (!(values as readonly string[]).includes(value)) {\n throw new Error(`${name} must be one of: ${values.join(\", \")}.`);\n }\n return value as TValue;\n};\n\nconst getCommaSeparatedValues = (env: Environment, name: string) => [\n ...new Set(\n (getValue(env, name) ?? \"\")\n .split(\",\")\n .map((value) => value.trim())\n .filter(Boolean),\n ),\n];\n\nconst getSameProviderModelId = (value: string, name: string) => {\n if (value.includes(\"/\")) {\n throw new Error(\n `${name} must be a model or deployment id without a provider prefix. ` +\n \"All survey assistant models use SURVEY_ASSISTANT_PROVIDER.\",\n );\n }\n return value;\n};\n\nconst getOptionalSameProviderModelId = (env: Environment, name: string) => {\n const value = getValue(env, name);\n return value ? getSameProviderModelId(value, name) : undefined;\n};\n\nexport const resolveSurveyAssistantProviderOptionsKey = (\n provider: SurveyAssistantProvider,\n): SurveyAssistantProviderOptionsKey => (provider === \"azure-openai\" ? \"azure\" : provider);\n\nconst parseProvider = (\n env: Environment,\n fallback: SurveyAssistantProvider,\n): SurveyAssistantProvider => {\n const value = getValue(env, \"SURVEY_ASSISTANT_PROVIDER\")?.toLowerCase();\n if (value === \"azure\" || value === \"azure-openai\") return \"azure-openai\";\n if (value === \"openai\" || value === \"mistral\") return value;\n if (value) {\n throw new Error(\"SURVEY_ASSISTANT_PROVIDER must be one of: openai, mistral, azure-openai.\");\n }\n return fallback;\n};\n\nconst parseAzureManagement = (\n env: Environment,\n): AzureOpenAIGatewayConfig[\"management\"] | undefined => {\n if (!getBoolean(env, \"SURVEY_ASSISTANT_AZURE_DISCOVER_MODELS\", false)) return undefined;\n const management = {\n tenantId: getValue(env, \"AZURE_TENANT_ID\"),\n clientId: getValue(env, \"AZURE_CLIENT_ID\"),\n clientSecret: getValue(env, \"AZURE_CLIENT_SECRET\"),\n subscriptionId: getValue(env, \"AZURE_SUBSCRIPTION_ID\"),\n resourceGroup: getValue(env, \"AZURE_RESOURCE_GROUP\"),\n };\n return Object.values(management).every(Boolean)\n ? (management as AzureOpenAIGatewayConfig[\"management\"])\n : undefined;\n};\n\nconst getReadinessError = ({\n azure,\n env,\n modelWasConfigured,\n provider,\n requireStorage,\n}: {\n azure?: SurveyAssistantAzureConfig;\n env: Environment;\n modelWasConfigured: boolean;\n provider: SurveyAssistantProvider;\n requireStorage: boolean;\n}) => {\n if (\n requireStorage &&\n !getValue(env, \"SURVEY_ASSISTANT_DATABASE_URL\") &&\n !getValue(env, \"DATABASE_URL\")\n ) {\n return \"Survey assistant storage is not configured.\";\n }\n if (provider === \"openai\" && !getValue(env, \"OPENAI_API_KEY\")) {\n return \"The OpenAI API key is not configured for the survey assistant.\";\n }\n if (provider === \"mistral\" && !getValue(env, \"MISTRAL_API_KEY\")) {\n return \"The Mistral API key is not configured for the survey assistant.\";\n }\n if (provider === \"azure-openai\") {\n if (!azure?.resourceName) {\n return \"The Azure OpenAI resource name is not configured for the survey assistant.\";\n }\n if (!azure.apiKey) {\n return \"The Azure OpenAI API key is not configured for the survey assistant.\";\n }\n if (!modelWasConfigured) {\n return \"The Azure OpenAI deployment name is not configured for the survey assistant.\";\n }\n if (azure.discoverModels && !azure.management) {\n return \"Azure deployment discovery requires complete tenant, client, subscription, and resource-group settings.\";\n }\n }\n return null;\n};\n\nexport const parseSurveyAssistantEnvironment = (\n env: Environment,\n {\n defaultMistralModel = \"mistral-medium-latest\",\n defaultOpenAIModel = \"gpt-5.4-nano\",\n defaultProvider = \"openai\",\n requireExperimentalIdentityOptIn = false,\n requireStorage = true,\n }: ParseSurveyAssistantEnvironmentOptions = {},\n): SurveyAssistantRuntimeConfig => {\n const provider = parseProvider(env, defaultProvider);\n const configuredModelId = getOptionalSameProviderModelId(env, \"SURVEY_ASSISTANT_MODEL\");\n const defaultModelId =\n configuredModelId ??\n getSameProviderModelId(\n provider === \"mistral\" ? defaultMistralModel : defaultOpenAIModel,\n provider === \"mistral\" ? \"defaultMistralModel\" : \"defaultOpenAIModel\",\n );\n const modelIds = [\n ...new Set([\n defaultModelId,\n ...getCommaSeparatedValues(env, \"SURVEY_ASSISTANT_MODELS\").map((modelId) =>\n getSameProviderModelId(modelId, \"SURVEY_ASSISTANT_MODELS\"),\n ),\n ]),\n ];\n const taskModelId = getOptionalSameProviderModelId(env, \"SURVEY_ASSISTANT_TASK_MODEL\");\n const sendReasoning = getBoolean(env, \"SURVEY_ASSISTANT_SEND_REASONING\", true);\n const providerOptionsKey = resolveSurveyAssistantProviderOptionsKey(provider);\n const providerReasoningEffort = getValue(\n env,\n `SURVEY_ASSISTANT_${providerOptionsKey.toUpperCase()}_REASONING_EFFORT`,\n );\n const reasoningEffort =\n providerReasoningEffort ??\n getValue(env, \"SURVEY_ASSISTANT_REASONING_EFFORT\") ??\n (provider === \"openai\" || provider === \"azure-openai\" ? \"low\" : \"none\");\n const promptCacheRetention = getEnum(\n env,\n provider === \"azure-openai\"\n ? \"SURVEY_ASSISTANT_AZURE_PROMPT_CACHE_RETENTION\"\n : \"SURVEY_ASSISTANT_PROMPT_CACHE_RETENTION\",\n [\"in_memory\", \"24h\"] as const,\n );\n const serviceTier = getEnum(env, \"SURVEY_ASSISTANT_OPENAI_SERVICE_TIER\", [\n \"auto\",\n \"flex\",\n \"priority\",\n \"default\",\n ] as const);\n const textVerbosity = getEnum(env, \"SURVEY_ASSISTANT_OPENAI_TEXT_VERBOSITY\", [\n \"low\",\n \"medium\",\n \"high\",\n ] as const);\n const reasoningSummaryValue = getEnum(env, \"SURVEY_ASSISTANT_OPENAI_REASONING_SUMMARY\", [\n \"auto\",\n \"concise\",\n \"detailed\",\n \"off\",\n \"none\",\n ] as const);\n const reasoningSummary =\n reasoningSummaryValue === \"off\" || reasoningSummaryValue === \"none\"\n ? undefined\n : (reasoningSummaryValue ?? \"auto\");\n const resolvedReasoningEffort =\n reasoningEffort === \"default\" || reasoningEffort === \"provider-default\"\n ? undefined\n : reasoningEffort;\n const providerOptions: AgentExecutionOptions[\"providerOptions\"] = {\n [providerOptionsKey]: {\n parallelToolCalls: false,\n ...(resolvedReasoningEffort ? { reasoningEffort: resolvedReasoningEffort } : {}),\n ...(provider === \"openai\" || provider === \"azure-openai\"\n ? {\n promptCacheKey:\n getValue(env, \"SURVEY_ASSISTANT_PROMPT_CACHE_KEY\") ?? \"survey-assistant-chat-v21\",\n ...(promptCacheRetention ? { promptCacheRetention } : {}),\n ...(sendReasoning && reasoningSummary ? { reasoningSummary } : {}),\n ...(provider === \"openai\" && serviceTier ? { serviceTier } : {}),\n ...(textVerbosity ? { textVerbosity } : {}),\n }\n : {}),\n },\n };\n const azure: SurveyAssistantAzureConfig | undefined =\n provider === \"azure-openai\"\n ? {\n resourceName: getValue(env, \"AZURE_RESOURCE_NAME\"),\n apiKey: getValue(env, \"AZURE_API_KEY\"),\n apiVersion: getValue(env, \"SURVEY_ASSISTANT_AZURE_API_VERSION\") ?? \"v1\",\n discoverModels: getBoolean(env, \"SURVEY_ASSISTANT_AZURE_DISCOVER_MODELS\", false),\n management: parseAzureManagement(env),\n }\n : undefined;\n const memoryModelId =\n getOptionalSameProviderModelId(env, \"SURVEY_ASSISTANT_MEMORY_MODEL\") ?? defaultModelId;\n const memoryModel = `${provider}/${memoryModelId}`;\n const observationalMemory = getBoolean(env, \"SURVEY_ASSISTANT_MEMORY_ENABLED\", true)\n ? createSurveyAssistantObservationalMemoryOptions({\n model: memoryModel,\n temporalMarkers: getBoolean(env, \"SURVEY_ASSISTANT_MEMORY_TEMPORAL_MARKERS\", false),\n observation: {\n messageTokens: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MEMORY_MESSAGE_TOKENS\",\n SURVEY_ASSISTANT_OBSERVATIONAL_MEMORY_DEFAULTS.messageTokens,\n ),\n bufferOnIdle: getBoolean(env, \"SURVEY_ASSISTANT_MEMORY_BUFFER_ON_IDLE\", false),\n observeAttachments: false,\n },\n reflection: {\n observationTokens: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MEMORY_OBSERVATION_TOKENS\",\n SURVEY_ASSISTANT_OBSERVATIONAL_MEMORY_DEFAULTS.observationTokens,\n ),\n },\n })\n : false;\n const configuredMaxSteps = getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_STEPS\",\n DEFAULT_MAX_STEPS,\n );\n const enabledSetting = getValue(env, \"SURVEY_ASSISTANT_ENABLED\")?.toLowerCase();\n if (enabledSetting !== undefined && enabledSetting !== \"true\" && enabledSetting !== \"false\") {\n throw new Error('SURVEY_ASSISTANT_ENABLED must be \"true\" or \"false\".');\n }\n const enabled =\n enabledSetting === \"false\"\n ? false\n : enabledSetting === \"true\"\n ? !requireExperimentalIdentityOptIn ||\n env.NODE_ENV === \"development\" ||\n getBoolean(env, \"SURVEY_ASSISTANT_ALLOW_EXPERIMENTAL_IDENTITY\", false)\n : env.NODE_ENV === \"development\";\n\n return {\n provider,\n defaultModelId,\n memoryModelId,\n modelIds,\n modelCatalogTtlMs: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MODEL_CATALOG_TTL_MS\",\n DEFAULT_CATALOG_TTL_MS,\n ),\n azure,\n enabled,\n readinessError: getReadinessError({\n azure,\n env,\n modelWasConfigured: Boolean(configuredModelId),\n provider,\n requireStorage,\n }),\n requestLimits: {\n maxAttachmentBytes: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_ATTACHMENT_BYTES\",\n SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxAttachmentBytes,\n ),\n maxAttachments: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_ATTACHMENTS\",\n SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxAttachments,\n ),\n maxRequestBytes: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_REQUEST_BYTES\",\n SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxRequestBytes,\n ),\n maxTextPartChars: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_TEXT_PART_CHARS\",\n SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxTextPartChars,\n ),\n maxTotalAttachmentBytes: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_TOTAL_ATTACHMENT_BYTES\",\n SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxTotalAttachmentBytes,\n ),\n },\n execution: {\n maxConcurrentRequests: getPositiveNumber(env, \"SURVEY_ASSISTANT_MAX_CONCURRENT_REQUESTS\", 4),\n maxDurationMs: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_DURATION_MS\",\n DEFAULT_MAX_DURATION_MS,\n ),\n maxSteps: Math.min(configuredMaxSteps, HARD_MAX_STEPS),\n providerOptions,\n sendReasoning,\n },\n observationalMemory,\n taskModelId,\n };\n};\n","import type { AgentExecutionOptions } from \"@mastra/core/agent\";\nimport { AzureOpenAIGateway, type MastraModelGatewayInterface } from \"@mastra/core/llm\";\nimport type { Mastra } from \"@mastra/core/mastra\";\nimport type { RequestContext } from \"@mastra/core/request-context\";\nimport type { SurveyAssistantModelCatalog } from \"../protocol\";\nimport { createSurveyAssistantAgent, type CreateSurveyAssistantAgentOptions } from \"./agent\";\nimport { SURVEY_ASSISTANT_AGENT_ID, SURVEY_ASSISTANT_TASK_AGENT_ID } from \"./constants\";\nimport {\n createSurveyAssistantChatHandler,\n SurveyAssistantAuthorizationError,\n type SurveyAssistantAuthorize,\n type SurveyAssistantChatHandlerOptions,\n type SurveyAssistantResolveModel,\n} from \"./handler\";\nimport { createMastraMemoryThreadRepository } from \"./memory-thread-repository\";\nimport type { SurveyAssistantRequestContext } from \"./request-context\";\nimport type { SurveyAssistantCapabilitySet } from \"../engine\";\nimport type { SurveyAssistantRuntimeConfig } from \"./runtime-config\";\nimport {\n createSurveyAssistantTaskAgent,\n createSurveyAssistantTaskHandler,\n type CreateSurveyAssistantTaskHandlerOptions,\n type SurveyAssistantTaskModelResolutionInput,\n} from \"./tasks\";\nimport type { SurveyAssistantThreadDocumentRepository } from \"./thread-documents\";\nimport {\n createSurveyAssistantThreadHandlers,\n type CreateSurveyAssistantThreadHandlersOptions,\n} from \"./thread-handlers\";\nimport { SURVEY_ASSISTANT_TOOL_IDS } from \"./tools\";\n\nexport {\n parseSurveyAssistantEnvironment,\n resolveSurveyAssistantProviderOptionsKey,\n type ParseSurveyAssistantEnvironmentOptions,\n type SurveyAssistantAzureConfig,\n type SurveyAssistantExecutionConfig,\n type SurveyAssistantProvider,\n type SurveyAssistantProviderOptionsKey,\n type SurveyAssistantRuntimeConfig,\n} from \"./runtime-config\";\n\nexport interface SurveyAssistantModelRouter {\n defaultModel: string;\n gateways?: Record<string, MastraModelGatewayInterface>;\n getCatalog(options?: { refresh?: boolean }): Promise<SurveyAssistantModelCatalog>;\n memoryModel: string;\n providerName: string;\n providerOptions?: AgentExecutionOptions[\"providerOptions\"];\n resolveModel: SurveyAssistantResolveModel;\n resolveTaskModel(\n input: SurveyAssistantTaskModelResolutionInput,\n ): ReturnType<SurveyAssistantResolveModel>;\n taskModel?: string;\n}\n\nexport const createSurveyAssistantModelRouter = (\n config: SurveyAssistantRuntimeConfig,\n): SurveyAssistantModelRouter => {\n const toProviderModel = (modelId: string, configName: string) => {\n if (modelId.includes(\"/\")) {\n throw new Error(\n `${configName} must be a model or deployment id without a provider prefix. ` +\n \"All survey assistant models use the configured provider.\",\n );\n }\n return `${config.provider}/${modelId}`;\n };\n const defaultModel = toProviderModel(config.defaultModelId, \"defaultModelId\");\n const chatModelIds = config.modelIds.map((modelId) => {\n toProviderModel(modelId, \"modelIds\");\n return modelId;\n });\n if (!chatModelIds.includes(config.defaultModelId)) {\n throw new Error(\"modelIds must include defaultModelId.\");\n }\n const taskModel = config.taskModelId\n ? toProviderModel(config.taskModelId, \"taskModelId\")\n : undefined;\n const memoryModel = toProviderModel(config.memoryModelId, \"memoryModelId\");\n if (config.observationalMemory !== false) {\n if (\n typeof config.observationalMemory.model !== \"string\" ||\n config.observationalMemory.model !== memoryModel ||\n config.observationalMemory.observation?.model !== undefined ||\n config.observationalMemory.reflection?.model !== undefined\n ) {\n throw new Error(\n \"The standard runtime requires observationalMemory to use memoryModelId \" +\n \"for both observation and reflection. Use the low-level Agent factory \" +\n \"for custom memory model routing.\",\n );\n }\n }\n const deploymentIds = [\n ...new Set([\n ...chatModelIds,\n ...(config.taskModelId ? [config.taskModelId] : []),\n config.memoryModelId,\n ]),\n ];\n const azureGateway = config.azure\n ? new AzureOpenAIGateway({\n resourceName: config.azure.resourceName ?? \"\",\n apiKey: config.azure.apiKey,\n apiVersion: config.azure.apiVersion,\n useResponsesAPI: true,\n ...(config.azure.management\n ? { management: config.azure.management }\n : { deployments: deploymentIds }),\n })\n : undefined;\n let cachedCatalog: { expiresAt: number; value: SurveyAssistantModelCatalog } | undefined;\n\n const getCatalog = async ({ refresh = false }: { refresh?: boolean } = {}) => {\n if (!refresh && cachedCatalog && cachedCatalog.expiresAt > Date.now()) {\n return cachedCatalog.value;\n }\n let ids = chatModelIds;\n if (azureGateway && config.azure?.discoverModels) {\n try {\n const providers = await azureGateway.fetchProviders();\n ids = [...new Set([...chatModelIds, ...(providers[\"azure-openai\"]?.models ?? [])])];\n } catch {\n // Keep the explicit catalog available when Azure management discovery is temporarily down.\n }\n }\n const value = {\n defaultModelId: config.defaultModelId,\n models: ids.map((id) => ({ id, label: id })),\n } satisfies SurveyAssistantModelCatalog;\n cachedCatalog = { expiresAt: Date.now() + config.modelCatalogTtlMs, value };\n return value;\n };\n const resolveRequestedModel = async (requestedModelId?: string) => {\n const catalog = await getCatalog();\n const id = requestedModelId ?? catalog.defaultModelId;\n return catalog.models.some((model) => model.id === id)\n ? { id, model: toProviderModel(id, \"requestedModelId\") }\n : null;\n };\n\n return {\n defaultModel,\n gateways: azureGateway\n ? {\n // Mastra 1.47 narrows one method's environment type in the concrete class.\n \"azure-openai\": azureGateway as unknown as MastraModelGatewayInterface,\n }\n : undefined,\n getCatalog,\n memoryModel,\n providerName: config.provider,\n providerOptions: config.execution.providerOptions,\n resolveModel: async ({ requestedModelId }) => resolveRequestedModel(requestedModelId),\n resolveTaskModel: async ({ requestedModelId }) =>\n config.taskModelId\n ? { id: config.taskModelId, model: taskModel! }\n : resolveRequestedModel(requestedModelId),\n taskModel,\n };\n};\n\nexport interface SurveyAssistantRuntimeComponents {\n agents: Record<\n string,\n | ReturnType<typeof createSurveyAssistantAgent>\n | ReturnType<typeof createSurveyAssistantTaskAgent>\n >;\n gateways?: Record<string, MastraModelGatewayInterface>;\n modelRouter: SurveyAssistantModelRouter;\n}\n\nexport const createSurveyAssistantRuntimeComponents = (\n config: SurveyAssistantRuntimeConfig,\n): SurveyAssistantRuntimeComponents => {\n const modelRouter = createSurveyAssistantModelRouter(config);\n const chatModel: CreateSurveyAssistantAgentOptions[\"model\"] = ({\n requestContext,\n }: {\n requestContext: RequestContext<SurveyAssistantRequestContext>;\n }) => requestContext.get(\"modelSelection\")?.model ?? modelRouter.defaultModel;\n const taskModel = modelRouter.taskModel ?? chatModel;\n return {\n agents: {\n [SURVEY_ASSISTANT_AGENT_ID]: createSurveyAssistantAgent({\n model: chatModel,\n observationalMemory: config.observationalMemory,\n }),\n [SURVEY_ASSISTANT_TASK_AGENT_ID]: createSurveyAssistantTaskAgent({ model: taskModel }),\n },\n gateways: modelRouter.gateways,\n modelRouter,\n };\n};\n\ntype ChatHandlerOverrides = Partial<\n Omit<\n SurveyAssistantChatHandlerOptions,\n \"authorize\" | \"mastra\" | \"providerName\" | \"providerOptions\" | \"resolveModel\"\n >\n>;\ntype TaskHandlerOverrides = Partial<\n Omit<\n CreateSurveyAssistantTaskHandlerOptions,\n \"agent\" | \"authorize\" | \"providerOptions\" | \"resolveModel\"\n >\n>;\n\nexport interface CreateSurveyAssistantRuntimeHandlersOptions {\n authorize: {\n chat: SurveyAssistantAuthorize;\n model?: (request: Request) => unknown | Promise<unknown>;\n task: CreateSurveyAssistantTaskHandlerOptions[\"authorize\"];\n thread: CreateSurveyAssistantThreadHandlersOptions[\"authorize\"];\n };\n chat?: ChatHandlerOverrides;\n config: SurveyAssistantRuntimeConfig;\n mastra: Mastra | (() => Mastra | Promise<Mastra>);\n modelRouter: SurveyAssistantModelRouter;\n task?: TaskHandlerOverrides;\n threadDocuments?: SurveyAssistantThreadDocumentRepository;\n}\n\nexport type CreateConfiguredSurveyAssistantRuntimeHandlersOptions = Omit<\n CreateSurveyAssistantRuntimeHandlersOptions,\n \"config\" | \"modelRouter\"\n>;\n\nconst resolveMastra = async (mastra: Mastra | (() => Mastra | Promise<Mastra>)) =>\n typeof mastra === \"function\" ? mastra() : mastra;\n\nexport const createSurveyAssistantRuntimeHandlers = ({\n authorize,\n chat = {},\n config,\n mastra,\n modelRouter,\n task = {},\n threadDocuments,\n}: CreateSurveyAssistantRuntimeHandlersOptions) => {\n const isEnabled = chat.isEnabled ?? (() => config.enabled);\n const getReadinessError = chat.getReadinessError ?? (() => config.readinessError);\n const chatHandler = createSurveyAssistantChatHandler({\n ...chat,\n mastra,\n agentId: SURVEY_ASSISTANT_AGENT_ID,\n activeTools:\n chat.activeTools ??\n (config.observationalMemory === false\n ? SURVEY_ASSISTANT_TOOL_IDS\n : [...SURVEY_ASSISTANT_TOOL_IDS, \"recall\"]),\n authorize: authorize.chat,\n getReadinessError,\n isEnabled,\n maxConcurrentRequests: chat.maxConcurrentRequests ?? config.execution.maxConcurrentRequests,\n maxDurationMs: chat.maxDurationMs ?? config.execution.maxDurationMs,\n maxSteps: chat.maxSteps ?? config.execution.maxSteps,\n providerName: modelRouter.providerName,\n providerOptions: modelRouter.providerOptions,\n requestLimits: { ...config.requestLimits, ...chat.requestLimits },\n resolveModel: modelRouter.resolveModel,\n sendReasoning: chat.sendReasoning ?? config.execution.sendReasoning,\n threadDocuments,\n });\n const taskHandler = createSurveyAssistantTaskHandler({\n ...task,\n agent: async () => (await resolveMastra(mastra)).getAgent(SURVEY_ASSISTANT_TASK_AGENT_ID),\n authorize: authorize.task,\n getReadinessError: task.getReadinessError ?? getReadinessError,\n isEnabled: task.isEnabled ?? isEnabled,\n maxConcurrentRequests: task.maxConcurrentRequests ?? config.execution.maxConcurrentRequests,\n maxDurationMs: task.maxDurationMs ?? config.execution.maxDurationMs,\n providerOptions: modelRouter.providerOptions,\n resolveModel: modelRouter.resolveTaskModel,\n });\n const getMemory = async () => {\n const memory = await (\n await resolveMastra(mastra)\n )\n .getAgent(SURVEY_ASSISTANT_AGENT_ID)\n .getMemory();\n if (!memory) throw new Error(\"Survey assistant memory is not configured.\");\n return memory;\n };\n const threads = createSurveyAssistantThreadHandlers({\n authorize: async (request) => {\n if (!config.enabled) {\n throw new SurveyAssistantAuthorizationError(\"Survey assistant is disabled.\", 404);\n }\n return authorize.thread(request);\n },\n repository: createMastraMemoryThreadRepository({ getMemory, threadDocuments }),\n });\n const models = async (request: Request) => {\n if (!config.enabled) {\n return Response.json(\n { code: \"authorization_failed\", error: \"Survey assistant is disabled.\" },\n { status: 404 },\n );\n }\n try {\n if (authorize.model) {\n await authorize.model(request);\n } else {\n await authorize.task({ request });\n }\n return Response.json(await modelRouter.getCatalog());\n } catch (error) {\n const status =\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n typeof error.status === \"number\"\n ? error.status\n : 403;\n return Response.json(\n {\n code: \"authorization_failed\",\n error: \"The survey assistant request is not authorized.\",\n },\n { status },\n );\n }\n };\n\n return {\n chat: chatHandler,\n models,\n task: taskHandler,\n threads,\n };\n};\n\nexport interface SurveyAssistantRuntime extends SurveyAssistantRuntimeComponents {\n config: SurveyAssistantRuntimeConfig;\n createHandlers(\n options: CreateConfiguredSurveyAssistantRuntimeHandlersOptions,\n ): ReturnType<typeof createSurveyAssistantRuntimeHandlers>;\n}\n\nexport interface CreateSurveyAssistantRuntimeOptions {\n /** Trusted server-side capabilities for custom registry item types. */\n trustedCapabilities?: SurveyAssistantCapabilitySet;\n}\n\n/**\n * Creates the reusable assistant runtime without hiding Mastra from the host.\n * Register `agents` and `gateways` in the host's standard Mastra instance, then\n * call `createHandlers` with that instance and host authorization policy.\n */\nexport const createSurveyAssistantRuntime = (\n config: SurveyAssistantRuntimeConfig,\n runtimeOptions: CreateSurveyAssistantRuntimeOptions = {},\n): SurveyAssistantRuntime => {\n const components = createSurveyAssistantRuntimeComponents(config);\n return {\n ...components,\n config,\n createHandlers: (handlerOptions) =>\n createSurveyAssistantRuntimeHandlers({\n ...handlerOptions,\n chat: {\n ...handlerOptions.chat,\n trustedCapabilities:\n handlerOptions.chat?.trustedCapabilities ?? runtimeOptions.trustedCapabilities,\n },\n config,\n modelRouter: components.modelRouter,\n }),\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server-runtime.mjs","names":[],"sources":["../src/server/runtime-config.ts","../src/server/runtime.ts"],"sourcesContent":["import type { AgentExecutionOptions } from \"@mastra/core/agent\";\nimport type { AzureOpenAIGatewayConfig } from \"@mastra/core/llm\";\nimport {\n createSurveyAssistantObservationalMemoryOptions,\n SURVEY_ASSISTANT_OBSERVATIONAL_MEMORY_DEFAULTS,\n type SurveyAssistantObservationalMemoryOptions,\n} from \"./agent\";\nimport {\n SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS,\n type SurveyAssistantRequestLimits,\n} from \"./request-guardrails\";\n\nexport type SurveyAssistantProvider = \"azure-openai\" | \"lmstudio\" | \"mistral\" | \"openai\";\nexport type SurveyAssistantProviderOptionsKey = \"azure\" | \"lmstudio\" | \"mistral\" | \"openai\";\n\nexport interface SurveyAssistantAzureConfig {\n apiKey?: string;\n apiVersion: string;\n discoverModels: boolean;\n management?: AzureOpenAIGatewayConfig[\"management\"];\n resourceName?: string;\n}\n\nexport interface SurveyAssistantLmStudioConfig {\n apiKey?: string;\n baseUrl: string;\n}\n\nexport interface SurveyAssistantExecutionConfig {\n firstResponseTimeoutMs: number;\n idleTimeoutMs: number;\n maxConcurrentRequests: number;\n /** Absolute execution ceiling. Active streams still stop when this duration is reached. */\n maxDurationMs: number;\n maxSteps: number;\n providerOptions?: AgentExecutionOptions[\"providerOptions\"];\n sendReasoning: boolean;\n}\n\nexport interface SurveyAssistantRuntimeConfig {\n azure?: SurveyAssistantAzureConfig;\n lmstudio?: SurveyAssistantLmStudioConfig;\n /** Default chat model and fallback for chat requests without a selection. */\n defaultModelId: string;\n enabled: boolean;\n /** Fixed same-provider model shared by memory observation and reflection. */\n memoryModelId: string;\n modelCatalogTtlMs: number;\n modelIds: string[];\n observationalMemory: SurveyAssistantObservationalMemoryOptions | false;\n provider: SurveyAssistantProvider;\n requestLimits: Pick<\n SurveyAssistantRequestLimits,\n | \"maxAttachmentBytes\"\n | \"maxAttachments\"\n | \"maxRequestBytes\"\n | \"maxTextPartChars\"\n | \"maxTotalAttachmentBytes\"\n >;\n readinessError: string | null;\n /**\n * Fixed model for one-shot tasks. When omitted, tasks follow the\n * server-authorized chat model selection.\n */\n taskModelId?: string;\n execution: SurveyAssistantExecutionConfig;\n}\n\nexport interface ParseSurveyAssistantEnvironmentOptions {\n defaultLmStudioModel?: string;\n defaultMistralModel?: string;\n defaultOpenAIModel?: string;\n defaultProvider?: SurveyAssistantProvider;\n requireExperimentalIdentityOptIn?: boolean;\n requireStorage?: boolean;\n}\n\ntype Environment = Record<string, string | undefined>;\n\nconst DEFAULT_MAX_STEPS = 48;\nconst HARD_MAX_STEPS = 64;\nconst DEFAULT_FIRST_RESPONSE_TIMEOUT_MS = 15 * 60 * 1_000;\nconst DEFAULT_IDLE_TIMEOUT_MS = 5 * 60 * 1_000;\nconst DEFAULT_MAX_DURATION_MS = 60 * 60 * 1_000;\nconst DEFAULT_CATALOG_TTL_MS = 5 * 60 * 1_000;\n\nconst getValue = (env: Environment, name: string) => {\n const value = env[name]?.trim();\n return value || undefined;\n};\n\nconst getBoolean = (env: Environment, name: string, fallback: boolean) => {\n const value = getValue(env, name)?.toLowerCase();\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n if (value !== undefined) {\n throw new Error(`${name} must be \"true\" or \"false\".`);\n }\n return fallback;\n};\n\nconst getPositiveNumber = (env: Environment, name: string, fallback: number) => {\n const configured = getValue(env, name);\n if (configured === undefined) return fallback;\n const value = Number(configured);\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(`${name} must be a positive integer.`);\n }\n return value;\n};\n\nconst getEnum = <TValue extends string>(\n env: Environment,\n name: string,\n values: readonly TValue[],\n) => {\n const value = getValue(env, name);\n if (!value) return undefined;\n if (!(values as readonly string[]).includes(value)) {\n throw new Error(`${name} must be one of: ${values.join(\", \")}.`);\n }\n return value as TValue;\n};\n\nconst getCommaSeparatedValues = (env: Environment, name: string) => [\n ...new Set(\n (getValue(env, name) ?? \"\")\n .split(\",\")\n .map((value) => value.trim())\n .filter(Boolean),\n ),\n];\n\nconst getSameProviderModelId = (\n value: string,\n name: string,\n { allowNestedId = false }: { allowNestedId?: boolean } = {},\n) => {\n if (!allowNestedId && value.includes(\"/\")) {\n throw new Error(\n `${name} must be a model or deployment id without a provider prefix. ` +\n \"All survey assistant models use SURVEY_ASSISTANT_PROVIDER.\",\n );\n }\n return value;\n};\n\nconst getOptionalSameProviderModelId = (\n env: Environment,\n name: string,\n options?: { allowNestedId?: boolean },\n) => {\n const value = getValue(env, name);\n return value ? getSameProviderModelId(value, name, options) : undefined;\n};\n\nexport const resolveSurveyAssistantProviderOptionsKey = (\n provider: SurveyAssistantProvider,\n): SurveyAssistantProviderOptionsKey => (provider === \"azure-openai\" ? \"azure\" : provider);\n\nconst parseProvider = (\n env: Environment,\n fallback: SurveyAssistantProvider,\n): SurveyAssistantProvider => {\n const value = getValue(env, \"SURVEY_ASSISTANT_PROVIDER\")?.toLowerCase();\n if (value === \"azure\" || value === \"azure-openai\") return \"azure-openai\";\n if (value === \"lmstudio\" || value === \"openai\" || value === \"mistral\") return value;\n if (value) {\n throw new Error(\n \"SURVEY_ASSISTANT_PROVIDER must be one of: openai, mistral, lmstudio, azure-openai.\",\n );\n }\n return fallback;\n};\n\nconst parseAzureManagement = (\n env: Environment,\n): AzureOpenAIGatewayConfig[\"management\"] | undefined => {\n if (!getBoolean(env, \"SURVEY_ASSISTANT_AZURE_DISCOVER_MODELS\", false)) return undefined;\n const management = {\n tenantId: getValue(env, \"AZURE_TENANT_ID\"),\n clientId: getValue(env, \"AZURE_CLIENT_ID\"),\n clientSecret: getValue(env, \"AZURE_CLIENT_SECRET\"),\n subscriptionId: getValue(env, \"AZURE_SUBSCRIPTION_ID\"),\n resourceGroup: getValue(env, \"AZURE_RESOURCE_GROUP\"),\n };\n return Object.values(management).every(Boolean)\n ? (management as AzureOpenAIGatewayConfig[\"management\"])\n : undefined;\n};\n\nconst getReadinessError = ({\n azure,\n env,\n modelWasConfigured,\n provider,\n requireStorage,\n}: {\n azure?: SurveyAssistantAzureConfig;\n env: Environment;\n modelWasConfigured: boolean;\n provider: SurveyAssistantProvider;\n requireStorage: boolean;\n}) => {\n if (\n requireStorage &&\n !getValue(env, \"SURVEY_ASSISTANT_DATABASE_URL\") &&\n !getValue(env, \"DATABASE_URL\")\n ) {\n return \"Survey assistant storage is not configured.\";\n }\n if (provider === \"openai\" && !getValue(env, \"OPENAI_API_KEY\")) {\n return \"The OpenAI API key is not configured for the survey assistant.\";\n }\n if (provider === \"mistral\" && !getValue(env, \"MISTRAL_API_KEY\")) {\n return \"The Mistral API key is not configured for the survey assistant.\";\n }\n if (provider === \"azure-openai\") {\n if (!azure?.resourceName) {\n return \"The Azure OpenAI resource name is not configured for the survey assistant.\";\n }\n if (!azure.apiKey) {\n return \"The Azure OpenAI API key is not configured for the survey assistant.\";\n }\n if (!modelWasConfigured) {\n return \"The Azure OpenAI deployment name is not configured for the survey assistant.\";\n }\n if (azure.discoverModels && !azure.management) {\n return \"Azure deployment discovery requires complete tenant, client, subscription, and resource-group settings.\";\n }\n }\n return null;\n};\n\nexport const parseSurveyAssistantEnvironment = (\n env: Environment,\n {\n defaultLmStudioModel,\n defaultMistralModel = \"mistral-medium-latest\",\n defaultOpenAIModel = \"gpt-5.4-nano\",\n defaultProvider = \"openai\",\n requireExperimentalIdentityOptIn = false,\n requireStorage = true,\n }: ParseSurveyAssistantEnvironmentOptions = {},\n): SurveyAssistantRuntimeConfig => {\n const provider = parseProvider(env, defaultProvider);\n const modelIdOptions = { allowNestedId: provider === \"lmstudio\" };\n const configuredModelId = getOptionalSameProviderModelId(\n env,\n \"SURVEY_ASSISTANT_MODEL\",\n modelIdOptions,\n );\n if (provider === \"lmstudio\" && !configuredModelId && !defaultLmStudioModel) {\n throw new Error(\n \"SURVEY_ASSISTANT_MODEL must be configured when SURVEY_ASSISTANT_PROVIDER is lmstudio.\",\n );\n }\n const defaultModelId =\n configuredModelId ??\n getSameProviderModelId(\n provider === \"lmstudio\"\n ? defaultLmStudioModel!\n : provider === \"mistral\"\n ? defaultMistralModel\n : defaultOpenAIModel,\n provider === \"lmstudio\"\n ? \"defaultLmStudioModel\"\n : provider === \"mistral\"\n ? \"defaultMistralModel\"\n : \"defaultOpenAIModel\",\n modelIdOptions,\n );\n const configuredModelIds = getCommaSeparatedValues(env, \"SURVEY_ASSISTANT_MODELS\").map(\n (modelId) => getSameProviderModelId(modelId, \"SURVEY_ASSISTANT_MODELS\", modelIdOptions),\n );\n const modelIds = [\n ...new Set(\n configuredModelIds.includes(defaultModelId)\n ? configuredModelIds\n : [defaultModelId, ...configuredModelIds],\n ),\n ];\n const taskModelId = getOptionalSameProviderModelId(\n env,\n \"SURVEY_ASSISTANT_TASK_MODEL\",\n modelIdOptions,\n );\n const sendReasoning = getBoolean(env, \"SURVEY_ASSISTANT_SEND_REASONING\", true);\n const providerOptionsKey = resolveSurveyAssistantProviderOptionsKey(provider);\n const providerReasoningEffort = getValue(\n env,\n `SURVEY_ASSISTANT_${providerOptionsKey.toUpperCase()}_REASONING_EFFORT`,\n );\n const reasoningEffort =\n providerReasoningEffort ??\n getValue(env, \"SURVEY_ASSISTANT_REASONING_EFFORT\") ??\n (provider === \"openai\" || provider === \"azure-openai\" ? \"low\" : \"none\");\n const promptCacheRetention = getEnum(\n env,\n provider === \"azure-openai\"\n ? \"SURVEY_ASSISTANT_AZURE_PROMPT_CACHE_RETENTION\"\n : \"SURVEY_ASSISTANT_PROMPT_CACHE_RETENTION\",\n [\"in_memory\", \"24h\"] as const,\n );\n const serviceTier = getEnum(env, \"SURVEY_ASSISTANT_OPENAI_SERVICE_TIER\", [\n \"auto\",\n \"flex\",\n \"priority\",\n \"default\",\n ] as const);\n const textVerbosity = getEnum(env, \"SURVEY_ASSISTANT_OPENAI_TEXT_VERBOSITY\", [\n \"low\",\n \"medium\",\n \"high\",\n ] as const);\n const reasoningSummaryValue = getEnum(env, \"SURVEY_ASSISTANT_OPENAI_REASONING_SUMMARY\", [\n \"auto\",\n \"concise\",\n \"detailed\",\n \"off\",\n \"none\",\n ] as const);\n const reasoningSummary =\n reasoningSummaryValue === \"off\" || reasoningSummaryValue === \"none\"\n ? undefined\n : (reasoningSummaryValue ?? \"detailed\");\n const resolvedReasoningEffort =\n reasoningEffort === \"default\" || reasoningEffort === \"provider-default\"\n ? undefined\n : reasoningEffort;\n const providerOptions: AgentExecutionOptions[\"providerOptions\"] =\n provider === \"lmstudio\"\n ? undefined\n : {\n [providerOptionsKey]: {\n parallelToolCalls: false,\n ...(resolvedReasoningEffort ? { reasoningEffort: resolvedReasoningEffort } : {}),\n ...(provider === \"openai\" || provider === \"azure-openai\"\n ? {\n promptCacheKey:\n getValue(env, \"SURVEY_ASSISTANT_PROMPT_CACHE_KEY\") ??\n \"survey-assistant-chat-v21\",\n ...(promptCacheRetention ? { promptCacheRetention } : {}),\n ...(sendReasoning && reasoningSummary ? { reasoningSummary } : {}),\n ...(provider === \"openai\" && serviceTier ? { serviceTier } : {}),\n ...(textVerbosity ? { textVerbosity } : {}),\n }\n : {}),\n },\n };\n const azure: SurveyAssistantAzureConfig | undefined =\n provider === \"azure-openai\"\n ? {\n resourceName: getValue(env, \"AZURE_RESOURCE_NAME\"),\n apiKey: getValue(env, \"AZURE_API_KEY\"),\n apiVersion: getValue(env, \"SURVEY_ASSISTANT_AZURE_API_VERSION\") ?? \"v1\",\n discoverModels: getBoolean(env, \"SURVEY_ASSISTANT_AZURE_DISCOVER_MODELS\", false),\n management: parseAzureManagement(env),\n }\n : undefined;\n const lmstudio: SurveyAssistantLmStudioConfig | undefined =\n provider === \"lmstudio\"\n ? {\n baseUrl:\n getValue(env, \"SURVEY_ASSISTANT_LMSTUDIO_BASE_URL\") ?? \"http://127.0.0.1:1234/v1\",\n apiKey: getValue(env, \"SURVEY_ASSISTANT_LMSTUDIO_API_KEY\"),\n }\n : undefined;\n const memoryModelId =\n getOptionalSameProviderModelId(env, \"SURVEY_ASSISTANT_MEMORY_MODEL\", modelIdOptions) ??\n defaultModelId;\n const memoryModel = `${provider}/${memoryModelId}`;\n const observationalMemory = getBoolean(env, \"SURVEY_ASSISTANT_MEMORY_ENABLED\", true)\n ? createSurveyAssistantObservationalMemoryOptions({\n model: memoryModel,\n temporalMarkers: getBoolean(env, \"SURVEY_ASSISTANT_MEMORY_TEMPORAL_MARKERS\", false),\n observation: {\n messageTokens: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MEMORY_MESSAGE_TOKENS\",\n SURVEY_ASSISTANT_OBSERVATIONAL_MEMORY_DEFAULTS.messageTokens,\n ),\n bufferOnIdle: getBoolean(env, \"SURVEY_ASSISTANT_MEMORY_BUFFER_ON_IDLE\", false),\n observeAttachments: false,\n },\n reflection: {\n observationTokens: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MEMORY_OBSERVATION_TOKENS\",\n SURVEY_ASSISTANT_OBSERVATIONAL_MEMORY_DEFAULTS.observationTokens,\n ),\n },\n })\n : false;\n const configuredMaxSteps = getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_STEPS\",\n DEFAULT_MAX_STEPS,\n );\n const enabledSetting = getValue(env, \"SURVEY_ASSISTANT_ENABLED\")?.toLowerCase();\n if (enabledSetting !== undefined && enabledSetting !== \"true\" && enabledSetting !== \"false\") {\n throw new Error('SURVEY_ASSISTANT_ENABLED must be \"true\" or \"false\".');\n }\n const enabled =\n enabledSetting === \"false\"\n ? false\n : enabledSetting === \"true\"\n ? !requireExperimentalIdentityOptIn ||\n env.NODE_ENV === \"development\" ||\n getBoolean(env, \"SURVEY_ASSISTANT_ALLOW_EXPERIMENTAL_IDENTITY\", false)\n : env.NODE_ENV === \"development\";\n\n return {\n provider,\n defaultModelId,\n memoryModelId,\n modelIds,\n modelCatalogTtlMs: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MODEL_CATALOG_TTL_MS\",\n DEFAULT_CATALOG_TTL_MS,\n ),\n azure,\n lmstudio,\n enabled,\n readinessError: getReadinessError({\n azure,\n env,\n modelWasConfigured: Boolean(configuredModelId),\n provider,\n requireStorage,\n }),\n requestLimits: {\n maxAttachmentBytes: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_ATTACHMENT_BYTES\",\n SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxAttachmentBytes,\n ),\n maxAttachments: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_ATTACHMENTS\",\n SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxAttachments,\n ),\n maxRequestBytes: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_REQUEST_BYTES\",\n SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxRequestBytes,\n ),\n maxTextPartChars: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_TEXT_PART_CHARS\",\n SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxTextPartChars,\n ),\n maxTotalAttachmentBytes: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_TOTAL_ATTACHMENT_BYTES\",\n SURVEY_ASSISTANT_DEFAULT_REQUEST_LIMITS.maxTotalAttachmentBytes,\n ),\n },\n execution: {\n firstResponseTimeoutMs: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_FIRST_RESPONSE_TIMEOUT_MS\",\n DEFAULT_FIRST_RESPONSE_TIMEOUT_MS,\n ),\n idleTimeoutMs: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_IDLE_TIMEOUT_MS\",\n DEFAULT_IDLE_TIMEOUT_MS,\n ),\n maxConcurrentRequests: getPositiveNumber(env, \"SURVEY_ASSISTANT_MAX_CONCURRENT_REQUESTS\", 4),\n maxDurationMs: getPositiveNumber(\n env,\n \"SURVEY_ASSISTANT_MAX_DURATION_MS\",\n DEFAULT_MAX_DURATION_MS,\n ),\n maxSteps: Math.min(configuredMaxSteps, HARD_MAX_STEPS),\n providerOptions,\n sendReasoning,\n },\n observationalMemory,\n taskModelId,\n };\n};\n","import type { AgentExecutionOptions } from \"@mastra/core/agent\";\nimport { AzureOpenAIGateway, type MastraModelGatewayInterface } from \"@mastra/core/llm\";\nimport type { Mastra } from \"@mastra/core/mastra\";\nimport type { RequestContext } from \"@mastra/core/request-context\";\nimport type { SurveyAssistantModelCatalog } from \"../protocol\";\nimport { createSurveyAssistantAgent, type CreateSurveyAssistantAgentOptions } from \"./agent\";\nimport { SURVEY_ASSISTANT_AGENT_ID, SURVEY_ASSISTANT_TASK_AGENT_ID } from \"./constants\";\nimport {\n createSurveyAssistantChatHandler,\n SurveyAssistantAuthorizationError,\n type SurveyAssistantAuthorize,\n type SurveyAssistantChatHandlerOptions,\n type SurveyAssistantResolveModel,\n} from \"./handler\";\nimport { createMastraMemoryThreadRepository } from \"./memory-thread-repository\";\nimport type {\n SurveyAssistantModelSelection,\n SurveyAssistantRequestContext,\n} from \"./request-context\";\nimport type { SurveyAssistantCapabilitySet } from \"../engine\";\nimport type { SurveyAssistantRuntimeConfig } from \"./runtime-config\";\nimport {\n createSurveyAssistantTaskAgent,\n createSurveyAssistantTaskHandler,\n type CreateSurveyAssistantTaskHandlerOptions,\n type SurveyAssistantTaskModelResolutionInput,\n} from \"./tasks\";\nimport type { SurveyAssistantThreadDocumentRepository } from \"./thread-documents\";\nimport {\n createSurveyAssistantThreadHandlers,\n type CreateSurveyAssistantThreadHandlersOptions,\n} from \"./thread-handlers\";\nimport { SURVEY_ASSISTANT_TOOL_IDS } from \"./tools\";\n\nexport {\n parseSurveyAssistantEnvironment,\n resolveSurveyAssistantProviderOptionsKey,\n type ParseSurveyAssistantEnvironmentOptions,\n type SurveyAssistantAzureConfig,\n type SurveyAssistantExecutionConfig,\n type SurveyAssistantLmStudioConfig,\n type SurveyAssistantProvider,\n type SurveyAssistantProviderOptionsKey,\n type SurveyAssistantRuntimeConfig,\n} from \"./runtime-config\";\n\nexport interface SurveyAssistantModelRouter {\n defaultModel: SurveyAssistantModelSelection[\"model\"];\n gateways?: Record<string, MastraModelGatewayInterface>;\n getCatalog(options?: { refresh?: boolean }): Promise<SurveyAssistantModelCatalog>;\n memoryModel: SurveyAssistantModelSelection[\"model\"];\n providerName: string;\n providerOptions?: AgentExecutionOptions[\"providerOptions\"];\n resolveModel: SurveyAssistantResolveModel;\n resolveTaskModel(\n input: SurveyAssistantTaskModelResolutionInput,\n ): ReturnType<SurveyAssistantResolveModel>;\n taskModel?: SurveyAssistantModelSelection[\"model\"];\n}\n\nexport const createSurveyAssistantModelRouter = (\n config: SurveyAssistantRuntimeConfig,\n): SurveyAssistantModelRouter => {\n const toProviderModel = (\n modelId: string,\n configName: string,\n ): SurveyAssistantModelSelection[\"model\"] => {\n if (config.provider === \"lmstudio\") {\n if (!config.lmstudio) {\n throw new Error(\"LM Studio configuration is missing for the lmstudio provider.\");\n }\n return {\n providerId: \"lmstudio\",\n modelId,\n url: config.lmstudio.baseUrl,\n ...(config.lmstudio.apiKey ? { apiKey: config.lmstudio.apiKey } : {}),\n };\n }\n if (modelId.includes(\"/\")) {\n throw new Error(\n `${configName} must be a model or deployment id without a provider prefix. ` +\n \"All survey assistant models use the configured provider.\",\n );\n }\n return `${config.provider}/${modelId}`;\n };\n const defaultModel = toProviderModel(config.defaultModelId, \"defaultModelId\");\n const chatModelIds = config.modelIds.map((modelId) => {\n toProviderModel(modelId, \"modelIds\");\n return modelId;\n });\n if (!chatModelIds.includes(config.defaultModelId)) {\n throw new Error(\"modelIds must include defaultModelId.\");\n }\n const taskModel = config.taskModelId\n ? toProviderModel(config.taskModelId, \"taskModelId\")\n : undefined;\n const memoryModel = toProviderModel(config.memoryModelId, \"memoryModelId\");\n if (config.observationalMemory !== false) {\n const configuredMemoryModel = `${config.provider}/${config.memoryModelId}`;\n if (\n typeof config.observationalMemory.model !== \"string\" ||\n config.observationalMemory.model !== configuredMemoryModel ||\n config.observationalMemory.observation?.model !== undefined ||\n config.observationalMemory.reflection?.model !== undefined\n ) {\n throw new Error(\n \"The standard runtime requires observationalMemory to use memoryModelId \" +\n \"for both observation and reflection. Use the low-level Agent factory \" +\n \"for custom memory model routing.\",\n );\n }\n }\n const deploymentIds = [\n ...new Set([\n ...chatModelIds,\n ...(config.taskModelId ? [config.taskModelId] : []),\n config.memoryModelId,\n ]),\n ];\n const azureGateway = config.azure\n ? new AzureOpenAIGateway({\n resourceName: config.azure.resourceName ?? \"\",\n apiKey: config.azure.apiKey,\n apiVersion: config.azure.apiVersion,\n useResponsesAPI: true,\n ...(config.azure.management\n ? { management: config.azure.management }\n : { deployments: deploymentIds }),\n })\n : undefined;\n let cachedCatalog: { expiresAt: number; value: SurveyAssistantModelCatalog } | undefined;\n\n const getCatalog = async ({ refresh = false }: { refresh?: boolean } = {}) => {\n if (!refresh && cachedCatalog && cachedCatalog.expiresAt > Date.now()) {\n return cachedCatalog.value;\n }\n let ids = chatModelIds;\n if (azureGateway && config.azure?.discoverModels) {\n try {\n const providers = await azureGateway.fetchProviders();\n ids = [...new Set([...chatModelIds, ...(providers[\"azure-openai\"]?.models ?? [])])];\n } catch {\n // Keep the explicit catalog available when Azure management discovery is temporarily down.\n }\n }\n const value = {\n defaultModelId: config.defaultModelId,\n models: ids.map((id) => ({ id, label: id })),\n } satisfies SurveyAssistantModelCatalog;\n cachedCatalog = { expiresAt: Date.now() + config.modelCatalogTtlMs, value };\n return value;\n };\n const resolveRequestedModel = async (requestedModelId?: string) => {\n const catalog = await getCatalog();\n const id = requestedModelId ?? catalog.defaultModelId;\n return catalog.models.some((model) => model.id === id)\n ? { id, model: toProviderModel(id, \"requestedModelId\") }\n : null;\n };\n\n return {\n defaultModel,\n gateways: azureGateway\n ? {\n // Mastra 1.47 narrows one method's environment type in the concrete class.\n \"azure-openai\": azureGateway as unknown as MastraModelGatewayInterface,\n }\n : undefined,\n getCatalog,\n memoryModel,\n providerName: config.provider,\n providerOptions: config.execution.providerOptions,\n resolveModel: async ({ requestedModelId }) => resolveRequestedModel(requestedModelId),\n resolveTaskModel: async ({ requestedModelId }) =>\n config.taskModelId\n ? { id: config.taskModelId, model: taskModel! }\n : resolveRequestedModel(requestedModelId),\n taskModel,\n };\n};\n\nexport interface SurveyAssistantRuntimeComponents {\n agents: Record<\n string,\n | ReturnType<typeof createSurveyAssistantAgent>\n | ReturnType<typeof createSurveyAssistantTaskAgent>\n >;\n gateways?: Record<string, MastraModelGatewayInterface>;\n modelRouter: SurveyAssistantModelRouter;\n}\n\nexport const createSurveyAssistantRuntimeComponents = (\n config: SurveyAssistantRuntimeConfig,\n): SurveyAssistantRuntimeComponents => {\n const modelRouter = createSurveyAssistantModelRouter(config);\n const chatModel: CreateSurveyAssistantAgentOptions[\"model\"] = ({\n requestContext,\n }: {\n requestContext: RequestContext<SurveyAssistantRequestContext>;\n }) => requestContext.get(\"modelSelection\")?.model ?? modelRouter.defaultModel;\n const taskModel = modelRouter.taskModel ?? chatModel;\n const observationalMemory =\n config.provider === \"lmstudio\" && config.observationalMemory !== false\n ? { ...config.observationalMemory, model: modelRouter.memoryModel }\n : config.observationalMemory;\n return {\n agents: {\n [SURVEY_ASSISTANT_AGENT_ID]: createSurveyAssistantAgent({\n model: chatModel,\n observationalMemory,\n }),\n [SURVEY_ASSISTANT_TASK_AGENT_ID]: createSurveyAssistantTaskAgent({ model: taskModel }),\n },\n gateways: modelRouter.gateways,\n modelRouter,\n };\n};\n\ntype ChatHandlerOverrides = Partial<\n Omit<\n SurveyAssistantChatHandlerOptions,\n \"authorize\" | \"mastra\" | \"providerName\" | \"providerOptions\" | \"resolveModel\"\n >\n>;\ntype TaskHandlerOverrides = Partial<\n Omit<\n CreateSurveyAssistantTaskHandlerOptions,\n \"agent\" | \"authorize\" | \"providerOptions\" | \"resolveModel\"\n >\n>;\n\nexport interface CreateSurveyAssistantRuntimeHandlersOptions {\n authorize: {\n chat: SurveyAssistantAuthorize;\n model?: (request: Request) => unknown | Promise<unknown>;\n task: CreateSurveyAssistantTaskHandlerOptions[\"authorize\"];\n thread: CreateSurveyAssistantThreadHandlersOptions[\"authorize\"];\n };\n chat?: ChatHandlerOverrides;\n config: SurveyAssistantRuntimeConfig;\n mastra: Mastra | (() => Mastra | Promise<Mastra>);\n modelRouter: SurveyAssistantModelRouter;\n task?: TaskHandlerOverrides;\n threadDocuments?: SurveyAssistantThreadDocumentRepository;\n}\n\nexport type CreateConfiguredSurveyAssistantRuntimeHandlersOptions = Omit<\n CreateSurveyAssistantRuntimeHandlersOptions,\n \"config\" | \"modelRouter\"\n>;\n\nconst resolveMastra = async (mastra: Mastra | (() => Mastra | Promise<Mastra>)) =>\n typeof mastra === \"function\" ? mastra() : mastra;\n\nexport const createSurveyAssistantRuntimeHandlers = ({\n authorize,\n chat = {},\n config,\n mastra,\n modelRouter,\n task = {},\n threadDocuments,\n}: CreateSurveyAssistantRuntimeHandlersOptions) => {\n const isEnabled = chat.isEnabled ?? (() => config.enabled);\n const getReadinessError = chat.getReadinessError ?? (() => config.readinessError);\n const chatHandler = createSurveyAssistantChatHandler({\n ...chat,\n mastra,\n agentId: SURVEY_ASSISTANT_AGENT_ID,\n activeTools:\n chat.activeTools ??\n (config.observationalMemory === false\n ? SURVEY_ASSISTANT_TOOL_IDS\n : [...SURVEY_ASSISTANT_TOOL_IDS, \"recall\"]),\n authorize: authorize.chat,\n firstResponseTimeoutMs: chat.firstResponseTimeoutMs ?? config.execution.firstResponseTimeoutMs,\n getReadinessError,\n isEnabled,\n idleTimeoutMs: chat.idleTimeoutMs ?? config.execution.idleTimeoutMs,\n maxConcurrentRequests: chat.maxConcurrentRequests ?? config.execution.maxConcurrentRequests,\n maxDurationMs: chat.maxDurationMs ?? config.execution.maxDurationMs,\n maxSteps: chat.maxSteps ?? config.execution.maxSteps,\n providerName: modelRouter.providerName,\n providerOptions: modelRouter.providerOptions,\n requestLimits: { ...config.requestLimits, ...chat.requestLimits },\n resolveModel: modelRouter.resolveModel,\n sendReasoning: chat.sendReasoning ?? config.execution.sendReasoning,\n threadDocuments,\n });\n const taskHandler = createSurveyAssistantTaskHandler({\n ...task,\n agent: async () => (await resolveMastra(mastra)).getAgent(SURVEY_ASSISTANT_TASK_AGENT_ID),\n authorize: authorize.task,\n getReadinessError: task.getReadinessError ?? getReadinessError,\n isEnabled: task.isEnabled ?? isEnabled,\n maxConcurrentRequests: task.maxConcurrentRequests ?? config.execution.maxConcurrentRequests,\n maxDurationMs: task.maxDurationMs ?? config.execution.maxDurationMs,\n providerOptions: modelRouter.providerOptions,\n resolveModel: modelRouter.resolveTaskModel,\n });\n const getMemory = async () => {\n const memory = await (\n await resolveMastra(mastra)\n )\n .getAgent(SURVEY_ASSISTANT_AGENT_ID)\n .getMemory();\n if (!memory) throw new Error(\"Survey assistant memory is not configured.\");\n return memory;\n };\n const threads = createSurveyAssistantThreadHandlers({\n authorize: async (request) => {\n if (!config.enabled) {\n throw new SurveyAssistantAuthorizationError(\"Survey assistant is disabled.\", 404);\n }\n return authorize.thread(request);\n },\n repository: createMastraMemoryThreadRepository({ getMemory, threadDocuments }),\n });\n const models = async (request: Request) => {\n if (!config.enabled) {\n return Response.json(\n { code: \"authorization_failed\", error: \"Survey assistant is disabled.\" },\n { status: 404 },\n );\n }\n try {\n if (authorize.model) {\n await authorize.model(request);\n } else {\n await authorize.task({ request });\n }\n return Response.json(await modelRouter.getCatalog());\n } catch (error) {\n const status =\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n typeof error.status === \"number\"\n ? error.status\n : 403;\n return Response.json(\n {\n code: \"authorization_failed\",\n error: \"The survey assistant request is not authorized.\",\n },\n { status },\n );\n }\n };\n\n return {\n chat: chatHandler,\n models,\n task: taskHandler,\n threads,\n };\n};\n\nexport interface SurveyAssistantRuntime extends SurveyAssistantRuntimeComponents {\n config: SurveyAssistantRuntimeConfig;\n createHandlers(\n options: CreateConfiguredSurveyAssistantRuntimeHandlersOptions,\n ): ReturnType<typeof createSurveyAssistantRuntimeHandlers>;\n}\n\nexport interface CreateSurveyAssistantRuntimeOptions {\n /** Trusted server-side capabilities for custom registry item types. */\n trustedCapabilities?: SurveyAssistantCapabilitySet;\n}\n\n/**\n * Creates the reusable assistant runtime without hiding Mastra from the host.\n * Register `agents` and `gateways` in the host's standard Mastra instance, then\n * call `createHandlers` with that instance and host authorization policy.\n */\nexport const createSurveyAssistantRuntime = (\n config: SurveyAssistantRuntimeConfig,\n runtimeOptions: CreateSurveyAssistantRuntimeOptions = {},\n): SurveyAssistantRuntime => {\n const components = createSurveyAssistantRuntimeComponents(config);\n return {\n ...components,\n config,\n createHandlers: (handlerOptions) =>\n createSurveyAssistantRuntimeHandlers({\n ...handlerOptions,\n chat: {\n ...handlerOptions.chat,\n trustedCapabilities:\n handlerOptions.chat?.trustedCapabilities ?? runtimeOptions.trustedCapabilities,\n },\n config,\n modelRouter: components.modelRouter,\n }),\n };\n};\n"],"mappings":"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"}
|
package/dist/server-tasks.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as SurveyAssistantTaskAuthorizationInput, c as createSurveyAssistantTaskAgent, d as runSurveyAssistantSuggestItemLabelTask, f as runSurveyAssistantTask, i as RunSurveyAssistantTaskOptions, l as createSurveyAssistantTaskHandler, n as CreateSurveyAssistantTaskHandlerOptions, o as SurveyAssistantTaskAuthorizedIdentity, p as runSurveyAssistantTranslateContentTask, r as RunSurveyAssistantBuiltInTaskOptions, s as SurveyAssistantTaskModelResolutionInput, t as CreateSurveyAssistantTaskAgentOptions, u as runSurveyAssistantSuggestItemKeyTask } from "./tasks-
|
|
1
|
+
import { a as SurveyAssistantTaskAuthorizationInput, c as createSurveyAssistantTaskAgent, d as runSurveyAssistantSuggestItemLabelTask, f as runSurveyAssistantTask, i as RunSurveyAssistantTaskOptions, l as createSurveyAssistantTaskHandler, n as CreateSurveyAssistantTaskHandlerOptions, o as SurveyAssistantTaskAuthorizedIdentity, p as runSurveyAssistantTranslateContentTask, r as RunSurveyAssistantBuiltInTaskOptions, s as SurveyAssistantTaskModelResolutionInput, t as CreateSurveyAssistantTaskAgentOptions, u as runSurveyAssistantSuggestItemKeyTask } from "./tasks-DIZgr4nD.mjs";
|
|
2
2
|
export { CreateSurveyAssistantTaskAgentOptions, CreateSurveyAssistantTaskHandlerOptions, RunSurveyAssistantBuiltInTaskOptions, RunSurveyAssistantTaskOptions, SurveyAssistantTaskAuthorizationInput, SurveyAssistantTaskAuthorizedIdentity, SurveyAssistantTaskModelResolutionInput, createSurveyAssistantTaskAgent, createSurveyAssistantTaskHandler, runSurveyAssistantSuggestItemKeyTask, runSurveyAssistantSuggestItemLabelTask, runSurveyAssistantTask, runSurveyAssistantTranslateContentTask };
|
package/dist/server-tasks.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { T as surveyAssistantTaskRequestSchema } from "./protocol-DATvkr1S.mjs";
|
|
2
2
|
import { n as SURVEY_ASSISTANT_TASK_AGENT_ID } from "./constants-CFUWrRtl.mjs";
|
|
3
3
|
import { d as readSurveyAssistantRequestJson, u as SurveyAssistantRequestError } from "./request-guardrails-h4t6u8mP.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { i as surveyAuthoringReferences } from "./authoring-references-ChDTVnms.mjs";
|
|
5
|
+
import { n as FAIR_ITEM_KEY_RULES_TEXT } from "./fair-guidance-CEdJYccK.mjs";
|
|
5
6
|
import { z } from "zod";
|
|
6
7
|
import { RequestContext } from "@mastra/core/request-context";
|
|
7
8
|
import { Agent } from "@mastra/core/agent";
|
|
@@ -109,7 +110,7 @@ const runSurveyAssistantSuggestItemKeyTask = async (input, options) => {
|
|
|
109
110
|
"Return one surveyPattern key that follows the strongest detected local pattern. Preserve that pattern's casing and increment a clear sequence rather than copying an existing number. If no meaningful pattern exists, use a consistent descriptive key.",
|
|
110
111
|
"Return one compact key: a recognizable 2-5 character uppercase abbreviation using only A-Z and digits.",
|
|
111
112
|
"Return one preferred key: the key you consider clearest and most useful without category-specific naming constraints, while still using only letters, digits, and underscores.",
|
|
112
|
-
|
|
113
|
+
`Return one fair key following these FAIR-by-design rules: ${FAIR_ITEM_KEY_RULES_TEXT}. Meaning belongs in metadata, so do not turn it into a sentence.`,
|
|
113
114
|
`You may return up to ${Math.max(0, maxSuggestions - 4)} genuinely useful alternatives when another category has more than one strong candidate. Tag each alternative with its category.`,
|
|
114
115
|
"Never repeat the same suggestion, including case-only or punctuation-only variations.",
|
|
115
116
|
"Do not return the current key, a sibling key, or a semantically unrelated abbreviation.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-tasks.mjs","names":[],"sources":["../src/server/tasks.ts"],"sourcesContent":["import { Agent, type AgentConfig, type AgentExecutionOptions } from \"@mastra/core/agent\";\nimport { RequestContext } from \"@mastra/core/request-context\";\nimport { z } from \"zod\";\nimport { surveyAssistantTaskRequestSchema } from \"../protocol\";\nimport type {\n SurveyAssistantSuggestItemKeyInput,\n SurveyAssistantSuggestItemKeyResult,\n SurveyAssistantKeySuggestionCategory,\n SurveyAssistantSuggestItemLabelInput,\n SurveyAssistantSuggestItemLabelResult,\n SurveyAssistantTaskInvocationMode,\n SurveyAssistantTaskContext,\n SurveyAssistantTranslateContentInput,\n SurveyAssistantTranslateContentResult,\n} from \"../protocol\";\nimport {\n surveyAuthoringReferences,\n type SurveyAuthoringReferenceTopic,\n} from \"./authoring-references\";\nimport type {\n SurveyAssistantModelSelection,\n SurveyAssistantRequestContext,\n} from \"./request-context\";\nimport { SURVEY_ASSISTANT_TASK_AGENT_ID } from \"./constants\";\nimport { readSurveyAssistantRequestJson, SurveyAssistantRequestError } from \"./request-guardrails\";\n\ntype SurveyAssistantTaskAgentConfig = AgentConfig<\n typeof SURVEY_ASSISTANT_TASK_AGENT_ID,\n Record<string, never>,\n undefined,\n SurveyAssistantRequestContext\n>;\n\nexport interface CreateSurveyAssistantTaskAgentOptions {\n model: SurveyAssistantTaskAgentConfig[\"model\"];\n}\n\nexport const createSurveyAssistantTaskAgent = ({ model }: CreateSurveyAssistantTaskAgentOptions) =>\n new Agent<\n typeof SURVEY_ASSISTANT_TASK_AGENT_ID,\n Record<string, never>,\n undefined,\n SurveyAssistantRequestContext\n >({\n id: SURVEY_ASSISTANT_TASK_AGENT_ID,\n name: \"Survey Assistant Tasks\",\n instructions:\n \"Perform the supplied bounded survey-authoring task and return only its requested structured output.\",\n model,\n });\n\nexport interface RunSurveyAssistantTaskOptions<TSchema extends z.ZodType> {\n agent: Pick<Agent, \"generate\">;\n taskId: string;\n input: unknown;\n context: SurveyAssistantTaskContext;\n schema: TSchema;\n instructions: readonly string[];\n referenceTopics?: readonly SurveyAuthoringReferenceTopic[];\n requestContext?: RequestContext<SurveyAssistantRequestContext>;\n providerOptions?: AgentExecutionOptions[\"providerOptions\"];\n abortSignal?: AbortSignal;\n}\n\nconst BASE_TASK_INSTRUCTIONS = [\n \"You perform one bounded CASE Survey Editor AI task and return only the requested structured result.\",\n \"The supplied task context was derived from the current canonical survey document snapshot. Use it as current survey context, but do not mutate it and do not claim that any editor change was applied.\",\n \"Follow the supplied CASE authoring references where relevant. Do not invent item types, locales, ids, or capabilities that are absent from the task input and context.\",\n \"Keep generated respondent-facing wording neutral, concise, and consistent with the requested locale and surrounding survey content.\",\n] as const;\n\nexport const runSurveyAssistantTask = async <TSchema extends z.ZodType>({\n agent,\n taskId,\n input,\n context,\n schema,\n instructions,\n referenceTopics = [],\n requestContext,\n providerOptions,\n abortSignal,\n}: RunSurveyAssistantTaskOptions<TSchema>): Promise<z.output<TSchema>> => {\n const references = referenceTopics.map((topic) => ({\n topic,\n title: surveyAuthoringReferences[topic].title,\n content: surveyAuthoringReferences[topic].content,\n }));\n const response = await agent.generate(\n JSON.stringify({ taskId, input, currentSurveyContext: context }),\n {\n instructions: [\n ...BASE_TASK_INSTRUCTIONS,\n ...instructions,\n ...references.map((entry) => `Reference: ${entry.title}\\n${entry.content}`),\n ],\n activeTools: [],\n inputProcessors: [],\n maxSteps: 1,\n structuredOutput: {\n schema,\n errorStrategy: \"strict\",\n },\n ...(requestContext ? { requestContext } : {}),\n ...(providerOptions ? { providerOptions } : {}),\n ...(abortSignal ? { abortSignal } : {}),\n },\n );\n\n return schema.parse(response.object);\n};\n\nconst keySuggestionValueSchema = z.object({\n text: z.string().min(1),\n rationale: z.string().optional(),\n});\n\nconst keySuggestionCategorySchema = z.enum([\"survey-pattern\", \"compact\", \"preferred\", \"fair\"]);\n\nconst keySuggestionSchema = z.object({\n surveyPattern: keySuggestionValueSchema.describe(\n \"A key that follows the strongest naming and numbering pattern in the current survey.\",\n ),\n compact: keySuggestionValueSchema.extend({\n text: z\n .string()\n .min(2)\n .max(5)\n .regex(/^[A-Z][A-Z0-9]{1,4}$/)\n .describe(\"A recognizable 2-5 character uppercase abbreviation.\"),\n }),\n preferred: keySuggestionValueSchema.describe(\n \"The key the model considers clearest without a category-specific naming constraint.\",\n ),\n fair: keySuggestionValueSchema.extend({\n text: z\n .string()\n .min(1)\n .max(32)\n .regex(/^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/)\n .describe(\"A FAIR-by-design lowercase snake_case variable name.\"),\n }),\n alternatives: z\n .array(\n keySuggestionValueSchema.extend({\n category: keySuggestionCategorySchema,\n }),\n )\n .max(2),\n});\n\nconst labelSuggestionSchema = z.object({\n suggestions: z.array(\n z.object({\n text: z.string().min(1),\n }),\n ),\n});\n\nconst translationsSchema = z.object({\n translations: z.record(z.string(), z.record(z.string(), z.string())),\n});\n\nexport interface RunSurveyAssistantBuiltInTaskOptions {\n agent: Pick<Agent, \"generate\">;\n context: SurveyAssistantTaskContext;\n mode?: SurveyAssistantTaskInvocationMode;\n requestContext?: RequestContext<SurveyAssistantRequestContext>;\n providerOptions?: AgentExecutionOptions[\"providerOptions\"];\n abortSignal?: AbortSignal;\n}\n\nconst clampLimit = (value: number | undefined, fallback: number, maximum: number) =>\n Math.min(Math.max(1, value ?? fallback), maximum);\n\nconst sanitizeCodingKey = (value: string) =>\n value\n .trim()\n .replace(/[.\\s-]+/g, \"_\")\n .replace(/[^A-Za-z0-9_]+/g, \"_\")\n .replace(/_+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n\nconst getCodingKeyIdentity = (value: string) => sanitizeCodingKey(value).toLocaleLowerCase();\n\nconst getNumberedKeyParts = (value: string) => {\n const match = /^(.+?)_(\\d+)$/.exec(getCodingKeyIdentity(value));\n return match ? { stem: match[1], number: Number(match[2]) } : undefined;\n};\n\nconst isUnsupportedFocusedItemSequence = (\n candidate: string,\n input: SurveyAssistantSuggestItemKeyInput,\n context: SurveyAssistantTaskContext,\n) => {\n const candidateParts = getNumberedKeyParts(candidate);\n const focusItem = context.focus?.item;\n if (!candidateParts || !focusItem) return false;\n\n const focusedKeyParts = [input.currentKey, input.draftKey, focusItem.key]\n .map(getNumberedKeyParts)\n .find((parts) => parts?.stem === candidateParts.stem && parts.number < candidateParts.number);\n if (!focusedKeyParts) return false;\n\n return !context.naming?.keyExamples.some((example) => {\n const exampleParts = getNumberedKeyParts(example.key);\n return example.itemType === focusItem.itemType && exampleParts?.stem === candidateParts.stem;\n });\n};\n\nconst invocationInstruction = (mode: SurveyAssistantTaskInvocationMode | undefined) =>\n mode === \"background\"\n ? \"This is a background invocation. Be efficient, but do not relax task conventions, completeness, or output quality.\"\n : \"This is an explicit user invocation. Prioritize quality and useful variation.\";\n\nexport const runSurveyAssistantSuggestItemKeyTask = async (\n input: SurveyAssistantSuggestItemKeyInput,\n options: RunSurveyAssistantBuiltInTaskOptions,\n): Promise<SurveyAssistantSuggestItemKeyResult> => {\n const maxSuggestions = Math.min(Math.max(4, input.maxSuggestions ?? 6), 6);\n const result = await runSurveyAssistantTask({\n ...options,\n taskId: \"suggest-item-key\",\n input,\n schema: keySuggestionSchema,\n instructions: [\n \"Generate coding keys for the focused survey item, not editor labels or respondent-facing text.\",\n \"Infer the dominant topic from the focused item's visible text, descendants, hierarchy, and draft key.\",\n \"For a group or other container, treat its own descendants as the primary evidence for what the container represents. Derive a descriptive group key from those children before considering generic default container names.\",\n \"The input currentKey and draftKey, plus the focused item's key and fullKey in currentSurveyContext, identify the value being replaced. They may provide topic hints, but they are not evidence of an established naming or numbering pattern.\",\n \"Use only currentSurveyContext.naming.keyExamples and sibling keys from other items to infer the survey's established naming pattern. Pay particular attention to prefixes, casing, separators, numeric sequences, and zero padding.\",\n \"Treat a numeric pattern as established only when at least one other survey item supports it. For example, another item Q1_APPLES can support a topic-appropriate Q2_... key, while Q1_APPLES and Q2_ORANGES support Q3_.... The focused item's current key choice_1 by itself does not support choice_2 or a numeric suffix in other suggestions.\",\n \"In particular, a focused group named group_1 is a default placeholder, not a group-numbering pattern. Do not propose group_2 (or another group_N key) from it unless another group/container in currentSurveyContext.naming.keyExamples independently uses the same group_N pattern. The group's children provide semantic context, not evidence of a group-numbering pattern.\",\n \"Return one surveyPattern key that follows the strongest detected local pattern. Preserve that pattern's casing and increment a clear sequence rather than copying an existing number. If no meaningful pattern exists, use a consistent descriptive key.\",\n \"Return one compact key: a recognizable 2-5 character uppercase abbreviation using only A-Z and digits.\",\n \"Return one preferred key: the key you consider clearest and most useful without category-specific naming constraints, while still using only letters, digits, and underscores.\",\n \"Return one fair key following these FAIR-by-design rules: start with a letter; use lowercase ASCII letters, digits, and underscores only; use lowercase snake_case; stay at or below 32 characters; avoid programming/database reserved words; prefer a stable, language-neutral English concept name; use established instrument prefixes and sortable item numbers when applicable; distinguish raw from derived variables. Meaning belongs in metadata, so do not turn it into a sentence.\",\n `You may return up to ${Math.max(0, maxSuggestions - 4)} genuinely useful alternatives when another category has more than one strong candidate. Tag each alternative with its category.`,\n \"Never repeat the same suggestion, including case-only or punctuation-only variations.\",\n \"Do not return the current key, a sibling key, or a semantically unrelated abbreviation.\",\n `Return between 4 and ${maxSuggestions} distinct suggestions in total.`,\n invocationInstruction(options.mode),\n ],\n });\n\n const excluded = new Set(\n [input.currentKey, ...input.siblingKeys].map(getCodingKeyIdentity).filter(Boolean),\n );\n const seen = new Set<string>();\n const categorizedSuggestions: Array<{\n text: string;\n rationale?: string;\n category: SurveyAssistantKeySuggestionCategory;\n }> = [\n { ...result.surveyPattern, category: \"survey-pattern\" },\n { ...result.compact, category: \"compact\" },\n { ...result.preferred, category: \"preferred\" },\n { ...result.fair, category: \"fair\" },\n ...result.alternatives,\n ];\n const suggestions = categorizedSuggestions\n .flatMap((suggestion) => {\n const text = sanitizeCodingKey(suggestion.text);\n const identity = getCodingKeyIdentity(text);\n if (\n !text ||\n excluded.has(identity) ||\n seen.has(identity) ||\n isUnsupportedFocusedItemSequence(text, input, options.context)\n ) {\n return [];\n }\n seen.add(identity);\n return [{ ...suggestion, text }];\n })\n .slice(0, maxSuggestions);\n return { suggestions };\n};\n\nexport const runSurveyAssistantSuggestItemLabelTask = async (\n input: SurveyAssistantSuggestItemLabelInput,\n options: RunSurveyAssistantBuiltInTaskOptions,\n): Promise<SurveyAssistantSuggestItemLabelResult> => {\n const maxSuggestions = clampLimit(input.maxSuggestions, 3, 10);\n const locale = input.locale ?? options.context.survey.selectedLocale;\n const result = await runSurveyAssistantTask({\n ...options,\n taskId: \"suggest-item-label\",\n input,\n schema: labelSuggestionSchema,\n instructions: [\n \"Suggest concise editor-only item labels, not coding keys and not respondent-facing question text.\",\n \"Infer the item's purpose from its type, draft label, visible content, hierarchy, siblings, and descendants.\",\n \"Use currentSurveyContext.naming.labelExamples to infer established capitalization, prefixes, abbreviations, delimiters, and typical length.\",\n \"If existing label examples are available, the first suggestion must follow their dominant pattern while still describing the focused item accurately. Other suggestions may offer useful concise alternatives.\",\n \"Do not copy the subject matter of an unrelated example merely to imitate its style, and do not return an existing unrelated label verbatim.\",\n `Write labels in locale ${locale}.`,\n `Return at most ${maxSuggestions} distinct, specific, human-readable suggestions.`,\n invocationInstruction(options.mode),\n ],\n referenceTopics: [\"core-rules\"],\n });\n\n const normalizeLabel = (value: string) => value.trim().toLocaleLowerCase();\n const excludedLabels = new Set([\n normalizeLabel(input.draftLabel),\n ...(options.context.naming?.labelExamples ?? []).map((example) =>\n normalizeLabel(example.label),\n ),\n ]);\n const seen = new Set<string>();\n return {\n suggestions: result.suggestions\n .flatMap((suggestion) => {\n const text = suggestion.text.trim();\n const normalizedText = normalizeLabel(text);\n if (!text || excludedLabels.has(normalizedText) || seen.has(normalizedText)) return [];\n seen.add(normalizedText);\n return [{ ...suggestion, text }];\n })\n .slice(0, maxSuggestions),\n };\n};\n\nconst getProtectedTokens = (value: string) =>\n value.match(/\\{\\{[^{}]+\\}\\}|\\{[^{}]+\\}|\\$\\{[^{}]+\\}|%\\d*\\$?[a-z]/gi) ?? [];\n\nexport const runSurveyAssistantTranslateContentTask = async (\n input: SurveyAssistantTranslateContentInput,\n options: RunSurveyAssistantBuiltInTaskOptions,\n): Promise<SurveyAssistantTranslateContentResult> => {\n const result = await runSurveyAssistantTask({\n ...options,\n taskId: \"translate-content\",\n input,\n schema: translationsSchema,\n instructions: [\n \"Translate every supplied survey-content entry faithfully without adding explanations or omitting content.\",\n `Translate from ${input.sourceLocale} into exactly these target locales: ${input.targetLocales.join(\", \")}.`,\n \"Use currentSurveyContext.translation.examples as a terminology and style reference when relevant. The supplied source entries remain authoritative.\",\n \"Preserve meaning, register, survey terminology, punctuation, line breaks, response semantics, placeholders, interpolation tokens, URLs, and identifiers that should not be translated.\",\n \"Keep repeated terminology consistent across all entries and target locales. Do not use a neighboring translation when its meaning differs.\",\n \"Return plain strings keyed first by target locale and then by the original entry id. Return every requested locale and entry exactly once.\",\n invocationInstruction(options.mode),\n ],\n referenceTopics: [\"localization\"],\n });\n\n const translations: SurveyAssistantTranslateContentResult[\"translations\"] = {};\n for (const locale of input.targetLocales) {\n const entries = result.translations[locale];\n if (!entries) throw new Error(`Translation result is missing locale ${locale}.`);\n const translatedEntries: Record<string, string> = {};\n for (const entry of input.entries) {\n const translation = entries[entry.id];\n if (typeof translation !== \"string\" || translation.trim().length === 0) {\n throw new Error(`Translation result is missing entry ${entry.id} for locale ${locale}.`);\n }\n const sourceTokens = getProtectedTokens(entry.text).sort();\n const translatedTokens = getProtectedTokens(translation).sort();\n if (sourceTokens.join(\"\\u0000\") !== translatedTokens.join(\"\\u0000\")) {\n throw new Error(\n `Translation result changed protected tokens in entry ${entry.id} for locale ${locale}.`,\n );\n }\n translatedEntries[entry.id] = translation;\n }\n translations[locale] = translatedEntries;\n }\n return { translations };\n};\n\nconst MAX_TASK_REQUEST_BYTES = 512 * 1024;\nconst DEFAULT_MAX_TASK_CONCURRENT_REQUESTS = 4;\nconst DEFAULT_MAX_TASK_DURATION_MS = 60_000;\n\nexport interface SurveyAssistantTaskAuthorizedIdentity {\n resourceId: string;\n surveyId?: string;\n}\n\nexport interface SurveyAssistantTaskAuthorizationInput {\n request: Request;\n requestedResourceId?: string;\n requestedSurveyId?: string;\n}\n\nexport interface SurveyAssistantTaskModelResolutionInput {\n identity: SurveyAssistantTaskAuthorizedIdentity;\n request: Request;\n requestedModelId?: string;\n}\n\nexport interface CreateSurveyAssistantTaskHandlerOptions {\n agent:\n | Pick<Agent, \"generate\">\n | (() => Pick<Agent, \"generate\"> | Promise<Pick<Agent, \"generate\">>);\n authorize(\n input: SurveyAssistantTaskAuthorizationInput,\n ): SurveyAssistantTaskAuthorizedIdentity | Promise<SurveyAssistantTaskAuthorizedIdentity>;\n getReadinessError?(request: Request): string | null | Promise<string | null>;\n isEnabled?(request: Request): boolean | Promise<boolean>;\n maxConcurrentRequests?: number;\n maxDurationMs?: number;\n onTaskMetrics?(input: {\n durationMs: number;\n identity: SurveyAssistantTaskAuthorizedIdentity;\n status: \"completed\" | \"failed\";\n taskId: string;\n }): void;\n providerOptions?: AgentExecutionOptions[\"providerOptions\"];\n resolveModel?(\n input: SurveyAssistantTaskModelResolutionInput,\n ):\n | SurveyAssistantModelSelection\n | null\n | undefined\n | Promise<SurveyAssistantModelSelection | null | undefined>;\n}\n\nconst taskErrorResponse = (error: unknown) => {\n const status =\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n typeof error.status === \"number\"\n ? error.status\n : error instanceof SyntaxError || (error instanceof Error && error.name === \"ZodError\")\n ? 400\n : 500;\n const message =\n error instanceof SurveyAssistantRequestError\n ? error.message\n : status === 401 || status === 403 || status === 404\n ? status === 404\n ? \"Survey assistant task not found.\"\n : \"The survey assistant task is not authorized.\"\n : status >= 500\n ? \"The survey assistant task could not be completed.\"\n : \"The survey assistant task request is invalid.\";\n return Response.json(\n {\n code:\n status === 401 || status === 403 || status === 404\n ? \"authorization_failed\"\n : \"request_failed\",\n error: message,\n },\n { status },\n );\n};\n\nexport const createSurveyAssistantTaskHandler = ({\n agent,\n authorize,\n getReadinessError,\n isEnabled,\n maxConcurrentRequests = DEFAULT_MAX_TASK_CONCURRENT_REQUESTS,\n maxDurationMs = DEFAULT_MAX_TASK_DURATION_MS,\n onTaskMetrics,\n providerOptions,\n resolveModel,\n}: CreateSurveyAssistantTaskHandlerOptions) => {\n const concurrency =\n Number.isInteger(maxConcurrentRequests) && maxConcurrentRequests > 0\n ? maxConcurrentRequests\n : DEFAULT_MAX_TASK_CONCURRENT_REQUESTS;\n const duration =\n Number.isFinite(maxDurationMs) && maxDurationMs > 0\n ? maxDurationMs\n : DEFAULT_MAX_TASK_DURATION_MS;\n let activeRequests = 0;\n\n return async (request: Request): Promise<Response> => {\n if (activeRequests >= concurrency) {\n return Response.json(\n {\n code: \"rate_limited\",\n error: \"The survey assistant is handling too many tasks. Try again shortly.\",\n },\n { status: 429 },\n );\n }\n activeRequests += 1;\n const startedAt = Date.now();\n let metricsIdentity: SurveyAssistantTaskAuthorizedIdentity | undefined;\n let metricsTaskId = \"unknown\";\n let completed = false;\n try {\n if (isEnabled && !(await isEnabled(request))) {\n return Response.json(\n { code: \"request_failed\", error: \"Survey assistant is disabled.\" },\n { status: 404 },\n );\n }\n const task = surveyAssistantTaskRequestSchema.parse(\n await readSurveyAssistantRequestJson(request, MAX_TASK_REQUEST_BYTES),\n );\n metricsTaskId = task.taskId;\n const identity = await authorize({\n request,\n requestedResourceId: task.resourceId,\n requestedSurveyId: task.surveyId,\n });\n if (\n !identity?.resourceId?.trim() ||\n identity.resourceId.trim().length > 240 ||\n (identity.surveyId !== undefined &&\n (!identity.surveyId.trim() || identity.surveyId.trim().length > 240))\n ) {\n throw Object.assign(new Error(\"The host returned an invalid task identity.\"), {\n status: 500,\n });\n }\n metricsIdentity = {\n resourceId: identity.resourceId.trim(),\n ...(identity.surveyId?.trim() ? { surveyId: identity.surveyId.trim() } : {}),\n };\n\n const readinessError = await getReadinessError?.(request);\n if (readinessError) {\n return Response.json({ code: \"request_failed\", error: readinessError }, { status: 503 });\n }\n\n const requestContext = new RequestContext<SurveyAssistantRequestContext>();\n if (resolveModel) {\n const modelSelection = await resolveModel({\n identity: metricsIdentity,\n request,\n requestedModelId: task.modelId,\n });\n if (!modelSelection) {\n return Response.json(\n {\n code: \"request_failed\",\n error: \"The selected survey assistant model is unavailable.\",\n },\n { status: 400 },\n );\n }\n requestContext.set(\"modelSelection\", modelSelection);\n }\n\n const resolvedAgent = typeof agent === \"function\" ? await agent() : agent;\n const runtime: RunSurveyAssistantBuiltInTaskOptions = {\n abortSignal: AbortSignal.any([request.signal, AbortSignal.timeout(duration)]),\n agent: resolvedAgent,\n context: task.context,\n mode: task.mode,\n requestContext,\n providerOptions,\n };\n const result =\n task.taskId === \"suggest-item-key\"\n ? await runSurveyAssistantSuggestItemKeyTask(task.input, runtime)\n : task.taskId === \"suggest-item-label\"\n ? await runSurveyAssistantSuggestItemLabelTask(task.input, runtime)\n : await runSurveyAssistantTranslateContentTask(task.input, runtime);\n completed = true;\n return Response.json(result);\n } catch (error) {\n return taskErrorResponse(error);\n } finally {\n activeRequests = Math.max(0, activeRequests - 1);\n if (metricsIdentity) {\n try {\n onTaskMetrics?.({\n durationMs: Date.now() - startedAt,\n identity: metricsIdentity,\n status: completed ? \"completed\" : \"failed\",\n taskId: metricsTaskId,\n });\n } catch {\n // Host metrics must not change the task response.\n }\n }\n }\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server-tasks.mjs","names":[],"sources":["../src/server/tasks.ts"],"sourcesContent":["import { Agent, type AgentConfig, type AgentExecutionOptions } from \"@mastra/core/agent\";\nimport { RequestContext } from \"@mastra/core/request-context\";\nimport { z } from \"zod\";\nimport { surveyAssistantTaskRequestSchema } from \"../protocol\";\nimport type {\n SurveyAssistantSuggestItemKeyInput,\n SurveyAssistantSuggestItemKeyResult,\n SurveyAssistantKeySuggestionCategory,\n SurveyAssistantSuggestItemLabelInput,\n SurveyAssistantSuggestItemLabelResult,\n SurveyAssistantTaskInvocationMode,\n SurveyAssistantTaskContext,\n SurveyAssistantTranslateContentInput,\n SurveyAssistantTranslateContentResult,\n} from \"../protocol\";\nimport {\n surveyAuthoringReferences,\n type SurveyAuthoringReferenceTopic,\n} from \"./authoring-references\";\nimport type {\n SurveyAssistantModelSelection,\n SurveyAssistantRequestContext,\n} from \"./request-context\";\nimport { SURVEY_ASSISTANT_TASK_AGENT_ID } from \"./constants\";\nimport { FAIR_ITEM_KEY_RULES_TEXT } from \"./fair-guidance\";\nimport { readSurveyAssistantRequestJson, SurveyAssistantRequestError } from \"./request-guardrails\";\n\ntype SurveyAssistantTaskAgentConfig = AgentConfig<\n typeof SURVEY_ASSISTANT_TASK_AGENT_ID,\n Record<string, never>,\n undefined,\n SurveyAssistantRequestContext\n>;\n\nexport interface CreateSurveyAssistantTaskAgentOptions {\n model: SurveyAssistantTaskAgentConfig[\"model\"];\n}\n\nexport const createSurveyAssistantTaskAgent = ({ model }: CreateSurveyAssistantTaskAgentOptions) =>\n new Agent<\n typeof SURVEY_ASSISTANT_TASK_AGENT_ID,\n Record<string, never>,\n undefined,\n SurveyAssistantRequestContext\n >({\n id: SURVEY_ASSISTANT_TASK_AGENT_ID,\n name: \"Survey Assistant Tasks\",\n instructions:\n \"Perform the supplied bounded survey-authoring task and return only its requested structured output.\",\n model,\n });\n\nexport interface RunSurveyAssistantTaskOptions<TSchema extends z.ZodType> {\n agent: Pick<Agent, \"generate\">;\n taskId: string;\n input: unknown;\n context: SurveyAssistantTaskContext;\n schema: TSchema;\n instructions: readonly string[];\n referenceTopics?: readonly SurveyAuthoringReferenceTopic[];\n requestContext?: RequestContext<SurveyAssistantRequestContext>;\n providerOptions?: AgentExecutionOptions[\"providerOptions\"];\n abortSignal?: AbortSignal;\n}\n\nconst BASE_TASK_INSTRUCTIONS = [\n \"You perform one bounded CASE Survey Editor AI task and return only the requested structured result.\",\n \"The supplied task context was derived from the current canonical survey document snapshot. Use it as current survey context, but do not mutate it and do not claim that any editor change was applied.\",\n \"Follow the supplied CASE authoring references where relevant. Do not invent item types, locales, ids, or capabilities that are absent from the task input and context.\",\n \"Keep generated respondent-facing wording neutral, concise, and consistent with the requested locale and surrounding survey content.\",\n] as const;\n\nexport const runSurveyAssistantTask = async <TSchema extends z.ZodType>({\n agent,\n taskId,\n input,\n context,\n schema,\n instructions,\n referenceTopics = [],\n requestContext,\n providerOptions,\n abortSignal,\n}: RunSurveyAssistantTaskOptions<TSchema>): Promise<z.output<TSchema>> => {\n const references = referenceTopics.map((topic) => ({\n topic,\n title: surveyAuthoringReferences[topic].title,\n content: surveyAuthoringReferences[topic].content,\n }));\n const response = await agent.generate(\n JSON.stringify({ taskId, input, currentSurveyContext: context }),\n {\n instructions: [\n ...BASE_TASK_INSTRUCTIONS,\n ...instructions,\n ...references.map((entry) => `Reference: ${entry.title}\\n${entry.content}`),\n ],\n activeTools: [],\n inputProcessors: [],\n maxSteps: 1,\n structuredOutput: {\n schema,\n errorStrategy: \"strict\",\n },\n ...(requestContext ? { requestContext } : {}),\n ...(providerOptions ? { providerOptions } : {}),\n ...(abortSignal ? { abortSignal } : {}),\n },\n );\n\n return schema.parse(response.object);\n};\n\nconst keySuggestionValueSchema = z.object({\n text: z.string().min(1),\n rationale: z.string().optional(),\n});\n\nconst keySuggestionCategorySchema = z.enum([\"survey-pattern\", \"compact\", \"preferred\", \"fair\"]);\n\nconst keySuggestionSchema = z.object({\n surveyPattern: keySuggestionValueSchema.describe(\n \"A key that follows the strongest naming and numbering pattern in the current survey.\",\n ),\n compact: keySuggestionValueSchema.extend({\n text: z\n .string()\n .min(2)\n .max(5)\n .regex(/^[A-Z][A-Z0-9]{1,4}$/)\n .describe(\"A recognizable 2-5 character uppercase abbreviation.\"),\n }),\n preferred: keySuggestionValueSchema.describe(\n \"The key the model considers clearest without a category-specific naming constraint.\",\n ),\n fair: keySuggestionValueSchema.extend({\n text: z\n .string()\n .min(1)\n .max(32)\n .regex(/^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/)\n .describe(\"A FAIR-by-design lowercase snake_case variable name.\"),\n }),\n alternatives: z\n .array(\n keySuggestionValueSchema.extend({\n category: keySuggestionCategorySchema,\n }),\n )\n .max(2),\n});\n\nconst labelSuggestionSchema = z.object({\n suggestions: z.array(\n z.object({\n text: z.string().min(1),\n }),\n ),\n});\n\nconst translationsSchema = z.object({\n translations: z.record(z.string(), z.record(z.string(), z.string())),\n});\n\nexport interface RunSurveyAssistantBuiltInTaskOptions {\n agent: Pick<Agent, \"generate\">;\n context: SurveyAssistantTaskContext;\n mode?: SurveyAssistantTaskInvocationMode;\n requestContext?: RequestContext<SurveyAssistantRequestContext>;\n providerOptions?: AgentExecutionOptions[\"providerOptions\"];\n abortSignal?: AbortSignal;\n}\n\nconst clampLimit = (value: number | undefined, fallback: number, maximum: number) =>\n Math.min(Math.max(1, value ?? fallback), maximum);\n\nconst sanitizeCodingKey = (value: string) =>\n value\n .trim()\n .replace(/[.\\s-]+/g, \"_\")\n .replace(/[^A-Za-z0-9_]+/g, \"_\")\n .replace(/_+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n\nconst getCodingKeyIdentity = (value: string) => sanitizeCodingKey(value).toLocaleLowerCase();\n\nconst getNumberedKeyParts = (value: string) => {\n const match = /^(.+?)_(\\d+)$/.exec(getCodingKeyIdentity(value));\n return match ? { stem: match[1], number: Number(match[2]) } : undefined;\n};\n\nconst isUnsupportedFocusedItemSequence = (\n candidate: string,\n input: SurveyAssistantSuggestItemKeyInput,\n context: SurveyAssistantTaskContext,\n) => {\n const candidateParts = getNumberedKeyParts(candidate);\n const focusItem = context.focus?.item;\n if (!candidateParts || !focusItem) return false;\n\n const focusedKeyParts = [input.currentKey, input.draftKey, focusItem.key]\n .map(getNumberedKeyParts)\n .find((parts) => parts?.stem === candidateParts.stem && parts.number < candidateParts.number);\n if (!focusedKeyParts) return false;\n\n return !context.naming?.keyExamples.some((example) => {\n const exampleParts = getNumberedKeyParts(example.key);\n return example.itemType === focusItem.itemType && exampleParts?.stem === candidateParts.stem;\n });\n};\n\nconst invocationInstruction = (mode: SurveyAssistantTaskInvocationMode | undefined) =>\n mode === \"background\"\n ? \"This is a background invocation. Be efficient, but do not relax task conventions, completeness, or output quality.\"\n : \"This is an explicit user invocation. Prioritize quality and useful variation.\";\n\nexport const runSurveyAssistantSuggestItemKeyTask = async (\n input: SurveyAssistantSuggestItemKeyInput,\n options: RunSurveyAssistantBuiltInTaskOptions,\n): Promise<SurveyAssistantSuggestItemKeyResult> => {\n const maxSuggestions = Math.min(Math.max(4, input.maxSuggestions ?? 6), 6);\n const result = await runSurveyAssistantTask({\n ...options,\n taskId: \"suggest-item-key\",\n input,\n schema: keySuggestionSchema,\n instructions: [\n \"Generate coding keys for the focused survey item, not editor labels or respondent-facing text.\",\n \"Infer the dominant topic from the focused item's visible text, descendants, hierarchy, and draft key.\",\n \"For a group or other container, treat its own descendants as the primary evidence for what the container represents. Derive a descriptive group key from those children before considering generic default container names.\",\n \"The input currentKey and draftKey, plus the focused item's key and fullKey in currentSurveyContext, identify the value being replaced. They may provide topic hints, but they are not evidence of an established naming or numbering pattern.\",\n \"Use only currentSurveyContext.naming.keyExamples and sibling keys from other items to infer the survey's established naming pattern. Pay particular attention to prefixes, casing, separators, numeric sequences, and zero padding.\",\n \"Treat a numeric pattern as established only when at least one other survey item supports it. For example, another item Q1_APPLES can support a topic-appropriate Q2_... key, while Q1_APPLES and Q2_ORANGES support Q3_.... The focused item's current key choice_1 by itself does not support choice_2 or a numeric suffix in other suggestions.\",\n \"In particular, a focused group named group_1 is a default placeholder, not a group-numbering pattern. Do not propose group_2 (or another group_N key) from it unless another group/container in currentSurveyContext.naming.keyExamples independently uses the same group_N pattern. The group's children provide semantic context, not evidence of a group-numbering pattern.\",\n \"Return one surveyPattern key that follows the strongest detected local pattern. Preserve that pattern's casing and increment a clear sequence rather than copying an existing number. If no meaningful pattern exists, use a consistent descriptive key.\",\n \"Return one compact key: a recognizable 2-5 character uppercase abbreviation using only A-Z and digits.\",\n \"Return one preferred key: the key you consider clearest and most useful without category-specific naming constraints, while still using only letters, digits, and underscores.\",\n `Return one fair key following these FAIR-by-design rules: ${FAIR_ITEM_KEY_RULES_TEXT}. Meaning belongs in metadata, so do not turn it into a sentence.`,\n `You may return up to ${Math.max(0, maxSuggestions - 4)} genuinely useful alternatives when another category has more than one strong candidate. Tag each alternative with its category.`,\n \"Never repeat the same suggestion, including case-only or punctuation-only variations.\",\n \"Do not return the current key, a sibling key, or a semantically unrelated abbreviation.\",\n `Return between 4 and ${maxSuggestions} distinct suggestions in total.`,\n invocationInstruction(options.mode),\n ],\n });\n\n const excluded = new Set(\n [input.currentKey, ...input.siblingKeys].map(getCodingKeyIdentity).filter(Boolean),\n );\n const seen = new Set<string>();\n const categorizedSuggestions: Array<{\n text: string;\n rationale?: string;\n category: SurveyAssistantKeySuggestionCategory;\n }> = [\n { ...result.surveyPattern, category: \"survey-pattern\" },\n { ...result.compact, category: \"compact\" },\n { ...result.preferred, category: \"preferred\" },\n { ...result.fair, category: \"fair\" },\n ...result.alternatives,\n ];\n const suggestions = categorizedSuggestions\n .flatMap((suggestion) => {\n const text = sanitizeCodingKey(suggestion.text);\n const identity = getCodingKeyIdentity(text);\n if (\n !text ||\n excluded.has(identity) ||\n seen.has(identity) ||\n isUnsupportedFocusedItemSequence(text, input, options.context)\n ) {\n return [];\n }\n seen.add(identity);\n return [{ ...suggestion, text }];\n })\n .slice(0, maxSuggestions);\n return { suggestions };\n};\n\nexport const runSurveyAssistantSuggestItemLabelTask = async (\n input: SurveyAssistantSuggestItemLabelInput,\n options: RunSurveyAssistantBuiltInTaskOptions,\n): Promise<SurveyAssistantSuggestItemLabelResult> => {\n const maxSuggestions = clampLimit(input.maxSuggestions, 3, 10);\n const locale = input.locale ?? options.context.survey.selectedLocale;\n const result = await runSurveyAssistantTask({\n ...options,\n taskId: \"suggest-item-label\",\n input,\n schema: labelSuggestionSchema,\n instructions: [\n \"Suggest concise editor-only item labels, not coding keys and not respondent-facing question text.\",\n \"Infer the item's purpose from its type, draft label, visible content, hierarchy, siblings, and descendants.\",\n \"Use currentSurveyContext.naming.labelExamples to infer established capitalization, prefixes, abbreviations, delimiters, and typical length.\",\n \"If existing label examples are available, the first suggestion must follow their dominant pattern while still describing the focused item accurately. Other suggestions may offer useful concise alternatives.\",\n \"Do not copy the subject matter of an unrelated example merely to imitate its style, and do not return an existing unrelated label verbatim.\",\n `Write labels in locale ${locale}.`,\n `Return at most ${maxSuggestions} distinct, specific, human-readable suggestions.`,\n invocationInstruction(options.mode),\n ],\n referenceTopics: [\"core-rules\"],\n });\n\n const normalizeLabel = (value: string) => value.trim().toLocaleLowerCase();\n const excludedLabels = new Set([\n normalizeLabel(input.draftLabel),\n ...(options.context.naming?.labelExamples ?? []).map((example) =>\n normalizeLabel(example.label),\n ),\n ]);\n const seen = new Set<string>();\n return {\n suggestions: result.suggestions\n .flatMap((suggestion) => {\n const text = suggestion.text.trim();\n const normalizedText = normalizeLabel(text);\n if (!text || excludedLabels.has(normalizedText) || seen.has(normalizedText)) return [];\n seen.add(normalizedText);\n return [{ ...suggestion, text }];\n })\n .slice(0, maxSuggestions),\n };\n};\n\nconst getProtectedTokens = (value: string) =>\n value.match(/\\{\\{[^{}]+\\}\\}|\\{[^{}]+\\}|\\$\\{[^{}]+\\}|%\\d*\\$?[a-z]/gi) ?? [];\n\nexport const runSurveyAssistantTranslateContentTask = async (\n input: SurveyAssistantTranslateContentInput,\n options: RunSurveyAssistantBuiltInTaskOptions,\n): Promise<SurveyAssistantTranslateContentResult> => {\n const result = await runSurveyAssistantTask({\n ...options,\n taskId: \"translate-content\",\n input,\n schema: translationsSchema,\n instructions: [\n \"Translate every supplied survey-content entry faithfully without adding explanations or omitting content.\",\n `Translate from ${input.sourceLocale} into exactly these target locales: ${input.targetLocales.join(\", \")}.`,\n \"Use currentSurveyContext.translation.examples as a terminology and style reference when relevant. The supplied source entries remain authoritative.\",\n \"Preserve meaning, register, survey terminology, punctuation, line breaks, response semantics, placeholders, interpolation tokens, URLs, and identifiers that should not be translated.\",\n \"Keep repeated terminology consistent across all entries and target locales. Do not use a neighboring translation when its meaning differs.\",\n \"Return plain strings keyed first by target locale and then by the original entry id. Return every requested locale and entry exactly once.\",\n invocationInstruction(options.mode),\n ],\n referenceTopics: [\"localization\"],\n });\n\n const translations: SurveyAssistantTranslateContentResult[\"translations\"] = {};\n for (const locale of input.targetLocales) {\n const entries = result.translations[locale];\n if (!entries) throw new Error(`Translation result is missing locale ${locale}.`);\n const translatedEntries: Record<string, string> = {};\n for (const entry of input.entries) {\n const translation = entries[entry.id];\n if (typeof translation !== \"string\" || translation.trim().length === 0) {\n throw new Error(`Translation result is missing entry ${entry.id} for locale ${locale}.`);\n }\n const sourceTokens = getProtectedTokens(entry.text).sort();\n const translatedTokens = getProtectedTokens(translation).sort();\n if (sourceTokens.join(\"\\u0000\") !== translatedTokens.join(\"\\u0000\")) {\n throw new Error(\n `Translation result changed protected tokens in entry ${entry.id} for locale ${locale}.`,\n );\n }\n translatedEntries[entry.id] = translation;\n }\n translations[locale] = translatedEntries;\n }\n return { translations };\n};\n\nconst MAX_TASK_REQUEST_BYTES = 512 * 1024;\nconst DEFAULT_MAX_TASK_CONCURRENT_REQUESTS = 4;\nconst DEFAULT_MAX_TASK_DURATION_MS = 60_000;\n\nexport interface SurveyAssistantTaskAuthorizedIdentity {\n resourceId: string;\n surveyId?: string;\n}\n\nexport interface SurveyAssistantTaskAuthorizationInput {\n request: Request;\n requestedResourceId?: string;\n requestedSurveyId?: string;\n}\n\nexport interface SurveyAssistantTaskModelResolutionInput {\n identity: SurveyAssistantTaskAuthorizedIdentity;\n request: Request;\n requestedModelId?: string;\n}\n\nexport interface CreateSurveyAssistantTaskHandlerOptions {\n agent:\n | Pick<Agent, \"generate\">\n | (() => Pick<Agent, \"generate\"> | Promise<Pick<Agent, \"generate\">>);\n authorize(\n input: SurveyAssistantTaskAuthorizationInput,\n ): SurveyAssistantTaskAuthorizedIdentity | Promise<SurveyAssistantTaskAuthorizedIdentity>;\n getReadinessError?(request: Request): string | null | Promise<string | null>;\n isEnabled?(request: Request): boolean | Promise<boolean>;\n maxConcurrentRequests?: number;\n maxDurationMs?: number;\n onTaskMetrics?(input: {\n durationMs: number;\n identity: SurveyAssistantTaskAuthorizedIdentity;\n status: \"completed\" | \"failed\";\n taskId: string;\n }): void;\n providerOptions?: AgentExecutionOptions[\"providerOptions\"];\n resolveModel?(\n input: SurveyAssistantTaskModelResolutionInput,\n ):\n | SurveyAssistantModelSelection\n | null\n | undefined\n | Promise<SurveyAssistantModelSelection | null | undefined>;\n}\n\nconst taskErrorResponse = (error: unknown) => {\n const status =\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n typeof error.status === \"number\"\n ? error.status\n : error instanceof SyntaxError || (error instanceof Error && error.name === \"ZodError\")\n ? 400\n : 500;\n const message =\n error instanceof SurveyAssistantRequestError\n ? error.message\n : status === 401 || status === 403 || status === 404\n ? status === 404\n ? \"Survey assistant task not found.\"\n : \"The survey assistant task is not authorized.\"\n : status >= 500\n ? \"The survey assistant task could not be completed.\"\n : \"The survey assistant task request is invalid.\";\n return Response.json(\n {\n code:\n status === 401 || status === 403 || status === 404\n ? \"authorization_failed\"\n : \"request_failed\",\n error: message,\n },\n { status },\n );\n};\n\nexport const createSurveyAssistantTaskHandler = ({\n agent,\n authorize,\n getReadinessError,\n isEnabled,\n maxConcurrentRequests = DEFAULT_MAX_TASK_CONCURRENT_REQUESTS,\n maxDurationMs = DEFAULT_MAX_TASK_DURATION_MS,\n onTaskMetrics,\n providerOptions,\n resolveModel,\n}: CreateSurveyAssistantTaskHandlerOptions) => {\n const concurrency =\n Number.isInteger(maxConcurrentRequests) && maxConcurrentRequests > 0\n ? maxConcurrentRequests\n : DEFAULT_MAX_TASK_CONCURRENT_REQUESTS;\n const duration =\n Number.isFinite(maxDurationMs) && maxDurationMs > 0\n ? maxDurationMs\n : DEFAULT_MAX_TASK_DURATION_MS;\n let activeRequests = 0;\n\n return async (request: Request): Promise<Response> => {\n if (activeRequests >= concurrency) {\n return Response.json(\n {\n code: \"rate_limited\",\n error: \"The survey assistant is handling too many tasks. Try again shortly.\",\n },\n { status: 429 },\n );\n }\n activeRequests += 1;\n const startedAt = Date.now();\n let metricsIdentity: SurveyAssistantTaskAuthorizedIdentity | undefined;\n let metricsTaskId = \"unknown\";\n let completed = false;\n try {\n if (isEnabled && !(await isEnabled(request))) {\n return Response.json(\n { code: \"request_failed\", error: \"Survey assistant is disabled.\" },\n { status: 404 },\n );\n }\n const task = surveyAssistantTaskRequestSchema.parse(\n await readSurveyAssistantRequestJson(request, MAX_TASK_REQUEST_BYTES),\n );\n metricsTaskId = task.taskId;\n const identity = await authorize({\n request,\n requestedResourceId: task.resourceId,\n requestedSurveyId: task.surveyId,\n });\n if (\n !identity?.resourceId?.trim() ||\n identity.resourceId.trim().length > 240 ||\n (identity.surveyId !== undefined &&\n (!identity.surveyId.trim() || identity.surveyId.trim().length > 240))\n ) {\n throw Object.assign(new Error(\"The host returned an invalid task identity.\"), {\n status: 500,\n });\n }\n metricsIdentity = {\n resourceId: identity.resourceId.trim(),\n ...(identity.surveyId?.trim() ? { surveyId: identity.surveyId.trim() } : {}),\n };\n\n const readinessError = await getReadinessError?.(request);\n if (readinessError) {\n return Response.json({ code: \"request_failed\", error: readinessError }, { status: 503 });\n }\n\n const requestContext = new RequestContext<SurveyAssistantRequestContext>();\n if (resolveModel) {\n const modelSelection = await resolveModel({\n identity: metricsIdentity,\n request,\n requestedModelId: task.modelId,\n });\n if (!modelSelection) {\n return Response.json(\n {\n code: \"request_failed\",\n error: \"The selected survey assistant model is unavailable.\",\n },\n { status: 400 },\n );\n }\n requestContext.set(\"modelSelection\", modelSelection);\n }\n\n const resolvedAgent = typeof agent === \"function\" ? await agent() : agent;\n const runtime: RunSurveyAssistantBuiltInTaskOptions = {\n abortSignal: AbortSignal.any([request.signal, AbortSignal.timeout(duration)]),\n agent: resolvedAgent,\n context: task.context,\n mode: task.mode,\n requestContext,\n providerOptions,\n };\n const result =\n task.taskId === \"suggest-item-key\"\n ? await runSurveyAssistantSuggestItemKeyTask(task.input, runtime)\n : task.taskId === \"suggest-item-label\"\n ? await runSurveyAssistantSuggestItemLabelTask(task.input, runtime)\n : await runSurveyAssistantTranslateContentTask(task.input, runtime);\n completed = true;\n return Response.json(result);\n } catch (error) {\n return taskErrorResponse(error);\n } finally {\n activeRequests = Math.max(0, activeRequests - 1);\n if (metricsIdentity) {\n try {\n onTaskMetrics?.({\n durationMs: Date.now() - startedAt,\n identity: metricsIdentity,\n status: completed ? \"completed\" : \"failed\",\n taskId: metricsTaskId,\n });\n } catch {\n // Host metrics must not change the task response.\n }\n }\n }\n };\n};\n"],"mappings":"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"}
|
package/dist/server-tools.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as surveyAuditTool, n as surveyAssistantTools, r as surveyAssetTool, t as SURVEY_ASSISTANT_TOOL_IDS } from "./index-
|
|
1
|
+
import { i as surveyAuditTool, n as surveyAssistantTools, r as surveyAssetTool, t as SURVEY_ASSISTANT_TOOL_IDS } from "./index-Bp5W_oPa.mjs";
|
|
2
2
|
export { SURVEY_ASSISTANT_TOOL_IDS, surveyAssetTool, surveyAssistantTools, surveyAuditTool };
|
package/dist/server-tools.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as surveyAuditTool, n as surveyAssistantTools, r as surveyAssetTool, t as SURVEY_ASSISTANT_TOOL_IDS } from "./tools-
|
|
1
|
+
import { i as surveyAuditTool, n as surveyAssistantTools, r as surveyAssetTool, t as SURVEY_ASSISTANT_TOOL_IDS } from "./tools-GDd5_GUh.mjs";
|
|
2
2
|
export { SURVEY_ASSISTANT_TOOL_IDS, surveyAssetTool, surveyAssistantTools, surveyAuditTool };
|