@ykurilov/agent-chat-flows 0.64.0 → 0.65.1

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/react.js CHANGED
@@ -1,7 +1,9 @@
1
1
  import {
2
2
  FACT_PREFIX,
3
+ FLOW_DEADLINE_NOTICE,
4
+ FLOW_TIMER_NOTICE,
3
5
  fieldValueText
4
- } from "./chunk-22FWN7NU.js";
6
+ } from "./chunk-KRZMJJKG.js";
5
7
  import {
6
8
  ANY_STATE_LAYOUT_KEY,
7
9
  DEFAULT_LATE_START_HOURS,
@@ -29,7 +31,7 @@ import {
29
31
  startRun,
30
32
  stateById,
31
33
  timerDueAt
32
- } from "./chunk-5RDY7QBA.js";
34
+ } from "./chunk-7VR4YNTJ.js";
33
35
 
34
36
  // src/react/flow-labels.ts
35
37
  import { createContext, createElement, useContext } from "react";
@@ -599,6 +601,53 @@ var englishFlowMigrateLabels = {
599
601
  failed: "Could not move the chats. Try again"
600
602
  };
601
603
 
604
+ // src/labels/notices.ts
605
+ var withTarget = (head, condition, stateTitle) => `${head}${condition ? ` (${condition})` : ""}${stateTitle ? ` \u2192 \xAB${stateTitle}\xBB` : ""}`;
606
+ var russianFlowNoticeLabels = {
607
+ wroteFirst: (reasons) => `\u0410\u0433\u0435\u043D\u0442 \u043D\u0430\u043F\u0438\u0441\u0430\u043B \u043F\u0435\u0440\u0432\u044B\u043C \u2014 ${reasons}`,
608
+ separator: ", ",
609
+ silentFor: (duration) => `\u0447\u0435\u043B\u043E\u0432\u0435\u043A \u043C\u043E\u043B\u0447\u0430\u043B ${duration}`,
610
+ silence: "\u043A\u0430\u0441\u0430\u043D\u0438\u0435 \u043F\u043E\u0441\u043B\u0435 \u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044F",
611
+ morning: "\u0443\u0442\u0440\u043E \u043D\u043E\u0432\u043E\u0433\u043E \u0434\u043D\u044F",
612
+ daily: (at) => `\u043A\u0430\u0441\u0430\u043D\u0438\u0435 \u043F\u043E \u0440\u0430\u0441\u043F\u0438\u0441\u0430\u043D\u0438\u044E \u0432 ${at}`,
613
+ nightMessages: (count) => `\u043E\u0442\u0432\u0435\u0442 \u043D\u0430 \u043D\u043E\u0447\u043D\u044B\u0435 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u044F (${count})`,
614
+ farewell: "\u043F\u0440\u043E\u0449\u0430\u043D\u0438\u0435: \u0441\u0440\u043E\u043A \u043F\u0440\u043E\u0433\u0440\u0430\u043C\u043C\u044B \u0432\u044B\u0448\u0435\u043B",
615
+ stateDeadline: (condition, stateTitle) => withTarget("\u0441\u0440\u043E\u043A \u0448\u0430\u0433\u0430 \u0432\u044B\u0448\u0435\u043B", condition, stateTitle),
616
+ overallDeadline: (condition, stateTitle) => withTarget("\u043E\u0431\u0449\u0438\u0439 \u0441\u0440\u043E\u043A \u0432\u044B\u0448\u0435\u043B", condition, stateTitle),
617
+ conditions: {
618
+ stateDays: (duration) => `\u0448\u0430\u0433 \u0434\u043B\u0438\u043B\u0441\u044F ${duration}`,
619
+ programDay: (day) => `\u043D\u0430\u0441\u0442\u0443\u043F\u0438\u043B \u0434\u0435\u043D\u044C ${day}`,
620
+ timeOfDay: (at) => `\u043D\u0430\u0441\u0442\u0443\u043F\u0438\u043B\u043E ${at}`,
621
+ silence: (duration) => `\u0442\u0438\u0448\u0438\u043D\u0430 ${duration}`,
622
+ inState: (duration) => `\u0432 \u0448\u0430\u0433\u0435 ${duration}`,
623
+ sinceStart: (duration) => `${duration} \u0441 \u043D\u0430\u0447\u0430\u043B\u0430 \u0440\u0430\u0437\u0433\u043E\u0432\u043E\u0440\u0430`
624
+ },
625
+ units: { day: "\u0434", hour: "\u0447", minute: "\u043C\u0438\u043D" },
626
+ lessThanMinute: "\u043C\u0435\u043D\u044C\u0448\u0435 \u043C\u0438\u043D\u0443\u0442\u044B"
627
+ };
628
+ var englishFlowNoticeLabels = {
629
+ wroteFirst: (reasons) => `The agent wrote first \u2014 ${reasons}`,
630
+ separator: ", ",
631
+ silentFor: (duration) => `the person was silent for ${duration}`,
632
+ silence: "a nudge after silence",
633
+ morning: "a new day's morning",
634
+ daily: (at) => `a scheduled nudge at ${at}`,
635
+ nightMessages: (count) => `a reply to night messages (${count})`,
636
+ farewell: "a farewell: the program is over",
637
+ stateDeadline: (condition, stateTitle) => withTarget("the step's time is up", condition, stateTitle),
638
+ overallDeadline: (condition, stateTitle) => withTarget("the overall time is up", condition, stateTitle),
639
+ conditions: {
640
+ stateDays: (duration) => `the step lasted ${duration}`,
641
+ programDay: (day) => `day ${day} began`,
642
+ timeOfDay: (at) => `it's ${at}`,
643
+ silence: (duration) => `silence for ${duration}`,
644
+ inState: (duration) => `${duration} in the step`,
645
+ sinceStart: (duration) => `${duration} since the start`
646
+ },
647
+ units: { day: "d", hour: "h", minute: "min" },
648
+ lessThanMinute: "less than a minute"
649
+ };
650
+
602
651
  // src/labels/test-chat.ts
603
652
  var russianFlowTestChatLabels = {
604
653
  title: "\u0422\u0435\u0441\u0442\u043E\u0432\u044B\u0439 \u0447\u0430\u0442",
@@ -644,13 +693,15 @@ var russianFlowLabels = {
644
693
  editor: russianFlowEditorLabels,
645
694
  clientCard: russianClientCardLabels,
646
695
  migrate: russianFlowMigrateLabels,
647
- testChat: russianFlowTestChatLabels
696
+ testChat: russianFlowTestChatLabels,
697
+ notices: russianFlowNoticeLabels
648
698
  };
649
699
  var englishFlowLabels = {
650
700
  editor: englishFlowEditorLabels,
651
701
  clientCard: englishClientCardLabels,
652
702
  migrate: englishFlowMigrateLabels,
653
- testChat: englishFlowTestChatLabels
703
+ testChat: englishFlowTestChatLabels,
704
+ notices: englishFlowNoticeLabels
654
705
  };
655
706
 
656
707
  // src/react/flow-labels.ts
@@ -2497,6 +2548,84 @@ function ClientCardPanel({ skin, ...options }) {
2497
2548
  // src/react/test-chat/flow-test-chat.tsx
2498
2549
  import { createContext as createContext3, useContext as useContext3, useMemo as useMemo5 } from "react";
2499
2550
 
2551
+ // src/react/notice-lines.ts
2552
+ var MINUTE = 6e4;
2553
+ function flowNoticeLines(labels = russianFlowNoticeLabels) {
2554
+ const line = ({ data }) => {
2555
+ const parsed = firstMessageData(data);
2556
+ return parsed ? noticeLine(parsed, labels) : void 0;
2557
+ };
2558
+ return { [FLOW_TIMER_NOTICE]: line, [FLOW_DEADLINE_NOTICE]: line };
2559
+ }
2560
+ function firstMessageData(data) {
2561
+ if (typeof data !== "object" || data === null) return void 0;
2562
+ const { reasons, silentMs, exit } = data;
2563
+ if (!Array.isArray(reasons) || reasons.length === 0) return void 0;
2564
+ return {
2565
+ reasons: reasons.filter((reason) => typeof reason === "object" && reason !== null && typeof reason.kind === "string"),
2566
+ ...typeof silentMs === "number" && Number.isFinite(silentMs) && { silentMs },
2567
+ ...typeof exit === "object" && exit !== null && { exit }
2568
+ };
2569
+ }
2570
+ function noticeLine({ reasons, silentMs, exit }, labels) {
2571
+ const silentFor = silentMs === void 0 ? void 0 : labels.silentFor(durationText2(silentMs, labels));
2572
+ const parts = reasons.flatMap((reason) => {
2573
+ switch (reason.kind) {
2574
+ case "silence":
2575
+ return [silentFor ?? labels.silence];
2576
+ case "morning":
2577
+ return [labels.morning];
2578
+ case "daily":
2579
+ return [labels.daily(reason.at)];
2580
+ case "night_messages":
2581
+ return [labels.nightMessages(reason.count)];
2582
+ case "farewell":
2583
+ return [labels.farewell];
2584
+ case "transition":
2585
+ return [deadlineLine(exit, labels)];
2586
+ default:
2587
+ return [];
2588
+ }
2589
+ });
2590
+ if (parts.length === 0) return void 0;
2591
+ const withSilence = silentFor && !reasons.some((reason) => reason.kind === "silence") ? [...parts, silentFor] : parts;
2592
+ return labels.wroteFirst(withSilence.join(labels.separator));
2593
+ }
2594
+ function deadlineLine(exit, labels) {
2595
+ const when = exit?.when;
2596
+ const title = typeof exit?.stateTitle === "string" && exit.stateTitle ? exit.stateTitle : void 0;
2597
+ const condition = when?.type === "timer" ? timerText(when, labels) : void 0;
2598
+ return when?.type === "timer" && when.from === "since_start" ? labels.overallDeadline(condition, title) : labels.stateDeadline(condition, title);
2599
+ }
2600
+ var UNIT_MS = { min: MINUTE, h: 60 * MINUTE, d: 24 * 60 * MINUTE };
2601
+ function timerText(when, labels) {
2602
+ const { conditions } = labels;
2603
+ switch (when.from) {
2604
+ case "state_days":
2605
+ return conditions.stateDays(durationText2(when.days * UNIT_MS.d, labels));
2606
+ case "program_day":
2607
+ return conditions.programDay(when.day);
2608
+ case "time_of_day":
2609
+ return conditions.timeOfDay(when.at);
2610
+ default: {
2611
+ const span = UNIT_MS[when.unit];
2612
+ if (span === void 0) return void 0;
2613
+ const duration = durationText2(when.amount * span, labels);
2614
+ return when.from === "silence" ? conditions.silence(duration) : when.from === "in_state" ? conditions.inState(duration) : conditions.sinceStart(duration);
2615
+ }
2616
+ }
2617
+ }
2618
+ function durationText2(ms, labels) {
2619
+ const minutes = Math.round(ms / MINUTE);
2620
+ if (minutes < 1) return labels.lessThanMinute;
2621
+ const { day, hour, minute } = labels.units;
2622
+ return [
2623
+ [Math.floor(minutes / (24 * 60)), day],
2624
+ [Math.floor(minutes / 60) % 24, hour],
2625
+ [minutes % 60, minute]
2626
+ ].filter(([amount]) => amount > 0).map(([amount, unit]) => `${amount} ${unit}`).join(" ");
2627
+ }
2628
+
2500
2629
  // src/react/test-chat/use-flow-test-chat.ts
2501
2630
  import { useCallback as useCallback5, useEffect as useEffect4, useRef as useRef4, useState as useState6 } from "react";
2502
2631
  var RUN_POLL_MS = 1e3;
@@ -2591,12 +2720,12 @@ function useFlowTestChat(connection, flow) {
2591
2720
 
2592
2721
  // src/react/test-chat/flow-test-chat.tsx
2593
2722
  import { jsx as jsx4 } from "react/jsx-runtime";
2594
- var MINUTE = 6e4;
2595
- var HOUR = 60 * MINUTE;
2723
+ var MINUTE2 = 6e4;
2724
+ var HOUR = 60 * MINUTE2;
2596
2725
  var DAY = 24 * HOUR;
2597
- var DEFAULT_ADVANCE_STEPS = [20 * MINUTE, 3 * HOUR, DAY];
2726
+ var DEFAULT_ADVANCE_STEPS = [20 * MINUTE2, 3 * HOUR, DAY];
2598
2727
  function formatDuration(ms, units) {
2599
- const minutes = Math.round(ms / MINUTE);
2728
+ const minutes = Math.round(ms / MINUTE2);
2600
2729
  const parts = [
2601
2730
  [Math.floor(minutes / (24 * 60)), units.day],
2602
2731
  [Math.floor(minutes / 60) % 24, units.hour],
@@ -2639,7 +2768,8 @@ function withTestChat(skin) {
2639
2768
  return { ...skin, FlowHeader: Header, FlowEditorFrame: Frame, FlowStateNode: StateNode };
2640
2769
  }
2641
2770
  function FlowTestChat({ testChat, advanceSteps = DEFAULT_ADVANCE_STEPS, skin, ...editor }) {
2642
- const labels = useFlowLabels().testChat;
2771
+ const { testChat: labels, notices } = useFlowLabels();
2772
+ const noticeLines = useMemo5(() => flowNoticeLines(notices), [notices]);
2643
2773
  const controller = useFlowTestChat(testChat, editor.value);
2644
2774
  const testSkin = useMemo5(() => withTestChat(skin), [skin]);
2645
2775
  const state = controller.stateId === null ? void 0 : stateById(editor.value, controller.stateId);
@@ -2662,7 +2792,7 @@ function FlowTestChat({ testChat, advanceSteps = DEFAULT_ADVANCE_STEPS, skin, ..
2662
2792
  failed: controller.failed,
2663
2793
  onReset: controller.reset,
2664
2794
  onClose: controller.close,
2665
- children: controller.chatId === null ? null : testChat.renderChat(controller.chatId)
2795
+ children: controller.chatId === null ? null : testChat.renderChat(controller.chatId, { noticeLines })
2666
2796
  }
2667
2797
  ) : null;
2668
2798
  return /* @__PURE__ */ jsx4(TestChatContext.Provider, { value: { controller, panel }, children: /* @__PURE__ */ jsx4(FlowEditor, { skin: testSkin, ...editor }) });
@@ -2679,11 +2809,14 @@ export {
2679
2809
  chooseNothing,
2680
2810
  conditionText,
2681
2811
  englishFlowLabels,
2812
+ englishFlowNoticeLabels,
2813
+ flowNoticeLines,
2682
2814
  formatClockOffset,
2683
2815
  formatDayLine,
2684
2816
  formatDuration,
2685
2817
  nextQuestionField,
2686
2818
  russianFlowLabels,
2819
+ russianFlowNoticeLabels,
2687
2820
  sameFlow,
2688
2821
  setKnownValue,
2689
2822
  simulationChoices,