@case-framework/survey-assistant 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -4
- package/dist/{authoring-references-CW38pYzK.mjs → authoring-references-BJQ_1nMX.mjs} +2 -2
- package/dist/authoring-references-BJQ_1nMX.mjs.map +1 -0
- package/dist/capabilities-1KNnNO1_.mjs +73 -0
- package/dist/capabilities-1KNnNO1_.mjs.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 +22 -25
- package/dist/capabilities-default.mjs.map +1 -1
- package/dist/{constants-BMGTgfjv.d.mts → constants-Be91Gay9.d.mts} +3 -3
- package/dist/{constants-BMGTgfjv.d.mts.map → constants-Be91Gay9.d.mts.map} +1 -1
- package/dist/{controller-proxy-DMTqer6T.mjs → controller-proxy-BH05e-C2.mjs} +21 -8
- package/dist/controller-proxy-BH05e-C2.mjs.map +1 -0
- package/dist/{controller-proxy-mRvez2qw.d.mts → controller-proxy-Bd0ZHBPF.d.mts} +11 -11
- package/dist/controller-proxy-Bd0ZHBPF.d.mts.map +1 -0
- package/dist/{engine-CQwOAcwK.mjs → engine-Bo85Oyj0.mjs} +2985 -2347
- package/dist/engine-Bo85Oyj0.mjs.map +1 -0
- package/dist/engine.d.mts +2 -2
- package/dist/engine.mjs +3 -3
- package/dist/{index-D6nqkz0O.d.mts → index-Tnqv-yKW.d.mts} +56 -71
- package/dist/index-Tnqv-yKW.d.mts.map +1 -0
- package/dist/index-l_EK4yK7.d.mts +404 -0
- package/dist/index-l_EK4yK7.d.mts.map +1 -0
- package/dist/{index-DvTqML-0.d.mts → index-nhrgbgO5.d.mts} +19 -5
- package/dist/index-nhrgbgO5.d.mts.map +1 -0
- package/dist/{index-B0lxsAzx.d.mts → index-x0qprHgK.d.mts} +19 -7
- package/dist/index-x0qprHgK.d.mts.map +1 -0
- package/dist/{lifecycle-BmGAIUlv.d.mts → lifecycle-Bx0aq_4S.d.mts} +7 -1
- package/dist/{lifecycle-BmGAIUlv.d.mts.map → lifecycle-Bx0aq_4S.d.mts.map} +1 -1
- package/dist/{memory-thread-repository-CjFGVNZh.mjs → memory-thread-repository-KWHQWFEW.mjs} +43 -12
- package/dist/memory-thread-repository-KWHQWFEW.mjs.map +1 -0
- package/dist/{protocol-DJUP4gc0.mjs → protocol-BhzQbx81.mjs} +66 -16
- package/dist/protocol-BhzQbx81.mjs.map +1 -0
- package/dist/protocol.d.mts +3 -3
- package/dist/protocol.mjs +2 -2
- package/dist/react-B3ybjJ-X.mjs +1620 -0
- package/dist/react-B3ybjJ-X.mjs.map +1 -0
- package/dist/react-integration.d.mts +1 -1
- package/dist/react-integration.mjs +1 -1
- package/dist/react.d.mts +3 -3
- package/dist/react.mjs +3 -3
- package/dist/references/assistant-operations.md +45 -39
- package/dist/references/expressions.md +28 -0
- package/dist/references/item-types.md +1 -1
- package/dist/references/localization.md +5 -4
- package/dist/references/rich-text-content.md +60 -27
- package/dist/references/source-material-surveys.md +9 -2
- package/dist/references/survey-data-model.md +9 -1
- package/dist/{request-context-BjTHNcDd.mjs → request-context-CG4SWijt.mjs} +3 -3
- package/dist/{request-context-BjTHNcDd.mjs.map → request-context-CG4SWijt.mjs.map} +1 -1
- package/dist/server-agent.d.mts +19 -8
- package/dist/server-agent.d.mts.map +1 -1
- package/dist/server-agent.mjs +7 -11
- package/dist/server-agent.mjs.map +1 -1
- package/dist/server-runtime.d.mts +19 -13
- package/dist/server-runtime.d.mts.map +1 -1
- package/dist/server-runtime.mjs +7 -2
- package/dist/server-runtime.mjs.map +1 -1
- package/dist/server-tasks.d.mts +1 -1
- package/dist/server-tasks.mjs +2 -2
- package/dist/server-tools.d.mts +1 -1
- package/dist/server-tools.mjs +1 -1
- package/dist/server.d.mts +5 -5
- package/dist/server.mjs +3 -3
- package/dist/{tasks-DxzD25Zc.d.mts → tasks-CYqrcaRO.d.mts} +4 -4
- package/dist/{tasks-DxzD25Zc.d.mts.map → tasks-CYqrcaRO.d.mts.map} +1 -1
- package/dist/{thread-handlers-AbQbt4sX.d.mts → thread-handlers-DBAaU7BA.d.mts} +6 -4
- package/dist/thread-handlers-DBAaU7BA.d.mts.map +1 -0
- package/dist/{tools-CFh35R4d.mjs → tools-BvSovehT.mjs} +431 -495
- package/dist/tools-BvSovehT.mjs.map +1 -0
- package/dist/ui.css +1 -1
- package/dist/ui.d.mts +5 -4
- package/dist/ui.d.mts.map +1 -1
- package/dist/ui.mjs +619 -66
- package/dist/ui.mjs.map +1 -1
- package/docs/integration.md +40 -0
- package/package.json +21 -19
- package/dist/authoring-references-CW38pYzK.mjs.map +0 -1
- package/dist/controller-proxy-DMTqer6T.mjs.map +0 -1
- package/dist/controller-proxy-mRvez2qw.d.mts.map +0 -1
- package/dist/engine-CQwOAcwK.mjs.map +0 -1
- package/dist/form-authoring-kQDgC5oz.mjs +0 -155
- package/dist/form-authoring-kQDgC5oz.mjs.map +0 -1
- package/dist/index-B0lxsAzx.d.mts.map +0 -1
- package/dist/index-BS-Xjk1h.d.mts +0 -224
- package/dist/index-BS-Xjk1h.d.mts.map +0 -1
- package/dist/index-D6nqkz0O.d.mts.map +0 -1
- package/dist/index-DvTqML-0.d.mts.map +0 -1
- package/dist/memory-thread-repository-CjFGVNZh.mjs.map +0 -1
- package/dist/protocol-DJUP4gc0.mjs.map +0 -1
- package/dist/react-Dqlmasrs.mjs +0 -768
- package/dist/react-Dqlmasrs.mjs.map +0 -1
- package/dist/thread-handlers-AbQbt4sX.d.mts.map +0 -1
- package/dist/tools-CFh35R4d.mjs.map +0 -1
package/dist/react-Dqlmasrs.mjs
DELETED
|
@@ -1,768 +0,0 @@
|
|
|
1
|
-
import { H as surveyDocumentVersionSchema, M as surveyAssistantThreadSchema, N as surveyAssistantThreadTranscriptSchema, f as surveyChangeSetSchema, j as surveyAssistantThreadListSchema, l as surveyAssistantTurnFinalSchema, n as SURVEY_ASSISTANT_TURN_FINAL_PART_TYPE, o as surveyAssistantApplyOutcomeSchema, p as surveyAssistantModelCatalogSchema, r as applyReceiptSchema } from "./protocol-DJUP4gc0.mjs";
|
|
2
|
-
import { a as applySurveyAssistantLaunchUIContext, l as readSurveyAssistantJson } from "./controller-proxy-DMTqer6T.mjs";
|
|
3
|
-
import { DefaultChatTransport } from "ai";
|
|
4
|
-
import { useCallback, useEffect, useEffectEvent, useMemo, useReducer, useRef, useState } from "react";
|
|
5
|
-
import { useChat } from "@ai-sdk/react";
|
|
6
|
-
//#region src/react/session-state.ts
|
|
7
|
-
const isSurveyAssistantTurnActive = ({ isStreaming, state }) => state !== "aborted" && (isStreaming || state === "submitting" || state === "streaming" || state === "applying");
|
|
8
|
-
const reduceSurveyAssistantSessionState = (_state, event) => {
|
|
9
|
-
switch (event.type) {
|
|
10
|
-
case "submit": return "submitting";
|
|
11
|
-
case "stream-started": return "streaming";
|
|
12
|
-
case "completed": return "completed";
|
|
13
|
-
case "apply-started": return "applying";
|
|
14
|
-
case "applied": return "applied";
|
|
15
|
-
case "failed": return "failed";
|
|
16
|
-
case "aborted": return "aborted";
|
|
17
|
-
case "reset": return event.hasTranscript ? "completed" : "idle";
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
//#endregion
|
|
21
|
-
//#region src/react/turn-authorization.ts
|
|
22
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23
|
-
const isCompletedToolPart = (part) => (part.type === "dynamic-tool" || part.type.startsWith("tool-")) && "state" in part && part.state === "output-available" && "output" in part;
|
|
24
|
-
const unwrapSurveyAssistantToolOutput = (output) => {
|
|
25
|
-
if (isRecord(output) && "output" in output && output.output !== void 0) return output.output;
|
|
26
|
-
return output;
|
|
27
|
-
};
|
|
28
|
-
const parseSurveyChangeSet = (output) => {
|
|
29
|
-
const parsed = surveyChangeSetSchema.safeParse(unwrapSurveyAssistantToolOutput(output));
|
|
30
|
-
return parsed.success ? parsed.data : null;
|
|
31
|
-
};
|
|
32
|
-
const collectSurveyChangeSets = (messages) => {
|
|
33
|
-
const changes = [];
|
|
34
|
-
for (const message of messages) for (const part of message.parts) {
|
|
35
|
-
if (!isCompletedToolPart(part)) continue;
|
|
36
|
-
const change = parseSurveyChangeSet(part.output);
|
|
37
|
-
if (change) changes.push(change);
|
|
38
|
-
}
|
|
39
|
-
return changes;
|
|
40
|
-
};
|
|
41
|
-
const findLastUserMessageIndex$1 = (messages) => {
|
|
42
|
-
for (let index = messages.length - 1; index >= 0; index -= 1) if (messages[index]?.role === "user") return index;
|
|
43
|
-
return -1;
|
|
44
|
-
};
|
|
45
|
-
const resolveLatestSurveyTurnAuthorization = (messages) => {
|
|
46
|
-
const lastUserIndex = findLastUserMessageIndex$1(messages);
|
|
47
|
-
if (lastUserIndex < 0) return { status: "pending" };
|
|
48
|
-
const turnMessages = messages.slice(lastUserIndex + 1);
|
|
49
|
-
const finalParts = turnMessages.flatMap((message) => message.parts).filter((part) => part.type === SURVEY_ASSISTANT_TURN_FINAL_PART_TYPE);
|
|
50
|
-
if (finalParts.length === 0) return { status: "pending" };
|
|
51
|
-
if (finalParts.length !== 1) return {
|
|
52
|
-
status: "invalid",
|
|
53
|
-
reason: "The assistant returned multiple turn finals."
|
|
54
|
-
};
|
|
55
|
-
const finalPart = finalParts[0];
|
|
56
|
-
const finalParse = surveyAssistantTurnFinalSchema.safeParse(finalPart && "data" in finalPart ? finalPart.data : void 0);
|
|
57
|
-
if (!finalParse.success) return {
|
|
58
|
-
status: "invalid",
|
|
59
|
-
reason: "The assistant returned an invalid turn final."
|
|
60
|
-
};
|
|
61
|
-
const turnFinal = finalParse.data;
|
|
62
|
-
if (turnFinal.status !== "completed") return {
|
|
63
|
-
status: turnFinal.status,
|
|
64
|
-
turnFinal,
|
|
65
|
-
changeSets: []
|
|
66
|
-
};
|
|
67
|
-
const candidates = collectSurveyChangeSets(turnMessages).filter((change) => change.turnId === turnFinal.turnId);
|
|
68
|
-
const candidatesById = /* @__PURE__ */ new Map();
|
|
69
|
-
for (const candidate of candidates) {
|
|
70
|
-
if (candidatesById.has(candidate.id)) return {
|
|
71
|
-
status: "invalid",
|
|
72
|
-
turnId: turnFinal.turnId,
|
|
73
|
-
reason: `The assistant returned duplicate change set "${candidate.id}".`
|
|
74
|
-
};
|
|
75
|
-
candidatesById.set(candidate.id, candidate);
|
|
76
|
-
}
|
|
77
|
-
for (const blockedChangeSetId of turnFinal.blockedChangeSetIds ?? []) {
|
|
78
|
-
const candidate = candidatesById.get(blockedChangeSetId);
|
|
79
|
-
if (!candidate || candidate.status !== "rejected" || candidate.validation.valid) return {
|
|
80
|
-
status: "invalid",
|
|
81
|
-
turnId: turnFinal.turnId,
|
|
82
|
-
reason: `The assistant did not provide blocked change set "${blockedChangeSetId}".`
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
const changeSets = [];
|
|
86
|
-
for (const changeSetId of turnFinal.executableChangeSetIds) {
|
|
87
|
-
const candidate = candidatesById.get(changeSetId);
|
|
88
|
-
if (!candidate || candidate.status !== "validated" || !candidate.validation.valid) return {
|
|
89
|
-
status: "invalid",
|
|
90
|
-
turnId: turnFinal.turnId,
|
|
91
|
-
reason: `The assistant did not provide authorized change set "${changeSetId}".`
|
|
92
|
-
};
|
|
93
|
-
changeSets.push(candidate);
|
|
94
|
-
}
|
|
95
|
-
return {
|
|
96
|
-
status: "completed",
|
|
97
|
-
turnFinal,
|
|
98
|
-
changeSets
|
|
99
|
-
};
|
|
100
|
-
};
|
|
101
|
-
const resolveSurveyTurnOutcome = ({ applyResultsByChangeId, authorization }) => {
|
|
102
|
-
if (authorization.status === "failed" || authorization.status === "aborted") return {
|
|
103
|
-
status: authorization.status,
|
|
104
|
-
terminationReason: authorization.turnFinal.terminationReason
|
|
105
|
-
};
|
|
106
|
-
if (authorization.status !== "completed") return null;
|
|
107
|
-
const blockedChangeSetCount = authorization.turnFinal.blockedChangeSetIds?.length ?? 0;
|
|
108
|
-
if (blockedChangeSetCount > 0) return {
|
|
109
|
-
status: "blocked",
|
|
110
|
-
blockedChangeSetCount
|
|
111
|
-
};
|
|
112
|
-
if (authorization.changeSets.length === 0) return null;
|
|
113
|
-
const results = authorization.changeSets.map((change) => applyResultsByChangeId[change.id]);
|
|
114
|
-
if (results.some((result) => result === void 0)) return null;
|
|
115
|
-
const failedChangeSetCount = results.filter((result) => result.status !== "applied").length;
|
|
116
|
-
if (failedChangeSetCount === 0) return null;
|
|
117
|
-
return {
|
|
118
|
-
status: "apply-failed",
|
|
119
|
-
appliedChangeSetCount: results.length - failedChangeSetCount,
|
|
120
|
-
failedChangeSetCount
|
|
121
|
-
};
|
|
122
|
-
};
|
|
123
|
-
const getSurveyDocumentVersionFromSnapshot = (snapshot) => ({ ...snapshot.version });
|
|
124
|
-
const createApplyReceipts = ({ afterSnapshot, beforeSnapshot, changeSets, results, turnFinal, createdAt = (/* @__PURE__ */ new Date()).toISOString() }) => {
|
|
125
|
-
const beforeVersion = getSurveyDocumentVersionFromSnapshot(beforeSnapshot);
|
|
126
|
-
const afterVersion = afterSnapshot ? getSurveyDocumentVersionFromSnapshot(afterSnapshot) : void 0;
|
|
127
|
-
const resultsByChangeId = new Map(results.map((result) => [result.changeId, result]));
|
|
128
|
-
return changeSets.map((changeSet) => {
|
|
129
|
-
const result = resultsByChangeId.get(changeSet.id);
|
|
130
|
-
const status = result?.status ?? "failed";
|
|
131
|
-
return applyReceiptSchema.parse({
|
|
132
|
-
protocolVersion: 1,
|
|
133
|
-
turnId: turnFinal.turnId,
|
|
134
|
-
changeSetId: changeSet.id,
|
|
135
|
-
beforeVersion,
|
|
136
|
-
...status === "applied" && afterVersion ? { afterVersion } : {},
|
|
137
|
-
status,
|
|
138
|
-
operationCount: changeSet.operations.length,
|
|
139
|
-
...status === "applied" && afterVersion?.historyIndex !== void 0 ? { commit: { index: afterVersion.historyIndex } } : {},
|
|
140
|
-
...result?.issues ? { issues: result.issues } : {},
|
|
141
|
-
createdAt
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
};
|
|
145
|
-
//#endregion
|
|
146
|
-
//#region src/react/transport.ts
|
|
147
|
-
const findLastUserMessage = (messages) => {
|
|
148
|
-
for (let index = messages.length - 1; index >= 0; index -= 1) if (messages[index]?.role === "user") return messages[index];
|
|
149
|
-
};
|
|
150
|
-
const fetchSurveyAssistantChat = async (input, init) => {
|
|
151
|
-
const response = await globalThis.fetch(input, init);
|
|
152
|
-
if (!response.ok) await readSurveyAssistantJson(response);
|
|
153
|
-
return response;
|
|
154
|
-
};
|
|
155
|
-
const createSurveyAssistantTransport = ({ api = "/api/survey-assistant/chat", resourceId, surveyId, threadId }) => new DefaultChatTransport({
|
|
156
|
-
api,
|
|
157
|
-
body: {
|
|
158
|
-
resourceId,
|
|
159
|
-
...surveyId ? { surveyId } : {},
|
|
160
|
-
threadId
|
|
161
|
-
},
|
|
162
|
-
fetch: fetchSurveyAssistantChat,
|
|
163
|
-
prepareSendMessagesRequest: ({ api, body, credentials, headers, id, messageId, messages, trigger }) => {
|
|
164
|
-
const latestUserMessage = findLastUserMessage(messages);
|
|
165
|
-
return {
|
|
166
|
-
api,
|
|
167
|
-
credentials,
|
|
168
|
-
headers,
|
|
169
|
-
body: {
|
|
170
|
-
...body,
|
|
171
|
-
id,
|
|
172
|
-
messages: latestUserMessage ? [latestUserMessage] : [],
|
|
173
|
-
trigger,
|
|
174
|
-
messageId
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
//#endregion
|
|
180
|
-
//#region src/react/thread-client.ts
|
|
181
|
-
const createSurveyAssistantThreadClient = (api = "/api/survey-assistant/threads") => ({
|
|
182
|
-
async delete(threadId) {
|
|
183
|
-
const response = await fetch(`${api}/${encodeURIComponent(threadId)}`, { method: "DELETE" });
|
|
184
|
-
if (!response.ok) await readSurveyAssistantJson(response);
|
|
185
|
-
},
|
|
186
|
-
async create(title) {
|
|
187
|
-
const body = await readSurveyAssistantJson(await fetch(api, {
|
|
188
|
-
body: JSON.stringify(title ? { title } : {}),
|
|
189
|
-
headers: { "content-type": "application/json" },
|
|
190
|
-
method: "POST"
|
|
191
|
-
}));
|
|
192
|
-
return surveyAssistantThreadSchema.parse(body.thread);
|
|
193
|
-
},
|
|
194
|
-
async list() {
|
|
195
|
-
const body = await readSurveyAssistantJson(await fetch(api, { cache: "no-store" }));
|
|
196
|
-
return surveyAssistantThreadListSchema.parse(body).threads;
|
|
197
|
-
},
|
|
198
|
-
async listPage(options) {
|
|
199
|
-
const search = new URLSearchParams();
|
|
200
|
-
if (options?.cursor) search.set("cursor", options.cursor);
|
|
201
|
-
const body = await readSurveyAssistantJson(await fetch(`${api}${search.size ? `?${search}` : ""}`, { cache: "no-store" }));
|
|
202
|
-
return surveyAssistantThreadListSchema.parse(body);
|
|
203
|
-
},
|
|
204
|
-
async read(threadId, cursor) {
|
|
205
|
-
const search = cursor ? `?cursor=${encodeURIComponent(cursor)}` : "";
|
|
206
|
-
const body = await readSurveyAssistantJson(await fetch(`${api}/${encodeURIComponent(threadId)}${search}`, { cache: "no-store" }));
|
|
207
|
-
return surveyAssistantThreadTranscriptSchema.parse(body);
|
|
208
|
-
},
|
|
209
|
-
async rename(threadId, title) {
|
|
210
|
-
const body = await readSurveyAssistantJson(await fetch(`${api}/${encodeURIComponent(threadId)}`, {
|
|
211
|
-
body: JSON.stringify({
|
|
212
|
-
mode: "manual",
|
|
213
|
-
title
|
|
214
|
-
}),
|
|
215
|
-
headers: { "content-type": "application/json" },
|
|
216
|
-
method: "PATCH"
|
|
217
|
-
}));
|
|
218
|
-
return surveyAssistantThreadSchema.parse(body.thread);
|
|
219
|
-
},
|
|
220
|
-
async setAutomaticTitle(threadId, title) {
|
|
221
|
-
const body = await readSurveyAssistantJson(await fetch(`${api}/${encodeURIComponent(threadId)}`, {
|
|
222
|
-
body: JSON.stringify({
|
|
223
|
-
mode: "automatic",
|
|
224
|
-
...title ? { title } : {}
|
|
225
|
-
}),
|
|
226
|
-
headers: { "content-type": "application/json" },
|
|
227
|
-
method: "PATCH"
|
|
228
|
-
}));
|
|
229
|
-
return surveyAssistantThreadSchema.parse(body.thread);
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
//#endregion
|
|
233
|
-
//#region src/react/model-catalog.ts
|
|
234
|
-
const DEFAULT_MODEL_STORAGE_KEY = "survey-assistant-selected-model";
|
|
235
|
-
const createSurveyAssistantModelCatalogClient = (api = "/api/survey-assistant/models") => ({ async get() {
|
|
236
|
-
const body = await readSurveyAssistantJson(await fetch(api, { cache: "no-store" }), "The assistant model catalog could not be loaded.");
|
|
237
|
-
return surveyAssistantModelCatalogSchema.parse(body);
|
|
238
|
-
} });
|
|
239
|
-
const useSurveyAssistantModelCatalog = ({ api, client: providedClient, onModelChange, storageKey = DEFAULT_MODEL_STORAGE_KEY } = {}) => {
|
|
240
|
-
const [models, setModels] = useState([]);
|
|
241
|
-
const [modelId, setModelId] = useState();
|
|
242
|
-
const [error, setError] = useState(null);
|
|
243
|
-
const [loading, setLoading] = useState(true);
|
|
244
|
-
const [reloadToken, setReloadToken] = useState(0);
|
|
245
|
-
useEffect(() => {
|
|
246
|
-
let cancelled = false;
|
|
247
|
-
const client = providedClient ?? createSurveyAssistantModelCatalogClient(api);
|
|
248
|
-
setLoading(true);
|
|
249
|
-
setError(null);
|
|
250
|
-
client.get().then((catalog) => {
|
|
251
|
-
if (cancelled) return;
|
|
252
|
-
const rememberedId = storageKey && typeof window !== "undefined" ? window.localStorage.getItem(storageKey) ?? void 0 : void 0;
|
|
253
|
-
const selectedId = rememberedId && catalog.models.some((model) => model.id === rememberedId) ? rememberedId : catalog.defaultModelId;
|
|
254
|
-
setModels(catalog.models);
|
|
255
|
-
setModelId(selectedId);
|
|
256
|
-
onModelChange?.(selectedId);
|
|
257
|
-
}).catch((reason) => {
|
|
258
|
-
if (!cancelled) setError(reason instanceof Error ? reason : new Error(String(reason)));
|
|
259
|
-
}).finally(() => {
|
|
260
|
-
if (!cancelled) setLoading(false);
|
|
261
|
-
});
|
|
262
|
-
return () => {
|
|
263
|
-
cancelled = true;
|
|
264
|
-
};
|
|
265
|
-
}, [
|
|
266
|
-
api,
|
|
267
|
-
onModelChange,
|
|
268
|
-
providedClient,
|
|
269
|
-
reloadToken,
|
|
270
|
-
storageKey
|
|
271
|
-
]);
|
|
272
|
-
const selectModel = useCallback((nextModelId) => {
|
|
273
|
-
if (!models.some((model) => model.id === nextModelId)) return;
|
|
274
|
-
setModelId(nextModelId);
|
|
275
|
-
if (storageKey && typeof window !== "undefined") window.localStorage.setItem(storageKey, nextModelId);
|
|
276
|
-
onModelChange?.(nextModelId);
|
|
277
|
-
}, [
|
|
278
|
-
models,
|
|
279
|
-
onModelChange,
|
|
280
|
-
storageKey
|
|
281
|
-
]);
|
|
282
|
-
return {
|
|
283
|
-
error,
|
|
284
|
-
loading,
|
|
285
|
-
modelId,
|
|
286
|
-
models,
|
|
287
|
-
reload: useCallback(() => setReloadToken((current) => current + 1), []),
|
|
288
|
-
selectModel
|
|
289
|
-
};
|
|
290
|
-
};
|
|
291
|
-
//#endregion
|
|
292
|
-
//#region src/react/document-baseline.ts
|
|
293
|
-
const STORAGE_PREFIX = "case-survey-assistant:settled-document:";
|
|
294
|
-
const memoryBaselines = /* @__PURE__ */ new Map();
|
|
295
|
-
const getStorageKey = (resourceId, threadId) => `${STORAGE_PREFIX}${encodeURIComponent(resourceId)}:${encodeURIComponent(threadId)}`;
|
|
296
|
-
const getSessionStorage = () => {
|
|
297
|
-
if (typeof document === "undefined") return void 0;
|
|
298
|
-
try {
|
|
299
|
-
return window.sessionStorage;
|
|
300
|
-
} catch {
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
};
|
|
304
|
-
const readSettledDocumentVersion = ({ resourceId, threadId }) => {
|
|
305
|
-
const storageKey = getStorageKey(resourceId, threadId);
|
|
306
|
-
const storedInMemory = memoryBaselines.get(storageKey);
|
|
307
|
-
if (storedInMemory) return { ...storedInMemory };
|
|
308
|
-
const serialized = getSessionStorage()?.getItem(storageKey);
|
|
309
|
-
if (!serialized) return void 0;
|
|
310
|
-
try {
|
|
311
|
-
const parsed = surveyDocumentVersionSchema.safeParse(JSON.parse(serialized));
|
|
312
|
-
if (!parsed.success) return void 0;
|
|
313
|
-
memoryBaselines.set(storageKey, parsed.data);
|
|
314
|
-
return { ...parsed.data };
|
|
315
|
-
} catch {
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
|
-
const writeSettledDocumentVersion = ({ resourceId, snapshot, threadId }) => {
|
|
320
|
-
const storageKey = getStorageKey(resourceId, threadId);
|
|
321
|
-
const version = surveyDocumentVersionSchema.parse(snapshot.version);
|
|
322
|
-
memoryBaselines.set(storageKey, version);
|
|
323
|
-
try {
|
|
324
|
-
getSessionStorage()?.setItem(storageKey, JSON.stringify(version));
|
|
325
|
-
} catch {}
|
|
326
|
-
};
|
|
327
|
-
//#endregion
|
|
328
|
-
//#region src/react/use-survey-assistant-session.ts
|
|
329
|
-
const createLocalId = (prefix) => {
|
|
330
|
-
return `${prefix}-${globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2)}`;
|
|
331
|
-
};
|
|
332
|
-
const compactOutcomeText = (value, maximum, fallback) => {
|
|
333
|
-
const normalized = value.trim() || fallback;
|
|
334
|
-
return normalized.length > maximum ? `${normalized.slice(0, maximum - 1)}…` : normalized;
|
|
335
|
-
};
|
|
336
|
-
const createApplyOutcome = ({ message, preparedChanges, results, status, turnId }) => surveyAssistantApplyOutcomeSchema.parse({
|
|
337
|
-
protocolVersion: 1,
|
|
338
|
-
turnId,
|
|
339
|
-
status,
|
|
340
|
-
message: compactOutcomeText(message, 2e3, "No lifecycle detail was reported."),
|
|
341
|
-
...results && results.length > 0 ? { results: results.slice(0, 100).map((result) => ({
|
|
342
|
-
status: result.status,
|
|
343
|
-
changeId: compactOutcomeText(result.changeId, 240, "unknown-change"),
|
|
344
|
-
summary: compactOutcomeText(result.summary, 500, "Survey change"),
|
|
345
|
-
message: compactOutcomeText(result.message, 2e3, "No apply detail was reported."),
|
|
346
|
-
appliedOperations: result.appliedOperations
|
|
347
|
-
})) } : {},
|
|
348
|
-
...preparedChanges && preparedChanges.length > 0 ? { preparedChanges: preparedChanges.slice(-24).map((change) => ({
|
|
349
|
-
changeId: compactOutcomeText(change.id, 240, "unknown-change"),
|
|
350
|
-
status: change.status,
|
|
351
|
-
summary: compactOutcomeText(change.summary, 500, "Survey change"),
|
|
352
|
-
operationCount: change.operations.length
|
|
353
|
-
})) } : {},
|
|
354
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
355
|
-
});
|
|
356
|
-
const getAssistantTextParts = (message) => message.parts.filter((part) => part.type === "text" && part.text.trim().length > 0);
|
|
357
|
-
const findLastAssistantTextMessageIndex = (messages, endExclusive = messages.length) => {
|
|
358
|
-
for (let index = Math.min(messages.length, endExclusive) - 1; index >= 0; index -= 1) {
|
|
359
|
-
const message = messages[index];
|
|
360
|
-
if (message?.role === "assistant" && getAssistantTextParts(message).length > 0) return index;
|
|
361
|
-
}
|
|
362
|
-
return -1;
|
|
363
|
-
};
|
|
364
|
-
const findLastUserMessageIndex = (messages) => {
|
|
365
|
-
for (let index = messages.length - 1; index >= 0; index -= 1) if (messages[index]?.role === "user") return index;
|
|
366
|
-
return -1;
|
|
367
|
-
};
|
|
368
|
-
const pruneFailedMessagesForDisplay = (messages) => {
|
|
369
|
-
const lastUserIndex = findLastUserMessageIndex(messages);
|
|
370
|
-
const lastCompletedAssistantIndex = findLastAssistantTextMessageIndex(messages);
|
|
371
|
-
if (lastUserIndex > lastCompletedAssistantIndex) return messages.slice(0, lastUserIndex + 1);
|
|
372
|
-
return lastCompletedAssistantIndex >= 0 ? messages.slice(0, lastCompletedAssistantIndex + 1) : [];
|
|
373
|
-
};
|
|
374
|
-
const hasCompletedAssistantResponseAfterLastUser = (messages) => {
|
|
375
|
-
const lastUserIndex = findLastUserMessageIndex(messages);
|
|
376
|
-
return lastUserIndex >= 0 && findLastAssistantTextMessageIndex(messages) > lastUserIndex;
|
|
377
|
-
};
|
|
378
|
-
const collectChangeSetsAfterLastUser = (messages) => {
|
|
379
|
-
const lastUserIndex = findLastUserMessageIndex(messages);
|
|
380
|
-
return lastUserIndex < 0 ? [] : collectSurveyChangeSets(messages.slice(lastUserIndex + 1));
|
|
381
|
-
};
|
|
382
|
-
const getInitialSessionState = (messages) => {
|
|
383
|
-
if (messages.length === 0) return "idle";
|
|
384
|
-
const authorization = resolveLatestSurveyTurnAuthorization(messages);
|
|
385
|
-
if (authorization.status === "failed") return "failed";
|
|
386
|
-
if (authorization.status === "aborted") return "aborted";
|
|
387
|
-
return "completed";
|
|
388
|
-
};
|
|
389
|
-
const resolveSurveyAssistantReviewDecision = async ({ changeSets, onReviewChangeSets, turnFinal }) => {
|
|
390
|
-
if (!onReviewChangeSets) throw new Error("No survey assistant review adapter is available.");
|
|
391
|
-
return onReviewChangeSets(changeSets, turnFinal);
|
|
392
|
-
};
|
|
393
|
-
const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessages = [], modelId, onApplyReceipts, onSettleApply, onReviewChangeSets, onTurnActiveChange, resourceId: controlledResourceId, surveyId, threadId: controlledThreadId }) => {
|
|
394
|
-
const [localResourceId] = useState(() => createLocalId("survey-assistant-local-user"));
|
|
395
|
-
const [localThreadId] = useState(() => createLocalId("survey-assistant-local-thread"));
|
|
396
|
-
const resourceId = controlledResourceId ?? localResourceId;
|
|
397
|
-
const threadId = controlledThreadId ?? localThreadId;
|
|
398
|
-
const applyOutcomeScopeKey = `${resourceId}\u0000${threadId}`;
|
|
399
|
-
const [state, dispatch] = useReducer(reduceSurveyAssistantSessionState, initialMessages, getInitialSessionState);
|
|
400
|
-
const [applyResultsByChangeId, setApplyResultsByChangeId] = useState({});
|
|
401
|
-
const [authorizationError, setAuthorizationError] = useState(null);
|
|
402
|
-
const handledTurnIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
403
|
-
const localTurnAwaitingApplyRef = useRef(false);
|
|
404
|
-
const localTurnStreamStartedRef = useRef(false);
|
|
405
|
-
const captureSettledVersionRef = useRef(false);
|
|
406
|
-
const lastSubmittedUIContextRef = useRef(void 0);
|
|
407
|
-
const lastSubmittedModelIdRef = useRef(void 0);
|
|
408
|
-
const previousApplyOutcomesRef = useRef(/* @__PURE__ */ new Map());
|
|
409
|
-
const { messages, setMessages, sendMessage, status, stop: stopChat, error, clearError, regenerate } = useChat({
|
|
410
|
-
id: threadId,
|
|
411
|
-
messages: initialMessages,
|
|
412
|
-
transport: useMemo(() => createSurveyAssistantTransport({
|
|
413
|
-
api,
|
|
414
|
-
resourceId,
|
|
415
|
-
surveyId,
|
|
416
|
-
threadId
|
|
417
|
-
}), [
|
|
418
|
-
api,
|
|
419
|
-
resourceId,
|
|
420
|
-
surveyId,
|
|
421
|
-
threadId
|
|
422
|
-
])
|
|
423
|
-
});
|
|
424
|
-
const isStreaming = status === "submitted" || status === "streaming";
|
|
425
|
-
const isTurnActive = isSurveyAssistantTurnActive({
|
|
426
|
-
isStreaming,
|
|
427
|
-
state
|
|
428
|
-
});
|
|
429
|
-
const notifyTurnActiveChange = useEffectEvent((active) => {
|
|
430
|
-
onTurnActiveChange?.(active);
|
|
431
|
-
});
|
|
432
|
-
const prependMessages = useCallback((olderMessages) => {
|
|
433
|
-
setMessages((current) => {
|
|
434
|
-
const currentIds = new Set(current.map((message) => message.id));
|
|
435
|
-
return [...olderMessages.filter((message) => !currentIds.has(message.id)), ...current];
|
|
436
|
-
});
|
|
437
|
-
}, [setMessages]);
|
|
438
|
-
const turnAuthorization = useMemo(() => resolveLatestSurveyTurnAuthorization(messages), [messages]);
|
|
439
|
-
const latestTurnOutcome = useMemo(() => resolveSurveyTurnOutcome({
|
|
440
|
-
applyResultsByChangeId,
|
|
441
|
-
authorization: turnAuthorization
|
|
442
|
-
}), [applyResultsByChangeId, turnAuthorization]);
|
|
443
|
-
const hasUsefulLatestAssistantResponse = useMemo(() => hasCompletedAssistantResponseAfterLastUser(messages) || collectChangeSetsAfterLastUser(messages).length > 0, [messages]);
|
|
444
|
-
const reportAuthorizationError = useCallback((message) => {
|
|
445
|
-
queueMicrotask(() => {
|
|
446
|
-
setAuthorizationError(message);
|
|
447
|
-
dispatch({ type: "failed" });
|
|
448
|
-
});
|
|
449
|
-
}, []);
|
|
450
|
-
useEffect(() => {
|
|
451
|
-
if (status === "submitted") dispatch({ type: "submit" });
|
|
452
|
-
if (status === "streaming") dispatch({ type: "stream-started" });
|
|
453
|
-
}, [status]);
|
|
454
|
-
useEffect(() => {
|
|
455
|
-
notifyTurnActiveChange(isTurnActive);
|
|
456
|
-
return () => {
|
|
457
|
-
if (isTurnActive) notifyTurnActiveChange(false);
|
|
458
|
-
};
|
|
459
|
-
}, [isTurnActive]);
|
|
460
|
-
useEffect(() => {
|
|
461
|
-
if (!captureSettledVersionRef.current || isStreaming || state !== "completed" && state !== "failed" && state !== "aborted" && state !== "applied") return;
|
|
462
|
-
captureSettledVersionRef.current = false;
|
|
463
|
-
const snapshot = controller?.getSnapshot();
|
|
464
|
-
if (snapshot) writeSettledDocumentVersion({
|
|
465
|
-
resourceId,
|
|
466
|
-
snapshot,
|
|
467
|
-
threadId
|
|
468
|
-
});
|
|
469
|
-
}, [
|
|
470
|
-
controller,
|
|
471
|
-
isStreaming,
|
|
472
|
-
resourceId,
|
|
473
|
-
state,
|
|
474
|
-
threadId
|
|
475
|
-
]);
|
|
476
|
-
useEffect(() => {
|
|
477
|
-
if (isStreaming) {
|
|
478
|
-
localTurnStreamStartedRef.current = true;
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
if (!localTurnAwaitingApplyRef.current) return;
|
|
482
|
-
if (turnAuthorization.status === "pending") {
|
|
483
|
-
if (!localTurnStreamStartedRef.current) return;
|
|
484
|
-
const timeoutId = window.setTimeout(() => {
|
|
485
|
-
localTurnAwaitingApplyRef.current = false;
|
|
486
|
-
localTurnStreamStartedRef.current = false;
|
|
487
|
-
reportAuthorizationError("The assistant response ended without a valid turn final.");
|
|
488
|
-
}, 100);
|
|
489
|
-
return () => window.clearTimeout(timeoutId);
|
|
490
|
-
}
|
|
491
|
-
localTurnAwaitingApplyRef.current = false;
|
|
492
|
-
localTurnStreamStartedRef.current = false;
|
|
493
|
-
if (turnAuthorization.status === "invalid") {
|
|
494
|
-
reportAuthorizationError(turnAuthorization.reason);
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
const { turnFinal } = turnAuthorization;
|
|
498
|
-
if (handledTurnIdsRef.current.has(turnFinal.turnId)) return;
|
|
499
|
-
handledTurnIdsRef.current.add(turnFinal.turnId);
|
|
500
|
-
const preparedChanges = collectChangeSetsAfterLastUser(messages).filter((change) => change.turnId === turnFinal.turnId);
|
|
501
|
-
if (turnAuthorization.status === "failed") {
|
|
502
|
-
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
503
|
-
turnId: turnFinal.turnId,
|
|
504
|
-
status: "not-applied",
|
|
505
|
-
message: "The previous assistant turn failed before editor authorization. Every request-scoped draft change from that turn was discarded and was not applied.",
|
|
506
|
-
preparedChanges
|
|
507
|
-
}));
|
|
508
|
-
dispatch({ type: "failed" });
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
511
|
-
if (turnAuthorization.status === "aborted") {
|
|
512
|
-
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
513
|
-
turnId: turnFinal.turnId,
|
|
514
|
-
status: "not-applied",
|
|
515
|
-
message: "The previous assistant turn was interrupted before editor authorization. Every request-scoped draft change from that turn was discarded and was not applied.",
|
|
516
|
-
preparedChanges
|
|
517
|
-
}));
|
|
518
|
-
dispatch({ type: "aborted" });
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
if (turnAuthorization.changeSets.length === 0) {
|
|
522
|
-
if ((turnFinal.blockedChangeSetIds?.length ?? 0) > 0) previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
523
|
-
turnId: turnFinal.turnId,
|
|
524
|
-
status: "not-applied",
|
|
525
|
-
message: "The previous assistant turn ended with unresolved rejected changes. No request-scoped draft change from that turn was authorized or applied.",
|
|
526
|
-
preparedChanges
|
|
527
|
-
}));
|
|
528
|
-
dispatch({ type: "completed" });
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
if (applyPolicy === "deny") {
|
|
532
|
-
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
533
|
-
turnId: turnFinal.turnId,
|
|
534
|
-
status: "not-applied",
|
|
535
|
-
message: "The host apply policy did not authorize editor mutations for this turn.",
|
|
536
|
-
preparedChanges
|
|
537
|
-
}));
|
|
538
|
-
dispatch({ type: "completed" });
|
|
539
|
-
return;
|
|
540
|
-
}
|
|
541
|
-
dispatch({ type: "apply-started" });
|
|
542
|
-
(async () => {
|
|
543
|
-
if (applyPolicy === "review") {
|
|
544
|
-
let approved;
|
|
545
|
-
try {
|
|
546
|
-
approved = await resolveSurveyAssistantReviewDecision({
|
|
547
|
-
changeSets: turnAuthorization.changeSets,
|
|
548
|
-
onReviewChangeSets,
|
|
549
|
-
turnFinal
|
|
550
|
-
});
|
|
551
|
-
} catch (error) {
|
|
552
|
-
const message = error instanceof Error && error.message === "No survey assistant review adapter is available." ? error.message : "The survey assistant review could not be completed.";
|
|
553
|
-
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
554
|
-
turnId: turnFinal.turnId,
|
|
555
|
-
status: "not-applied",
|
|
556
|
-
message,
|
|
557
|
-
preparedChanges
|
|
558
|
-
}));
|
|
559
|
-
reportAuthorizationError(message);
|
|
560
|
-
return;
|
|
561
|
-
}
|
|
562
|
-
if (!approved) {
|
|
563
|
-
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
564
|
-
turnId: turnFinal.turnId,
|
|
565
|
-
status: "not-applied",
|
|
566
|
-
message: "The proposed editor changes were not approved during review.",
|
|
567
|
-
preparedChanges
|
|
568
|
-
}));
|
|
569
|
-
dispatch({ type: "completed" });
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
if (!controller?.applyAssistantChange && !controller?.applyAssistantChanges) {
|
|
574
|
-
const message = "No survey editor apply adapter is available.";
|
|
575
|
-
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
576
|
-
turnId: turnFinal.turnId,
|
|
577
|
-
status: "apply-failed",
|
|
578
|
-
message,
|
|
579
|
-
preparedChanges
|
|
580
|
-
}));
|
|
581
|
-
reportAuthorizationError(message);
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
const beforeSnapshot = controller.getSnapshot();
|
|
585
|
-
if (!beforeSnapshot) {
|
|
586
|
-
const message = "The editor state was unavailable when applying the assistant change.";
|
|
587
|
-
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
588
|
-
turnId: turnFinal.turnId,
|
|
589
|
-
status: "apply-failed",
|
|
590
|
-
message,
|
|
591
|
-
preparedChanges
|
|
592
|
-
}));
|
|
593
|
-
reportAuthorizationError(message);
|
|
594
|
-
return;
|
|
595
|
-
}
|
|
596
|
-
const result = controller.applyAssistantChanges?.(turnAuthorization.changeSets) ?? { results: turnAuthorization.changeSets.map((change) => controller.applyAssistantChange?.(change)).filter((applyResult) => Boolean(applyResult)) };
|
|
597
|
-
queueMicrotask(() => setApplyResultsByChangeId((current) => ({
|
|
598
|
-
...current,
|
|
599
|
-
...Object.fromEntries(result.results.map((applyResult) => [applyResult.changeId, applyResult]))
|
|
600
|
-
})));
|
|
601
|
-
const receipts = createApplyReceipts({
|
|
602
|
-
beforeSnapshot,
|
|
603
|
-
afterSnapshot: controller.getSnapshot(),
|
|
604
|
-
changeSets: turnAuthorization.changeSets,
|
|
605
|
-
results: result.results,
|
|
606
|
-
turnFinal
|
|
607
|
-
});
|
|
608
|
-
onApplyReceipts?.(receipts);
|
|
609
|
-
if (!result.results.every((applyResult) => applyResult.status === "applied")) {
|
|
610
|
-
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
611
|
-
turnId: turnFinal.turnId,
|
|
612
|
-
status: "apply-failed",
|
|
613
|
-
message: "One or more authorized survey changes could not be applied to the editor.",
|
|
614
|
-
preparedChanges,
|
|
615
|
-
results: result.results
|
|
616
|
-
}));
|
|
617
|
-
dispatch({ type: "completed" });
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
try {
|
|
621
|
-
await onSettleApply?.({
|
|
622
|
-
changeSets: turnAuthorization.changeSets,
|
|
623
|
-
receipts,
|
|
624
|
-
turnFinal
|
|
625
|
-
});
|
|
626
|
-
previousApplyOutcomesRef.current.delete(applyOutcomeScopeKey);
|
|
627
|
-
dispatch({ type: "applied" });
|
|
628
|
-
} catch {
|
|
629
|
-
const message = "The assistant changes were applied locally but could not be settled by the host.";
|
|
630
|
-
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
631
|
-
turnId: turnFinal.turnId,
|
|
632
|
-
status: "settle-failed",
|
|
633
|
-
message,
|
|
634
|
-
results: result.results
|
|
635
|
-
}));
|
|
636
|
-
reportAuthorizationError(message);
|
|
637
|
-
}
|
|
638
|
-
})();
|
|
639
|
-
}, [
|
|
640
|
-
applyPolicy,
|
|
641
|
-
applyOutcomeScopeKey,
|
|
642
|
-
controller,
|
|
643
|
-
isStreaming,
|
|
644
|
-
onApplyReceipts,
|
|
645
|
-
onReviewChangeSets,
|
|
646
|
-
onSettleApply,
|
|
647
|
-
reportAuthorizationError,
|
|
648
|
-
messages,
|
|
649
|
-
turnAuthorization
|
|
650
|
-
]);
|
|
651
|
-
useEffect(() => {
|
|
652
|
-
if (!error) return;
|
|
653
|
-
localTurnAwaitingApplyRef.current = false;
|
|
654
|
-
localTurnStreamStartedRef.current = false;
|
|
655
|
-
dispatch({ type: "failed" });
|
|
656
|
-
if (!hasUsefulLatestAssistantResponse) setMessages(pruneFailedMessagesForDisplay);
|
|
657
|
-
}, [
|
|
658
|
-
error,
|
|
659
|
-
hasUsefulLatestAssistantResponse,
|
|
660
|
-
setMessages
|
|
661
|
-
]);
|
|
662
|
-
const submit = useCallback(({ files, modelId: submittedModelId, text: rawText, uiContext }) => {
|
|
663
|
-
const text = rawText.trim();
|
|
664
|
-
if (!text && files.length === 0) return false;
|
|
665
|
-
if (isStreaming || localTurnAwaitingApplyRef.current) return false;
|
|
666
|
-
localTurnAwaitingApplyRef.current = true;
|
|
667
|
-
localTurnStreamStartedRef.current = false;
|
|
668
|
-
setAuthorizationError(null);
|
|
669
|
-
if (authorizationError || error) setMessages(pruneFailedMessagesForDisplay);
|
|
670
|
-
clearError();
|
|
671
|
-
dispatch({ type: "submit" });
|
|
672
|
-
captureSettledVersionRef.current = true;
|
|
673
|
-
lastSubmittedUIContextRef.current = uiContext;
|
|
674
|
-
lastSubmittedModelIdRef.current = submittedModelId ?? modelId;
|
|
675
|
-
const snapshot = applySurveyAssistantLaunchUIContext(controller?.getSnapshot() ?? null, uiContext);
|
|
676
|
-
sendMessage(files.length > 0 ? text ? {
|
|
677
|
-
text,
|
|
678
|
-
files
|
|
679
|
-
} : { files } : { text }, { body: {
|
|
680
|
-
snapshot,
|
|
681
|
-
previousSettledVersion: readSettledDocumentVersion({
|
|
682
|
-
resourceId,
|
|
683
|
-
threadId
|
|
684
|
-
}),
|
|
685
|
-
previousApplyOutcome: previousApplyOutcomesRef.current.get(applyOutcomeScopeKey),
|
|
686
|
-
...lastSubmittedModelIdRef.current ? { modelId: lastSubmittedModelIdRef.current } : {}
|
|
687
|
-
} });
|
|
688
|
-
return true;
|
|
689
|
-
}, [
|
|
690
|
-
authorizationError,
|
|
691
|
-
applyOutcomeScopeKey,
|
|
692
|
-
clearError,
|
|
693
|
-
controller,
|
|
694
|
-
error,
|
|
695
|
-
isStreaming,
|
|
696
|
-
modelId,
|
|
697
|
-
resourceId,
|
|
698
|
-
sendMessage,
|
|
699
|
-
setMessages,
|
|
700
|
-
threadId
|
|
701
|
-
]);
|
|
702
|
-
const stop = useCallback(() => {
|
|
703
|
-
localTurnAwaitingApplyRef.current = false;
|
|
704
|
-
localTurnStreamStartedRef.current = false;
|
|
705
|
-
dispatch({ type: "aborted" });
|
|
706
|
-
stopChat();
|
|
707
|
-
}, [stopChat]);
|
|
708
|
-
const retry = useCallback(() => {
|
|
709
|
-
localTurnAwaitingApplyRef.current = true;
|
|
710
|
-
localTurnStreamStartedRef.current = false;
|
|
711
|
-
setAuthorizationError(null);
|
|
712
|
-
clearError();
|
|
713
|
-
dispatch({ type: "submit" });
|
|
714
|
-
captureSettledVersionRef.current = true;
|
|
715
|
-
const controllerSnapshot = controller?.getSnapshot() ?? null;
|
|
716
|
-
const uiContext = lastSubmittedUIContextRef.current;
|
|
717
|
-
regenerate({ body: {
|
|
718
|
-
snapshot: applySurveyAssistantLaunchUIContext(controllerSnapshot, uiContext),
|
|
719
|
-
previousSettledVersion: readSettledDocumentVersion({
|
|
720
|
-
resourceId,
|
|
721
|
-
threadId
|
|
722
|
-
}),
|
|
723
|
-
previousApplyOutcome: previousApplyOutcomesRef.current.get(applyOutcomeScopeKey),
|
|
724
|
-
...lastSubmittedModelIdRef.current ? { modelId: lastSubmittedModelIdRef.current } : {}
|
|
725
|
-
} });
|
|
726
|
-
}, [
|
|
727
|
-
applyOutcomeScopeKey,
|
|
728
|
-
clearError,
|
|
729
|
-
controller,
|
|
730
|
-
modelId,
|
|
731
|
-
regenerate,
|
|
732
|
-
resourceId,
|
|
733
|
-
threadId
|
|
734
|
-
]);
|
|
735
|
-
return {
|
|
736
|
-
applyResultsByChangeId,
|
|
737
|
-
authorizationError,
|
|
738
|
-
dismissError: useCallback(() => {
|
|
739
|
-
localTurnAwaitingApplyRef.current = false;
|
|
740
|
-
localTurnStreamStartedRef.current = false;
|
|
741
|
-
setMessages(pruneFailedMessagesForDisplay);
|
|
742
|
-
setAuthorizationError(null);
|
|
743
|
-
clearError();
|
|
744
|
-
dispatch({
|
|
745
|
-
type: "reset",
|
|
746
|
-
hasTranscript: messages.length > 0
|
|
747
|
-
});
|
|
748
|
-
}, [
|
|
749
|
-
clearError,
|
|
750
|
-
messages.length,
|
|
751
|
-
setMessages
|
|
752
|
-
]),
|
|
753
|
-
error,
|
|
754
|
-
isStreaming,
|
|
755
|
-
latestTurnOutcome,
|
|
756
|
-
messages,
|
|
757
|
-
prependMessages,
|
|
758
|
-
state,
|
|
759
|
-
status,
|
|
760
|
-
stop,
|
|
761
|
-
submit,
|
|
762
|
-
retry
|
|
763
|
-
};
|
|
764
|
-
};
|
|
765
|
-
//#endregion
|
|
766
|
-
export { createSurveyAssistantTransport as a, getSurveyDocumentVersionFromSnapshot as c, resolveSurveyTurnOutcome as d, unwrapSurveyAssistantToolOutput as f, createSurveyAssistantThreadClient as i, parseSurveyChangeSet as l, reduceSurveyAssistantSessionState as m, createSurveyAssistantModelCatalogClient as n, collectSurveyChangeSets as o, isSurveyAssistantTurnActive as p, useSurveyAssistantModelCatalog as r, createApplyReceipts as s, useSurveyAssistantSession as t, resolveLatestSurveyTurnAuthorization as u };
|
|
767
|
-
|
|
768
|
-
//# sourceMappingURL=react-Dqlmasrs.mjs.map
|