@qilin-agent/client-ui-chat 0.0.0-stage → 3.1.4

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 (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.i18n.yaml +55 -0
  3. package/README.md +132 -2
  4. package/README.zh.md +134 -0
  5. package/lib/client.js +13900 -0
  6. package/lib/index.js +54 -0
  7. package/lib/types/chat-settings.d.ts +47 -0
  8. package/lib/types/client/apply.d.ts +15 -0
  9. package/lib/types/client/chat/ApprovalCommand.d.ts +20 -0
  10. package/lib/types/client/chat/AssistantMarkdown.d.ts +52 -0
  11. package/lib/types/client/chat/AssistantNodeView.d.ts +7 -0
  12. package/lib/types/client/chat/ChatFlow.d.ts +4 -0
  13. package/lib/types/client/chat/ChatGroupSeat.d.ts +15 -0
  14. package/lib/types/client/chat/ChatNodeSeat.d.ts +25 -0
  15. package/lib/types/client/chat/ChatView.d.ts +7 -0
  16. package/lib/types/client/chat/CommandNodeView.d.ts +9 -0
  17. package/lib/types/client/chat/CompactionCommandCard.d.ts +8 -0
  18. package/lib/types/client/chat/CompactionItem.d.ts +19 -0
  19. package/lib/types/client/chat/ContextBody.d.ts +131 -0
  20. package/lib/types/client/chat/ContextInjectionRow.d.ts +26 -0
  21. package/lib/types/client/chat/GenericCommandCard.d.ts +9 -0
  22. package/lib/types/client/chat/MessageIconActions.d.ts +37 -0
  23. package/lib/types/client/chat/MessageItem.d.ts +42 -0
  24. package/lib/types/client/chat/ReasoningContent.d.ts +16 -0
  25. package/lib/types/client/chat/ReasoningRow.d.ts +23 -0
  26. package/lib/types/client/chat/RunningSeal.d.ts +6 -0
  27. package/lib/types/client/chat/RunningStatus.d.ts +13 -0
  28. package/lib/types/client/chat/StatsPills.d.ts +71 -0
  29. package/lib/types/client/chat/SystemPromptRow.d.ts +22 -0
  30. package/lib/types/client/chat/TurnNavigator.d.ts +28 -0
  31. package/lib/types/client/chat/TurnProcessNodeView.d.ts +4 -0
  32. package/lib/types/client/chat/TurnTailNodeView.d.ts +7 -0
  33. package/lib/types/client/chat/TurnTriggerNodeView.d.ts +4 -0
  34. package/lib/types/client/chat/TurnUsagePanel.d.ts +15 -0
  35. package/lib/types/client/chat/flow-motion.d.ts +59 -0
  36. package/lib/types/client/chat/message-chrome.d.ts +50 -0
  37. package/lib/types/client/chat/register-node-renderers.d.ts +14 -0
  38. package/lib/types/client/chat/render-entry.d.ts +9 -0
  39. package/lib/types/client/chat/searchable-hidden.d.ts +17 -0
  40. package/lib/types/client/chat/stat-dialog.d.ts +20 -0
  41. package/lib/types/client/chat/step-process.d.ts +11 -0
  42. package/lib/types/client/chat/token-format.d.ts +25 -0
  43. package/lib/types/client/chat/turn-assistant.d.ts +8 -0
  44. package/lib/types/client/chat/turn-rail-items.d.ts +37 -0
  45. package/lib/types/client/chat/turn-trigger.d.ts +15 -0
  46. package/lib/types/client/chat/use-calendar-day.d.ts +6 -0
  47. package/lib/types/client/chat/use-chat-navigation.d.ts +69 -0
  48. package/lib/types/client/chat/use-chat-reading.d.ts +110 -0
  49. package/lib/types/client/chat/use-chat-scroll.d.ts +43 -0
  50. package/lib/types/client/chat/use-chat-viewport.d.ts +197 -0
  51. package/lib/types/client/chat/use-disclosure.d.ts +15 -0
  52. package/lib/types/client/chat/use-process-scroll.d.ts +23 -0
  53. package/lib/types/client/chat/use-scroll-follow.d.ts +106 -0
  54. package/lib/types/client/chat/use-turn-data.d.ts +9 -0
  55. package/lib/types/client/contract/assistant-content.d.ts +9 -0
  56. package/lib/types/client/contract/chat-nodes.d.ts +108 -0
  57. package/lib/types/client/contract/chat-visibility.d.ts +10 -0
  58. package/lib/types/client/contract/process-groups.d.ts +25 -0
  59. package/lib/types/client/contract/slots.d.ts +340 -0
  60. package/lib/types/client/contract/snapshot.d.ts +107 -0
  61. package/lib/types/client/contract/store.d.ts +15 -0
  62. package/lib/types/client/contract/turn-metrics.d.ts +19 -0
  63. package/lib/types/client/contract/turn-process.d.ts +40 -0
  64. package/lib/types/client/conversation-nodes/assistant.d.ts +36 -0
  65. package/lib/types/client/conversation-nodes/chat-snapshot-builder.d.ts +103 -0
  66. package/lib/types/client/conversation-nodes/command.d.ts +53 -0
  67. package/lib/types/client/conversation-nodes/common.d.ts +41 -0
  68. package/lib/types/client/conversation-nodes/compaction.d.ts +21 -0
  69. package/lib/types/client/conversation-nodes/event-projection.d.ts +63 -0
  70. package/lib/types/client/conversation-nodes/fallback.d.ts +16 -0
  71. package/lib/types/client/conversation-nodes/inbox.d.ts +40 -0
  72. package/lib/types/client/conversation-nodes/message.d.ts +42 -0
  73. package/lib/types/client/conversation-nodes/process-activity.d.ts +9 -0
  74. package/lib/types/client/conversation-nodes/process-groups.d.ts +27 -0
  75. package/lib/types/client/conversation-nodes/register.d.ts +7 -0
  76. package/lib/types/client/conversation-nodes/request-prompt.d.ts +44 -0
  77. package/lib/types/client/conversation-nodes/retry.d.ts +22 -0
  78. package/lib/types/client/conversation-nodes/tool.d.ts +23 -0
  79. package/lib/types/client/conversation-nodes/turn-error.d.ts +30 -0
  80. package/lib/types/client/conversation-nodes/turn-max-tokens.d.ts +22 -0
  81. package/lib/types/client/conversation-nodes/turn-navigation.d.ts +17 -0
  82. package/lib/types/client/conversation-nodes/turn-process-presentation.d.ts +30 -0
  83. package/lib/types/client/conversation-nodes/turn-process.d.ts +34 -0
  84. package/lib/types/client/conversation-nodes/turn-tail.d.ts +28 -0
  85. package/lib/types/client/index.d.ts +38 -0
  86. package/lib/types/client/locale.d.ts +386 -0
  87. package/lib/types/client/markdown-labels.d.ts +10 -0
  88. package/lib/types/client/model/conversation-context.d.ts +21 -0
  89. package/lib/types/client/model/tool-call-tree.d.ts +45 -0
  90. package/lib/types/client/performance-usage.d.ts +20 -0
  91. package/lib/types/client/presentation-policy.d.ts +37 -0
  92. package/lib/types/client/settings/LinkOpeningRow.d.ts +24 -0
  93. package/lib/types/client/settings/PerformanceUsageRow.d.ts +22 -0
  94. package/lib/types/client/settings/PreferenceRow.d.ts +18 -0
  95. package/lib/types/client/settings/TranscriptViewRow.d.ts +27 -0
  96. package/lib/types/client/stores.d.ts +30 -0
  97. package/lib/types/client/transcript-view.d.ts +35 -0
  98. package/lib/types/index.d.ts +6 -0
  99. package/package.json +106 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kkutysllb
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,55 @@
1
+ # Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
2
+ # section, a hash of its English and Chinese blocks outside code blocks and generated regions.
3
+ # After editing either side, bring the other along and re-record with:
4
+ # pnpm run verify-translation-pairing --write packages/client/ui-chat/README.md
5
+ /:
6
+ en: d88f75fc0178ba53
7
+ zh: 52bc7ae9551ab1cf
8
+ /qilin-agent-client-ui-chat:
9
+ en: 55cb66320f8c0adc
10
+ zh: df25aa9bcf226129
11
+ /qilin-agent-client-ui-chat/summary:
12
+ en: 98d792dbc1b1975e
13
+ zh: 96acf5c3a5165047
14
+ /qilin-agent-client-ui-chat/table-of-contents:
15
+ en: e7894dec53e4732d
16
+ zh: cdf9d812077b1741
17
+ /qilin-agent-client-ui-chat/reference-previews:
18
+ en: 66e17df4efe43eb8
19
+ zh: 82d91d704004d8f2
20
+ /qilin-agent-client-ui-chat/system-prompt-row:
21
+ en: 939728341ffbff11
22
+ zh: 74ec4ec5ca1fbd60
23
+ /qilin-agent-client-ui-chat/turn-token-usage:
24
+ en: a50c6802be7e4669
25
+ zh: 31233a9bd23fd04b
26
+ /qilin-agent-client-ui-chat/completed-turn-footer:
27
+ en: bb3e55382117d78f
28
+ zh: 75a2b59c1a5cf9ce
29
+ /qilin-agent-client-ui-chat/turn-process-folding:
30
+ en: d9b30a78f214ae90
31
+ zh: b33aef585fe6f756
32
+ /qilin-agent-client-ui-chat/grouped-rendering:
33
+ en: 60144aa1c496159f
34
+ zh: 67caa0891406578e
35
+ /qilin-agent-client-ui-chat/turn-triggers:
36
+ en: 4a2ec4ccc2f92b7c
37
+ zh: ac3f1402d0875ec4
38
+ /qilin-agent-client-ui-chat/tool-call-nodes:
39
+ en: 9d5d8bcce2e0e3c4
40
+ zh: ae109a2b3a807b92
41
+ /qilin-agent-client-ui-chat/scroll-ownership:
42
+ en: 65f44f8c91541f8f
43
+ zh: 9eec80f5360d936f
44
+ /qilin-agent-client-ui-chat/model-experience:
45
+ en: c17b4dd43a61c569
46
+ zh: f7414309810c3a08
47
+ /qilin-agent-client-ui-chat/model-experience/kv-cache-effect:
48
+ en: 15a7151ff9268f15
49
+ zh: 6eae68c718be579b
50
+ /qilin-agent-client-ui-chat/known-limitations-and-deferred-work:
51
+ en: f7e9784960922fb7
52
+ zh: 00df59b24fa66bf8
53
+ /qilin-agent-client-ui-chat/known-limitations-and-deferred-work/dev-note:
54
+ en: e67f633dc6fe7773
55
+ zh: e88aeb617ffb74ea
package/README.md CHANGED
@@ -1,3 +1,133 @@
1
- # Temporary Holding Version
1
+ ---
2
+ description: "Browser Chat target that renders Session conversation nodes, historical images, actions, localization, and scroll state."
3
+ kind: "package-reference"
4
+ ---
5
+ # @qilin-agent/client-ui-chat
2
6
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
7
+ English | [中文](README.zh.md)
8
+
9
+ ## Summary
10
+
11
+ Use this package to render a browser chat from recorded Session conversations, including historical images, localized actions, and restored scroll position. Compact display folds completed-turn process rows while keeping the final answer and independently useful context visible; packed historical Assistant runs remain collapsed. Local transcript and steering submissions appear immediately, remain in their original surface, and disappear atomically when authoritative Session records arrive, while queued submissions stay outside Chat. The package does not assemble or modify model requests.
12
+
13
+ File-mention providers receive the viewed Session ID with the closing-turn owner, so links into inherited history can address the fork itself.
14
+
15
+ ## Table of Contents
16
+
17
+ - [Reference previews](#reference-previews)
18
+ - [System prompt row](#system-prompt-row)
19
+ - [Turn token usage](#turn-token-usage)
20
+ - [Completed-turn footer](#completed-turn-footer)
21
+ - [Turn Process Folding](#turn-process-folding)
22
+ - [Grouped rendering](#grouped-rendering)
23
+ - [Turn triggers](#turn-triggers)
24
+ - [Tool call nodes](#tool-call-nodes)
25
+ - [Scroll ownership](#scroll-ownership)
26
+ - [Model Experience](#model-experience)
27
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
28
+ - [Dev Note](#dev-note)
29
+
30
+ -----
31
+
32
+ <a id="reference-previews"></a>
33
+ ## Reference previews
34
+
35
+ Chat supplies file and HTTP(S) navigation through one `MarkdownDelegateProvider` around its node list. Assistant Markdown file links open in the right Sidebar after the message settles, including references to unmodified files. Relative paths resolve in the viewed Session's workspace; absolute paths retain the same Session's filesystem access. `#L24` and `#L24-L30` navigate to the first specified line and reuse an existing file tab. Missing files show the preview's error state.
36
+
37
+ Standalone Markdown images show contained previews and open the shared image lightbox; local paths resolve against the viewed workspace after settlement. Image file links keep their sidebar activation and show a thumbnail after hover dwell or keyboard focus. Escape dismisses the thumbnail. Failed images retain a localized status and their description; no duplicate-image filtering is applied.
38
+
39
+ HTTP(S) links in Assistant Markdown open a new right-Sidebar Browser tab on ordinary clicks when that type is registered, or the system browser otherwise; modified clicks retain the native external-link behavior. Sent file references and skills confirmed by the message’s logged invocation also open in the right Sidebar. File paths use the viewed Session; skill names resolve through its current input-trigger source. Both use the prose file-link dotted underline on hover or focus. Sessions, directories, and command labels remain non-navigating references.
40
+
41
+ <a id="system-prompt-row"></a>
42
+ ## System prompt row
43
+
44
+ Each nonempty appended `system/message` owns a collapsed prompt row, including a complete prompt at the start of a headerless window; the same-step header does not duplicate it. Chat also shows a collapsed `System prompt` row for a non-empty initial request, explicit message-series start, or `system/message` surface node replacement whose text differs, reading the last nonempty surviving system node in surface order at the `request/header`; a non-initial request whose preceding header is outside the loaded history window also shows one. A resume repeats the row even when its system text is unchanged, including after pagination supplies the preceding header and system node; same-series config-only or tool-only changes, tool steps, and retries create no repetition, and a `system/message` event is never rendered as a transcript message. The row appears before that request's user messages, matching the provider envelope, and expands to the exact model-visible text with its original line breaks. A request whose system node is empty or outside the loaded window creates no row until the page holding the node arrives.
45
+
46
+ <a id="turn-token-usage"></a>
47
+ ## Turn token usage
48
+
49
+ A completed Turn shows an expandable usage row only when the loaded window includes `turn/start` and every started model attempt reports safe, exact usage. The row omits unavailable optional buckets. Incomplete or contradictory accounting hides the complete disclosure instead of presenting a partial total.
50
+
51
+ After Assistant replies settle, the completed-turn footer carries the usage disclosure alone: elapsed Turn time stays in the Turn-process control's title, and neither TTFT nor decoding speed appears after live replies or after reopening history. The Session Stats pill reads timing independently from its durable projection.
52
+
53
+ <a id="completed-turn-footer"></a>
54
+ ## Completed-turn footer
55
+
56
+ The completed-turn action footer starts 20px below the preceding prose or extension content.
57
+
58
+ -----
59
+
60
+ <a id="turn-process-folding"></a>
61
+ ## Turn Process Folding
62
+
63
+ Each reasoning row starts collapsed, including during streaming and in reasoning-only replies. Clicking the row opens or closes its complete Markdown; incoming answer text, Tool calls, and stream completion preserve that choice. Expanded reasoning uses compact secondary typography: headings add bold weight without changing text size, line height, or color. The collapsed summary stays on one line, follows the latest reasoning line while streaming, and shows the first line after settlement.
64
+
65
+ Settings → General exposes a persisted, localized `Compact` / `Standard` / `Detailed` / `Full detail` conversation-display preference in the `ui-chat` namespace; `Standard` is the default. `Full detail` leaves process rows visible and renders no Turn-process control. Every folding mode keeps the System prompt independently visible before the opening User throughout the Turn. Context injection, reasoning, Assistant material, Tool rows, and Retry rows remain expanded while a Turn is open. At `turn/end`, its latest Step becomes the final-answer boundary only when it contains non-blank text, an image, or an unknown visible block—and no Tool-call block; preceding Context injection, reasoning, earlier Assistant material, Tool rows, and Retry rows then collapse by default. The control's title reports the Turn's status rather than its counts: `Working for <duration>` while the Turn runs, then `Took <duration>`, `Worked`, `Stopped`, or `Failed`. Turn-wide durable counts for non-subagent Tool calls, reply-bearing Assistant messages before the final answer, and subagent delegation calls stay on the control's data attributes for test assertions. A Turn with neither external process nor inline reasoning has nothing to collapse: the control renders disabled without a collapse action, and its Context and System-prompt rows stay available to find-in-page. A full-width divider below the summary separates it from the answer or expanded process rows. User and steering messages, System prompt, error, max-token, and turn-tail rows stay outside, and a closed Turn with no final answer keeps all process evidence visible. The preference scales the transcript itself: `Compact` drops the settled reasoning preview and the running-activity detail in group titles; every mode keeps settled tool bodies behind the row toggle, opened only by a reader click; `Full detail` alone leaves the completed Turn unfolded. The separate `Performance & usage` setting gates the composer statistics dialogs and the per-turn usage pill; its `Compact` level keeps only the speed and cache-hit readings. A newly available process control is inserted without changing the relative order of existing rows: opening human input precedes the control and process rows from their first projection, while System prompt remains above that input. A loaded Turn end is enough to fold: unloaded older history no longer withholds the control. Each group header names its ranked activity categories and the running activity instead of listing them inside the answer row. Stable Chat Node Seats keep every renderer mounted, hidden members add no flow spacing, and a closed control sits 8px above its answer only when no independent input intervenes. Completion collapse does not depend on tail-follow position, so a reader above the tail may see the transcript reflow. An automatic collapse that would hide keyboard focus keeps the group open and leaves focus in place; a manual close focuses the process control before hiding its members. The session-scoped store records only manually expanded Turn-and-answer-Step generations; a different answer generation starts collapsed.
66
+
67
+ -----
68
+
69
+ <a id="grouped-rendering"></a>
70
+ ## Grouped rendering
71
+
72
+ Consecutive reasoning, Tool, and Assistant rows between independent inputs become activity groups owned by one Chat Group Definition. A group seat subscribes only to its member array, and each member keeps its keyed Node source and renderer. `groupPart` selects the renderer-owned part, with a distinct DOM anchor per part. System-prompt, Context injection, and command rows remain independent rows and end the preceding group: the upstream infrastructure-row filter is not ported, so grouping keeps those kinds outside every process group. Presentation modes change group visibility, never member parents. The [business-rule reference](src/client/conversation-nodes/README.md) owns segmentation, display-mode titles, and activity summaries.
73
+
74
+ The Settings row below Work details offers an [independent collapse-timing preference](src/client/conversation-nodes/README.md#collapse-timing).
75
+
76
+ The Chat Builder publishes `bottomSource` per Node: true for visible Nodes belonging to the last Turn in the loaded timeline, not just the final row. Advancing the bottom Turn notifies only Nodes in the old and new bottom Turns. Groups read their first member's position. Pending-input deduplication and collapse decisions remain in the Chat view, outside the Builder.
77
+
78
+
79
+ -----
80
+
81
+ <a id="turn-triggers"></a>
82
+ ## Turn triggers
83
+
84
+ Non-human input claimed from the next-turn Inbox appears as an independent trigger notice instead of a context row. A first-step next-step claim also qualifies when that Turn has no next-turn claim or human input in its next-step batch. Titles recognize schedules, jobs, goals, agent and team messages, subagent settlements, webhooks, and Cordis runner outcomes; unknown sources keep generic attribution. The notice starts collapsed and expands independently of process folding.
85
+
86
+ -----
87
+
88
+
89
+ <a id="tool-call-nodes"></a>
90
+ ## Tool call nodes
91
+
92
+ The `tool-call` Chat Node owns one call's preparing, dispatched, and result stages under a single callId, so a call that the model names before its arguments are complete appears once and keeps its identity when `tool/call` arrives. Live tool deltas share reasoning's frame-batched publication; durable calls and results publish immediately. Native and nested results retain event presentation metadata, so historical file and command labels use the operation's location. Repeated named deltas retain the Tool node and its data reference when the projected call, anchor, location, and visibility are unchanged. Historical windows never expand a settled Assistant message back into live deltas, so replay presents start → result directly.
93
+
94
+ -----
95
+
96
+ <a id="scroll-ownership"></a>
97
+ ## Scroll ownership
98
+
99
+ Under completion-time folding, Chat restores semantic anchors across history prepend and renderer remounts. `ChatViewport` owns the scrollport's DOM operations, the ledger that attributes each delivery to the reader or to a programmatic write, and every landing write. Pinned deliveries without reader movement update follow ownership immediately, before subsequent layout changes can invalidate their floor; reader movement remains pending until the sampling interval or `scrollend`, even inside the follow threshold, so layout growth cannot erase small scroll gestures. While the reader is pinned to the floor, the transcript disables native scroll anchoring (`data-chat-following-tail`) and `ResizeObserver` follows the new floor, selecting the latest loaded Turn without reading row geometry. Once the reader moves away, a layout change re-aligns their sampled row and the reading-line geometry selects the active Turn; paging retains one semantic row, plus its group's inner scroller, and compensates the inner scroll range first. Wheel, touch, pointer, key, and find-in-page intents release that retention, and rail scrolling never reaches the transcript. Turn-rail previews paint above sticky Markdown code-block banners, while the rail frame remains inside the transcript band above the composer. `use-chat-viewport` owns geometry and landings, `use-chat-reading` owns follow intent, reader sampling, and the active Turn, `use-chat-navigation` owns Turn jumps and prepend anchoring, and `use-chat-scroll` reconciles them after each commit; `ChatView` renders what they publish.
100
+
101
+ The delayed-fold experiment pauses automatic tail following and browser scroll anchoring while process rows fade and close. Bottom space preserves the scroll range; final content and the new input move upward together. Once the rows close, remaining input is revealed with native smooth scrolling, without a fixed continuation speed. Reader gestures cancel waiting and active follow motion; unloading Chat cancels its waiting callbacks and row transitions. Reduced-motion users receive immediate visibility and positioning changes.
102
+
103
+ Fold coordination is viewport-local: reservations and idle callbacks never broadcast to other Chat views. ChatView supplies its motion capability once to `conversation.chat.flow` through the render's `hookContext`. Flow binds the group and header behavior hooks, owns node and image rendering, and shares the existing Chat store and Session node sources. Layout nodes and inline reasoning receive the bound hooks without receiving the motion controller or changing content parents. Generic searchable hiding applies before paint and owns focus protection and beforematch handling; pending-input reconciliation remains in ChatView.
104
+
105
+
106
+ -----
107
+
108
+ <a id="model-experience"></a>
109
+ ## Model Experience
110
+
111
+ None, as this package renders logged conversation state in the browser and registers nothing model-facing.
112
+
113
+ #### KV Cache effect
114
+
115
+ None; Chat presentation does not assemble or mutate provider requests.
116
+
117
+ ## Known Limitations and Deferred Work
118
+
119
+ <a id="known-limitations-and-deferred-work"></a>
120
+
121
+ - **The transcript reflects the loaded Session window** — older transcript nodes become available only after Session Controller loads the preceding event page. Turn navigation is wider than the window: the rail merges the loaded Turns with the host `turnOutline` projection, so every started Turn gets a fixed-pitch mark (10px apart; the rail virtualizes, mounting only the marks near its own viewport, and a ladder taller than the frame scrolls inside it with gradient fades without consuming transcript wheel input), and activating an unloaded mark pages history through the Turn's `turn/start` seq before landing on its row. Without the projection (assemblies not mounting `qilin-session-turn-outline`) the rail falls back to loaded Turns only.
122
+ - **Rail previews are card-sized** — one prompt line (50 characters) and up to three response lines (120), on loaded and unloaded Turns alike; an unloaded Turn's response arrives from the outline only once the Turn settled, so an open Turn previews its prompt (or just the Turn number) until then.
123
+
124
+
125
+ <a id="dev-note"></a>
126
+ ### Dev Note
127
+
128
+ <details>
129
+ <summary>Working context for maintainers — click to expand</summary>
130
+
131
+ None.
132
+
133
+ </details>
package/README.zh.md ADDED
@@ -0,0 +1,134 @@
1
+ ---
2
+ description: "渲染会话对话节点、历史图片、操作、本地化和滚动状态的浏览器 Chat target。"
3
+ kind: "package-reference"
4
+ ---
5
+ # @qilin-agent/client-ui-chat
6
+
7
+ [English](README.md) | 中文
8
+
9
+ ## 概述
10
+
11
+ 使用本包可在浏览器中渲染已记录的 Session 对话,包括历史图片、本地化操作和滚动位置恢复。紧凑显示会收起已完成轮次的过程行,同时保持最终答案和独立有用的上下文可见;已打包的历史 Assistant 连续消息保持收起。本地 transcript(文本记录)与 steering(中途引导)提交会立即显示并保留在原区域,在权威会话记录到达时原子地消失,而排队中的提交始终不进入 Chat。本包不组装或修改模型请求。
12
+
13
+ 文件提及提供方同时接收当前查看的会话 ID 与收尾轮次的属主信息,因此继承历史中的链接可以指向 fork 自身。
14
+
15
+ ## 目录
16
+
17
+ - [引用预览](#reference-previews)
18
+ - [系统提示词行](#system-prompt-row)
19
+ - [轮次 token 用量](#turn-token-usage)
20
+ - [已完成轮次的页脚](#completed-turn-footer)
21
+ - [轮次过程折叠](#turn-process-folding)
22
+ - [分组渲染](#grouped-rendering)
23
+ - [轮次触发提示](#turn-triggers)
24
+ - [工具调用节点](#tool-call-nodes)
25
+ - [滚动归属](#scroll-ownership)
26
+ - [模型体验](#model-experience)
27
+ - [已知限制与暂缓事项](#known-limitations-and-deferred-work)
28
+ - [开发备注](#dev-note)
29
+
30
+ -----
31
+
32
+ <a id="reference-previews"></a>
33
+ ## 引用预览
34
+
35
+ Chat 在节点列表外通过一个 `MarkdownDelegateProvider` 提供文件及 HTTP(S) 导航。Assistant Markdown 文件链接在消息落定后可于右侧栏打开,包括未修改文件的引用。相对路径基于当前查看的 Session 工作区解析;绝对路径仍使用同一 Session 的文件系统访问。`#L24` 和 `#L24-L30` 定位到指定起始行,并复用现有文件标签。文件缺失时显示预览错误状态。
36
+
37
+ 独立的 Markdown 图片以内嵌预览显示,点击打开共享图片浮层;本地路径在消息落定后基于当前查看的工作区解析。图片文件链接保持点击打开侧栏,鼠标停留或键盘聚焦时显示缩略图,Esc 关闭缩略图。图片加载失败时保留本地化状态与图片说明;不执行重复图片过滤。
38
+
39
+ Assistant Markdown 中的 HTTP(S) 链接在普通点击时会在该类型已注册时打开新的右侧 Sidebar Browser tab,否则改用系统浏览器;带修饰键的点击保留原生外部链接行为。已发送的文件引用及消息日志确认调用的 skill 也可在右侧栏打开预览。文件路径使用当前查看的 Session;skill 名称由该 Session 当前的输入触发源解析。两者悬停或聚焦时均使用正文文件链接的虚线下划线。会话、目录和命令标签仍只作为引用展示。
40
+
41
+ <a id="system-prompt-row"></a>
42
+ ## 系统提示词行
43
+
44
+ 每个非空追加的 `system/message` 都拥有一行折叠提示词,包括无 header 窗口起点的完整提示词;同一步骤的 header 不会重复它。Chat 也会为非空的初始请求、显式消息序列起点、文本发生变化的 `system/message` surface 节点替换(文本读取自 `request/header` 处 surface 顺序中最后一个非空存活系统节点),或前序 header 尚未进入已加载历史窗口的非初始请求显示一行默认折叠的 `系统提示词`。即使系统文本未变,恢复也会重复该行,包括分页补齐前序 header 和系统节点后;同一序列内仅配置或仅工具变化、工具步骤与重试不会重复,且 `system/message` 事件绝不会渲染为对话消息。该行位于请求的用户消息之前,与提供方 envelope 顺序一致;展开后显示模型所见的确切文本,并保留其原始换行。系统节点为空或位于已加载窗口之外的请求不创建该行,直到包含该节点的分页到达。
45
+
46
+ -----
47
+
48
+ <a id="turn-token-usage"></a>
49
+ ## 轮次 token 用量
50
+
51
+ 只有当已加载窗口包含 `turn/start`,且每次已启动的模型尝试都报告安全、精确的用量时,已完成轮次才显示可展开的用量行。该行会省略不可用的可选用量桶。记账不完整或相互矛盾时,整个详情都不显示,避免把部分总量冒充完整结果。
52
+
53
+ Assistant 回复结算后,已完成轮次的页脚只保留用量入口:轮次总耗时由轮次过程控件的标题承担,实时回复完成后与重新打开历史后都不显示 TTFT 和解码速度。Session Stats 药丸从其持久化投影独立读取计时。
54
+
55
+ <a id="completed-turn-footer"></a>
56
+ ## 已完成轮次的页脚
57
+
58
+ 已完成轮次的操作页脚位于前方正文或扩展内容下方 20px。
59
+
60
+ -----
61
+
62
+ <a id="turn-process-folding"></a>
63
+ ## 轮次过程折叠
64
+
65
+ 每个思考行初始都折叠,包括流式输出期间和仅含思考的回复。点击该行可展开或收起完整 Markdown;后续回答文本、工具调用和流结束都保留用户的选择。展开的思考采用紧凑的次级排版:标题只加粗,不改变字号、行高或颜色。折叠摘要保持单行,在流式输出期间跟随最新思考行,结算后显示第一行。
66
+
67
+ 「设置 → 通用设置」提供持久化到 `ui-chat` 命名空间的「简洁」/「标准」/「详细」/「完全展开」对话显示偏好,默认使用「标准」。「完全展开」保持所有过程行可见且不渲染轮次过程控件。每个折叠档位下,系统提示词在整个轮次中始终独立显示于开场 User 上方。轮次打开期间,上下文注入、推理、Assistant 内容、工具行与重试行始终展开。到 `turn/end` 时,最后一个步骤只有在包含非空文本、图片或未知可见块且不含工具调用块时才成为最终答案边界;边界之前的上下文注入、推理、较早 Assistant 内容、工具行与重试行随后默认收起。控件标题展示轮次状态而非计数:运行中为「QiLin...,用时{duration}」,结算后为「用时 {duration}」「已完成工作」「已停止」或「处理失败」;覆盖整个轮次的非 subagent 工具调用数、最终答案之前带回复内容的 Assistant 消息数和 subagent 委派数只保留在控件的数据属性上供测试断言。轮次既无外部过程也无内联推理时没有可折叠内容:控件渲染为禁用、不提供折叠动作,其上下文注入与系统提示词行保留给「页内查找」而非点击展开。摘要下方的通栏分隔线将其与正文或展开后的过程行隔开。用户与 steering 消息、系统提示词、错误、最大 token 与 turn-tail 行留在过程组外;关闭时没有最终答案的轮次保留全部过程证据。该偏好会改变会话本体的渲染:「简洁」档隐藏已结算思考预览与分组标题中的运行活动细节;各档都把已结算的工具明细保留在行展开开关之后、只按读者点击展开;仅「完全展开」档另外不折叠已完成的轮次。「性能与用量」设置单独控制编写区统计对话框与轮次用量入口:其「简洁」档只保留速度与缓存命中读数。新的过程控件插入时不会改变既有行的相对顺序:开场人工输入从首次投影起便位于控件和过程行之前,系统提示词则始终位于该输入上方。只要已加载轮次结束即可折叠:更早的未加载历史不再阻止过程控件出现。每个分组标题列出其排序后的活动类别与运行中的活动,而不再由正文行承担该信息。稳定 Chat Node Seat 会让每个 renderer 保持挂载,隐藏成员不产生消息流间距;只有中间没有独立输入时,收起控件才与正文相隔 8px。完成后的收起不依赖是否跟随尾部,因此正在上方阅读的用户可能看到 transcript 重排。若自动收起会隐藏当前键盘焦点,则过程组保持展开且焦点留在原处;手动收起会先把焦点移到过程控件,再隐藏成员。会话作用域存储只记录用户手动展开的「轮次 + 正文步骤」generation;不同正文 generation 默认收起。
68
+
69
+ -----
70
+
71
+ <a id="grouped-rendering"></a>
72
+ ## 分组渲染
73
+
74
+ 独立输入之间的连续推理、工具与 Assistant 行会组成活动分组,由 Chat 的一个分组定义拥有。分组座位只订阅自己的成员数组,每个成员继续使用原有的键控 Node 来源与 renderer。`groupPart` 选择 renderer 自有的部分,每个部分拥有独立的 DOM 锚点。系统提示词、上下文注入与命令行仍是独立行,并会结束前面的分组:上游的「基础设施行过滤」未移植,因此分组会把这些类型留在所有过程分组之外。展示档位只改变分组的可见性,不改变成员的父级。[业务规则参考](src/client/conversation-nodes/README.zh.md)负责分段、展示档位标题与活动摘要的完整定义。
75
+
76
+ 工作步骤展示下方的设置行提供[独立的收起时机设置](src/client/conversation-nodes/README.zh.md#collapse-timing)。
77
+
78
+ Chat Builder 按节点发布 `bottomSource`:节点可见且属于已加载时间线的最后一轮时为 true,而不只是列表最后一行。底部轮次推进时,只有旧、新底部轮次的节点收到位置变化通知。Group 读取其首个成员的位置。待发送消息去重与收起判断仍由 Chat 视图处理,不进入 Builder。
79
+
80
+
81
+ -----
82
+
83
+ <a id="turn-triggers"></a>
84
+ ## 轮次触发提示
85
+
86
+ 从 next-turn 收件箱认领的非人类输入会显示为独立的触发提示行,而不是上下文行。当该轮次没有 next-turn 认领、或其 next-step 批次中没有人类输入时,第一步的 next-step 认领同样符合条件。标题可识别定时任务、后台任务、目标、agent 与团队消息、子代理结算、webhook 以及 Cordis 运行器结果;未知来源保留通用归因。提示行默认折叠,展开与过程折叠互不影响。
87
+
88
+ -----
89
+
90
+ <a id="tool-call-nodes"></a>
91
+ ## 工具调用节点
92
+
93
+ `tool-call` Chat Node 在同一个 callId 下拥有准备、派发与结果三个阶段,因此模型在参数完整前已给出名称的调用只出现一次,并在 `tool/call` 到达时保持同一身份。实时工具 delta 与推理共用按帧合并的发布节奏;持久调用和结果立即发布。原生与嵌套结果保留事件中的展示元数据,使历史文件与命令标签使用执行时的位置。重复具名 delta 在投影调用、锚点、位置及可见性均未变化时保留 Tool 节点及其数据引用。历史窗口不会把已结束的 Assistant 消息重新展开为实时 delta,因此回放直接呈现 start → result。
94
+
95
+ -----
96
+
97
+ <a id="scroll-ownership"></a>
98
+ ## 滚动归属
99
+
100
+ 采用完成时收起时,Chat 会在历史前插与 renderer 重新挂载时恢复语义锚点。`ChatViewport` 持有滚动容器的 DOM 操作、把每次投递归属到读者或程序化写入的账本,以及所有落位写入。没有读者移动的贴底投递会立即更新跟随归属,避免后续布局变化使其底部位置失效;读者移动即使位于跟随阈值内,也保持待处理直到采样周期或 `scrollend`,防止布局增长抵消小幅滚动操作。读者跟随底部时,transcript 关闭原生滚动锚定(`data-chat-following-tail`),`ResizeObserver` 追随新的底部,并且无需读取行几何就选中最后一个已加载轮次。读者离开底部后,布局变化会把其采样行重新对齐,再由阅读线几何选择活跃轮次;分页保留一个语义行及其分组内层滚动容器,并优先补偿内层滚动区间。滚轮、触摸、指针、按键与页内查找意图会释放该保留,轨道自身的滚动不会传到 transcript。轮次导航预览位于 Markdown 代码块粘性头栏上方,而导航外框始终处于 composer 上方的 transcript 区域内。职责拆分:`use-chat-viewport` 负责几何与落位,`use-chat-reading` 负责跟随意图、读者采样与活跃轮次,`use-chat-navigation` 负责轮次跳转与前插锚定,`use-chat-scroll` 在每次提交后协调三者;`ChatView` 只渲染它们发布的结果。
101
+
102
+ 延后折叠实验在过程行淡出并收起期间暂停自动跟尾和浏览器滚动锚定。底部空间保留可滚动范围,最终正文与新输入一起向上移动。过程行收起后,以原生平滑滚动揭示尚未露出的输入,不保证固定续滚速度。读者手势取消等待中和进行中的跟随动画;卸载 Chat 时取消其等待回调和行过渡。启用减少动态效果偏好时,可见性和定位立即变化。
103
+
104
+ 折叠协调状态由各自的 viewport 持有,空间预留和空闲回调不会广播到其他 Chat 视图。ChatView 通过本次渲染的 `hookContext`,向 `conversation.chat.flow` 交接一次动画能力。Flow 绑定组内容与组头的行为 hook,负责节点和图片渲染,并共享既有 Chat store 与 Session 节点来源。布局节点和行内思考接收绑定后的 hook,不接收动画控制器,也不改变内容的父级。通用的可搜索隐藏在绘制前生效,并负责焦点保护及 beforematch;pending 输入对账仍留在 ChatView。
105
+
106
+
107
+ -----
108
+
109
+ <a id="model-experience"></a>
110
+ ## 模型体验
111
+
112
+ 无,因为本包在浏览器中渲染已记录的对话状态,不注册任何面向模型的内容。
113
+
114
+ #### KV Cache 影响
115
+
116
+ 无;Chat 呈现不会组装或修改提供方请求。
117
+
118
+ ## 已知限制与暂缓事项
119
+
120
+ <a id="known-limitations-and-deferred-work"></a>
121
+
122
+ - **transcript 只反映已加载的 Session 窗口**——只有会话控制器加载前一页事件后,更早的 transcript node 才会出现。轮次导航比窗口更宽:轨道把已加载的轮次与宿主 `turnOutline` 投影合并,每个已开始的轮次都有固定间距刻度(相隔 10px;轨道做虚拟化,只挂载其自身视窗附近的刻度,阶梯高于外框时在框内滚动并以渐变淡出标示可滚方向,且不吞掉 transcript 的滚轮输入),激活未加载刻度会先把历史分页拉到该轮次的 `turn/start` seq 再落到它的行上。没有该投影时(未挂载 `qilin-session-turn-outline` 的装配),轨道回退到仅显示已加载轮次。
123
+ - **导航预览按卡片尺寸截断**——提示词一行(50 字符)、回复至多三行(120 字符),已加载与未加载 Turn 一致;未加载 Turn 的回复要等该轮落定后才随大纲到达,进行中的轮次在此之前只预览提示词(或仅轮次号)。
124
+
125
+
126
+ <a id="dev-note"></a>
127
+ ### 开发备注
128
+
129
+ <details>
130
+ <summary>维护者工作上下文——点击展开</summary>
131
+
132
+ 无。
133
+
134
+ </details>