@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
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as applySurveyAssistantLaunchUIContext, l as readSurveyAssistantJson } from "./controller-proxy-
|
|
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-DATvkr1S.mjs";
|
|
2
|
+
import { a as applySurveyAssistantLaunchUIContext, l as readSurveyAssistantJson } from "./controller-proxy-DY36XFV3.mjs";
|
|
3
3
|
import { DefaultChatTransport } from "ai";
|
|
4
4
|
import { useCallback, useEffect, useEffectEvent, useMemo, useReducer, useRef, useState } from "react";
|
|
5
5
|
import { useChat } from "@ai-sdk/react";
|
|
@@ -99,6 +99,10 @@ const resolveLatestSurveyTurnAuthorization = (messages) => {
|
|
|
99
99
|
};
|
|
100
100
|
};
|
|
101
101
|
const resolveSurveyTurnOutcome = ({ applyResultsByChangeId, authorization }) => {
|
|
102
|
+
if (authorization.status === "failed" || authorization.status === "aborted") return {
|
|
103
|
+
status: authorization.status,
|
|
104
|
+
terminationReason: authorization.turnFinal.terminationReason
|
|
105
|
+
};
|
|
102
106
|
if (authorization.status !== "completed") return null;
|
|
103
107
|
const blockedChangeSetCount = authorization.turnFinal.blockedChangeSetIds?.length ?? 0;
|
|
104
108
|
if (blockedChangeSetCount > 0) return {
|
|
@@ -312,6 +316,30 @@ const writeSettledDocumentVersion = ({ resourceId, snapshot, threadId }) => {
|
|
|
312
316
|
const createLocalId = (prefix) => {
|
|
313
317
|
return `${prefix}-${globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2)}`;
|
|
314
318
|
};
|
|
319
|
+
const compactOutcomeText = (value, maximum, fallback) => {
|
|
320
|
+
const normalized = value.trim() || fallback;
|
|
321
|
+
return normalized.length > maximum ? `${normalized.slice(0, maximum - 1)}…` : normalized;
|
|
322
|
+
};
|
|
323
|
+
const createApplyOutcome = ({ message, preparedChanges, results, status, turnId }) => surveyAssistantApplyOutcomeSchema.parse({
|
|
324
|
+
protocolVersion: 1,
|
|
325
|
+
turnId,
|
|
326
|
+
status,
|
|
327
|
+
message: compactOutcomeText(message, 2e3, "No lifecycle detail was reported."),
|
|
328
|
+
...results && results.length > 0 ? { results: results.slice(0, 100).map((result) => ({
|
|
329
|
+
status: result.status,
|
|
330
|
+
changeId: compactOutcomeText(result.changeId, 240, "unknown-change"),
|
|
331
|
+
summary: compactOutcomeText(result.summary, 500, "Survey change"),
|
|
332
|
+
message: compactOutcomeText(result.message, 2e3, "No apply detail was reported."),
|
|
333
|
+
appliedOperations: result.appliedOperations
|
|
334
|
+
})) } : {},
|
|
335
|
+
...preparedChanges && preparedChanges.length > 0 ? { preparedChanges: preparedChanges.slice(-24).map((change) => ({
|
|
336
|
+
changeId: compactOutcomeText(change.id, 240, "unknown-change"),
|
|
337
|
+
status: change.status,
|
|
338
|
+
summary: compactOutcomeText(change.summary, 500, "Survey change"),
|
|
339
|
+
operationCount: change.operations.length
|
|
340
|
+
})) } : {},
|
|
341
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
342
|
+
});
|
|
315
343
|
const getAssistantTextParts = (message) => message.parts.filter((part) => part.type === "text" && part.text.trim().length > 0);
|
|
316
344
|
const findLastAssistantTextMessageIndex = (messages, endExclusive = messages.length) => {
|
|
317
345
|
for (let index = Math.min(messages.length, endExclusive) - 1; index >= 0; index -= 1) {
|
|
@@ -338,6 +366,13 @@ const collectChangeSetsAfterLastUser = (messages) => {
|
|
|
338
366
|
const lastUserIndex = findLastUserMessageIndex(messages);
|
|
339
367
|
return lastUserIndex < 0 ? [] : collectSurveyChangeSets(messages.slice(lastUserIndex + 1));
|
|
340
368
|
};
|
|
369
|
+
const getInitialSessionState = (messages) => {
|
|
370
|
+
if (messages.length === 0) return "idle";
|
|
371
|
+
const authorization = resolveLatestSurveyTurnAuthorization(messages);
|
|
372
|
+
if (authorization.status === "failed") return "failed";
|
|
373
|
+
if (authorization.status === "aborted") return "aborted";
|
|
374
|
+
return "completed";
|
|
375
|
+
};
|
|
341
376
|
const resolveSurveyAssistantReviewDecision = async ({ changeSets, onReviewChangeSets, turnFinal }) => {
|
|
342
377
|
if (!onReviewChangeSets) throw new Error("No survey assistant review adapter is available.");
|
|
343
378
|
return onReviewChangeSets(changeSets, turnFinal);
|
|
@@ -347,7 +382,8 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
347
382
|
const [localThreadId] = useState(() => createLocalId("survey-assistant-local-thread"));
|
|
348
383
|
const resourceId = controlledResourceId ?? localResourceId;
|
|
349
384
|
const threadId = controlledThreadId ?? localThreadId;
|
|
350
|
-
const
|
|
385
|
+
const applyOutcomeScopeKey = `${resourceId}\u0000${threadId}`;
|
|
386
|
+
const [state, dispatch] = useReducer(reduceSurveyAssistantSessionState, initialMessages, getInitialSessionState);
|
|
351
387
|
const [applyResultsByChangeId, setApplyResultsByChangeId] = useState({});
|
|
352
388
|
const [authorizationError, setAuthorizationError] = useState(null);
|
|
353
389
|
const handledTurnIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
@@ -355,6 +391,7 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
355
391
|
const localTurnStreamStartedRef = useRef(false);
|
|
356
392
|
const captureSettledVersionRef = useRef(false);
|
|
357
393
|
const lastSubmittedUIContextRef = useRef(void 0);
|
|
394
|
+
const previousApplyOutcomesRef = useRef(/* @__PURE__ */ new Map());
|
|
358
395
|
const { messages, setMessages, sendMessage, status, stop: stopChat, error, clearError, regenerate } = useChat({
|
|
359
396
|
id: threadId,
|
|
360
397
|
messages: initialMessages,
|
|
@@ -440,11 +477,44 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
440
477
|
const { turnFinal } = turnAuthorization;
|
|
441
478
|
if (handledTurnIdsRef.current.has(turnFinal.turnId)) return;
|
|
442
479
|
handledTurnIdsRef.current.add(turnFinal.turnId);
|
|
443
|
-
|
|
480
|
+
const preparedChanges = collectChangeSetsAfterLastUser(messages).filter((change) => change.turnId === turnFinal.turnId);
|
|
481
|
+
if (turnAuthorization.status === "failed") {
|
|
482
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
483
|
+
turnId: turnFinal.turnId,
|
|
484
|
+
status: "not-applied",
|
|
485
|
+
message: "The previous assistant turn failed before editor authorization. Every request-scoped draft change from that turn was discarded and was not applied.",
|
|
486
|
+
preparedChanges
|
|
487
|
+
}));
|
|
488
|
+
dispatch({ type: "failed" });
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
if (turnAuthorization.status === "aborted") {
|
|
492
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
493
|
+
turnId: turnFinal.turnId,
|
|
494
|
+
status: "not-applied",
|
|
495
|
+
message: "The previous assistant turn was interrupted before editor authorization. Every request-scoped draft change from that turn was discarded and was not applied.",
|
|
496
|
+
preparedChanges
|
|
497
|
+
}));
|
|
498
|
+
dispatch({ type: "aborted" });
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
if (turnAuthorization.changeSets.length === 0) {
|
|
502
|
+
if ((turnFinal.blockedChangeSetIds?.length ?? 0) > 0) previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
503
|
+
turnId: turnFinal.turnId,
|
|
504
|
+
status: "not-applied",
|
|
505
|
+
message: "The previous assistant turn ended with unresolved rejected changes. No request-scoped draft change from that turn was authorized or applied.",
|
|
506
|
+
preparedChanges
|
|
507
|
+
}));
|
|
444
508
|
dispatch({ type: "completed" });
|
|
445
509
|
return;
|
|
446
510
|
}
|
|
447
511
|
if (applyPolicy === "deny") {
|
|
512
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
513
|
+
turnId: turnFinal.turnId,
|
|
514
|
+
status: "not-applied",
|
|
515
|
+
message: "The host apply policy did not authorize editor mutations for this turn.",
|
|
516
|
+
preparedChanges
|
|
517
|
+
}));
|
|
448
518
|
dispatch({ type: "completed" });
|
|
449
519
|
return;
|
|
450
520
|
}
|
|
@@ -459,21 +529,48 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
459
529
|
turnFinal
|
|
460
530
|
});
|
|
461
531
|
} catch (error) {
|
|
462
|
-
|
|
532
|
+
const message = error instanceof Error && error.message === "No survey assistant review adapter is available." ? error.message : "The survey assistant review could not be completed.";
|
|
533
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
534
|
+
turnId: turnFinal.turnId,
|
|
535
|
+
status: "not-applied",
|
|
536
|
+
message,
|
|
537
|
+
preparedChanges
|
|
538
|
+
}));
|
|
539
|
+
reportAuthorizationError(message);
|
|
463
540
|
return;
|
|
464
541
|
}
|
|
465
542
|
if (!approved) {
|
|
543
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
544
|
+
turnId: turnFinal.turnId,
|
|
545
|
+
status: "not-applied",
|
|
546
|
+
message: "The proposed editor changes were not approved during review.",
|
|
547
|
+
preparedChanges
|
|
548
|
+
}));
|
|
466
549
|
dispatch({ type: "completed" });
|
|
467
550
|
return;
|
|
468
551
|
}
|
|
469
552
|
}
|
|
470
553
|
if (!controller?.applyAssistantChange && !controller?.applyAssistantChanges) {
|
|
471
|
-
|
|
554
|
+
const message = "No survey editor apply adapter is available.";
|
|
555
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
556
|
+
turnId: turnFinal.turnId,
|
|
557
|
+
status: "apply-failed",
|
|
558
|
+
message,
|
|
559
|
+
preparedChanges
|
|
560
|
+
}));
|
|
561
|
+
reportAuthorizationError(message);
|
|
472
562
|
return;
|
|
473
563
|
}
|
|
474
564
|
const beforeSnapshot = controller.getSnapshot();
|
|
475
565
|
if (!beforeSnapshot) {
|
|
476
|
-
|
|
566
|
+
const message = "The editor state was unavailable when applying the assistant change.";
|
|
567
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
568
|
+
turnId: turnFinal.turnId,
|
|
569
|
+
status: "apply-failed",
|
|
570
|
+
message,
|
|
571
|
+
preparedChanges
|
|
572
|
+
}));
|
|
573
|
+
reportAuthorizationError(message);
|
|
477
574
|
return;
|
|
478
575
|
}
|
|
479
576
|
const result = controller.applyAssistantChanges?.(turnAuthorization.changeSets) ?? { results: turnAuthorization.changeSets.map((change) => controller.applyAssistantChange?.(change)).filter((applyResult) => Boolean(applyResult)) };
|
|
@@ -490,6 +587,13 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
490
587
|
});
|
|
491
588
|
onApplyReceipts?.(receipts);
|
|
492
589
|
if (!result.results.every((applyResult) => applyResult.status === "applied")) {
|
|
590
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
591
|
+
turnId: turnFinal.turnId,
|
|
592
|
+
status: "apply-failed",
|
|
593
|
+
message: "One or more authorized survey changes could not be applied to the editor.",
|
|
594
|
+
preparedChanges,
|
|
595
|
+
results: result.results
|
|
596
|
+
}));
|
|
493
597
|
dispatch({ type: "completed" });
|
|
494
598
|
return;
|
|
495
599
|
}
|
|
@@ -499,19 +603,29 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
499
603
|
receipts,
|
|
500
604
|
turnFinal
|
|
501
605
|
});
|
|
606
|
+
previousApplyOutcomesRef.current.delete(applyOutcomeScopeKey);
|
|
502
607
|
dispatch({ type: "applied" });
|
|
503
608
|
} catch {
|
|
504
|
-
|
|
609
|
+
const message = "The assistant changes were applied locally but could not be settled by the host.";
|
|
610
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
611
|
+
turnId: turnFinal.turnId,
|
|
612
|
+
status: "settle-failed",
|
|
613
|
+
message,
|
|
614
|
+
results: result.results
|
|
615
|
+
}));
|
|
616
|
+
reportAuthorizationError(message);
|
|
505
617
|
}
|
|
506
618
|
})();
|
|
507
619
|
}, [
|
|
508
620
|
applyPolicy,
|
|
621
|
+
applyOutcomeScopeKey,
|
|
509
622
|
controller,
|
|
510
623
|
isStreaming,
|
|
511
624
|
onApplyReceipts,
|
|
512
625
|
onReviewChangeSets,
|
|
513
626
|
onSettleApply,
|
|
514
627
|
reportAuthorizationError,
|
|
628
|
+
messages,
|
|
515
629
|
turnAuthorization
|
|
516
630
|
]);
|
|
517
631
|
useEffect(() => {
|
|
@@ -547,11 +661,13 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
547
661
|
resourceId,
|
|
548
662
|
threadId
|
|
549
663
|
}),
|
|
664
|
+
previousApplyOutcome: previousApplyOutcomesRef.current.get(applyOutcomeScopeKey),
|
|
550
665
|
...modelId ? { modelId } : {}
|
|
551
666
|
} });
|
|
552
667
|
return true;
|
|
553
668
|
}, [
|
|
554
669
|
authorizationError,
|
|
670
|
+
applyOutcomeScopeKey,
|
|
555
671
|
clearError,
|
|
556
672
|
controller,
|
|
557
673
|
error,
|
|
@@ -583,9 +699,11 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
583
699
|
resourceId,
|
|
584
700
|
threadId
|
|
585
701
|
}),
|
|
702
|
+
previousApplyOutcome: previousApplyOutcomesRef.current.get(applyOutcomeScopeKey),
|
|
586
703
|
...modelId ? { modelId } : {}
|
|
587
704
|
} });
|
|
588
705
|
}, [
|
|
706
|
+
applyOutcomeScopeKey,
|
|
589
707
|
clearError,
|
|
590
708
|
controller,
|
|
591
709
|
modelId,
|
|
@@ -625,4 +743,4 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
625
743
|
//#endregion
|
|
626
744
|
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 };
|
|
627
745
|
|
|
628
|
-
//# sourceMappingURL=react-
|
|
746
|
+
//# sourceMappingURL=react-3kSE6WtS.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-3kSE6WtS.mjs","names":["findLastUserMessageIndex"],"sources":["../src/react/session-state.ts","../src/react/turn-authorization.ts","../src/react/transport.ts","../src/react/thread-client.ts","../src/react/model-catalog.ts","../src/react/document-baseline.ts","../src/react/use-survey-assistant-session.ts"],"sourcesContent":["export type SurveyAssistantSessionState =\n | \"idle\"\n | \"submitting\"\n | \"streaming\"\n | \"completed\"\n | \"failed\"\n | \"aborted\"\n | \"applying\"\n | \"applied\";\n\nexport type SurveyAssistantSessionEvent =\n | { type: \"submit\" }\n | { type: \"stream-started\" }\n | { type: \"completed\" }\n | { type: \"apply-started\" }\n | { type: \"applied\" }\n | { type: \"failed\" }\n | { type: \"aborted\" }\n | { type: \"reset\"; hasTranscript: boolean };\n\nexport const isSurveyAssistantTurnActive = ({\n isStreaming,\n state,\n}: {\n isStreaming: boolean;\n state: SurveyAssistantSessionState;\n}): boolean =>\n state !== \"aborted\" &&\n (isStreaming || state === \"submitting\" || state === \"streaming\" || state === \"applying\");\n\nexport const reduceSurveyAssistantSessionState = (\n _state: SurveyAssistantSessionState,\n event: SurveyAssistantSessionEvent,\n): SurveyAssistantSessionState => {\n switch (event.type) {\n case \"submit\":\n return \"submitting\";\n case \"stream-started\":\n return \"streaming\";\n case \"completed\":\n return \"completed\";\n case \"apply-started\":\n return \"applying\";\n case \"applied\":\n return \"applied\";\n case \"failed\":\n return \"failed\";\n case \"aborted\":\n return \"aborted\";\n case \"reset\":\n return event.hasTranscript ? \"completed\" : \"idle\";\n }\n};\n","import {\n SURVEY_ASSISTANT_PROTOCOL_VERSION,\n SURVEY_ASSISTANT_TURN_FINAL_PART_TYPE,\n applyReceiptSchema,\n surveyAssistantTurnFinalSchema,\n surveyChangeSetSchema,\n type ApplyReceipt,\n type SurveyAssistantSnapshot,\n type SurveyAssistantTurnFinal,\n type SurveyApplyResult,\n type SurveyChangeSet,\n type SurveyDocumentVersion,\n} from \"../protocol\";\nimport type { UIMessage } from \"ai\";\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isCompletedToolPart = (\n part: UIMessage[\"parts\"][number],\n): part is UIMessage[\"parts\"][number] & { state: \"output-available\"; output: unknown } =>\n (part.type === \"dynamic-tool\" || part.type.startsWith(\"tool-\")) &&\n \"state\" in part &&\n part.state === \"output-available\" &&\n \"output\" in part;\n\nexport const unwrapSurveyAssistantToolOutput = (output: unknown) => {\n if (isRecord(output) && \"output\" in output && output.output !== undefined) {\n return output.output;\n }\n return output;\n};\n\nexport const parseSurveyChangeSet = (output: unknown): SurveyChangeSet | null => {\n const parsed = surveyChangeSetSchema.safeParse(unwrapSurveyAssistantToolOutput(output));\n return parsed.success ? parsed.data : null;\n};\n\nexport const collectSurveyChangeSets = (messages: UIMessage[]): SurveyChangeSet[] => {\n const changes: SurveyChangeSet[] = [];\n for (const message of messages) {\n for (const part of message.parts) {\n if (!isCompletedToolPart(part)) {\n continue;\n }\n const change = parseSurveyChangeSet(part.output);\n if (change) {\n changes.push(change);\n }\n }\n }\n return changes;\n};\n\nconst findLastUserMessageIndex = (messages: UIMessage[]) => {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n if (messages[index]?.role === \"user\") return index;\n }\n return -1;\n};\n\nexport type SurveyTurnAuthorization =\n | { status: \"pending\" }\n | { status: \"invalid\"; reason: string; turnId?: string }\n | {\n status: \"failed\" | \"aborted\";\n turnFinal: SurveyAssistantTurnFinal;\n changeSets: [];\n }\n | {\n status: \"completed\";\n turnFinal: SurveyAssistantTurnFinal;\n changeSets: SurveyChangeSet[];\n };\n\nexport type SurveyTurnOutcome =\n | {\n status: \"failed\";\n terminationReason?: SurveyAssistantTurnFinal[\"terminationReason\"];\n }\n | {\n status: \"aborted\";\n terminationReason?: SurveyAssistantTurnFinal[\"terminationReason\"];\n }\n | {\n status: \"blocked\";\n blockedChangeSetCount: number;\n }\n | {\n status: \"apply-failed\";\n appliedChangeSetCount: number;\n failedChangeSetCount: number;\n };\n\nexport const resolveLatestSurveyTurnAuthorization = (\n messages: UIMessage[],\n): SurveyTurnAuthorization => {\n const lastUserIndex = findLastUserMessageIndex(messages);\n if (lastUserIndex < 0) {\n return { status: \"pending\" };\n }\n\n const turnMessages = messages.slice(lastUserIndex + 1);\n const finalParts = turnMessages\n .flatMap((message) => message.parts)\n .filter((part) => part.type === SURVEY_ASSISTANT_TURN_FINAL_PART_TYPE);\n if (finalParts.length === 0) {\n return { status: \"pending\" };\n }\n if (finalParts.length !== 1) {\n return { status: \"invalid\", reason: \"The assistant returned multiple turn finals.\" };\n }\n\n const finalPart = finalParts[0];\n const finalParse = surveyAssistantTurnFinalSchema.safeParse(\n finalPart && \"data\" in finalPart ? finalPart.data : undefined,\n );\n if (!finalParse.success) {\n return { status: \"invalid\", reason: \"The assistant returned an invalid turn final.\" };\n }\n const turnFinal = finalParse.data;\n if (turnFinal.status !== \"completed\") {\n return { status: turnFinal.status, turnFinal, changeSets: [] };\n }\n\n const candidates = collectSurveyChangeSets(turnMessages).filter(\n (change) => change.turnId === turnFinal.turnId,\n );\n const candidatesById = new Map<string, SurveyChangeSet>();\n for (const candidate of candidates) {\n if (candidatesById.has(candidate.id)) {\n return {\n status: \"invalid\",\n turnId: turnFinal.turnId,\n reason: `The assistant returned duplicate change set \"${candidate.id}\".`,\n };\n }\n candidatesById.set(candidate.id, candidate);\n }\n\n for (const blockedChangeSetId of turnFinal.blockedChangeSetIds ?? []) {\n const candidate = candidatesById.get(blockedChangeSetId);\n if (!candidate || candidate.status !== \"rejected\" || candidate.validation.valid) {\n return {\n status: \"invalid\",\n turnId: turnFinal.turnId,\n reason: `The assistant did not provide blocked change set \"${blockedChangeSetId}\".`,\n };\n }\n }\n\n const changeSets: SurveyChangeSet[] = [];\n for (const changeSetId of turnFinal.executableChangeSetIds) {\n const candidate = candidatesById.get(changeSetId);\n if (!candidate || candidate.status !== \"validated\" || !candidate.validation.valid) {\n return {\n status: \"invalid\",\n turnId: turnFinal.turnId,\n reason: `The assistant did not provide authorized change set \"${changeSetId}\".`,\n };\n }\n changeSets.push(candidate);\n }\n\n return { status: \"completed\", turnFinal, changeSets };\n};\n\nexport const resolveSurveyTurnOutcome = ({\n applyResultsByChangeId,\n authorization,\n}: {\n applyResultsByChangeId: Record<string, SurveyApplyResult>;\n authorization: SurveyTurnAuthorization;\n}): SurveyTurnOutcome | null => {\n if (authorization.status === \"failed\" || authorization.status === \"aborted\") {\n return {\n status: authorization.status,\n terminationReason: authorization.turnFinal.terminationReason,\n };\n }\n if (authorization.status !== \"completed\") {\n return null;\n }\n\n const blockedChangeSetCount = authorization.turnFinal.blockedChangeSetIds?.length ?? 0;\n if (blockedChangeSetCount > 0) {\n return { status: \"blocked\", blockedChangeSetCount };\n }\n\n if (authorization.changeSets.length === 0) {\n return null;\n }\n\n const results = authorization.changeSets.map((change) => applyResultsByChangeId[change.id]);\n if (results.some((result) => result === undefined)) {\n return null;\n }\n\n const failedChangeSetCount = results.filter((result) => result.status !== \"applied\").length;\n if (failedChangeSetCount === 0) {\n return null;\n }\n\n return {\n status: \"apply-failed\",\n appliedChangeSetCount: results.length - failedChangeSetCount,\n failedChangeSetCount,\n };\n};\n\nexport const getSurveyDocumentVersionFromSnapshot = (\n snapshot: SurveyAssistantSnapshot,\n): SurveyDocumentVersion => ({ ...snapshot.version });\n\nexport const createApplyReceipts = ({\n afterSnapshot,\n beforeSnapshot,\n changeSets,\n results,\n turnFinal,\n createdAt = new Date().toISOString(),\n}: {\n afterSnapshot: SurveyAssistantSnapshot | null;\n beforeSnapshot: SurveyAssistantSnapshot;\n changeSets: SurveyChangeSet[];\n results: SurveyApplyResult[];\n turnFinal: SurveyAssistantTurnFinal;\n createdAt?: string;\n}): ApplyReceipt[] => {\n const beforeVersion = getSurveyDocumentVersionFromSnapshot(beforeSnapshot);\n const afterVersion = afterSnapshot\n ? getSurveyDocumentVersionFromSnapshot(afterSnapshot)\n : undefined;\n const resultsByChangeId = new Map(results.map((result) => [result.changeId, result]));\n\n return changeSets.map((changeSet) => {\n const result = resultsByChangeId.get(changeSet.id);\n const status = result?.status ?? \"failed\";\n return applyReceiptSchema.parse({\n protocolVersion: SURVEY_ASSISTANT_PROTOCOL_VERSION,\n turnId: turnFinal.turnId,\n changeSetId: changeSet.id,\n beforeVersion,\n ...(status === \"applied\" && afterVersion ? { afterVersion } : {}),\n status,\n operationCount: changeSet.operations.length,\n ...(status === \"applied\" && afterVersion?.historyIndex !== undefined\n ? { commit: { index: afterVersion.historyIndex } }\n : {}),\n ...(result?.issues ? { issues: result.issues } : {}),\n createdAt,\n });\n });\n};\n","import { DefaultChatTransport, type UIMessage } from \"ai\";\n\nconst findLastUserMessage = (messages: UIMessage[]): UIMessage | undefined => {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n if (messages[index]?.role === \"user\") return messages[index];\n }\n return undefined;\n};\n\nexport const createSurveyAssistantTransport = ({\n api = \"/api/survey-assistant/chat\",\n resourceId,\n surveyId,\n threadId,\n}: {\n api?: string;\n resourceId: string;\n surveyId?: string;\n threadId: string;\n}) =>\n new DefaultChatTransport({\n api,\n body: { resourceId, ...(surveyId ? { surveyId } : {}), threadId },\n prepareSendMessagesRequest: ({\n api,\n body,\n credentials,\n headers,\n id,\n messageId,\n messages,\n trigger,\n }) => {\n const latestUserMessage = findLastUserMessage(messages);\n return {\n api,\n credentials,\n headers,\n body: {\n ...body,\n id,\n messages: latestUserMessage ? [latestUserMessage] : [],\n trigger,\n messageId,\n },\n };\n },\n });\n","import {\n surveyAssistantThreadListSchema,\n surveyAssistantThreadSchema,\n surveyAssistantThreadTranscriptSchema,\n type SurveyAssistantThread,\n type SurveyAssistantThreadTranscript,\n} from \"../protocol\";\nimport { readSurveyAssistantJson } from \"./client-error\";\n\nexport interface SurveyAssistantThreadClient {\n delete(threadId: string): Promise<void>;\n create(title?: string): Promise<SurveyAssistantThread>;\n list(): Promise<SurveyAssistantThread[]>;\n read(threadId: string): Promise<SurveyAssistantThreadTranscript>;\n rename(threadId: string, title: string): Promise<SurveyAssistantThread>;\n setAutomaticTitle(threadId: string, title?: string): Promise<SurveyAssistantThread>;\n}\n\nexport const createSurveyAssistantThreadClient = (\n api = \"/api/survey-assistant/threads\",\n): SurveyAssistantThreadClient => ({\n async delete(threadId) {\n const response = await fetch(`${api}/${encodeURIComponent(threadId)}`, { method: \"DELETE\" });\n if (!response.ok) await readSurveyAssistantJson(response);\n },\n async create(title) {\n const body = await readSurveyAssistantJson(\n await fetch(api, {\n body: JSON.stringify(title ? { title } : {}),\n headers: { \"content-type\": \"application/json\" },\n method: \"POST\",\n }),\n );\n return surveyAssistantThreadSchema.parse(body.thread);\n },\n async list() {\n const body = await readSurveyAssistantJson(await fetch(api, { cache: \"no-store\" }));\n return surveyAssistantThreadListSchema.parse(body).threads;\n },\n async read(threadId) {\n const body = await readSurveyAssistantJson(\n await fetch(`${api}/${encodeURIComponent(threadId)}`, { cache: \"no-store\" }),\n );\n return surveyAssistantThreadTranscriptSchema.parse(body);\n },\n async rename(threadId, title) {\n const body = await readSurveyAssistantJson(\n await fetch(`${api}/${encodeURIComponent(threadId)}`, {\n body: JSON.stringify({ mode: \"manual\", title }),\n headers: { \"content-type\": \"application/json\" },\n method: \"PATCH\",\n }),\n );\n return surveyAssistantThreadSchema.parse(body.thread);\n },\n async setAutomaticTitle(threadId, title) {\n const body = await readSurveyAssistantJson(\n await fetch(`${api}/${encodeURIComponent(threadId)}`, {\n body: JSON.stringify({ mode: \"automatic\", ...(title ? { title } : {}) }),\n headers: { \"content-type\": \"application/json\" },\n method: \"PATCH\",\n }),\n );\n return surveyAssistantThreadSchema.parse(body.thread);\n },\n});\n","import { useCallback, useEffect, useState } from \"react\";\nimport {\n surveyAssistantModelCatalogSchema,\n type SurveyAssistantModelCatalog,\n type SurveyAssistantModelOption,\n} from \"../protocol\";\nimport { readSurveyAssistantJson } from \"./client-error\";\n\nconst DEFAULT_MODEL_STORAGE_KEY = \"survey-assistant-selected-model\";\n\nexport interface SurveyAssistantModelCatalogClient {\n get(): Promise<SurveyAssistantModelCatalog>;\n}\n\nexport const createSurveyAssistantModelCatalogClient = (\n api = \"/api/survey-assistant/models\",\n): SurveyAssistantModelCatalogClient => ({\n async get() {\n const body = await readSurveyAssistantJson(\n await fetch(api, { cache: \"no-store\" }),\n \"The assistant model catalog could not be loaded.\",\n );\n return surveyAssistantModelCatalogSchema.parse(body);\n },\n});\n\nexport interface UseSurveyAssistantModelCatalogOptions {\n api?: string;\n client?: SurveyAssistantModelCatalogClient;\n onModelChange?(modelId: string): void;\n storageKey?: string | false;\n}\n\nexport interface SurveyAssistantModelCatalogState {\n error: Error | null;\n loading: boolean;\n modelId?: string;\n models: SurveyAssistantModelOption[];\n reload(): void;\n selectModel(modelId: string): void;\n}\n\nexport const useSurveyAssistantModelCatalog = ({\n api,\n client: providedClient,\n onModelChange,\n storageKey = DEFAULT_MODEL_STORAGE_KEY,\n}: UseSurveyAssistantModelCatalogOptions = {}): SurveyAssistantModelCatalogState => {\n const [models, setModels] = useState<SurveyAssistantModelOption[]>([]);\n const [modelId, setModelId] = useState<string>();\n const [error, setError] = useState<Error | null>(null);\n const [loading, setLoading] = useState(true);\n const [reloadToken, setReloadToken] = useState(0);\n\n useEffect(() => {\n let cancelled = false;\n const client = providedClient ?? createSurveyAssistantModelCatalogClient(api);\n setLoading(true);\n setError(null);\n void client\n .get()\n .then((catalog) => {\n if (cancelled) return;\n const rememberedId =\n storageKey && typeof window !== \"undefined\"\n ? (window.localStorage.getItem(storageKey) ?? undefined)\n : undefined;\n const selectedId =\n rememberedId && catalog.models.some((model) => model.id === rememberedId)\n ? rememberedId\n : catalog.defaultModelId;\n setModels(catalog.models);\n setModelId(selectedId);\n onModelChange?.(selectedId);\n })\n .catch((reason: unknown) => {\n if (!cancelled) setError(reason instanceof Error ? reason : new Error(String(reason)));\n })\n .finally(() => {\n if (!cancelled) setLoading(false);\n });\n return () => {\n cancelled = true;\n };\n }, [api, onModelChange, providedClient, reloadToken, storageKey]);\n\n const selectModel = useCallback(\n (nextModelId: string) => {\n if (!models.some((model) => model.id === nextModelId)) return;\n setModelId(nextModelId);\n if (storageKey && typeof window !== \"undefined\") {\n window.localStorage.setItem(storageKey, nextModelId);\n }\n onModelChange?.(nextModelId);\n },\n [models, onModelChange, storageKey],\n );\n\n const reload = useCallback(() => setReloadToken((current) => current + 1), []);\n\n return { error, loading, modelId, models, reload, selectModel };\n};\n","\"use client\";\n\nimport {\n surveyDocumentVersionSchema,\n type SurveyAssistantSnapshot,\n type SurveyDocumentVersion,\n} from \"../protocol\";\n\nconst STORAGE_PREFIX = \"case-survey-assistant:settled-document:\";\nconst memoryBaselines = new Map<string, SurveyDocumentVersion>();\n\nconst getStorageKey = (resourceId: string, threadId: string) =>\n `${STORAGE_PREFIX}${encodeURIComponent(resourceId)}:${encodeURIComponent(threadId)}`;\n\nconst getSessionStorage = (): Storage | undefined => {\n if (typeof document === \"undefined\") return undefined;\n\n try {\n return window.sessionStorage;\n } catch {\n return undefined;\n }\n};\n\nexport const readSettledDocumentVersion = ({\n resourceId,\n threadId,\n}: {\n resourceId: string;\n threadId: string;\n}): SurveyDocumentVersion | undefined => {\n const storageKey = getStorageKey(resourceId, threadId);\n const storedInMemory = memoryBaselines.get(storageKey);\n if (storedInMemory) return { ...storedInMemory };\n\n const serialized = getSessionStorage()?.getItem(storageKey);\n if (!serialized) return undefined;\n\n try {\n const parsed = surveyDocumentVersionSchema.safeParse(JSON.parse(serialized));\n if (!parsed.success) return undefined;\n memoryBaselines.set(storageKey, parsed.data);\n return { ...parsed.data };\n } catch {\n return undefined;\n }\n};\n\nexport const writeSettledDocumentVersion = ({\n resourceId,\n snapshot,\n threadId,\n}: {\n resourceId: string;\n snapshot: SurveyAssistantSnapshot;\n threadId: string;\n}): void => {\n const storageKey = getStorageKey(resourceId, threadId);\n const version = surveyDocumentVersionSchema.parse(snapshot.version);\n memoryBaselines.set(storageKey, version);\n\n try {\n getSessionStorage()?.setItem(storageKey, JSON.stringify(version));\n } catch {\n // In-memory continuity still works when browser storage is disabled or full.\n }\n};\n","\"use client\";\n\nimport { useChat } from \"@ai-sdk/react\";\nimport {\n SURVEY_ASSISTANT_PROTOCOL_VERSION,\n surveyAssistantApplyOutcomeSchema,\n type ApplyReceipt,\n type SurveyAssistantApplyOutcome,\n type SurveyApplyResult,\n type SurveyAssistantApplyPolicy,\n type SurveyAssistantTurnFinal,\n type SurveyChangeSet,\n} from \"../protocol\";\nimport type { ChatStatus, FileUIPart, UIMessage } from \"ai\";\nimport {\n useCallback,\n useEffect,\n useEffectEvent,\n useMemo,\n useReducer,\n useRef,\n useState,\n} from \"react\";\nimport {\n collectSurveyChangeSets,\n createApplyReceipts,\n resolveLatestSurveyTurnAuthorization,\n resolveSurveyTurnOutcome,\n} from \"./turn-authorization\";\nimport { isSurveyAssistantTurnActive, reduceSurveyAssistantSessionState } from \"./session-state\";\nimport type { SurveyAssistantSessionState } from \"./session-state\";\nimport type { SurveyTurnOutcome } from \"./turn-authorization\";\nimport { createSurveyAssistantTransport } from \"./transport\";\nimport type { SurveyAssistantController } from \"./controller\";\nimport { readSettledDocumentVersion, writeSettledDocumentVersion } from \"./document-baseline\";\nimport {\n applySurveyAssistantLaunchUIContext,\n type SurveyAssistantLaunchUIContext,\n} from \"./thread-launcher\";\n\nconst createLocalId = (prefix: string) => {\n const id = globalThis.crypto?.randomUUID?.() ?? Math.random().toString(36).slice(2);\n return `${prefix}-${id}`;\n};\n\nconst compactOutcomeText = (value: string, maximum: number, fallback: string) => {\n const normalized = value.trim() || fallback;\n return normalized.length > maximum ? `${normalized.slice(0, maximum - 1)}…` : normalized;\n};\n\nconst createApplyOutcome = ({\n message,\n preparedChanges,\n results,\n status,\n turnId,\n}: {\n message: string;\n preparedChanges?: SurveyChangeSet[];\n results?: SurveyApplyResult[];\n status: SurveyAssistantApplyOutcome[\"status\"];\n turnId: string;\n}): SurveyAssistantApplyOutcome =>\n surveyAssistantApplyOutcomeSchema.parse({\n protocolVersion: SURVEY_ASSISTANT_PROTOCOL_VERSION,\n turnId,\n status,\n message: compactOutcomeText(message, 2_000, \"No lifecycle detail was reported.\"),\n ...(results && results.length > 0\n ? {\n results: results.slice(0, 100).map((result) => ({\n status: result.status,\n changeId: compactOutcomeText(result.changeId, 240, \"unknown-change\"),\n summary: compactOutcomeText(result.summary, 500, \"Survey change\"),\n message: compactOutcomeText(result.message, 2_000, \"No apply detail was reported.\"),\n appliedOperations: result.appliedOperations,\n })),\n }\n : {}),\n ...(preparedChanges && preparedChanges.length > 0\n ? {\n preparedChanges: preparedChanges.slice(-24).map((change) => ({\n changeId: compactOutcomeText(change.id, 240, \"unknown-change\"),\n status: change.status,\n summary: compactOutcomeText(change.summary, 500, \"Survey change\"),\n operationCount: change.operations.length,\n })),\n }\n : {}),\n createdAt: new Date().toISOString(),\n });\n\ntype AssistantTextPart = Extract<UIMessage[\"parts\"][number], { type: \"text\" }>;\n\nconst getAssistantTextParts = (message: UIMessage) =>\n message.parts.filter(\n (part): part is AssistantTextPart => part.type === \"text\" && part.text.trim().length > 0,\n );\n\nconst findLastAssistantTextMessageIndex = (\n messages: UIMessage[],\n endExclusive = messages.length,\n) => {\n for (let index = Math.min(messages.length, endExclusive) - 1; index >= 0; index -= 1) {\n const message = messages[index];\n if (message?.role === \"assistant\" && getAssistantTextParts(message).length > 0) return index;\n }\n return -1;\n};\n\nconst findLastUserMessageIndex = (messages: UIMessage[]) => {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n if (messages[index]?.role === \"user\") return index;\n }\n return -1;\n};\n\nconst pruneFailedMessagesForDisplay = (messages: UIMessage[]): UIMessage[] => {\n const lastUserIndex = findLastUserMessageIndex(messages);\n const lastCompletedAssistantIndex = findLastAssistantTextMessageIndex(messages);\n\n if (lastUserIndex > lastCompletedAssistantIndex) return messages.slice(0, lastUserIndex + 1);\n return lastCompletedAssistantIndex >= 0 ? messages.slice(0, lastCompletedAssistantIndex + 1) : [];\n};\n\nconst hasCompletedAssistantResponseAfterLastUser = (messages: UIMessage[]) => {\n const lastUserIndex = findLastUserMessageIndex(messages);\n return lastUserIndex >= 0 && findLastAssistantTextMessageIndex(messages) > lastUserIndex;\n};\n\nconst collectChangeSetsAfterLastUser = (messages: UIMessage[]) => {\n const lastUserIndex = findLastUserMessageIndex(messages);\n return lastUserIndex < 0 ? [] : collectSurveyChangeSets(messages.slice(lastUserIndex + 1));\n};\n\nconst getInitialSessionState = (messages: UIMessage[]): SurveyAssistantSessionState => {\n if (messages.length === 0) return \"idle\";\n const authorization = resolveLatestSurveyTurnAuthorization(messages);\n if (authorization.status === \"failed\") return \"failed\";\n if (authorization.status === \"aborted\") return \"aborted\";\n return \"completed\";\n};\n\nexport interface SurveyAssistantSessionOptions {\n api?: string;\n /** Explicit host decision: apply immediately, present for review, or deny mutations. */\n applyPolicy: SurveyAssistantApplyPolicy;\n controller?: SurveyAssistantController | null;\n initialMessages?: UIMessage[];\n modelId?: string;\n onApplyReceipts?: (receipts: ApplyReceipt[]) => void;\n /**\n * Production persistence/audit barrier. The turn remains active until this\n * resolves; rejection leaves the settled baseline unchanged.\n */\n onSettleApply?: (input: {\n changeSets: SurveyChangeSet[];\n receipts: ApplyReceipt[];\n turnFinal: SurveyAssistantTurnFinal;\n }) => void | Promise<void>;\n /**\n * Required for `review`. Resolve true to apply the authorized change sets,\n * or false to leave the editor unchanged.\n */\n onReviewChangeSets?: (\n changeSets: SurveyChangeSet[],\n turnFinal: SurveyAssistantTurnFinal,\n ) => boolean | Promise<boolean>;\n /** Reports when a turn owns the editor state, including submission, streaming, and apply. */\n onTurnActiveChange?: (active: boolean) => void;\n resourceId?: string;\n /** Host survey id sent as untrusted request context for server-side authorization. */\n surveyId?: string;\n threadId?: string;\n}\n\nexport const resolveSurveyAssistantReviewDecision = async ({\n changeSets,\n onReviewChangeSets,\n turnFinal,\n}: {\n changeSets: SurveyChangeSet[];\n onReviewChangeSets?: SurveyAssistantSessionOptions[\"onReviewChangeSets\"];\n turnFinal: SurveyAssistantTurnFinal;\n}) => {\n if (!onReviewChangeSets) {\n throw new Error(\"No survey assistant review adapter is available.\");\n }\n return onReviewChangeSets(changeSets, turnFinal);\n};\n\nexport interface SurveyAssistantSubmitMessage {\n text: string;\n files: FileUIPart[];\n /** Turn-local UI context layered over the controller snapshot for this submission. */\n uiContext?: SurveyAssistantLaunchUIContext;\n}\n\nexport interface SurveyAssistantSession {\n applyResultsByChangeId: Record<string, SurveyApplyResult>;\n authorizationError: string | null;\n dismissError(): void;\n error: Error | undefined;\n isStreaming: boolean;\n latestTurnOutcome: SurveyTurnOutcome | null;\n messages: UIMessage[];\n state: SurveyAssistantSessionState;\n status: ChatStatus;\n stop(): void;\n submit(message: SurveyAssistantSubmitMessage): boolean;\n retry(): void;\n}\n\nexport const useSurveyAssistantSession = ({\n api,\n applyPolicy,\n controller,\n initialMessages = [],\n modelId,\n onApplyReceipts,\n onSettleApply,\n onReviewChangeSets,\n onTurnActiveChange,\n resourceId: controlledResourceId,\n surveyId,\n threadId: controlledThreadId,\n}: SurveyAssistantSessionOptions): SurveyAssistantSession => {\n const [localResourceId] = useState(() => createLocalId(\"survey-assistant-local-user\"));\n const [localThreadId] = useState(() => createLocalId(\"survey-assistant-local-thread\"));\n const resourceId = controlledResourceId ?? localResourceId;\n const threadId = controlledThreadId ?? localThreadId;\n const applyOutcomeScopeKey = `${resourceId}\\u0000${threadId}`;\n const [state, dispatch] = useReducer(\n reduceSurveyAssistantSessionState,\n initialMessages,\n getInitialSessionState,\n );\n const [applyResultsByChangeId, setApplyResultsByChangeId] = useState<\n Record<string, SurveyApplyResult>\n >({});\n const [authorizationError, setAuthorizationError] = useState<string | null>(null);\n const handledTurnIdsRef = useRef<Set<string>>(new Set());\n const localTurnAwaitingApplyRef = useRef(false);\n const localTurnStreamStartedRef = useRef(false);\n const captureSettledVersionRef = useRef(false);\n const lastSubmittedUIContextRef = useRef<SurveyAssistantLaunchUIContext | undefined>(undefined);\n const previousApplyOutcomesRef = useRef<Map<string, SurveyAssistantApplyOutcome>>(new Map());\n\n const transport = useMemo(\n () => createSurveyAssistantTransport({ api, resourceId, surveyId, threadId }),\n [api, resourceId, surveyId, threadId],\n );\n const {\n messages,\n setMessages,\n sendMessage,\n status,\n stop: stopChat,\n error,\n clearError,\n regenerate,\n } = useChat({ id: threadId, messages: initialMessages, transport });\n const isStreaming = status === \"submitted\" || status === \"streaming\";\n const isTurnActive = isSurveyAssistantTurnActive({ isStreaming, state });\n const notifyTurnActiveChange = useEffectEvent((active: boolean) => {\n onTurnActiveChange?.(active);\n });\n const turnAuthorization = useMemo(\n () => resolveLatestSurveyTurnAuthorization(messages),\n [messages],\n );\n const latestTurnOutcome = useMemo(\n () => resolveSurveyTurnOutcome({ applyResultsByChangeId, authorization: turnAuthorization }),\n [applyResultsByChangeId, turnAuthorization],\n );\n const hasUsefulLatestAssistantResponse = useMemo(\n () =>\n hasCompletedAssistantResponseAfterLastUser(messages) ||\n collectChangeSetsAfterLastUser(messages).length > 0,\n [messages],\n );\n\n const reportAuthorizationError = useCallback((message: string) => {\n queueMicrotask(() => {\n setAuthorizationError(message);\n dispatch({ type: \"failed\" });\n });\n }, []);\n\n useEffect(() => {\n if (status === \"submitted\") dispatch({ type: \"submit\" });\n if (status === \"streaming\") dispatch({ type: \"stream-started\" });\n }, [status]);\n\n useEffect(() => {\n notifyTurnActiveChange(isTurnActive);\n\n return () => {\n if (isTurnActive) notifyTurnActiveChange(false);\n };\n }, [isTurnActive]);\n\n useEffect(() => {\n if (\n !captureSettledVersionRef.current ||\n isStreaming ||\n (state !== \"completed\" && state !== \"failed\" && state !== \"aborted\" && state !== \"applied\")\n ) {\n return;\n }\n\n captureSettledVersionRef.current = false;\n const snapshot = controller?.getSnapshot();\n if (snapshot) {\n writeSettledDocumentVersion({ resourceId, snapshot, threadId });\n }\n }, [controller, isStreaming, resourceId, state, threadId]);\n\n useEffect(() => {\n if (isStreaming) {\n localTurnStreamStartedRef.current = true;\n return;\n }\n if (!localTurnAwaitingApplyRef.current) return;\n\n if (turnAuthorization.status === \"pending\") {\n if (!localTurnStreamStartedRef.current) return;\n const timeoutId = window.setTimeout(() => {\n localTurnAwaitingApplyRef.current = false;\n localTurnStreamStartedRef.current = false;\n reportAuthorizationError(\"The assistant response ended without a valid turn final.\");\n }, 100);\n return () => window.clearTimeout(timeoutId);\n }\n\n localTurnAwaitingApplyRef.current = false;\n localTurnStreamStartedRef.current = false;\n if (turnAuthorization.status === \"invalid\") {\n reportAuthorizationError(turnAuthorization.reason);\n return;\n }\n\n const { turnFinal } = turnAuthorization;\n if (handledTurnIdsRef.current.has(turnFinal.turnId)) return;\n handledTurnIdsRef.current.add(turnFinal.turnId);\n const preparedChanges = collectChangeSetsAfterLastUser(messages).filter(\n (change) => change.turnId === turnFinal.turnId,\n );\n\n if (turnAuthorization.status === \"failed\") {\n previousApplyOutcomesRef.current.set(\n applyOutcomeScopeKey,\n createApplyOutcome({\n turnId: turnFinal.turnId,\n status: \"not-applied\",\n message:\n \"The previous assistant turn failed before editor authorization. Every request-scoped draft change from that turn was discarded and was not applied.\",\n preparedChanges,\n }),\n );\n dispatch({ type: \"failed\" });\n return;\n }\n if (turnAuthorization.status === \"aborted\") {\n previousApplyOutcomesRef.current.set(\n applyOutcomeScopeKey,\n createApplyOutcome({\n turnId: turnFinal.turnId,\n status: \"not-applied\",\n message:\n \"The previous assistant turn was interrupted before editor authorization. Every request-scoped draft change from that turn was discarded and was not applied.\",\n preparedChanges,\n }),\n );\n dispatch({ type: \"aborted\" });\n return;\n }\n if (turnAuthorization.changeSets.length === 0) {\n if ((turnFinal.blockedChangeSetIds?.length ?? 0) > 0) {\n previousApplyOutcomesRef.current.set(\n applyOutcomeScopeKey,\n createApplyOutcome({\n turnId: turnFinal.turnId,\n status: \"not-applied\",\n message:\n \"The previous assistant turn ended with unresolved rejected changes. No request-scoped draft change from that turn was authorized or applied.\",\n preparedChanges,\n }),\n );\n }\n dispatch({ type: \"completed\" });\n return;\n }\n if (applyPolicy === \"deny\") {\n previousApplyOutcomesRef.current.set(\n applyOutcomeScopeKey,\n createApplyOutcome({\n turnId: turnFinal.turnId,\n status: \"not-applied\",\n message: \"The host apply policy did not authorize editor mutations for this turn.\",\n preparedChanges,\n }),\n );\n dispatch({ type: \"completed\" });\n return;\n }\n dispatch({ type: \"apply-started\" });\n void (async () => {\n if (applyPolicy === \"review\") {\n let approved: boolean;\n try {\n approved = await resolveSurveyAssistantReviewDecision({\n changeSets: turnAuthorization.changeSets,\n onReviewChangeSets,\n turnFinal,\n });\n } catch (error) {\n const message =\n error instanceof Error &&\n error.message === \"No survey assistant review adapter is available.\"\n ? error.message\n : \"The survey assistant review could not be completed.\";\n previousApplyOutcomesRef.current.set(\n applyOutcomeScopeKey,\n createApplyOutcome({\n turnId: turnFinal.turnId,\n status: \"not-applied\",\n message,\n preparedChanges,\n }),\n );\n reportAuthorizationError(message);\n return;\n }\n if (!approved) {\n previousApplyOutcomesRef.current.set(\n applyOutcomeScopeKey,\n createApplyOutcome({\n turnId: turnFinal.turnId,\n status: \"not-applied\",\n message: \"The proposed editor changes were not approved during review.\",\n preparedChanges,\n }),\n );\n dispatch({ type: \"completed\" });\n return;\n }\n }\n\n if (!controller?.applyAssistantChange && !controller?.applyAssistantChanges) {\n const message = \"No survey editor apply adapter is available.\";\n previousApplyOutcomesRef.current.set(\n applyOutcomeScopeKey,\n createApplyOutcome({\n turnId: turnFinal.turnId,\n status: \"apply-failed\",\n message,\n preparedChanges,\n }),\n );\n reportAuthorizationError(message);\n return;\n }\n const beforeSnapshot = controller.getSnapshot();\n if (!beforeSnapshot) {\n const message = \"The editor state was unavailable when applying the assistant change.\";\n previousApplyOutcomesRef.current.set(\n applyOutcomeScopeKey,\n createApplyOutcome({\n turnId: turnFinal.turnId,\n status: \"apply-failed\",\n message,\n preparedChanges,\n }),\n );\n reportAuthorizationError(message);\n return;\n }\n\n const result = controller.applyAssistantChanges?.(turnAuthorization.changeSets) ?? {\n results: turnAuthorization.changeSets\n .map((change) => controller.applyAssistantChange?.(change))\n .filter((applyResult): applyResult is SurveyApplyResult => Boolean(applyResult)),\n };\n queueMicrotask(() =>\n setApplyResultsByChangeId((current) => ({\n ...current,\n ...Object.fromEntries(\n result.results.map((applyResult) => [applyResult.changeId, applyResult]),\n ),\n })),\n );\n const receipts = createApplyReceipts({\n beforeSnapshot,\n afterSnapshot: controller.getSnapshot(),\n changeSets: turnAuthorization.changeSets,\n results: result.results,\n turnFinal,\n });\n onApplyReceipts?.(receipts);\n if (!result.results.every((applyResult) => applyResult.status === \"applied\")) {\n previousApplyOutcomesRef.current.set(\n applyOutcomeScopeKey,\n createApplyOutcome({\n turnId: turnFinal.turnId,\n status: \"apply-failed\",\n message: \"One or more authorized survey changes could not be applied to the editor.\",\n preparedChanges,\n results: result.results,\n }),\n );\n dispatch({ type: \"completed\" });\n return;\n }\n try {\n await onSettleApply?.({\n changeSets: turnAuthorization.changeSets,\n receipts,\n turnFinal,\n });\n previousApplyOutcomesRef.current.delete(applyOutcomeScopeKey);\n dispatch({ type: \"applied\" });\n } catch {\n const message =\n \"The assistant changes were applied locally but could not be settled by the host.\";\n previousApplyOutcomesRef.current.set(\n applyOutcomeScopeKey,\n createApplyOutcome({\n turnId: turnFinal.turnId,\n status: \"settle-failed\",\n message,\n results: result.results,\n }),\n );\n reportAuthorizationError(message);\n }\n })();\n }, [\n applyPolicy,\n applyOutcomeScopeKey,\n controller,\n isStreaming,\n onApplyReceipts,\n onReviewChangeSets,\n onSettleApply,\n reportAuthorizationError,\n messages,\n turnAuthorization,\n ]);\n\n useEffect(() => {\n if (!error) return;\n localTurnAwaitingApplyRef.current = false;\n localTurnStreamStartedRef.current = false;\n dispatch({ type: \"failed\" });\n if (!hasUsefulLatestAssistantResponse) setMessages(pruneFailedMessagesForDisplay);\n }, [error, hasUsefulLatestAssistantResponse, setMessages]);\n\n const submit = useCallback(\n ({ files, text: rawText, uiContext }: SurveyAssistantSubmitMessage) => {\n const text = rawText.trim();\n if (!text && files.length === 0) return false;\n if (isStreaming || localTurnAwaitingApplyRef.current) return false;\n\n localTurnAwaitingApplyRef.current = true;\n localTurnStreamStartedRef.current = false;\n setAuthorizationError(null);\n if (authorizationError || error) setMessages(pruneFailedMessagesForDisplay);\n clearError();\n dispatch({ type: \"submit\" });\n captureSettledVersionRef.current = true;\n lastSubmittedUIContextRef.current = uiContext;\n\n const controllerSnapshot = controller?.getSnapshot() ?? null;\n const snapshot = applySurveyAssistantLaunchUIContext(controllerSnapshot, uiContext);\n void sendMessage(files.length > 0 ? (text ? { text, files } : { files }) : { text }, {\n body: {\n snapshot,\n previousSettledVersion: readSettledDocumentVersion({ resourceId, threadId }),\n previousApplyOutcome: previousApplyOutcomesRef.current.get(applyOutcomeScopeKey),\n ...(modelId ? { modelId } : {}),\n },\n });\n return true;\n },\n [\n authorizationError,\n applyOutcomeScopeKey,\n clearError,\n controller,\n error,\n isStreaming,\n modelId,\n resourceId,\n sendMessage,\n setMessages,\n threadId,\n ],\n );\n\n const stop = useCallback(() => {\n localTurnAwaitingApplyRef.current = false;\n localTurnStreamStartedRef.current = false;\n dispatch({ type: \"aborted\" });\n void stopChat();\n }, [stopChat]);\n\n const retry = useCallback(() => {\n localTurnAwaitingApplyRef.current = true;\n localTurnStreamStartedRef.current = false;\n setAuthorizationError(null);\n clearError();\n dispatch({ type: \"submit\" });\n captureSettledVersionRef.current = true;\n const controllerSnapshot = controller?.getSnapshot() ?? null;\n const uiContext = lastSubmittedUIContextRef.current;\n const snapshot = applySurveyAssistantLaunchUIContext(controllerSnapshot, uiContext);\n void regenerate({\n body: {\n snapshot,\n previousSettledVersion: readSettledDocumentVersion({ resourceId, threadId }),\n previousApplyOutcome: previousApplyOutcomesRef.current.get(applyOutcomeScopeKey),\n ...(modelId ? { modelId } : {}),\n },\n });\n }, [applyOutcomeScopeKey, clearError, controller, modelId, regenerate, resourceId, threadId]);\n\n const dismissError = useCallback(() => {\n localTurnAwaitingApplyRef.current = false;\n localTurnStreamStartedRef.current = false;\n setMessages(pruneFailedMessagesForDisplay);\n setAuthorizationError(null);\n clearError();\n dispatch({ type: \"reset\", hasTranscript: messages.length > 0 });\n }, [clearError, messages.length, setMessages]);\n\n return {\n applyResultsByChangeId,\n authorizationError,\n dismissError,\n error,\n isStreaming,\n latestTurnOutcome,\n messages,\n state,\n status,\n stop,\n submit,\n retry,\n };\n};\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as createSurveyAssistantThreadLauncher, a as SurveyAssistantController, c as SurveyAssistantTaskExecutionOptions, d as SurveyAssistantTaskExecutorRequestOptions, f as createSurveyAssistantTaskClient, g as SurveyAssistantThreadLauncher, h as SurveyAssistantThreadLaunch, i as createSurveyAssistantControllerProxy, l as SurveyAssistantTaskExecutor, m as SurveyAssistantLaunchUIContext, n as SurveyAssistantControllerBridge, o as SurveyAssistantTaskClient, p as createSurveyAssistantTaskExecutor, r as createSurveyAssistantControllerBridge, s as SurveyAssistantTaskClientOptions, t as CreateSurveyAssistantControllerProxyOptions, u as SurveyAssistantTaskExecutorCacheContext } from "./controller-proxy-
|
|
1
|
+
import { _ as createSurveyAssistantThreadLauncher, a as SurveyAssistantController, c as SurveyAssistantTaskExecutionOptions, d as SurveyAssistantTaskExecutorRequestOptions, f as createSurveyAssistantTaskClient, g as SurveyAssistantThreadLauncher, h as SurveyAssistantThreadLaunch, i as createSurveyAssistantControllerProxy, l as SurveyAssistantTaskExecutor, m as SurveyAssistantLaunchUIContext, n as SurveyAssistantControllerBridge, o as SurveyAssistantTaskClient, p as createSurveyAssistantTaskExecutor, r as createSurveyAssistantControllerBridge, s as SurveyAssistantTaskClientOptions, t as CreateSurveyAssistantControllerProxyOptions, u as SurveyAssistantTaskExecutorCacheContext } from "./controller-proxy-CIDRd8Wu.mjs";
|
|
2
2
|
export { type CreateSurveyAssistantControllerProxyOptions, type SurveyAssistantController, type SurveyAssistantControllerBridge, type SurveyAssistantLaunchUIContext, type SurveyAssistantTaskClient, type SurveyAssistantTaskClientOptions, type SurveyAssistantTaskExecutionOptions, type SurveyAssistantTaskExecutor, type SurveyAssistantTaskExecutorCacheContext, type SurveyAssistantTaskExecutorRequestOptions, type SurveyAssistantThreadLaunch, type SurveyAssistantThreadLauncher, createSurveyAssistantControllerBridge, createSurveyAssistantControllerProxy, createSurveyAssistantTaskClient, createSurveyAssistantTaskExecutor, createSurveyAssistantThreadLauncher };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { i as createSurveyAssistantTaskExecutor, n as createSurveyAssistantControllerProxy, r as createSurveyAssistantTaskClient, s as createSurveyAssistantThreadLauncher, t as createSurveyAssistantControllerBridge } from "./controller-proxy-
|
|
2
|
+
import { i as createSurveyAssistantTaskExecutor, n as createSurveyAssistantControllerProxy, r as createSurveyAssistantTaskClient, s as createSurveyAssistantThreadLauncher, t as createSurveyAssistantControllerBridge } from "./controller-proxy-DY36XFV3.mjs";
|
|
3
3
|
export { createSurveyAssistantControllerBridge, createSurveyAssistantControllerProxy, createSurveyAssistantTaskClient, createSurveyAssistantTaskExecutor, createSurveyAssistantThreadLauncher };
|
package/dist/react.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { C as SurveyAssistantSessionEvent, E as reduceSurveyAssistantSessionState, S as unwrapSurveyAssistantToolOutput, T as isSurveyAssistantTurnActive, _ as createApplyReceipts, a as SurveyAssistantModelCatalogClient, b as resolveLatestSurveyTurnAuthorization, c as createSurveyAssistantModelCatalogClient, d as SurveyAssistantThreadClient, f as createSurveyAssistantThreadClient, g as collectSurveyChangeSets, h as SurveyTurnOutcome, i as useSurveyAssistantSession, l as useSurveyAssistantModelCatalog, m as SurveyTurnAuthorization, n as SurveyAssistantSessionOptions, o as SurveyAssistantModelCatalogState, p as createSurveyAssistantTransport, r as SurveyAssistantSubmitMessage, s as UseSurveyAssistantModelCatalogOptions, t as SurveyAssistantSession, u as SurveyAssistantClientError, v as getSurveyDocumentVersionFromSnapshot, w as SurveyAssistantSessionState, x as resolveSurveyTurnOutcome, y as parseSurveyChangeSet } from "./index-
|
|
2
|
-
import { _ as createSurveyAssistantThreadLauncher, a as SurveyAssistantController, c as SurveyAssistantTaskExecutionOptions, d as SurveyAssistantTaskExecutorRequestOptions, f as createSurveyAssistantTaskClient, g as SurveyAssistantThreadLauncher, h as SurveyAssistantThreadLaunch, i as createSurveyAssistantControllerProxy, l as SurveyAssistantTaskExecutor, m as SurveyAssistantLaunchUIContext, n as SurveyAssistantControllerBridge, o as SurveyAssistantTaskClient, p as createSurveyAssistantTaskExecutor, r as createSurveyAssistantControllerBridge, s as SurveyAssistantTaskClientOptions, t as CreateSurveyAssistantControllerProxyOptions, u as SurveyAssistantTaskExecutorCacheContext } from "./controller-proxy-
|
|
1
|
+
import { C as SurveyAssistantSessionEvent, E as reduceSurveyAssistantSessionState, S as unwrapSurveyAssistantToolOutput, T as isSurveyAssistantTurnActive, _ as createApplyReceipts, a as SurveyAssistantModelCatalogClient, b as resolveLatestSurveyTurnAuthorization, c as createSurveyAssistantModelCatalogClient, d as SurveyAssistantThreadClient, f as createSurveyAssistantThreadClient, g as collectSurveyChangeSets, h as SurveyTurnOutcome, i as useSurveyAssistantSession, l as useSurveyAssistantModelCatalog, m as SurveyTurnAuthorization, n as SurveyAssistantSessionOptions, o as SurveyAssistantModelCatalogState, p as createSurveyAssistantTransport, r as SurveyAssistantSubmitMessage, s as UseSurveyAssistantModelCatalogOptions, t as SurveyAssistantSession, u as SurveyAssistantClientError, v as getSurveyDocumentVersionFromSnapshot, w as SurveyAssistantSessionState, x as resolveSurveyTurnOutcome, y as parseSurveyChangeSet } from "./index-SPHf3OoJ.mjs";
|
|
2
|
+
import { _ as createSurveyAssistantThreadLauncher, a as SurveyAssistantController, c as SurveyAssistantTaskExecutionOptions, d as SurveyAssistantTaskExecutorRequestOptions, f as createSurveyAssistantTaskClient, g as SurveyAssistantThreadLauncher, h as SurveyAssistantThreadLaunch, i as createSurveyAssistantControllerProxy, l as SurveyAssistantTaskExecutor, m as SurveyAssistantLaunchUIContext, n as SurveyAssistantControllerBridge, o as SurveyAssistantTaskClient, p as createSurveyAssistantTaskExecutor, r as createSurveyAssistantControllerBridge, s as SurveyAssistantTaskClientOptions, t as CreateSurveyAssistantControllerProxyOptions, u as SurveyAssistantTaskExecutorCacheContext } from "./controller-proxy-CIDRd8Wu.mjs";
|
|
3
3
|
export { CreateSurveyAssistantControllerProxyOptions, SurveyAssistantClientError, SurveyAssistantController, SurveyAssistantControllerBridge, SurveyAssistantLaunchUIContext, SurveyAssistantModelCatalogClient, SurveyAssistantModelCatalogState, SurveyAssistantSession, SurveyAssistantSessionEvent, SurveyAssistantSessionOptions, SurveyAssistantSessionState, SurveyAssistantSubmitMessage, SurveyAssistantTaskClient, SurveyAssistantTaskClientOptions, SurveyAssistantTaskExecutionOptions, SurveyAssistantTaskExecutor, SurveyAssistantTaskExecutorCacheContext, SurveyAssistantTaskExecutorRequestOptions, SurveyAssistantThreadClient, SurveyAssistantThreadLaunch, SurveyAssistantThreadLauncher, SurveyTurnAuthorization, SurveyTurnOutcome, UseSurveyAssistantModelCatalogOptions, collectSurveyChangeSets, createApplyReceipts, createSurveyAssistantControllerBridge, createSurveyAssistantControllerProxy, createSurveyAssistantModelCatalogClient, createSurveyAssistantTaskClient, createSurveyAssistantTaskExecutor, createSurveyAssistantThreadClient, createSurveyAssistantThreadLauncher, createSurveyAssistantTransport, getSurveyDocumentVersionFromSnapshot, isSurveyAssistantTurnActive, parseSurveyChangeSet, reduceSurveyAssistantSessionState, resolveLatestSurveyTurnAuthorization, resolveSurveyTurnOutcome, unwrapSurveyAssistantToolOutput, useSurveyAssistantModelCatalog, useSurveyAssistantSession };
|
package/dist/react.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { a as createSurveyAssistantTransport, c as getSurveyDocumentVersionFromSnapshot, d as resolveSurveyTurnOutcome, f as unwrapSurveyAssistantToolOutput, i as createSurveyAssistantThreadClient, l as parseSurveyChangeSet, m as reduceSurveyAssistantSessionState, n as createSurveyAssistantModelCatalogClient, o as collectSurveyChangeSets, p as isSurveyAssistantTurnActive, r as useSurveyAssistantModelCatalog, s as createApplyReceipts, t as useSurveyAssistantSession, u as resolveLatestSurveyTurnAuthorization } from "./react-
|
|
3
|
-
import { c as SurveyAssistantClientError, i as createSurveyAssistantTaskExecutor, n as createSurveyAssistantControllerProxy, r as createSurveyAssistantTaskClient, s as createSurveyAssistantThreadLauncher, t as createSurveyAssistantControllerBridge } from "./controller-proxy-
|
|
2
|
+
import { a as createSurveyAssistantTransport, c as getSurveyDocumentVersionFromSnapshot, d as resolveSurveyTurnOutcome, f as unwrapSurveyAssistantToolOutput, i as createSurveyAssistantThreadClient, l as parseSurveyChangeSet, m as reduceSurveyAssistantSessionState, n as createSurveyAssistantModelCatalogClient, o as collectSurveyChangeSets, p as isSurveyAssistantTurnActive, r as useSurveyAssistantModelCatalog, s as createApplyReceipts, t as useSurveyAssistantSession, u as resolveLatestSurveyTurnAuthorization } from "./react-3kSE6WtS.mjs";
|
|
3
|
+
import { c as SurveyAssistantClientError, i as createSurveyAssistantTaskExecutor, n as createSurveyAssistantControllerProxy, r as createSurveyAssistantTaskClient, s as createSurveyAssistantThreadLauncher, t as createSurveyAssistantControllerBridge } from "./controller-proxy-DY36XFV3.mjs";
|
|
4
4
|
export { SurveyAssistantClientError, collectSurveyChangeSets, createApplyReceipts, createSurveyAssistantControllerBridge, createSurveyAssistantControllerProxy, createSurveyAssistantModelCatalogClient, createSurveyAssistantTaskClient, createSurveyAssistantTaskExecutor, createSurveyAssistantThreadClient, createSurveyAssistantThreadLauncher, createSurveyAssistantTransport, getSurveyDocumentVersionFromSnapshot, isSurveyAssistantTurnActive, parseSurveyChangeSet, reduceSurveyAssistantSessionState, resolveLatestSurveyTurnAuthorization, resolveSurveyTurnOutcome, unwrapSurveyAssistantToolOutput, useSurveyAssistantModelCatalog, useSurveyAssistantSession };
|
|
@@ -109,6 +109,7 @@ Minimal valid examples:
|
|
|
109
109
|
"itemType": "formItem",
|
|
110
110
|
"config": {
|
|
111
111
|
"id": "personal_data",
|
|
112
|
+
"authoringMode": "simple",
|
|
112
113
|
"fieldGroups": [
|
|
113
114
|
{
|
|
114
115
|
"id": "main",
|
|
@@ -183,11 +184,16 @@ Minimal valid examples:
|
|
|
183
184
|
- Target a top-level form with `{ "itemId": "<form-id>" }` or a choice option's form with `{ "itemId": "<choice-id>", "optionId": "<option-id>" }`.
|
|
184
185
|
- Add visible labels, placeholders, option labels, and validation messages in the operation's `translations` array so structure and content remain atomic.
|
|
185
186
|
- Group and field identifiers are stable ids; reorder operations require the complete current id set.
|
|
187
|
+
- Simple forms contain one group and one field. Compatible updates to that same field may remain
|
|
188
|
+
simple; structural changes automatically make the form custom. This applies to top-level and
|
|
189
|
+
embedded forms and is intentionally one-way.
|
|
186
190
|
|
|
187
191
|
`set-embedded-form`, `remove-embedded-form`
|
|
188
192
|
|
|
189
193
|
- Add or remove a choice option's inline form using item and option ids, without raw array-index patches.
|
|
190
194
|
- `set-embedded-form` accepts the full form config plus its visible translations in the same operation.
|
|
195
|
+
- Set `form.authoringMode` to `simple` only for exactly one group with one field; otherwise use
|
|
196
|
+
`custom`. Malformed simple input is normalized to custom without dropping form data.
|
|
191
197
|
- Form layout values are responsive column counts from 1 to 4, not spans; one column makes a lone field full width.
|
|
192
198
|
|
|
193
199
|
`move-item`, `reorder-items`
|
|
@@ -195,16 +201,16 @@ Minimal valid examples:
|
|
|
195
201
|
- Move an existing item to a group/index or set a group's complete direct-child order.
|
|
196
202
|
- The validator rejects root moves, cycles, missing children, duplicates, and incomplete reorder lists.
|
|
197
203
|
|
|
198
|
-
`update-survey-metadata`, `update-survey-pagination`, `update-survey-translation`, `remove-survey-locale`
|
|
204
|
+
`update-survey-metadata`, `update-survey-pagination`, `update-survey-translation`, `add-survey-locale`, `remove-survey-locale`
|
|
199
205
|
|
|
200
|
-
- Use typed survey-level operations for metadata, page limits, survey-card/navigation/validation content, and locale
|
|
201
|
-
-
|
|
206
|
+
- Use typed survey-level operations for metadata, page limits, survey-card/navigation/validation content, and locale lifecycle.
|
|
207
|
+
- `add-survey-locale` registers an empty locale and is only for an explicitly requested empty registration. An ordinary request to add/localize/translate a language requires real respondent-facing translations; those translation operations introduce an absent locale themselves. `remove-survey-locale` is intentionally explicit and destructive: it deletes all survey-level and item-level translations stored for that locale.
|
|
202
208
|
|
|
203
209
|
`set-image-asset`, `update-image-asset-metadata`, `remove-image-asset`
|
|
204
210
|
|
|
205
211
|
- Prefer `survey_asset import-attachment` for binary image imports so the model never copies attachment base64.
|
|
206
212
|
- To use that import in a new item, follow it with a `survey_change` call and embed `{ "type": "image", "source": { "type": "asset", "assetId": "<returned-id>" } }` directly in the new item's rich-text translation. The import is retained automatically in the turn draft.
|
|
207
|
-
- Metadata and removal are typed and validated. `survey_asset remove` refuses an asset that is still referenced in the
|
|
213
|
+
- Metadata and removal are typed and validated. `survey_asset remove` refuses an asset that is still referenced in the current request-scoped draft.
|
|
208
214
|
- To remove referenced images and their asset atomically, use one `survey_change` call whose `operations` contain every reference removal first and `{ "kind": "remove-image-asset", "assetId": "..." }` last. For example, deleting an image-only info card and its asset is `[remove-item, remove-image-asset]` in one candidate.
|
|
209
215
|
|
|
210
216
|
`remove-item`
|
|
@@ -242,23 +248,12 @@ Update a form field-group layout:
|
|
|
242
248
|
}
|
|
243
249
|
```
|
|
244
250
|
|
|
245
|
-
|
|
251
|
+
Only when the user explicitly requests an empty registration, add a missing locale shell after inspection confirms that the locale does not exist:
|
|
246
252
|
|
|
247
253
|
```json
|
|
248
254
|
{
|
|
249
|
-
"kind": "survey-
|
|
250
|
-
"
|
|
251
|
-
{
|
|
252
|
-
"op": "add",
|
|
253
|
-
"path": "/translations/nl",
|
|
254
|
-
"value": {
|
|
255
|
-
"itemTranslations": {},
|
|
256
|
-
"surveyCardContent": {},
|
|
257
|
-
"navigationContent": {},
|
|
258
|
-
"validationMessages": {}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
]
|
|
255
|
+
"kind": "add-survey-locale",
|
|
256
|
+
"locale": "nl"
|
|
262
257
|
}
|
|
263
258
|
```
|
|
264
259
|
|
|
@@ -22,9 +22,14 @@ Use this reference when a choice option needs an inline input such as “Other,
|
|
|
22
22
|
The config key is singular `embeddedForm`, but translation content-key prefixes are plural
|
|
23
23
|
`embeddedForms.<optionId>`. Do not interchange them.
|
|
24
24
|
|
|
25
|
-
`embeddedForm` is a flat object containing `id` and `fieldGroups`. Fields belong inside each field
|
|
25
|
+
`embeddedForm` is a flat object containing `id`, `authoringMode`, and `fieldGroups`. Fields belong inside each field
|
|
26
26
|
group; there is no `itemType`, `config`, or top-level `fields` wrapper.
|
|
27
27
|
|
|
28
|
+
Default to `authoringMode: "simple"` for an inline follow-up with one supported field in one
|
|
29
|
+
ordinary single-column group. Use `authoringMode: "custom"` only for a blank, multi-field,
|
|
30
|
+
multi-group, conditional, or layout-customized follow-up. Any structural change is a one-way
|
|
31
|
+
transition to custom; retain existing fields and translations.
|
|
32
|
+
|
|
28
33
|
`fieldGroups[].layout` values are responsive column counts, not field spans. Use `1` at every
|
|
29
34
|
breakpoint for one full-width field. Supported counts are `1` through `4`.
|
|
30
35
|
|
|
@@ -34,6 +39,7 @@ breakpoint for one full-width field. Supported counts are `1` through `4`.
|
|
|
34
39
|
"key": "other",
|
|
35
40
|
"embeddedForm": {
|
|
36
41
|
"id": "other",
|
|
42
|
+
"authoringMode": "simple",
|
|
37
43
|
"fieldGroups": [
|
|
38
44
|
{
|
|
39
45
|
"id": "other_details",
|
|
@@ -54,6 +60,37 @@ breakpoint for one full-width field. Supported counts are `1` through `4`.
|
|
|
54
60
|
}
|
|
55
61
|
```
|
|
56
62
|
|
|
63
|
+
For comparison, use `custom` when the follow-up really needs multiple controls. Keep its fields
|
|
64
|
+
and their translations together; do not use this shape for a single text field just because it is
|
|
65
|
+
inside a choice option.
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"id": "contact_details",
|
|
70
|
+
"authoringMode": "custom",
|
|
71
|
+
"fieldGroups": [
|
|
72
|
+
{
|
|
73
|
+
"id": "details",
|
|
74
|
+
"layout": { "base": 1, "xs": 1, "sm": 1, "md": 1, "xl": 1 },
|
|
75
|
+
"fields": [
|
|
76
|
+
{
|
|
77
|
+
"id": "contact_name",
|
|
78
|
+
"key": "contact_name",
|
|
79
|
+
"type": "input",
|
|
80
|
+
"controller": { "type": "input", "inputMode": "text" }
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"id": "contact_note",
|
|
84
|
+
"key": "contact_note",
|
|
85
|
+
"type": "textarea",
|
|
86
|
+
"controller": { "type": "textarea", "rows": 3 }
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
57
94
|
Use an explicit, stable option id. The config option id, translation prefix, and embedded response
|
|
58
95
|
reference must agree exactly. When editing an existing option, copy its current `id` exactly,
|
|
59
96
|
including case. The `embeddedForms.<optionId>` translation segment always comes from the containing
|
|
@@ -77,11 +114,13 @@ specify”, use option label “Other” and field label “Please specify”.
|
|
|
77
114
|
## Existing-Item Typed Operation Checklist
|
|
78
115
|
|
|
79
116
|
1. Inspect the existing choice item and copy the exact item and option ids.
|
|
80
|
-
2. Call `set-embedded-form` with the complete flat form structure
|
|
117
|
+
2. Call `set-embedded-form` with the complete flat form structure and explicit `authoringMode`.
|
|
81
118
|
3. Use canonical field types such as `input`, with a matching controller; there is no `text` type.
|
|
82
119
|
4. Put relative content keys such as `fields.other_text.label` in the same operation's
|
|
83
120
|
`translations`; the engine adds `embeddedForms.<optionId>.` automatically.
|
|
84
121
|
5. Use one column at every breakpoint when a lone field should fill the form width.
|
|
122
|
+
6. Before adding/reordering groups or fields on a simple follow-up, let the typed mutation promote
|
|
123
|
+
it to custom; do not construct multi-field data with `authoringMode: "simple"`.
|
|
85
124
|
|
|
86
125
|
Embedded response slots use `embedded.<optionId>.<fieldKey>`, for example
|
|
87
126
|
`embedded.other.other_text`.
|