@case-framework/survey-assistant 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{authoring-references-DYuOAdVx.mjs → authoring-references-yyYC4Ydi.mjs} +9 -3
- package/dist/authoring-references-yyYC4Ydi.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-DrGZXtQf.d.mts} +12 -7
- package/dist/constants-DrGZXtQf.d.mts.map +1 -0
- package/dist/{controller-proxy-0WJZUZYx.mjs → controller-proxy-CpkQRezb.mjs} +3 -2
- package/dist/controller-proxy-CpkQRezb.mjs.map +1 -0
- package/dist/{controller-proxy-Hkuub9dt.d.mts → controller-proxy-DmBdzqKs.d.mts} +5 -2
- package/dist/controller-proxy-DmBdzqKs.d.mts.map +1 -0
- 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-JXH-t2EJ.d.mts → index-Bo4dHAo8.d.mts} +68 -6
- package/dist/index-Bo4dHAo8.d.mts.map +1 -0
- package/dist/{index-MEOL9_Gr.d.mts → index-D4OitUg4.d.mts} +5 -430
- package/dist/index-D4OitUg4.d.mts.map +1 -0
- package/dist/{index-BcyfBeDj.d.mts → index-DZk20e3k.d.mts} +44 -22
- package/dist/index-DZk20e3k.d.mts.map +1 -0
- package/dist/{index-CneD8ibB.d.mts → index-Dxgg0-D_.d.mts} +12 -3
- package/dist/index-Dxgg0-D_.d.mts.map +1 -0
- package/dist/lifecycle-DWv5CiSu.d.mts +523 -0
- package/dist/lifecycle-DWv5CiSu.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 +4 -3
- package/dist/protocol.mjs +2 -2
- package/dist/{react-DXK5zWNo.mjs → react-Br5YE8H-.mjs} +132 -12
- package/dist/react-Br5YE8H-.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 +44 -22
- package/dist/server-agent.d.mts.map +1 -1
- package/dist/server-agent.mjs +71 -14
- 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 +6 -4
- 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-DQgL449A.d.mts} +8 -4
- package/dist/tasks-DQgL449A.d.mts.map +1 -0
- package/dist/{thread-documents-BlxNjc7S.d.mts → thread-documents-Dvo6XS7o.d.mts} +1 -1
- package/dist/{thread-documents-BlxNjc7S.d.mts.map → thread-documents-Dvo6XS7o.d.mts.map} +1 -1
- package/dist/{thread-handlers-uddXwQjp.d.mts → thread-handlers-CeYl45xG.d.mts} +9 -4
- package/dist/thread-handlers-CeYl45xG.d.mts.map +1 -0
- package/dist/{tools-wgLen05n.mjs → tools-Dg9HZrYU.mjs} +404 -78
- package/dist/tools-Dg9HZrYU.mjs.map +1 -0
- package/dist/ui.css +2 -2
- package/dist/ui.d.mts +94 -10
- package/dist/ui.d.mts.map +1 -1
- package/dist/ui.mjs +343 -112
- package/dist/ui.mjs.map +1 -1
- package/docs/integration.md +74 -6
- package/package.json +25 -19
- 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/controller-proxy-0WJZUZYx.mjs.map +0 -1
- package/dist/controller-proxy-Hkuub9dt.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/index-MEOL9_Gr.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
|
@@ -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-CpkQRezb.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,8 @@ 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 lastSubmittedModelIdRef = useRef(void 0);
|
|
395
|
+
const previousApplyOutcomesRef = useRef(/* @__PURE__ */ new Map());
|
|
358
396
|
const { messages, setMessages, sendMessage, status, stop: stopChat, error, clearError, regenerate } = useChat({
|
|
359
397
|
id: threadId,
|
|
360
398
|
messages: initialMessages,
|
|
@@ -440,11 +478,44 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
440
478
|
const { turnFinal } = turnAuthorization;
|
|
441
479
|
if (handledTurnIdsRef.current.has(turnFinal.turnId)) return;
|
|
442
480
|
handledTurnIdsRef.current.add(turnFinal.turnId);
|
|
443
|
-
|
|
481
|
+
const preparedChanges = collectChangeSetsAfterLastUser(messages).filter((change) => change.turnId === turnFinal.turnId);
|
|
482
|
+
if (turnAuthorization.status === "failed") {
|
|
483
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
484
|
+
turnId: turnFinal.turnId,
|
|
485
|
+
status: "not-applied",
|
|
486
|
+
message: "The previous assistant turn failed before editor authorization. Every request-scoped draft change from that turn was discarded and was not applied.",
|
|
487
|
+
preparedChanges
|
|
488
|
+
}));
|
|
489
|
+
dispatch({ type: "failed" });
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
if (turnAuthorization.status === "aborted") {
|
|
493
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
494
|
+
turnId: turnFinal.turnId,
|
|
495
|
+
status: "not-applied",
|
|
496
|
+
message: "The previous assistant turn was interrupted before editor authorization. Every request-scoped draft change from that turn was discarded and was not applied.",
|
|
497
|
+
preparedChanges
|
|
498
|
+
}));
|
|
499
|
+
dispatch({ type: "aborted" });
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
if (turnAuthorization.changeSets.length === 0) {
|
|
503
|
+
if ((turnFinal.blockedChangeSetIds?.length ?? 0) > 0) previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
504
|
+
turnId: turnFinal.turnId,
|
|
505
|
+
status: "not-applied",
|
|
506
|
+
message: "The previous assistant turn ended with unresolved rejected changes. No request-scoped draft change from that turn was authorized or applied.",
|
|
507
|
+
preparedChanges
|
|
508
|
+
}));
|
|
444
509
|
dispatch({ type: "completed" });
|
|
445
510
|
return;
|
|
446
511
|
}
|
|
447
512
|
if (applyPolicy === "deny") {
|
|
513
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
514
|
+
turnId: turnFinal.turnId,
|
|
515
|
+
status: "not-applied",
|
|
516
|
+
message: "The host apply policy did not authorize editor mutations for this turn.",
|
|
517
|
+
preparedChanges
|
|
518
|
+
}));
|
|
448
519
|
dispatch({ type: "completed" });
|
|
449
520
|
return;
|
|
450
521
|
}
|
|
@@ -459,21 +530,48 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
459
530
|
turnFinal
|
|
460
531
|
});
|
|
461
532
|
} catch (error) {
|
|
462
|
-
|
|
533
|
+
const message = error instanceof Error && error.message === "No survey assistant review adapter is available." ? error.message : "The survey assistant review could not be completed.";
|
|
534
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
535
|
+
turnId: turnFinal.turnId,
|
|
536
|
+
status: "not-applied",
|
|
537
|
+
message,
|
|
538
|
+
preparedChanges
|
|
539
|
+
}));
|
|
540
|
+
reportAuthorizationError(message);
|
|
463
541
|
return;
|
|
464
542
|
}
|
|
465
543
|
if (!approved) {
|
|
544
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
545
|
+
turnId: turnFinal.turnId,
|
|
546
|
+
status: "not-applied",
|
|
547
|
+
message: "The proposed editor changes were not approved during review.",
|
|
548
|
+
preparedChanges
|
|
549
|
+
}));
|
|
466
550
|
dispatch({ type: "completed" });
|
|
467
551
|
return;
|
|
468
552
|
}
|
|
469
553
|
}
|
|
470
554
|
if (!controller?.applyAssistantChange && !controller?.applyAssistantChanges) {
|
|
471
|
-
|
|
555
|
+
const message = "No survey editor apply adapter is available.";
|
|
556
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
557
|
+
turnId: turnFinal.turnId,
|
|
558
|
+
status: "apply-failed",
|
|
559
|
+
message,
|
|
560
|
+
preparedChanges
|
|
561
|
+
}));
|
|
562
|
+
reportAuthorizationError(message);
|
|
472
563
|
return;
|
|
473
564
|
}
|
|
474
565
|
const beforeSnapshot = controller.getSnapshot();
|
|
475
566
|
if (!beforeSnapshot) {
|
|
476
|
-
|
|
567
|
+
const message = "The editor state was unavailable when applying the assistant change.";
|
|
568
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
569
|
+
turnId: turnFinal.turnId,
|
|
570
|
+
status: "apply-failed",
|
|
571
|
+
message,
|
|
572
|
+
preparedChanges
|
|
573
|
+
}));
|
|
574
|
+
reportAuthorizationError(message);
|
|
477
575
|
return;
|
|
478
576
|
}
|
|
479
577
|
const result = controller.applyAssistantChanges?.(turnAuthorization.changeSets) ?? { results: turnAuthorization.changeSets.map((change) => controller.applyAssistantChange?.(change)).filter((applyResult) => Boolean(applyResult)) };
|
|
@@ -490,6 +588,13 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
490
588
|
});
|
|
491
589
|
onApplyReceipts?.(receipts);
|
|
492
590
|
if (!result.results.every((applyResult) => applyResult.status === "applied")) {
|
|
591
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
592
|
+
turnId: turnFinal.turnId,
|
|
593
|
+
status: "apply-failed",
|
|
594
|
+
message: "One or more authorized survey changes could not be applied to the editor.",
|
|
595
|
+
preparedChanges,
|
|
596
|
+
results: result.results
|
|
597
|
+
}));
|
|
493
598
|
dispatch({ type: "completed" });
|
|
494
599
|
return;
|
|
495
600
|
}
|
|
@@ -499,19 +604,29 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
499
604
|
receipts,
|
|
500
605
|
turnFinal
|
|
501
606
|
});
|
|
607
|
+
previousApplyOutcomesRef.current.delete(applyOutcomeScopeKey);
|
|
502
608
|
dispatch({ type: "applied" });
|
|
503
609
|
} catch {
|
|
504
|
-
|
|
610
|
+
const message = "The assistant changes were applied locally but could not be settled by the host.";
|
|
611
|
+
previousApplyOutcomesRef.current.set(applyOutcomeScopeKey, createApplyOutcome({
|
|
612
|
+
turnId: turnFinal.turnId,
|
|
613
|
+
status: "settle-failed",
|
|
614
|
+
message,
|
|
615
|
+
results: result.results
|
|
616
|
+
}));
|
|
617
|
+
reportAuthorizationError(message);
|
|
505
618
|
}
|
|
506
619
|
})();
|
|
507
620
|
}, [
|
|
508
621
|
applyPolicy,
|
|
622
|
+
applyOutcomeScopeKey,
|
|
509
623
|
controller,
|
|
510
624
|
isStreaming,
|
|
511
625
|
onApplyReceipts,
|
|
512
626
|
onReviewChangeSets,
|
|
513
627
|
onSettleApply,
|
|
514
628
|
reportAuthorizationError,
|
|
629
|
+
messages,
|
|
515
630
|
turnAuthorization
|
|
516
631
|
]);
|
|
517
632
|
useEffect(() => {
|
|
@@ -525,7 +640,7 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
525
640
|
hasUsefulLatestAssistantResponse,
|
|
526
641
|
setMessages
|
|
527
642
|
]);
|
|
528
|
-
const submit = useCallback(({ files, text: rawText, uiContext }) => {
|
|
643
|
+
const submit = useCallback(({ files, modelId: submittedModelId, text: rawText, uiContext }) => {
|
|
529
644
|
const text = rawText.trim();
|
|
530
645
|
if (!text && files.length === 0) return false;
|
|
531
646
|
if (isStreaming || localTurnAwaitingApplyRef.current) return false;
|
|
@@ -537,6 +652,7 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
537
652
|
dispatch({ type: "submit" });
|
|
538
653
|
captureSettledVersionRef.current = true;
|
|
539
654
|
lastSubmittedUIContextRef.current = uiContext;
|
|
655
|
+
lastSubmittedModelIdRef.current = submittedModelId ?? modelId;
|
|
540
656
|
const snapshot = applySurveyAssistantLaunchUIContext(controller?.getSnapshot() ?? null, uiContext);
|
|
541
657
|
sendMessage(files.length > 0 ? text ? {
|
|
542
658
|
text,
|
|
@@ -547,11 +663,13 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
547
663
|
resourceId,
|
|
548
664
|
threadId
|
|
549
665
|
}),
|
|
550
|
-
|
|
666
|
+
previousApplyOutcome: previousApplyOutcomesRef.current.get(applyOutcomeScopeKey),
|
|
667
|
+
...lastSubmittedModelIdRef.current ? { modelId: lastSubmittedModelIdRef.current } : {}
|
|
551
668
|
} });
|
|
552
669
|
return true;
|
|
553
670
|
}, [
|
|
554
671
|
authorizationError,
|
|
672
|
+
applyOutcomeScopeKey,
|
|
555
673
|
clearError,
|
|
556
674
|
controller,
|
|
557
675
|
error,
|
|
@@ -583,9 +701,11 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
583
701
|
resourceId,
|
|
584
702
|
threadId
|
|
585
703
|
}),
|
|
586
|
-
|
|
704
|
+
previousApplyOutcome: previousApplyOutcomesRef.current.get(applyOutcomeScopeKey),
|
|
705
|
+
...lastSubmittedModelIdRef.current ? { modelId: lastSubmittedModelIdRef.current } : {}
|
|
587
706
|
} });
|
|
588
707
|
}, [
|
|
708
|
+
applyOutcomeScopeKey,
|
|
589
709
|
clearError,
|
|
590
710
|
controller,
|
|
591
711
|
modelId,
|
|
@@ -625,4 +745,4 @@ const useSurveyAssistantSession = ({ api, applyPolicy, controller, initialMessag
|
|
|
625
745
|
//#endregion
|
|
626
746
|
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
747
|
|
|
628
|
-
//# sourceMappingURL=react-
|
|
748
|
+
//# sourceMappingURL=react-Br5YE8H-.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-Br5YE8H-.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 /** Optional model used for this turn instead of the session's selected model. */\n modelId?: string;\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 lastSubmittedModelIdRef = useRef<string | 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 ({\n files,\n modelId: submittedModelId,\n text: rawText,\n uiContext,\n }: 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 lastSubmittedModelIdRef.current = submittedModelId ?? modelId;\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 ...(lastSubmittedModelIdRef.current ? { modelId: lastSubmittedModelIdRef.current } : {}),\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 ...(lastSubmittedModelIdRef.current ? { modelId: lastSubmittedModelIdRef.current } : {}),\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-DmBdzqKs.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-CpkQRezb.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-Dxgg0-D_.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-DmBdzqKs.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-Br5YE8H-.mjs";
|
|
3
|
+
import { c as SurveyAssistantClientError, i as createSurveyAssistantTaskExecutor, n as createSurveyAssistantControllerProxy, r as createSurveyAssistantTaskClient, s as createSurveyAssistantThreadLauncher, t as createSurveyAssistantControllerBridge } from "./controller-proxy-CpkQRezb.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`.
|