@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.
Files changed (107) hide show
  1. package/dist/{authoring-references-DYuOAdVx.mjs → authoring-references-yyYC4Ydi.mjs} +9 -3
  2. package/dist/authoring-references-yyYC4Ydi.mjs.map +1 -0
  3. package/dist/{capabilities-DlC1l6qy.d.mts → capabilities-CnsVuJ1k.d.mts} +12 -4
  4. package/dist/capabilities-CnsVuJ1k.d.mts.map +1 -0
  5. package/dist/capabilities-default.d.mts +1 -1
  6. package/dist/capabilities-default.d.mts.map +1 -1
  7. package/dist/capabilities-default.mjs +38 -4
  8. package/dist/capabilities-default.mjs.map +1 -1
  9. package/dist/{constants-D-5m_KGB.d.mts → constants-DrGZXtQf.d.mts} +12 -7
  10. package/dist/constants-DrGZXtQf.d.mts.map +1 -0
  11. package/dist/{controller-proxy-0WJZUZYx.mjs → controller-proxy-CpkQRezb.mjs} +3 -2
  12. package/dist/controller-proxy-CpkQRezb.mjs.map +1 -0
  13. package/dist/{controller-proxy-Hkuub9dt.d.mts → controller-proxy-DmBdzqKs.d.mts} +5 -2
  14. package/dist/controller-proxy-DmBdzqKs.d.mts.map +1 -0
  15. package/dist/{digest-BvXpeWcR.d.mts → digest-Dyjch_sC.d.mts} +2 -2
  16. package/dist/{digest-BvXpeWcR.d.mts.map → digest-Dyjch_sC.d.mts.map} +1 -1
  17. package/dist/digest.d.mts +1 -1
  18. package/dist/{engine-0AJrv0hI.mjs → engine-CWTuN3o2.mjs} +866 -663
  19. package/dist/engine-CWTuN3o2.mjs.map +1 -0
  20. package/dist/engine.d.mts +3 -3
  21. package/dist/engine.mjs +3 -3
  22. package/dist/fair-guidance-CEdJYccK.mjs +21 -0
  23. package/dist/fair-guidance-CEdJYccK.mjs.map +1 -0
  24. package/dist/form-authoring-DCd9XfXf.mjs +155 -0
  25. package/dist/form-authoring-DCd9XfXf.mjs.map +1 -0
  26. package/dist/{index-JXH-t2EJ.d.mts → index-Bo4dHAo8.d.mts} +68 -6
  27. package/dist/index-Bo4dHAo8.d.mts.map +1 -0
  28. package/dist/{index-MEOL9_Gr.d.mts → index-D4OitUg4.d.mts} +5 -430
  29. package/dist/index-D4OitUg4.d.mts.map +1 -0
  30. package/dist/{index-BcyfBeDj.d.mts → index-DZk20e3k.d.mts} +44 -22
  31. package/dist/index-DZk20e3k.d.mts.map +1 -0
  32. package/dist/{index-CneD8ibB.d.mts → index-Dxgg0-D_.d.mts} +12 -3
  33. package/dist/index-Dxgg0-D_.d.mts.map +1 -0
  34. package/dist/lifecycle-DWv5CiSu.d.mts +523 -0
  35. package/dist/lifecycle-DWv5CiSu.d.mts.map +1 -0
  36. package/dist/{memory-thread-repository-1ocPOda8.mjs → memory-thread-repository-acbz6HZJ.mjs} +181 -26
  37. package/dist/memory-thread-repository-acbz6HZJ.mjs.map +1 -0
  38. package/dist/{protocol-DpCYmCjr.mjs → protocol-DATvkr1S.mjs} +125 -6
  39. package/dist/protocol-DATvkr1S.mjs.map +1 -0
  40. package/dist/protocol.d.mts +4 -3
  41. package/dist/protocol.mjs +2 -2
  42. package/dist/{react-DXK5zWNo.mjs → react-Br5YE8H-.mjs} +132 -12
  43. package/dist/react-Br5YE8H-.mjs.map +1 -0
  44. package/dist/react-integration.d.mts +1 -1
  45. package/dist/react-integration.mjs +1 -1
  46. package/dist/react.d.mts +2 -2
  47. package/dist/react.mjs +2 -2
  48. package/dist/references/assistant-operations.md +13 -18
  49. package/dist/references/embedded-forms.md +41 -2
  50. package/dist/references/expressions.md +17 -9
  51. package/dist/references/fair-by-design.md +80 -0
  52. package/dist/references/item-types.md +19 -3
  53. package/dist/references/localization.md +7 -4
  54. package/dist/references/source-material-surveys.md +6 -4
  55. package/dist/{request-context-BBzU3VdG.mjs → request-context-BEjnaaFr.mjs} +10 -5
  56. package/dist/request-context-BEjnaaFr.mjs.map +1 -0
  57. package/dist/server-agent.d.mts +44 -22
  58. package/dist/server-agent.d.mts.map +1 -1
  59. package/dist/server-agent.mjs +71 -14
  60. package/dist/server-agent.mjs.map +1 -1
  61. package/dist/server-runtime.d.mts +22 -11
  62. package/dist/server-runtime.d.mts.map +1 -1
  63. package/dist/server-runtime.mjs +47 -19
  64. package/dist/server-runtime.mjs.map +1 -1
  65. package/dist/server-tasks.d.mts +1 -1
  66. package/dist/server-tasks.mjs +6 -4
  67. package/dist/server-tasks.mjs.map +1 -1
  68. package/dist/server-tools.d.mts +1 -1
  69. package/dist/server-tools.mjs +1 -1
  70. package/dist/server.d.mts +16 -7
  71. package/dist/server.d.mts.map +1 -1
  72. package/dist/server.mjs +4 -4
  73. package/dist/storage-postgres.d.mts +1 -1
  74. package/dist/{tasks-DcfQNJwO.d.mts → tasks-DQgL449A.d.mts} +8 -4
  75. package/dist/tasks-DQgL449A.d.mts.map +1 -0
  76. package/dist/{thread-documents-BlxNjc7S.d.mts → thread-documents-Dvo6XS7o.d.mts} +1 -1
  77. package/dist/{thread-documents-BlxNjc7S.d.mts.map → thread-documents-Dvo6XS7o.d.mts.map} +1 -1
  78. package/dist/{thread-handlers-uddXwQjp.d.mts → thread-handlers-CeYl45xG.d.mts} +9 -4
  79. package/dist/thread-handlers-CeYl45xG.d.mts.map +1 -0
  80. package/dist/{tools-wgLen05n.mjs → tools-Dg9HZrYU.mjs} +404 -78
  81. package/dist/tools-Dg9HZrYU.mjs.map +1 -0
  82. package/dist/ui.css +2 -2
  83. package/dist/ui.d.mts +94 -10
  84. package/dist/ui.d.mts.map +1 -1
  85. package/dist/ui.mjs +343 -112
  86. package/dist/ui.mjs.map +1 -1
  87. package/docs/integration.md +74 -6
  88. package/package.json +25 -19
  89. package/dist/authoring-references-DYuOAdVx.mjs.map +0 -1
  90. package/dist/capabilities-DKbNCnBf.mjs +0 -66
  91. package/dist/capabilities-DKbNCnBf.mjs.map +0 -1
  92. package/dist/capabilities-DlC1l6qy.d.mts.map +0 -1
  93. package/dist/constants-D-5m_KGB.d.mts.map +0 -1
  94. package/dist/controller-proxy-0WJZUZYx.mjs.map +0 -1
  95. package/dist/controller-proxy-Hkuub9dt.d.mts.map +0 -1
  96. package/dist/engine-0AJrv0hI.mjs.map +0 -1
  97. package/dist/index-BcyfBeDj.d.mts.map +0 -1
  98. package/dist/index-CneD8ibB.d.mts.map +0 -1
  99. package/dist/index-JXH-t2EJ.d.mts.map +0 -1
  100. package/dist/index-MEOL9_Gr.d.mts.map +0 -1
  101. package/dist/memory-thread-repository-1ocPOda8.mjs.map +0 -1
  102. package/dist/protocol-DpCYmCjr.mjs.map +0 -1
  103. package/dist/react-DXK5zWNo.mjs.map +0 -1
  104. package/dist/request-context-BBzU3VdG.mjs.map +0 -1
  105. package/dist/tasks-DcfQNJwO.d.mts.map +0 -1
  106. package/dist/thread-handlers-uddXwQjp.d.mts.map +0 -1
  107. package/dist/tools-wgLen05n.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
- import { A as surveyAssistantThreadSchema, B as surveyDocumentVersionSchema, c as surveyAssistantTurnFinalSchema, d as surveyAssistantModelCatalogSchema, j as surveyAssistantThreadTranscriptSchema, k as surveyAssistantThreadListSchema, n as SURVEY_ASSISTANT_TURN_FINAL_PART_TYPE, r as applyReceiptSchema, u as surveyChangeSetSchema } from "./protocol-DpCYmCjr.mjs";
2
- import { a as applySurveyAssistantLaunchUIContext, l as readSurveyAssistantJson } from "./controller-proxy-0WJZUZYx.mjs";
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 [state, dispatch] = useReducer(reduceSurveyAssistantSessionState, "idle");
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
- if (turnAuthorization.status !== "completed" || turnAuthorization.changeSets.length === 0) {
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
- reportAuthorizationError(error instanceof Error && error.message === "No survey assistant review adapter is available." ? error.message : "The survey assistant review could not be completed.");
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
- reportAuthorizationError("No survey editor apply adapter is available.");
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
- reportAuthorizationError("The editor state was unavailable when applying the assistant change.");
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
- reportAuthorizationError("The assistant changes were applied locally but could not be settled by the host.");
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
- ...modelId ? { modelId } : {}
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
- ...modelId ? { modelId } : {}
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-DXK5zWNo.mjs.map
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-Hkuub9dt.mjs";
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-0WJZUZYx.mjs";
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-CneD8ibB.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-Hkuub9dt.mjs";
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-DXK5zWNo.mjs";
3
- import { c as SurveyAssistantClientError, i as createSurveyAssistantTaskExecutor, n as createSurveyAssistantControllerProxy, r as createSurveyAssistantTaskClient, s as createSurveyAssistantThreadLauncher, t as createSurveyAssistantControllerBridge } from "./controller-proxy-0WJZUZYx.mjs";
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 removal.
201
- - Removing the final locale is rejected. Locale removal is intentionally explicit and destructive.
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 immutable snapshot.
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
- Add a missing locale shell only after inspection confirms that the locale does not exist:
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-json-patch",
250
- "patches": [
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`.