@case-framework/survey-assistant 0.2.2 → 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-D-5m_KGB.d.mts → constants-BK1-g6pR.d.mts} +12 -7
- package/dist/constants-BK1-g6pR.d.mts.map +1 -0
- package/dist/{controller-proxy-Hkuub9dt.d.mts → controller-proxy-CIDRd8Wu.d.mts} +2 -2
- package/dist/{controller-proxy-Hkuub9dt.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-BcyfBeDj.d.mts → index-Bp5W_oPa.d.mts} +25 -5
- package/dist/index-Bp5W_oPa.d.mts.map +1 -0
- package/dist/{index-JXH-t2EJ.d.mts → index-CPOQgkTN.d.mts} +67 -6
- package/dist/index-CPOQgkTN.d.mts.map +1 -0
- package/dist/{index-MEOL9_Gr.d.mts → index-EDL1V168.d.mts} +98 -4
- package/dist/{index-MEOL9_Gr.d.mts.map → index-EDL1V168.d.mts.map} +1 -1
- package/dist/{index-CneD8ibB.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 +26 -6
- 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-DcfQNJwO.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-uddXwQjp.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 +3 -3
- 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-D-5m_KGB.d.mts.map +0 -1
- package/dist/engine-0AJrv0hI.mjs.map +0 -1
- package/dist/index-BcyfBeDj.d.mts.map +0 -1
- package/dist/index-CneD8ibB.d.mts.map +0 -1
- package/dist/index-JXH-t2EJ.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-DcfQNJwO.d.mts.map +0 -1
- package/dist/thread-handlers-uddXwQjp.d.mts.map +0 -1
- package/dist/tools-wgLen05n.mjs.map +0 -1
package/dist/ui.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { f as unwrapSurveyAssistantToolOutput, i as createSurveyAssistantThreadClient, l as parseSurveyChangeSet, p as isSurveyAssistantTurnActive, r as useSurveyAssistantModelCatalog, t as useSurveyAssistantSession } from "./react-
|
|
4
|
-
import { o as connectSurveyAssistantThreadLauncher } from "./controller-proxy-
|
|
2
|
+
import { jt as parseSurveyAssistantError, l as surveyAssistantTurnFinalSchema, n as SURVEY_ASSISTANT_TURN_FINAL_PART_TYPE } from "./protocol-DATvkr1S.mjs";
|
|
3
|
+
import { f as unwrapSurveyAssistantToolOutput, i as createSurveyAssistantThreadClient, l as parseSurveyChangeSet, p as isSurveyAssistantTurnActive, r as useSurveyAssistantModelCatalog, t as useSurveyAssistantSession } from "./react-3kSE6WtS.mjs";
|
|
4
|
+
import { o as connectSurveyAssistantThreadLauncher } from "./controller-proxy-DY36XFV3.mjs";
|
|
5
5
|
import { getToolName, isFileUIPart, isReasoningUIPart, isToolUIPart } from "ai";
|
|
6
6
|
import { createContext, createElement, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
7
7
|
import { Collapsible, Select, Slot } from "radix-ui";
|
|
@@ -15,6 +15,7 @@ import { createLocalizationTranslator, mergeLocalizationCatalogs } from "@case-f
|
|
|
15
15
|
import { cva } from "class-variance-authority";
|
|
16
16
|
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
|
17
17
|
import { Streamdown } from "streamdown";
|
|
18
|
+
import { bundledLanguages } from "shiki/langs";
|
|
18
19
|
//#region src/ui/internal/collapsible.tsx
|
|
19
20
|
function Collapsible$1({ ...props }) {
|
|
20
21
|
return /* @__PURE__ */ jsx(Collapsible.Root, {
|
|
@@ -114,7 +115,25 @@ const surveyAssistantEnMessages = {
|
|
|
114
115
|
startConversation: "Start a conversation to see messages here",
|
|
115
116
|
scrollToLatest: "Scroll to latest message",
|
|
116
117
|
working: "Working...",
|
|
117
|
-
stopped: "Stopped"
|
|
118
|
+
stopped: "Stopped",
|
|
119
|
+
incomplete: "Response interrupted"
|
|
120
|
+
},
|
|
121
|
+
turn: {
|
|
122
|
+
failedTitle: "The assistant did not complete this turn.",
|
|
123
|
+
abortedTitle: "The turn was stopped.",
|
|
124
|
+
reasons: {
|
|
125
|
+
clientAbort: "The request was stopped by the client.",
|
|
126
|
+
firstResponseTimeout: "No meaningful response arrived before the initial deadline.",
|
|
127
|
+
idleTimeout: "The assistant stopped producing activity.",
|
|
128
|
+
maxDuration: "The one-hour execution ceiling was reached.",
|
|
129
|
+
maxSteps: "The assistant reached its tool-step limit before finishing.",
|
|
130
|
+
lengthLimit: "The model reached its output-length limit.",
|
|
131
|
+
contentFilter: "The provider stopped the response because of its content policy.",
|
|
132
|
+
providerError: "The model provider reported an error.",
|
|
133
|
+
streamError: "The response stream ended with an error.",
|
|
134
|
+
incompleteResponse: "The response ended without a normal completion.",
|
|
135
|
+
unknown: "The response ended before completion."
|
|
136
|
+
}
|
|
118
137
|
},
|
|
119
138
|
status: {
|
|
120
139
|
applying: "Applying changes",
|
|
@@ -282,7 +301,25 @@ const surveyAssistantNlMessages = {
|
|
|
282
301
|
startConversation: "Start een gesprek om hier berichten te zien",
|
|
283
302
|
scrollToLatest: "Naar het nieuwste bericht scrollen",
|
|
284
303
|
working: "Bezig...",
|
|
285
|
-
stopped: "Gestopt"
|
|
304
|
+
stopped: "Gestopt",
|
|
305
|
+
incomplete: "Antwoord onderbroken"
|
|
306
|
+
},
|
|
307
|
+
turn: {
|
|
308
|
+
failedTitle: "De assistent heeft deze beurt niet voltooid.",
|
|
309
|
+
abortedTitle: "De beurt is gestopt.",
|
|
310
|
+
reasons: {
|
|
311
|
+
clientAbort: "Het verzoek is door de client gestopt.",
|
|
312
|
+
firstResponseTimeout: "Er kwam geen betekenisvol antwoord vóór de eerste tijdslimiet.",
|
|
313
|
+
idleTimeout: "De assistent produceerde geen activiteit meer.",
|
|
314
|
+
maxDuration: "De maximale uitvoertijd van één uur is bereikt.",
|
|
315
|
+
maxSteps: "De assistent bereikte de limiet voor hulpmiddelstappen voordat hij klaar was.",
|
|
316
|
+
lengthLimit: "Het model bereikte de maximale antwoordlengte.",
|
|
317
|
+
contentFilter: "De provider stopte het antwoord vanwege het inhoudsbeleid.",
|
|
318
|
+
providerError: "De modelprovider meldde een fout.",
|
|
319
|
+
streamError: "De antwoordstream eindigde met een fout.",
|
|
320
|
+
incompleteResponse: "Het antwoord eindigde zonder normale voltooiing.",
|
|
321
|
+
unknown: "Het antwoord eindigde voordat het voltooid was."
|
|
322
|
+
}
|
|
286
323
|
},
|
|
287
324
|
status: {
|
|
288
325
|
applying: "Wijzigingen toepassen",
|
|
@@ -919,14 +956,6 @@ const stringifyToolTechnicalDetails = (value) => JSON.stringify(value, function
|
|
|
919
956
|
return currentValue;
|
|
920
957
|
}, 2);
|
|
921
958
|
//#endregion
|
|
922
|
-
//#region src/ui/internal/response.tsx
|
|
923
|
-
const Response = ({ children, className, controls = false, ...props }) => /* @__PURE__ */ jsx(Streamdown, {
|
|
924
|
-
className: cn("leading-6", "[&>:first-child]:mt-0 [&>:last-child]:mb-0", "[&_a]:text-primary [&_a]:underline [&_a]:underline-offset-2", "[&_blockquote]:my-3 [&_blockquote]:border-l-2 [&_blockquote]:border-border [&_blockquote]:pl-3 [&_blockquote]:text-muted-foreground", "[&_code]:rounded-md [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.85em]", "[&_h1]:mb-2 [&_h1]:mt-4 [&_h1]:text-base [&_h1]:font-semibold", "[&_h2]:mb-2 [&_h2]:mt-4 [&_h2]:text-sm [&_h2]:font-semibold", "[&_h3]:mb-1.5 [&_h3]:mt-3 [&_h3]:text-sm [&_h3]:font-semibold", "[&_li]:my-1 [&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-5 [&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-5", "[&_p]:my-2", "[&_pre]:my-3 [&_pre]:overflow-x-auto [&_pre]:rounded-lg [&_pre]:border [&_pre]:bg-muted [&_pre]:p-3", "[&_pre_code]:bg-transparent [&_pre_code]:p-0", "[&_strong]:font-semibold", "[&_table]:my-3 [&_table]:w-full [&_table]:border-collapse [&_td]:border [&_td]:border-border [&_td]:px-2 [&_td]:py-1 [&_th]:border [&_th]:border-border [&_th]:px-2 [&_th]:py-1 [&_th]:text-left [&_th]:font-semibold", className),
|
|
925
|
-
controls,
|
|
926
|
-
...props,
|
|
927
|
-
children
|
|
928
|
-
});
|
|
929
|
-
//#endregion
|
|
930
959
|
//#region src/ui/internal/select.tsx
|
|
931
960
|
function Select$1({ ...props }) {
|
|
932
961
|
return /* @__PURE__ */ jsx(Select.Root, {
|
|
@@ -1172,6 +1201,30 @@ const CodeBlock = ({ code, language, showLineNumbers = false, className, childre
|
|
|
1172
1201
|
});
|
|
1173
1202
|
};
|
|
1174
1203
|
//#endregion
|
|
1204
|
+
//#region src/ui/internal/response.tsx
|
|
1205
|
+
const highlightedLanguages = Object.keys(bundledLanguages);
|
|
1206
|
+
const codeHighlighter = {
|
|
1207
|
+
getSupportedLanguages: () => highlightedLanguages,
|
|
1208
|
+
getThemes: () => ["github-light", "github-dark"],
|
|
1209
|
+
highlight: ({ code, language }, callback) => highlightCode(code, language, callback),
|
|
1210
|
+
name: "shiki",
|
|
1211
|
+
supportsLanguage: (language) => language in bundledLanguages,
|
|
1212
|
+
type: "code-highlighter"
|
|
1213
|
+
};
|
|
1214
|
+
const Response = ({ children, className, controls = false, plugins, ...props }) => {
|
|
1215
|
+
const responsePlugins = useMemo(() => ({
|
|
1216
|
+
...plugins,
|
|
1217
|
+
code: plugins?.code ?? codeHighlighter
|
|
1218
|
+
}), [plugins]);
|
|
1219
|
+
return /* @__PURE__ */ jsx(Streamdown, {
|
|
1220
|
+
className: cn("leading-6", "*:first:mt-0 *:last:mb-0", "[&_a]:text-primary [&_a]:underline [&_a]:underline-offset-2", "[&_blockquote]:my-3 [&_blockquote]:border-l-2 [&_blockquote]:border-border [&_blockquote]:pl-3 [&_blockquote]:text-muted-foreground", "[&_h1]:mb-2 [&_h1]:mt-4 [&_h1]:text-base [&_h1]:font-semibold", "[&_h2]:mb-2 [&_h2]:mt-4 [&_h2]:text-sm [&_h2]:font-semibold", "[&_h3]:mb-1.5 [&_h3]:mt-3 [&_h3]:text-sm [&_h3]:font-semibold", "[&_li]:my-1 [&_ol]:my-2 [&_ol]:list-decimal [&_ol]:pl-5 [&_ul]:my-2 [&_ul]:list-disc [&_ul]:pl-5", "[&_p]:my-2", "**:data-[streamdown=code-block]:my-3 **:data-[streamdown=code-block]:gap-0 **:data-[streamdown=code-block]:overflow-hidden **:data-[streamdown=code-block]:rounded-lg **:data-[streamdown=code-block]:bg-muted/40 **:data-[streamdown=code-block]:p-0", "**:data-[streamdown=code-block-header]:px-2", "**:data-[streamdown=code-block-body]:rounded-none **:data-[streamdown=code-block-body]:border-0 **:data-[streamdown=code-block-body]:border-t **:data-[streamdown=code-block-body]:bg-background **:data-[streamdown=code-block-body]:p-3", "[&_strong]:font-semibold", "[&_table]:my-3 [&_table]:w-full [&_table]:border-collapse [&_td]:border [&_td]:border-border [&_td]:px-2 [&_td]:py-1 [&_th]:border [&_th]:border-border [&_th]:px-2 [&_th]:py-1 [&_th]:text-left [&_th]:font-semibold", className),
|
|
1221
|
+
controls,
|
|
1222
|
+
plugins: responsePlugins,
|
|
1223
|
+
...props,
|
|
1224
|
+
children
|
|
1225
|
+
});
|
|
1226
|
+
};
|
|
1227
|
+
//#endregion
|
|
1175
1228
|
//#region src/ui/internal/message-timing.ts
|
|
1176
1229
|
const isRecord$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1177
1230
|
const asTimestamp = (value) => {
|
|
@@ -1198,6 +1251,9 @@ const getPartTimestamps = (part) => {
|
|
|
1198
1251
|
* time here keeps restored chats informative without a second timing store.
|
|
1199
1252
|
*/
|
|
1200
1253
|
const getPersistedMessageDurationSeconds = (message) => {
|
|
1254
|
+
const turnFinalPart = message.parts.find((part) => part.type === SURVEY_ASSISTANT_TURN_FINAL_PART_TYPE);
|
|
1255
|
+
const turnFinal = surveyAssistantTurnFinalSchema.safeParse(turnFinalPart && "data" in turnFinalPart ? turnFinalPart.data : void 0);
|
|
1256
|
+
if (turnFinal.success && turnFinal.data.durationMs !== void 0) return Math.max(1, Math.ceil(turnFinal.data.durationMs / 1e3));
|
|
1201
1257
|
if (!isRecord$1(message.metadata)) return void 0;
|
|
1202
1258
|
const startedAt = asTimestamp(message.metadata.createdAt);
|
|
1203
1259
|
if (startedAt === void 0) return void 0;
|
|
@@ -1206,6 +1262,16 @@ const getPersistedMessageDurationSeconds = (message) => {
|
|
|
1206
1262
|
return Math.max(1, Math.ceil((completedAt - startedAt) / 1e3));
|
|
1207
1263
|
};
|
|
1208
1264
|
//#endregion
|
|
1265
|
+
//#region src/ui/internal/message-turn-status.ts
|
|
1266
|
+
const getPersistedMessageTurnStatus = (message) => {
|
|
1267
|
+
for (let index = message.parts.length - 1; index >= 0; index -= 1) {
|
|
1268
|
+
const part = message.parts[index];
|
|
1269
|
+
if (part?.type !== SURVEY_ASSISTANT_TURN_FINAL_PART_TYPE || !("data" in part)) continue;
|
|
1270
|
+
const parsed = surveyAssistantTurnFinalSchema.safeParse(part.data);
|
|
1271
|
+
if (parsed.success) return parsed.data.status;
|
|
1272
|
+
}
|
|
1273
|
+
};
|
|
1274
|
+
//#endregion
|
|
1209
1275
|
//#region src/ui/survey-assistant-panel.tsx
|
|
1210
1276
|
const getAssistantQuickPrompts = (t) => [
|
|
1211
1277
|
{
|
|
@@ -1373,7 +1439,7 @@ const getStoppedToolStatusMeta = (t) => ({
|
|
|
1373
1439
|
label: t("activity.stopped"),
|
|
1374
1440
|
stepStatus: "complete"
|
|
1375
1441
|
});
|
|
1376
|
-
const SurveyAssistantToolStep = ({ applyResultsByChangeId,
|
|
1442
|
+
const SurveyAssistantToolStep = ({ applyResultsByChangeId, terminalTurnStatus, part, isLast }) => {
|
|
1377
1443
|
const t = useSurveyAssistantTranslation();
|
|
1378
1444
|
const toolStatusMeta = getToolStatusMeta(t);
|
|
1379
1445
|
const toolName = getToolName(part);
|
|
@@ -1382,7 +1448,11 @@ const SurveyAssistantToolStep = ({ applyResultsByChangeId, isAborted, part, isLa
|
|
|
1382
1448
|
const changeSet = output === void 0 ? null : getChangeSet(output);
|
|
1383
1449
|
const applyResult = changeSet ? applyResultsByChangeId[changeSet.id] : void 0;
|
|
1384
1450
|
const title = changeSet ? toolName === "survey_expression" ? t("activity.expressionChange") : t("activity.surveyChange") : getToolTitle(t, toolName, part.state);
|
|
1385
|
-
const meta =
|
|
1451
|
+
const meta = terminalTurnStatus && toolStatusMeta[part.state].stepStatus === "active" ? terminalTurnStatus === "aborted" ? getStoppedToolStatusMeta(t) : {
|
|
1452
|
+
icon: /* @__PURE__ */ jsx(XCircleIcon, { className: "size-3 text-red-600" }),
|
|
1453
|
+
label: t("activity.failed"),
|
|
1454
|
+
stepStatus: "complete"
|
|
1455
|
+
} : toolStatusMeta[part.state];
|
|
1386
1456
|
const metaTitle = meta.label ?? (part.state === "output-denied" ? t("activity.skipped") : part.state === "output-error" ? t("activity.failed") : meta.stepStatus === "active" ? t("activity.workingShort") : t("activity.done"));
|
|
1387
1457
|
const [detailsOpen, setDetailsOpen] = useState(part.state === "output-error");
|
|
1388
1458
|
const hasDetails = part.input !== void 0 || output !== void 0 || Boolean(errorText);
|
|
@@ -1508,7 +1578,7 @@ const buildMessageBlocks = (parts) => {
|
|
|
1508
1578
|
flushChain();
|
|
1509
1579
|
return blocks;
|
|
1510
1580
|
};
|
|
1511
|
-
const SurveyAssistantMessageParts = ({ applyResultsByChangeId,
|
|
1581
|
+
const SurveyAssistantMessageParts = ({ applyResultsByChangeId, isLastMessage, isStreaming, message, showProgress, terminalTurnStatus }) => {
|
|
1512
1582
|
const blocks = useMemo(() => buildMessageBlocks(message.parts), [message.parts]);
|
|
1513
1583
|
const persistedDuration = useMemo(() => getPersistedMessageDurationSeconds(message), [message]);
|
|
1514
1584
|
const lastPart = message.parts.at(-1);
|
|
@@ -1522,11 +1592,9 @@ const SurveyAssistantMessageParts = ({ applyResultsByChangeId, isAborted, isLast
|
|
|
1522
1592
|
}, block.key);
|
|
1523
1593
|
return /* @__PURE__ */ jsx("span", { children: block.text }, block.key);
|
|
1524
1594
|
}
|
|
1525
|
-
if (block.type === "file") return /* @__PURE__ */ jsxs("
|
|
1526
|
-
className: "inline-flex max-w-full items-center gap-2 rounded-md border border-border bg-muted px-2 py-1 text-xs
|
|
1527
|
-
|
|
1528
|
-
rel: "noreferrer",
|
|
1529
|
-
target: "_blank",
|
|
1595
|
+
if (block.type === "file") return /* @__PURE__ */ jsxs("span", {
|
|
1596
|
+
className: "inline-flex max-w-full items-center gap-2 rounded-md border border-border bg-muted px-2 py-1 text-xs",
|
|
1597
|
+
title: getFilePartLabel(block.part),
|
|
1530
1598
|
children: [
|
|
1531
1599
|
/* @__PURE__ */ jsx(FileIcon, { className: "size-3.5 shrink-0 text-muted-foreground" }),
|
|
1532
1600
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -1560,6 +1628,7 @@ const SurveyAssistantMessageParts = ({ applyResultsByChangeId, isAborted, isLast
|
|
|
1560
1628
|
className: "w-full rounded-md bg-muted/35 px-2 py-1.5",
|
|
1561
1629
|
defaultDuration: persistedDuration,
|
|
1562
1630
|
defaultOpen: isChainActive,
|
|
1631
|
+
duration: isChainActive ? void 0 : persistedDuration,
|
|
1563
1632
|
isStreaming: isChainActive,
|
|
1564
1633
|
children: [/* @__PURE__ */ jsx(ChainOfThoughtHeader, { className: "text-xs font-medium" }), /* @__PURE__ */ jsxs(ChainOfThoughtContent, {
|
|
1565
1634
|
className: "relative mt-2",
|
|
@@ -1574,9 +1643,9 @@ const SurveyAssistantMessageParts = ({ applyResultsByChangeId, isAborted, isLast
|
|
|
1574
1643
|
}, entry.key);
|
|
1575
1644
|
return /* @__PURE__ */ jsx(SurveyAssistantToolStep, {
|
|
1576
1645
|
applyResultsByChangeId,
|
|
1577
|
-
isAborted,
|
|
1578
1646
|
isLast: isLastEntry,
|
|
1579
|
-
part: entry.part
|
|
1647
|
+
part: entry.part,
|
|
1648
|
+
terminalTurnStatus
|
|
1580
1649
|
}, entry.key);
|
|
1581
1650
|
})]
|
|
1582
1651
|
})]
|
|
@@ -1585,6 +1654,33 @@ const SurveyAssistantMessageParts = ({ applyResultsByChangeId, isAborted, isLast
|
|
|
1585
1654
|
};
|
|
1586
1655
|
const SurveyAssistantTurnOutcomeNotice = (outcome) => {
|
|
1587
1656
|
const t = useSurveyAssistantTranslation();
|
|
1657
|
+
if (outcome.status === "failed" || outcome.status === "aborted") {
|
|
1658
|
+
const reason = (() => {
|
|
1659
|
+
switch (outcome.terminationReason) {
|
|
1660
|
+
case "client-abort": return t("turn.reasons.clientAbort");
|
|
1661
|
+
case "first-response-timeout": return t("turn.reasons.firstResponseTimeout");
|
|
1662
|
+
case "idle-timeout": return t("turn.reasons.idleTimeout");
|
|
1663
|
+
case "max-duration": return t("turn.reasons.maxDuration");
|
|
1664
|
+
case "max-steps": return t("turn.reasons.maxSteps");
|
|
1665
|
+
case "length-limit": return t("turn.reasons.lengthLimit");
|
|
1666
|
+
case "content-filter": return t("turn.reasons.contentFilter");
|
|
1667
|
+
case "provider-error": return t("turn.reasons.providerError");
|
|
1668
|
+
case "stream-error": return t("turn.reasons.streamError");
|
|
1669
|
+
case "incomplete-response": return t("turn.reasons.incompleteResponse");
|
|
1670
|
+
default: return t("turn.reasons.unknown");
|
|
1671
|
+
}
|
|
1672
|
+
})();
|
|
1673
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1674
|
+
className: cn("rounded-lg border px-3 py-2 text-xs", outcome.status === "aborted" ? "border-border bg-muted/50 text-foreground" : "border-destructive/20 bg-destructive/5 text-foreground"),
|
|
1675
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
1676
|
+
className: "font-medium",
|
|
1677
|
+
children: t(outcome.status === "aborted" ? "turn.abortedTitle" : "turn.failedTitle")
|
|
1678
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
1679
|
+
className: "mt-1 text-muted-foreground",
|
|
1680
|
+
children: reason
|
|
1681
|
+
})]
|
|
1682
|
+
});
|
|
1683
|
+
}
|
|
1588
1684
|
const description = outcome.status === "blocked" ? t(outcome.blockedChangeSetCount === 1 ? "changes.blocked" : "changes.blockedPlural", { count: outcome.blockedChangeSetCount }) : t(outcome.appliedChangeSetCount === 1 ? "changes.partial" : "changes.partialPlural", {
|
|
1589
1685
|
applied: outcome.appliedChangeSetCount,
|
|
1590
1686
|
failed: outcome.failedChangeSetCount
|
|
@@ -1642,6 +1738,7 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
1642
1738
|
surveyId,
|
|
1643
1739
|
threadId
|
|
1644
1740
|
});
|
|
1741
|
+
const hasSubmittedMessageRef = useRef((initialMessages?.length ?? 0) > 0);
|
|
1645
1742
|
const showAssistantError = Boolean(authorizationError) || Boolean(error);
|
|
1646
1743
|
const assistantErrorPresentation = getAssistantErrorPresentation(authorizationError ?? error, t);
|
|
1647
1744
|
const selectedModelLabel = models.find((model) => model.id === modelId)?.label ?? modelId ?? t("input.defaultModel");
|
|
@@ -1691,7 +1788,7 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
1691
1788
|
onTurnSettled
|
|
1692
1789
|
]);
|
|
1693
1790
|
const showPendingAssistantRow = isAssistantTurnActive && (!lastMessage || lastMessage.role !== "assistant");
|
|
1694
|
-
const sessionStatusLabel = state === "applying" ? t("status.applying") : state === "applied" ? t("status.applied") : state === "aborted" ? t("status.stopped") : isAssistantTurnActive ? getStreamingProgressLabel(t, lastMessage) : showAssistantError ? t("status.attention") : t("status.ready");
|
|
1791
|
+
const sessionStatusLabel = state === "applying" ? t("status.applying") : state === "applied" ? t("status.applied") : state === "aborted" ? t("status.stopped") : isAssistantTurnActive ? getStreamingProgressLabel(t, lastMessage) : showAssistantError || state === "failed" ? t("status.attention") : t("status.ready");
|
|
1695
1792
|
const handleSubmit = useCallback((message) => {
|
|
1696
1793
|
if (isAssistantTurnActive) return false;
|
|
1697
1794
|
const submittedFromFocusedPrompt = document.activeElement === promptTextareaRef.current;
|
|
@@ -1701,7 +1798,10 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
1701
1798
|
});
|
|
1702
1799
|
if (accepted) {
|
|
1703
1800
|
shouldRestorePromptFocusRef.current = submittedFromFocusedPrompt;
|
|
1704
|
-
|
|
1801
|
+
if (!hasSubmittedMessageRef.current) {
|
|
1802
|
+
hasSubmittedMessageRef.current = true;
|
|
1803
|
+
onFirstSubmit(message.text);
|
|
1804
|
+
}
|
|
1705
1805
|
}
|
|
1706
1806
|
return accepted;
|
|
1707
1807
|
}, [
|
|
@@ -1720,7 +1820,10 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
1720
1820
|
text: initialLaunch.prompt,
|
|
1721
1821
|
uiContext: initialLaunch.uiContext
|
|
1722
1822
|
})) {
|
|
1723
|
-
|
|
1823
|
+
if (!hasSubmittedMessageRef.current) {
|
|
1824
|
+
hasSubmittedMessageRef.current = true;
|
|
1825
|
+
onFirstSubmit(initialLaunch.prompt);
|
|
1826
|
+
}
|
|
1724
1827
|
onInitialLaunchHandled();
|
|
1725
1828
|
}
|
|
1726
1829
|
}, [
|
|
@@ -1736,7 +1839,7 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
1736
1839
|
/* @__PURE__ */ jsxs("header", {
|
|
1737
1840
|
className: "box-content flex h-9 shrink-0 items-center justify-between gap-2 border-b border-border bg-muted/20 px-2.5",
|
|
1738
1841
|
children: [/* @__PURE__ */ jsx(SurveyAssistantHeaderIdentity, {
|
|
1739
|
-
indicatorClassName: showAssistantError ? "bg-destructive" : isAssistantTurnActive ? "animate-pulse bg-blue-500" : state === "aborted" ? "bg-muted-foreground" : "bg-emerald-500",
|
|
1842
|
+
indicatorClassName: showAssistantError || state === "failed" ? "bg-destructive" : isAssistantTurnActive ? "animate-pulse bg-blue-500" : state === "aborted" ? "bg-muted-foreground" : "bg-emerald-500",
|
|
1740
1843
|
status: sessionStatusLabel,
|
|
1741
1844
|
title: threadTitle
|
|
1742
1845
|
}), threadControls]
|
|
@@ -1791,6 +1894,8 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
1791
1894
|
})
|
|
1792
1895
|
}) : /* @__PURE__ */ jsxs(Fragment, { children: [messages.map((message, index) => {
|
|
1793
1896
|
const isLastMessage = index === messages.length - 1;
|
|
1897
|
+
const persistedTurnStatus = getPersistedMessageTurnStatus(message);
|
|
1898
|
+
const terminalTurnStatus = persistedTurnStatus === "aborted" || persistedTurnStatus === "failed" ? persistedTurnStatus : isLastMessage && (state === "aborted" || state === "failed") ? state : void 0;
|
|
1794
1899
|
const shouldShowProgress = isAssistantTurnActive && isLastMessage && message.role === "assistant";
|
|
1795
1900
|
return /* @__PURE__ */ jsx(Message, {
|
|
1796
1901
|
className: "max-w-[96%] gap-1",
|
|
@@ -1799,17 +1904,17 @@ const SurveyAssistantChatPanel = ({ api, applyPolicy, controller, embedded = fal
|
|
|
1799
1904
|
className: cn(message.role === "assistant" && "w-full space-y-2"),
|
|
1800
1905
|
children: hasRenderableParts(message) ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(SurveyAssistantMessageParts, {
|
|
1801
1906
|
applyResultsByChangeId,
|
|
1802
|
-
isAborted: state === "aborted",
|
|
1803
1907
|
isLastMessage,
|
|
1804
1908
|
isStreaming: isAssistantTurnActive,
|
|
1805
1909
|
message,
|
|
1806
|
-
showProgress: shouldShowProgress
|
|
1807
|
-
|
|
1910
|
+
showProgress: shouldShowProgress,
|
|
1911
|
+
terminalTurnStatus
|
|
1912
|
+
}), isLastMessage && latestTurnOutcome && /* @__PURE__ */ jsx(SurveyAssistantTurnOutcomeNotice, { ...latestTurnOutcome })] }) : shouldShowProgress ? /* @__PURE__ */ jsx(SurveyAssistantProgressIndicator, { message }) : isLastMessage && latestTurnOutcome ? /* @__PURE__ */ jsx(SurveyAssistantTurnOutcomeNotice, { ...latestTurnOutcome }) : state === "aborted" ? /* @__PURE__ */ jsx("span", {
|
|
1808
1913
|
className: "text-muted-foreground text-sm",
|
|
1809
1914
|
children: t("conversation.stopped")
|
|
1810
1915
|
}) : /* @__PURE__ */ jsx("span", {
|
|
1811
1916
|
className: "text-muted-foreground text-sm",
|
|
1812
|
-
children: t("conversation.
|
|
1917
|
+
children: t("conversation.incomplete")
|
|
1813
1918
|
})
|
|
1814
1919
|
})
|
|
1815
1920
|
}, message.id);
|
|
@@ -1924,7 +2029,7 @@ const createThreadTitle = (text, fallback) => {
|
|
|
1924
2029
|
const words = normalized.split(" ").slice(0, 8).join(" ");
|
|
1925
2030
|
return words.length > 64 ? `${words.slice(0, 61).trimEnd()}...` : words;
|
|
1926
2031
|
};
|
|
1927
|
-
const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], onConfirmDeleteThread, onModelChange = () => {}, resourceId, selectedThreadStorageKey, surveyId, threadApi, threadClient: providedThreadClient, threadLauncher, ...sessionProps }) => {
|
|
2032
|
+
const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], onConfirmDeleteThread, onModelChange = () => {}, onTurnActiveChange: onAssistantTurnActiveChange, resourceId, selectedThreadStorageKey, surveyId, threadApi, threadClient: providedThreadClient, threadLauncher, ...sessionProps }) => {
|
|
1928
2033
|
const t = useSurveyAssistantTranslation();
|
|
1929
2034
|
const threadClient = useMemo(() => providedThreadClient ?? createSurveyAssistantThreadClient(threadApi), [providedThreadClient, threadApi]);
|
|
1930
2035
|
const storageKey = selectedThreadStorageKey === false ? null : selectedThreadStorageKey ?? `${SELECTED_THREAD_STORAGE_KEY}:${encodeURIComponent(resourceId)}${surveyId ? `:${encodeURIComponent(surveyId)}` : ""}`;
|
|
@@ -1936,6 +2041,7 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
1936
2041
|
const [editingTitle, setEditingTitle] = useState("");
|
|
1937
2042
|
const [threadError, setThreadError] = useState(null);
|
|
1938
2043
|
const [loadingThread, setLoadingThread] = useState(true);
|
|
2044
|
+
const [assistantTurnActive, setAssistantTurnActive] = useState(false);
|
|
1939
2045
|
const [initialLaunch, setInitialLaunch] = useState();
|
|
1940
2046
|
const historyControlsRef = useRef(null);
|
|
1941
2047
|
const selectModel = useCallback((modelId) => {
|
|
@@ -2062,6 +2168,14 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2062
2168
|
setEditingThreadId(null);
|
|
2063
2169
|
setEditingTitle("");
|
|
2064
2170
|
}, []);
|
|
2171
|
+
const handleTurnActiveChange = useCallback((active) => {
|
|
2172
|
+
setAssistantTurnActive(active);
|
|
2173
|
+
onAssistantTurnActiveChange?.(active);
|
|
2174
|
+
if (active) {
|
|
2175
|
+
cancelEditingThread();
|
|
2176
|
+
setHistoryOpen(false);
|
|
2177
|
+
}
|
|
2178
|
+
}, [cancelEditingThread, onAssistantTurnActiveChange]);
|
|
2065
2179
|
const commitEditingThread = useCallback(async () => {
|
|
2066
2180
|
if (!editingThreadId) return;
|
|
2067
2181
|
const thread = threads.find((item) => item.id === editingThreadId);
|
|
@@ -2094,10 +2208,9 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2094
2208
|
threads
|
|
2095
2209
|
]);
|
|
2096
2210
|
const handleFirstSubmit = useCallback((text) => {
|
|
2097
|
-
if (!selectedThread ||
|
|
2211
|
+
if (!selectedThread || selectedThread.titleMode === "manual") return;
|
|
2098
2212
|
setAutomaticTitle(selectedThread, createThreadTitle(text, t("threads.newChat")));
|
|
2099
2213
|
}, [
|
|
2100
|
-
initialMessages.length,
|
|
2101
2214
|
selectedThread,
|
|
2102
2215
|
setAutomaticTitle,
|
|
2103
2216
|
t
|
|
@@ -2193,7 +2306,8 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2193
2306
|
children: [
|
|
2194
2307
|
/* @__PURE__ */ jsx("button", {
|
|
2195
2308
|
"aria-label": t("threads.newChat"),
|
|
2196
|
-
className: "flex size-8 items-center justify-center rounded-lg text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
2309
|
+
className: "flex size-8 items-center justify-center rounded-lg text-muted-foreground hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-50",
|
|
2310
|
+
disabled: assistantTurnActive,
|
|
2197
2311
|
onClick: () => void createThread(),
|
|
2198
2312
|
title: t("threads.newChat"),
|
|
2199
2313
|
type: "button",
|
|
@@ -2202,7 +2316,8 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2202
2316
|
/* @__PURE__ */ jsx("button", {
|
|
2203
2317
|
"aria-expanded": historyOpen,
|
|
2204
2318
|
"aria-label": t("threads.history"),
|
|
2205
|
-
className: "flex size-8 items-center justify-center rounded-lg text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
2319
|
+
className: "flex size-8 items-center justify-center rounded-lg text-muted-foreground hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-50",
|
|
2320
|
+
disabled: assistantTurnActive,
|
|
2206
2321
|
onClick: toggleHistory,
|
|
2207
2322
|
title: t("threads.history"),
|
|
2208
2323
|
type: "button",
|
|
@@ -2286,6 +2401,7 @@ const SurveyAssistantPanelContent = ({ embedded = false, modelId, models = [], o
|
|
|
2286
2401
|
onModelChange: selectModel,
|
|
2287
2402
|
onFirstSubmit: handleFirstSubmit,
|
|
2288
2403
|
onTurnSettled: handleTurnSettled,
|
|
2404
|
+
onTurnActiveChange: handleTurnActiveChange,
|
|
2289
2405
|
resourceId,
|
|
2290
2406
|
surveyId,
|
|
2291
2407
|
threadControls,
|