dsh-plugin-core 0.26.0 → 0.28.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 (63) hide show
  1. package/dist/explorer/open.d.ts +5 -4
  2. package/dist/explorer/open.d.ts.map +1 -1
  3. package/dist/explorer/open.js +12 -2
  4. package/dist/explorer/open.js.map +1 -1
  5. package/dist/session/SessionViewModal.d.ts.map +1 -1
  6. package/dist/session/SessionViewModal.js +70 -20
  7. package/dist/session/SessionViewModal.js.map +1 -1
  8. package/dist/session/mirror/ChatView.d.ts.map +1 -1
  9. package/dist/session/mirror/ChatView.js +9 -1
  10. package/dist/session/mirror/ChatView.js.map +1 -1
  11. package/dist/session/mirror/Deliverables.d.ts.map +1 -1
  12. package/dist/session/mirror/Deliverables.js +42 -27
  13. package/dist/session/mirror/Deliverables.js.map +1 -1
  14. package/dist/session/mirror/GenericCommandCard.d.ts.map +1 -1
  15. package/dist/session/mirror/GenericCommandCard.js +2 -3
  16. package/dist/session/mirror/GenericCommandCard.js.map +1 -1
  17. package/dist/session/mirror/MessageIconActions.d.ts.map +1 -1
  18. package/dist/session/mirror/MessageIconActions.js +3 -5
  19. package/dist/session/mirror/MessageIconActions.js.map +1 -1
  20. package/dist/session/mirror/MessageItem.d.ts +5 -0
  21. package/dist/session/mirror/MessageItem.d.ts.map +1 -1
  22. package/dist/session/mirror/MessageItem.js +30 -12
  23. package/dist/session/mirror/MessageItem.js.map +1 -1
  24. package/dist/session/mirror/ReasoningRow.d.ts.map +1 -1
  25. package/dist/session/mirror/ReasoningRow.js +79 -17
  26. package/dist/session/mirror/ReasoningRow.js.map +1 -1
  27. package/dist/session/mirror/RunningStatus.d.ts +12 -0
  28. package/dist/session/mirror/RunningStatus.d.ts.map +1 -0
  29. package/dist/session/mirror/RunningStatus.js +57 -0
  30. package/dist/session/mirror/RunningStatus.js.map +1 -0
  31. package/dist/session/mirror/TurnProcessNodeView.d.ts.map +1 -1
  32. package/dist/session/mirror/TurnProcessNodeView.js +27 -38
  33. package/dist/session/mirror/TurnProcessNodeView.js.map +1 -1
  34. package/dist/session/mirror/TurnTailNodeView.d.ts +25 -0
  35. package/dist/session/mirror/TurnTailNodeView.d.ts.map +1 -1
  36. package/dist/session/mirror/TurnTailNodeView.js +65 -7
  37. package/dist/session/mirror/TurnTailNodeView.js.map +1 -1
  38. package/dist/session/mirror/TurnTriggerNodeView.d.ts.map +1 -1
  39. package/dist/session/mirror/TurnTriggerNodeView.js +36 -20
  40. package/dist/session/mirror/TurnTriggerNodeView.js.map +1 -1
  41. package/dist/session/mirror/message-chrome.d.ts +10 -4
  42. package/dist/session/mirror/message-chrome.d.ts.map +1 -1
  43. package/dist/session/mirror/message-chrome.js +11 -16
  44. package/dist/session/mirror/message-chrome.js.map +1 -1
  45. package/dist/session/official-classes.d.ts.map +1 -1
  46. package/dist/session/official-classes.js +5 -3
  47. package/dist/session/official-classes.js.map +1 -1
  48. package/dist/session/session-css.generated.d.ts +1 -1
  49. package/dist/session/session-css.generated.d.ts.map +1 -1
  50. package/dist/session/session-css.generated.js +1 -1
  51. package/dist/session/session-css.generated.js.map +1 -1
  52. package/dist/utils/i18n.d.ts +1 -1
  53. package/dist/utils/i18n.d.ts.map +1 -1
  54. package/dist/utils/i18n.js +24 -14
  55. package/dist/utils/i18n.js.map +1 -1
  56. package/docs/help/explorer.doc.ts +9 -9
  57. package/docs/help/explorer.md +7 -7
  58. package/docs/help/integration.doc.ts +5 -3
  59. package/docs/help/integration.md +5 -3
  60. package/docs/help/session.doc.ts +4 -3
  61. package/docs/help/session.md +4 -3
  62. package/docs/requirements.md +3 -1
  63. package/package.json +1 -1
@@ -1,35 +1,86 @@
1
- // 官方对照:packages/client/ui-chat/src/client/chat/ReasoningRow.tsx(0.1.7-rc.2 lib/client.js:5718-5778)
1
+ // 官方对照:ui-chat@0.2.1-rc.5 lib/client.js:6107-6260(reasoningText / latestCompletedParagraphFirstLine /
2
+ // ReasoningRow)+ ReasoningContent(lib/client.js:6568-6576)。
2
3
  // root[data-variant=think][data-state=running|ok][data-expanded][data-preview]
3
- // > DisclosureRow(icon=IconThinkOutlineRegular 14px,title=t("message.think")=「思考」,
4
- // collapsedContent = separator(2×2px) + summary(首行、去 **),content = thinkBody MarkdownText compact)
5
- // 折叠态 root 固定一行高(contain:size layout + height 24px+delta);预览受 settledReasoningPreview 政策控制。
6
- // 官方截图里组内思考行 = 「思考 · Let me submit the receipt now.」——标题是「思考」,不是「思考过程」。
7
- import { Fragment, createElement as h, useState } from 'react';
8
- import { DisclosureRow, IconThinkOutlineRegular, MarkdownText } from '../../ui/official.js';
4
+ // > [running] visuallyHidden「正在思考」
5
+ // > DisclosureRow(icon=IconThinkOutlineRegular 14px,title=t("message.think")=「思考」,running ⇒ 整行 shimmer)
6
+ // collapsedContent = separator(data-shimmer-decoration, 2×2px) + summary[data-streaming]
7
+ // > summaryText > TextShimmer(summary)
8
+ // content = thinkBody > MarkdownText(compact, streaming=running)
9
+ // 折叠态 root 固定一行高(contain:size layout + height 24px+delta);[data-preview] 缺失 ⇒ separator/summary 隐藏。
10
+ import { Fragment, createElement as h, useMemo, useState } from 'react';
11
+ import { DisclosureRow, IconThinkOutlineRegular, MarkdownText, TextShimmer } from '../../ui/official.js';
9
12
  import { officialClass } from '../official-classes.js';
10
13
  import { markdownLabels } from '../../explorer/preview/md-labels.js';
11
- /** 官方 firstLine(lib/client.js:5687):首行。 */
14
+ /** 官方 firstLine(lib/client.js:6140 区):首行。 */
12
15
  function firstLine(text) {
13
16
  const newline = text.indexOf('\n');
14
17
  return newline === -1 ? text : text.slice(0, newline);
15
18
  }
19
+ /** 官方 reasoningText:剥掉模型签名包裹(`<signature>…</signature>`),无可见内容返回空串。 */
20
+ function reasoningText(text) {
21
+ if (text[0] !== '<')
22
+ return text;
23
+ const opening = '<signature>';
24
+ if (opening.startsWith(text))
25
+ return '';
26
+ if (!text.startsWith(opening))
27
+ return text;
28
+ const end = text.indexOf('</signature>', 11);
29
+ if (end === -1)
30
+ return '';
31
+ let start = end + 12;
32
+ while (start < text.length) {
33
+ if (text[start] === '\n')
34
+ start += 1;
35
+ else if (text[start] === '\r' && text[start + 1] === '\n')
36
+ start += 2;
37
+ else
38
+ break;
39
+ }
40
+ return text.slice(start);
41
+ }
42
+ /** 官方 latestCompletedParagraphFirstLine:最后一段已结束段落的首行(流式预览用)。 */
43
+ function latestCompletedParagraphFirstLine(text) {
44
+ let summary = '';
45
+ let paragraphStart = 0;
46
+ const separator = /\r?\n(?:[\t ]*\r?\n)+/g;
47
+ for (;;) {
48
+ const nextParagraph = separator.exec(text);
49
+ const paragraphEnd = nextParagraph === null ? text.length : nextParagraph.index + nextParagraph[0].indexOf('\n');
50
+ const newline = text.indexOf('\n', paragraphStart);
51
+ if (newline !== -1 && newline <= paragraphEnd) {
52
+ const candidate = text.slice(paragraphStart, newline).trim();
53
+ if (candidate !== '')
54
+ summary = candidate;
55
+ }
56
+ if (nextParagraph === null)
57
+ return summary;
58
+ paragraphStart = nextParagraph.index + nextParagraph[0].length;
59
+ }
60
+ }
16
61
  /** 思考行:折叠 = 「思考 · 首行预览 ⌄」;展开 = thinkBody 全文(MarkdownText compact)。 */
17
62
  export function ReasoningRowMirror(props) {
18
- const { text, running = false, preview = true, t } = props;
63
+ const { text: rawText, running = false, preview: settledPreview = true, t } = props;
19
64
  const [open, setOpen] = useState(false);
20
- if (text.trim() === '')
65
+ const text = useMemo(() => reasoningText(rawText), [rawText]);
66
+ if (text !== rawText && text.trim() === '')
21
67
  return null;
68
+ const summaryText = running ? latestCompletedParagraphFirstLine(text) : firstLine(text);
22
69
  // lib 目标是 ES2020(无 String.replaceAll)⇒ split/join 等价去 `**`。
23
- const summary = firstLine(text).split('**').join('');
70
+ const summary = summaryText.split('**').join('');
71
+ const preview = !open && summary !== '' && (running || settledPreview);
24
72
  return h('div', {
25
73
  className: officialClass('ReasoningRow', 'root') ?? '',
26
74
  'data-variant': 'think',
27
75
  'data-state': running ? 'running' : 'ok',
28
76
  'data-expanded': open || undefined,
29
- 'data-preview': preview && summary !== '' || undefined,
30
- }, h(DisclosureRow, {
77
+ 'data-preview': preview || undefined,
78
+ }, running
79
+ ? h('span', { className: officialClass('accessibility', 'visuallyHidden') ?? '' }, t('reasoningRunning'))
80
+ : null, h(DisclosureRow, {
31
81
  icon: h(IconThinkOutlineRegular, { size: 14 }),
32
82
  title: t('thinkLabel'),
83
+ running,
33
84
  open,
34
85
  expandable: true,
35
86
  expandOnRowClick: true,
@@ -37,12 +88,23 @@ export function ReasoningRowMirror(props) {
37
88
  rowClassName: officialClass('ReasoningRow', 'row') ?? '',
38
89
  leadingClassName: officialClass('ReasoningRow', 'leading') ?? '',
39
90
  titleClassName: officialClass('ReasoningRow', 'title') ?? '',
40
- chevronClassName: officialClass('ReasoningRow', 'chevron') ?? '',
41
- collapsedContent: h(Fragment, null, h('span', { className: officialClass('ReasoningRow', 'separator') ?? '', 'aria-hidden': true }),
91
+ collapsedContent: h(Fragment, null, h('span', {
92
+ className: officialClass('ReasoningRow', 'separator') ?? '',
93
+ 'data-shimmer-decoration': true,
94
+ 'aria-hidden': true,
95
+ }),
42
96
  // 官方是 summary > summaryText 两层:外层 nowrap 截断、内层 text-overflow:ellipsis(省略号)。
43
- h('span', { className: officialClass('ReasoningRow', 'summary') ?? '' }, h('span', { className: officialClass('ReasoningRow', 'summaryText') ?? '' }, summary))),
97
+ h('span', {
98
+ className: officialClass('ReasoningRow', 'summary') ?? '',
99
+ 'data-streaming': running || undefined,
100
+ }, h('span', { className: officialClass('ReasoningRow', 'summaryText') ?? '' }, h(TextShimmer, null, summary)))),
44
101
  children: open
45
- ? h('div', { className: officialClass('ReasoningRow', 'thinkBody') ?? '' }, h(MarkdownText, { text, labels: markdownLabels(), variant: 'compact' }))
102
+ ? h('div', { className: officialClass('ReasoningRow', 'thinkBody') ?? '' }, h(MarkdownText, {
103
+ text,
104
+ streaming: running,
105
+ labels: markdownLabels(),
106
+ variant: 'compact',
107
+ }))
46
108
  : undefined,
47
109
  }));
48
110
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ReasoningRow.js","sourceRoot":"","sources":["../../../src/session/mirror/ReasoningRow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ReasoningRow.js","sourceRoot":"","sources":["../../../src/session/mirror/ReasoningRow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { createElement as h } from 'react';
2
+ import type { Translate } from '../../utils/i18n.js';
3
+ /**
4
+ * 运行中状态行:会话流末尾一行「深度求索中,用时 N 秒 ···」(蓝色 shimmer)。
5
+ * @param startTime - 当前 turn 开始时间;undefined = 尚未起轮(只显示「深度求索中」)。
6
+ * @param t - 翻译席位。
7
+ */
8
+ export declare function RunningStatusMirror(props: {
9
+ startTime: number | undefined;
10
+ t: Translate;
11
+ }): ReturnType<typeof h>;
12
+ //# sourceMappingURL=RunningStatus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RunningStatus.d.ts","sourceRoot":"","sources":["../../../src/session/mirror/RunningStatus.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAuB,MAAM,OAAO,CAAA;AAG/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAuBpD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,CAAC,EAAE,SAAS,CAAA;CACb,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CA+BvB"}
@@ -0,0 +1,57 @@
1
+ // 官方对照:ui-chat@0.2.1-rc.5 lib/client.js:5580-5638(RunningWhaleTail + RunningStatus;
2
+ // 0.2.2-alpha.3 仅多 paused/holding 两个占位参数,默认渲染同构)
3
+ // root div.running[data-chat-running]
4
+ // > visuallyHidden(role=status) > runningDivider(.5px 顶部横线,官方 CSS 按「前一项是否 tail」显隐)
5
+ // > runningContent > runningIcon(鲸尾:animated APNG mask + still SVG 兜底)+ TextShimmer(label)
6
+ // label:startTime 缺失 =「深度求索中」;否则「深度求索中,用时 {duration} ···」(duration = formatRunDuration)。
7
+ // ⚠ 0.2.x 起运行态只由这一行代表:turn 未关闭时官方 TurnProcessNodeView 整块不渲染(见 TurnProcessNodeView.ts)。
8
+ import { createElement as h, useEffect, useState } from 'react';
9
+ import { TextShimmer } from '../../ui/official.js';
10
+ import { officialClass } from '../official-classes.js';
11
+ import { durationText, formatRunDuration } from './message-chrome.js';
12
+ /** 官方 LIVE_RUN_CLOCK_INTERVAL_MS(lib/client.js:979)。 */
13
+ const LIVE_RUN_CLOCK_INTERVAL_MS = 1000;
14
+ /** 官方静态兜底 SVG 的鲸尾路径(lib/client.js:6340 REST_PATH,16×16)。 */
15
+ const REST_PATH = 'M8.844 13.742C8.967 12.328 8.45 10.4 8.45 9.65C8.45 8.94 8.88 8.43 9.6 8.43C11.285 8.43 12.106 8.281 12.685 8.104C13.71 7.791 14.585 6.768 15.055 5.945C15.137 5.803 14.99 5.641 14.829 5.671C13.829 5.86 12.828 5.376 11.827 4.978C10.659 4.514 9.491 4.707 8.935 4.876C8.805 4.915 8.658 4.819 8.636 4.686C8.468 3.643 7.405 2.615 5.498 2.238C4.54 2.048 3.748 1.574 3.347 1.202C3.252 1.113 3.088 1.125 3.03 1.242C2.628 2.059 2.168 3.82 5.248 6.115C5.82 6.494 6.31 6.785 6.574 7.637C6.72 8.104 6.157 9.168 6.061 9.368C5.157 11.27 5.089 12.19 4.926 13.742';
16
+ /** 官方 RunningWhaleTail:APNG mask 动画(官方 CSS 提供资源)+ 静态 SVG 兜底。 */
17
+ function RunningWhaleTail() {
18
+ return h('span', { className: officialClass('ChatView', 'runningIcon') ?? '', 'aria-hidden': 'true' }, h('span', { className: officialClass('ChatView', 'runningWhaleAnimated') ?? '' }), h('svg', {
19
+ className: officialClass('ChatView', 'runningWhaleStill') ?? '',
20
+ width: '100%',
21
+ height: '100%',
22
+ viewBox: '0 0 16 16',
23
+ fill: 'none',
24
+ }, h('path', { d: REST_PATH, stroke: 'currentColor', strokeWidth: 1 })));
25
+ }
26
+ /**
27
+ * 运行中状态行:会话流末尾一行「深度求索中,用时 N 秒 ···」(蓝色 shimmer)。
28
+ * @param startTime - 当前 turn 开始时间;undefined = 尚未起轮(只显示「深度求索中」)。
29
+ * @param t - 翻译席位。
30
+ */
31
+ export function RunningStatusMirror(props) {
32
+ const { startTime, t } = props;
33
+ const [now, setNow] = useState(() => Date.now());
34
+ useEffect(() => {
35
+ if (startTime === undefined)
36
+ return;
37
+ setNow(Date.now());
38
+ const timer = setInterval(() => { setNow(Date.now()); }, LIVE_RUN_CLOCK_INTERVAL_MS);
39
+ return () => { clearInterval(timer); };
40
+ }, [startTime]);
41
+ const label = startTime === undefined
42
+ ? t('chatDeepDiving')
43
+ : t('chatDeepDivingFor', { duration: durationText(formatRunDuration(Math.max(1000, now - startTime), t)) });
44
+ return h('div', {
45
+ className: officialClass('ChatView', 'running') ?? '',
46
+ 'data-chat-running': true,
47
+ }, h('span', {
48
+ className: officialClass('accessibility', 'visuallyHidden') ?? '',
49
+ role: 'status',
50
+ 'aria-live': 'polite',
51
+ 'aria-atomic': 'true',
52
+ }, t('chatDeepDiving')), h('span', { className: officialClass('ChatView', 'runningDivider') ?? '', 'aria-hidden': 'true' }), h('span', { className: officialClass('ChatView', 'runningContent') ?? '' }, h(RunningWhaleTail, null), h(TextShimmer, {
53
+ active: true,
54
+ className: officialClass('ChatView', 'runningText') ?? '',
55
+ }, label)));
56
+ }
57
+ //# sourceMappingURL=RunningStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RunningStatus.js","sourceRoot":"","sources":["../../../src/session/mirror/RunningStatus.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TurnProcessNodeView.d.ts","sourceRoot":"","sources":["../../../src/session/mirror/TurnProcessNodeView.ts"],"names":[],"mappings":"AAQA,OAAO,EAAY,aAAa,IAAI,CAAC,EAAuB,MAAM,OAAO,CAAA;AAGzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAM5E,qDAAqD;AACrD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE;IAC/C,IAAI,EAAE,gBAAgB,GAAG,SAAS,CAAA;IAClC,WAAW,EAAE,iBAAiB,CAAA;IAC9B,CAAC,EAAE,SAAS,CAAA;CACb,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CAuD9B"}
1
+ {"version":3,"file":"TurnProcessNodeView.d.ts","sourceRoot":"","sources":["../../../src/session/mirror/TurnProcessNodeView.ts"],"names":[],"mappings":"AASA,OAAO,EAAY,aAAa,IAAI,CAAC,EAAE,MAAM,OAAO,CAAA;AAGpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAG5E,qDAAqD;AACrD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE;IAC/C,IAAI,EAAE,gBAAgB,GAAG,SAAS,CAAA;IAClC,WAAW,EAAE,iBAAiB,CAAA;IAC9B,CAAC,EAAE,SAAS,CAAA;CACb,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CAiD9B"}
@@ -1,56 +1,42 @@
1
- // 官方对照:packages/client/ui-chat/src/client/chat/TurnProcessNodeView.tsx(0.1.7-rc.2 lib/client.js:6129-6196)
1
+ // 官方对照:packages/client/ui-chat@0.2.2-alpha.3 lib/client.js:8668-8730(TurnProcessNodeView)
2
2
  // root(button,高 calc(33px + delta)、border-bottom .5px border-l2、padding 0 0 8px、flex)
3
- // :disabled{cursor:default} / :not(:disabled):hover{color:primary} / :not([data-open]){margin-bottom:8px}
4
- // > label(13px,ellipsis)> chevron(14px caption,[data-open] 旋转 180°)
5
- // label 官方文案(源码 6167-6170 逐字):
6
- // running → 「深度求索中,用时D」;aborted → 「已停止」;error → 「处理失败」;
7
- // 其余 → 有时长「用时 D」、无时长「已完成工作」。D 由 turn 位置(start/end)算出,下限 1 秒。
8
- // 这就是官方原图里那行「用时 34 秒 ⌄」——它把整个 turn 的过程(工具调用 / 中间文本 / 思考)折在下面。
9
- import { Fragment, createElement as h, useEffect, useState } from 'react';
3
+ // :disabled{cursor:default} / :hover:not(:disabled){color:secondary} / [data-open] 内 chevron 旋转 180°
4
+ // > label(13px,ellipsis)> chevron(14px,color:inherit)
5
+ // label:stopped(aborted/interrupted)→「已停止」;error →「处理失败」;
6
+ // 有时长 →「已完成,用时 」+ duration parts(数字段套 durationNumber 等宽数字);无时长 →「已完成」。
7
+ // ⚠ 0.2.x 起 turn 未关闭时**整块不渲染**(`turn?.status !== "closed"` return null)——
8
+ // 运行中的「深度求索中,用时 N 秒 ···」改由 ChatView 的 RunningStatus 在流末尾单独一行显示
9
+ // (见 RunningStatus.ts)。别再把 running 分支加回来,否则与官方重叠出两行。
10
+ import { Fragment, createElement as h } from 'react';
10
11
  import { IconChevronDownOutlineRegular } from '../../ui/official.js';
11
12
  import { officialClass } from '../official-classes.js';
12
- import { formatLiveRunDuration, formatRunDuration } from './message-chrome.js';
13
- /** 官方 LIVE_RUN_CLOCK_INTERVAL_MS(lib/client.js:979)。 */
14
- const LIVE_RUN_CLOCK_INTERVAL_MS = 1000;
13
+ import { formatRunDuration } from './message-chrome.js';
15
14
  /** Turn 过程行:折叠时只有 label + 箭头;点开由外层 seat 把过程节点放出来。 */
16
15
  export function TurnProcessNodeViewMirror(props) {
17
16
  const { turn, turnProcess, t } = props;
18
- const open = !turnProcess.foldable || turnProcess.open;
19
- const [now, setNow] = useState(() => Date.now());
20
- const ticking = turn?.status === 'open' && turn.start !== undefined;
21
- useEffect(() => {
22
- if (!ticking)
23
- return;
24
- setNow(Date.now());
25
- const timer = setInterval(() => { setNow(Date.now()); }, LIVE_RUN_CLOCK_INTERVAL_MS);
26
- return () => { clearInterval(timer); };
27
- }, [ticking]);
28
- if (turn === undefined || (turn.start === undefined && turn.status !== 'closed'))
17
+ if (turn === undefined || turn.status !== 'closed')
29
18
  return null;
19
+ const open = !turnProcess.foldable || turnProcess.open;
30
20
  const canCollapse = turnProcess.foldable && turnProcess.hasContent && !turnProcess.alwaysOpen;
31
- const running = turn.status === 'open';
32
21
  const reason = turn.end?.data?.reason?.kind;
33
- const elapsedMs = turn.start === undefined ? undefined : Math.max(1000, (turn.end?.time ?? now) - turn.start.time);
34
- const duration = elapsedMs === undefined
22
+ const stopped = reason === 'aborted' || reason === 'interrupted';
23
+ const elapsedMs = turn.start === undefined || turn.end === undefined
24
+ ? undefined
25
+ : Math.max(1000, turn.end.time - turn.start.time);
26
+ const duration = elapsedMs === undefined || stopped || reason === 'error'
35
27
  ? undefined
36
- : running ? formatLiveRunDuration(elapsedMs, t) : formatRunDuration(elapsedMs, t);
37
- const label = running
38
- ? (duration === undefined ? t('chatDeepDiving') : t('turnProcessDeepDiving', { duration }))
39
- : reason === 'aborted' ? t('turnStopped')
40
- : reason === 'error' ? t('turnProcessFailed')
41
- : duration === undefined ? t('turnProcessWorked') : t('turnProcessTook', { duration });
42
- const announcement = running
43
- ? t('chatDeepDiving')
44
- : reason === 'aborted' ? t('turnStopped')
45
- : reason === 'error' ? t('turnProcessFailed')
46
- : t('turnProcessWorked');
28
+ : formatRunDuration(elapsedMs, t);
29
+ const label = stopped ? t('turnStopped')
30
+ : reason === 'error' ? t('turnProcessFailed')
31
+ : duration === undefined ? t('turnProcessWorked') : t('turnProcessTook');
32
+ const durationNumberClass = officialClass('TurnProcessNodeView', 'durationNumber') ?? undefined;
47
33
  const spec = turnProcess.spec;
48
34
  return h(Fragment, null, h('span', {
49
35
  className: officialClass('accessibility', 'visuallyHidden') ?? '',
50
36
  role: 'status',
51
37
  'aria-live': 'polite',
52
38
  'aria-atomic': 'true',
53
- }, announcement), h('button', {
39
+ }, stopped ? t('turnStopped') : reason === 'error' ? t('turnProcessFailed') : t('turnProcessWorked')), h('button', {
54
40
  type: 'button',
55
41
  className: officialClass('TurnProcessNodeView', 'root') ?? '',
56
42
  'data-open': open || undefined,
@@ -61,7 +47,10 @@ export function TurnProcessNodeViewMirror(props) {
61
47
  disabled: !canCollapse,
62
48
  'aria-expanded': turnProcess.hasContent ? open : undefined,
63
49
  onClick: () => { turnProcess.setOpen(!open); },
64
- }, h('span', { className: officialClass('TurnProcessNodeView', 'label') ?? '' }, label), canCollapse
50
+ }, h('span', { className: officialClass('TurnProcessNodeView', 'label') ?? '' }, label, duration?.map((part, index) => h('span', {
51
+ key: index,
52
+ className: part.numeric ? durationNumberClass : undefined,
53
+ }, part.text))), canCollapse
65
54
  ? h(IconChevronDownOutlineRegular, { className: officialClass('TurnProcessNodeView', 'chevron') ?? '' })
66
55
  : null));
67
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TurnProcessNodeView.js","sourceRoot":"","sources":["../../../src/session/mirror/TurnProcessNodeView.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TurnProcessNodeView.js","sourceRoot":"","sources":["../../../src/session/mirror/TurnProcessNodeView.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { createElement as h, type ReactNode } from 'react';
2
2
  import type { Translate } from '../../utils/i18n.js';
3
+ import type { ChatNodeStoreFace } from '../faces.js';
3
4
  import { type TurnTokenUsageFace } from './TurnUsagePanel.js';
4
5
  /** 官方 AssistantContentBlock 的消费面(只用到 kind / text)。 */
5
6
  interface ContentBlockFace {
@@ -13,12 +14,34 @@ export interface TurnTailDataFace {
13
14
  closing: {
14
15
  time: number;
15
16
  blocks: ReadonlyArray<ContentBlockFace>;
17
+ /** 官方 closing.finalNode.seq(判定「该轮之后还有内容」用)。 */
18
+ finalNode?: {
19
+ seq: number;
20
+ };
16
21
  } | null;
17
22
  branchUnavailable?: boolean;
18
23
  tokenUsage?: TurnTokenUsageFace;
19
24
  }
20
25
  /** 官方 hasAssistantReplyContent。 */
21
26
  export declare function hasAssistantReplyContent(blocks: ReadonlyArray<ContentBlockFace>): boolean;
27
+ /** 尾部操作行要的两个判定(官方用 nodeStore 快照算;这里按同一 order/store 预计算)。 */
28
+ export interface TurnTailFacts {
29
+ /** 官方 endsWithResponse:操作行常显(true)还是悬停才显(false)。 */
30
+ endsWithResponse(turn: number): boolean;
31
+ /** 官方 hasLaterChatNode:该轮之后还有内容(分支不可用)。 */
32
+ hasLaterChatNode(turn: number, anchorSeq: number): boolean;
33
+ }
34
+ /**
35
+ * 按 order + nodeStore 预计算尾部事实。
36
+ * @param props.order - 渲染顺序(官方 order)。
37
+ * @param props.store - 节点仓库。
38
+ * @param props.lastTurn - 最后一轮的 turn 号(官方 timeline.turnOrder.at(-1))。
39
+ */
40
+ export declare function buildTurnTailFacts(props: {
41
+ order: readonly string[];
42
+ store: ChatNodeStoreFace;
43
+ lastTurn: number | undefined;
44
+ }): TurnTailFacts;
22
45
  /** Turn 尾部操作行:复制 / 分支 / 用量 / 结束时钟。 */
23
46
  export declare function TurnTailNodeViewMirror(props: {
24
47
  data: TurnTailDataFace;
@@ -26,6 +49,8 @@ export declare function TurnTailNodeViewMirror(props: {
26
49
  onBranchAt?: (seq: number) => void;
27
50
  /** 官方 conversation.chat.turnTail 插槽内容(如 DeliverablesTail),渲染在操作行之前。 */
28
51
  tailSlot?: ReactNode;
52
+ /** 官方 endsWithResponse / hasLaterChatNode(undefined = 操作行常显、分支可用)。 */
53
+ facts?: TurnTailFacts;
29
54
  t: Translate;
30
55
  }): ReturnType<typeof h> | null;
31
56
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"TurnTailNodeView.d.ts","sourceRoot":"","sources":["../../../src/session/mirror/TurnTailNodeView.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAEpD,OAAO,EAAwB,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAEnF,sDAAsD;AACtD,UAAU,gBAAgB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,sEAAsE;AACtE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAA;KAAE,GAAG,IAAI,CAAA;IACzE,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,UAAU,CAAC,EAAE,kBAAkB,CAAA;CAChC;AAED,mCAAmC;AACnC,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAMzF;AAOD,sCAAsC;AACtC,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,IAAI,EAAE,gBAAgB,CAAA;IACtB,kDAAkD;IAClD,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,CAAC,EAAE,SAAS,CAAA;CACb,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CAuB9B"}
1
+ {"version":3,"file":"TurnTailNodeView.d.ts","sourceRoot":"","sources":["../../../src/session/mirror/TurnTailNodeView.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,KAAK,EAAgB,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAGlE,OAAO,EAAwB,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAEnF,sDAAsD;AACtD,UAAU,gBAAgB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,sEAAsE;AACtE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAA;QACvC,+CAA+C;QAC/C,SAAS,CAAC,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,CAAA;KAC5B,GAAG,IAAI,CAAA;IACR,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,UAAU,CAAC,EAAE,kBAAkB,CAAA;CAChC;AAED,mCAAmC;AACnC,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAMzF;AAkBD,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IACvC,2CAA2C;IAC3C,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAA;CAC3D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,KAAK,EAAE,iBAAiB,CAAA;IACxB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;CAC7B,GAAG,aAAa,CA8BhB;AAED,sCAAsC;AACtC,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,IAAI,EAAE,gBAAgB,CAAA;IACtB,kDAAkD;IAClD,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,sEAAsE;IACtE,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,CAAC,EAAE,SAAS,CAAA;CACb,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI,CA0B9B"}
@@ -1,11 +1,13 @@
1
- // 官方对照:packages/client/ui-chat/src/client/chat/TurnTailNodeView.tsx(0.1.7-rc.2 lib/client.js:6460-6546)
2
- // root(flex column,gap 16px)> actions(margin-top 4px / margin-left -6px)
3
- // data-turn-tail = turn;data-actions-reveal 官方 = always(最后一轮且有回复)| hover(历史轮,悬停才显);
4
- // 弹窗偏差(用户拍板 2026-09-27):归档会话轮数少,恒 'always' 每轮操作行全部常显,不做 hover 显隐。
1
+ // 官方对照:ui-chat@0.2.1-rc.5 lib/client.js:6986-7045(lastContent / TurnTailNodeView)
2
+ // root(flex column,gap 16px)> [tailSlot] > actions(margin-top 4px / margin-left -6px)
3
+ // data-turn-tail = turn;data-actions-reveal = endsWithResponse ? "always" : "hover"
4
+ // endsWithResponse = 该轮是最后一场 turn,且该轮最后一条内容节点的最后一个可见块算「回复」
5
+ // (reasoning / tool-call 不算,空文本不算)——官方据此决定操作行常显还是悬停才显。
5
6
  // closing === null(本轮没有回复)⇒ 只留 turnTail 插槽;弹窗无插槽 ⇒ 整块不渲染。
6
- // hasAssistantReplyContent(lib/client.js:6466):reasoning / tool-call 不算回复,空文本不算。
7
+ // branchUnavailable = data.branchUnavailable || hasLaterChatNode(该轮之后还有内容 ⇒ 不能从这轮开分支)。
7
8
  import { createElement as h } from 'react';
8
9
  import { officialClass } from '../official-classes.js';
10
+ import { turnOf } from './ChatNodeSeat.js';
9
11
  import { MessageIconActionsMirror } from './MessageIconActions.js';
10
12
  import { TurnUsagePanelMirror } from './TurnUsagePanel.js';
11
13
  /** 官方 hasAssistantReplyContent。 */
@@ -22,17 +24,71 @@ export function hasAssistantReplyContent(blocks) {
22
24
  function assistantText(blocks) {
23
25
  return blocks.flatMap(block => (block.kind === 'text' ? [block.text ?? ''] : [])).join('');
24
26
  }
27
+ /** 官方 lastContent:该轮最后一个内容节点(跳过 turn-tail / turn-process,可选跳过 turn-max-tokens)。 */
28
+ function lastContent(nodes, skipMaxTokens) {
29
+ for (let index = nodes.length - 1; index >= 0; index--) {
30
+ const node = nodes[index];
31
+ if (node === undefined || node.kind === 'turn-tail' || node.kind === 'turn-process')
32
+ continue;
33
+ if (skipMaxTokens && node.kind === 'turn-max-tokens')
34
+ continue;
35
+ return node;
36
+ }
37
+ return undefined;
38
+ }
39
+ /**
40
+ * 按 order + nodeStore 预计算尾部事实。
41
+ * @param props.order - 渲染顺序(官方 order)。
42
+ * @param props.store - 节点仓库。
43
+ * @param props.lastTurn - 最后一轮的 turn 号(官方 timeline.turnOrder.at(-1))。
44
+ */
45
+ export function buildTurnTailFacts(props) {
46
+ const { order, store, lastTurn } = props;
47
+ const nodesOfTurn = (turn) => {
48
+ const out = [];
49
+ for (const key of order) {
50
+ const node = store.get(key);
51
+ if (node !== undefined && turnOf(node) === turn)
52
+ out.push(node);
53
+ }
54
+ return out;
55
+ };
56
+ return {
57
+ endsWithResponse(turn) {
58
+ if (lastTurn !== turn)
59
+ return false;
60
+ const last = lastContent(nodesOfTurn(turn), false);
61
+ const blocks = last?.kind === 'assistant-step' ? last.data?.blocks : undefined;
62
+ if (!Array.isArray(blocks))
63
+ return false;
64
+ for (let index = blocks.length - 1; index >= 0; index--) {
65
+ const block = blocks[index];
66
+ if (block === undefined)
67
+ continue;
68
+ // 官方 findLast 条件:非 text/reasoning 块,或文本非空。
69
+ if ((block.kind !== 'text' && block.kind !== 'reasoning') || (block.text ?? '').trim() !== '') {
70
+ return hasAssistantReplyContent([block]);
71
+ }
72
+ }
73
+ return false;
74
+ },
75
+ hasLaterChatNode(turn, anchorSeq) {
76
+ return (lastContent(nodesOfTurn(turn), true)?.anchorSeq ?? -1) > anchorSeq;
77
+ },
78
+ };
79
+ }
25
80
  /** Turn 尾部操作行:复制 / 分支 / 用量 / 结束时钟。 */
26
81
  export function TurnTailNodeViewMirror(props) {
27
- const { data, onBranchAt, tailSlot, t } = props;
82
+ const { data, onBranchAt, tailSlot, facts, t } = props;
28
83
  const closing = data.closing;
29
84
  if (closing === null || closing === undefined)
30
85
  return null;
31
86
  const text = assistantText(closing.blocks);
87
+ const anchorSeq = closing.finalNode?.seq ?? data.seq;
32
88
  return h('div', {
33
89
  className: officialClass('TurnTailNodeView', 'root') ?? '',
34
90
  'data-turn-tail': data.turn,
35
- 'data-actions-reveal': 'always',
91
+ 'data-actions-reveal': facts === undefined || facts.endsWithResponse(data.turn) ? 'always' : 'hover',
36
92
  }, tailSlot === undefined || tailSlot === null ? null : tailSlot, h(MessageIconActionsMirror, {
37
93
  text,
38
94
  time: closing.time,
@@ -40,6 +96,8 @@ export function TurnTailNodeViewMirror(props) {
40
96
  // 分支:点分支 = 确认框 → fork({ atSeq: 该轮 tail seq })——从这条消息位置截断开分支;
41
97
  // 头部按钮 = 省略 atSeq(最新已完成 turn 前缀)。
42
98
  onBranch: onBranchAt === undefined ? undefined : () => { onBranchAt(data.seq); },
99
+ branchUnavailable: data.branchUnavailable === true
100
+ || facts?.hasLaterChatNode(data.turn, anchorSeq),
43
101
  className: officialClass('TurnTailNodeView', 'actions') ?? '',
44
102
  usageAction: data.tokenUsage === undefined ? undefined : h(TurnUsagePanelMirror, { usage: data.tokenUsage, t }),
45
103
  t,
@@ -1 +1 @@
1
- {"version":3,"file":"TurnTailNodeView.js","sourceRoot":"","sources":["../../../src/session/mirror/TurnTailNodeView.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,2EAA2E;AAC3E,sFAAsF;AACtF,oEAAoE;AACpE,4DAA4D;AAC5D,iFAAiF;AACjF,OAAO,EAAE,aAAa,IAAI,CAAC,EAAkB,MAAM,OAAO,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAEtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,EAAE,oBAAoB,EAA2B,MAAM,qBAAqB,CAAA;AAiBnF,mCAAmC;AACnC,MAAM,UAAU,wBAAwB,CAAC,MAAuC;IAC9E,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;YAAE,OAAO,KAAK,CAAA;QAC1E,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAA;QAClE,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,kCAAkC;AAClC,SAAS,aAAa,CAAC,MAAuC;IAC5D,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AAC5F,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,sBAAsB,CAAC,KAOtC;IACC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,KAAK,CAAA;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;IAC5B,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IAC1D,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAC1C,OAAO,CAAC,CAAC,KAAK,EAAE;QACd,SAAS,EAAE,aAAa,CAAC,kBAAkB,EAAE,MAAM,CAAC,IAAI,EAAE;QAC1D,gBAAgB,EAAE,IAAI,CAAC,IAAI;QAC3B,qBAAqB,EAAE,QAAQ;KAChC,EACC,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAC7D,CAAC,CAAC,wBAAwB,EAAE;QAC1B,IAAI;QACJ,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,KAAK,EAAE,KAAK;QACZ,6DAA6D;QAC7D,kCAAkC;QAClC,QAAQ,EAAE,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA,CAAC,CAAC;QAC/E,SAAS,EAAE,aAAa,CAAC,kBAAkB,EAAE,SAAS,CAAC,IAAI,EAAE;QAC7D,WAAW,EAAE,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC;QAC/G,CAAC;KACF,CAAC,CACH,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"TurnTailNodeView.js","sourceRoot":"","sources":["../../../src/session/mirror/TurnTailNodeView.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TurnTriggerNodeView.d.ts","sourceRoot":"","sources":["../../../src/session/mirror/TurnTriggerNodeView.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAY,MAAM,OAAO,CAAA;AAepD,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAiBpE,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAmB3F;AAED,6CAA6C;AAC7C,wBAAgB,yBAAyB,CAAC,KAAK,EAAE;IAC/C,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;IACzC,CAAC,EAAE,SAAS,CAAA;CACb,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CA0CvB"}
1
+ {"version":3,"file":"TurnTriggerNodeView.d.ts","sourceRoot":"","sources":["../../../src/session/mirror/TurnTriggerNodeView.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,aAAa,IAAI,CAAC,EAAmB,MAAM,OAAO,CAAA;AAe3D,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAoBpE,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAmB3F;AAED,6CAA6C;AAC7C,wBAAgB,yBAAyB,CAAC,KAAK,EAAE;IAC/C,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;IACzC,CAAC,EAAE,SAAS,CAAA;CACb,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAiDvB"}