@theia/ai-chat-ui 1.67.0-next.56 → 1.67.0-next.59

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 (161) hide show
  1. package/lib/browser/ai-chat-ui-contribution.d.ts +66 -0
  2. package/lib/browser/ai-chat-ui-contribution.d.ts.map +1 -0
  3. package/lib/browser/ai-chat-ui-contribution.js +587 -0
  4. package/lib/browser/ai-chat-ui-contribution.js.map +1 -0
  5. package/lib/browser/ai-chat-ui-frontend-module.d.ts +5 -0
  6. package/lib/browser/ai-chat-ui-frontend-module.d.ts.map +1 -0
  7. package/lib/browser/ai-chat-ui-frontend-module.js +153 -0
  8. package/lib/browser/ai-chat-ui-frontend-module.js.map +1 -0
  9. package/lib/browser/change-set-actions/change-set-accept-action.d.ts +10 -0
  10. package/lib/browser/change-set-actions/change-set-accept-action.d.ts.map +1 -0
  11. package/lib/browser/change-set-actions/change-set-accept-action.js +47 -0
  12. package/lib/browser/change-set-actions/change-set-accept-action.js.map +1 -0
  13. package/lib/browser/change-set-actions/change-set-action-service.d.ts +31 -0
  14. package/lib/browser/change-set-actions/change-set-action-service.d.ts.map +1 -0
  15. package/lib/browser/change-set-actions/change-set-action-service.js +57 -0
  16. package/lib/browser/change-set-actions/change-set-action-service.js.map +1 -0
  17. package/lib/browser/chat-input-agent-suggestions.d.ts +11 -0
  18. package/lib/browser/chat-input-agent-suggestions.d.ts.map +1 -0
  19. package/lib/browser/chat-input-agent-suggestions.js +76 -0
  20. package/lib/browser/chat-input-agent-suggestions.js.map +1 -0
  21. package/lib/browser/chat-input-history-contribution.d.ts +17 -0
  22. package/lib/browser/chat-input-history-contribution.d.ts.map +1 -0
  23. package/lib/browser/chat-input-history-contribution.js +158 -0
  24. package/lib/browser/chat-input-history-contribution.js.map +1 -0
  25. package/lib/browser/chat-input-history.d.ts +32 -0
  26. package/lib/browser/chat-input-history.d.ts.map +1 -0
  27. package/lib/browser/chat-input-history.js +125 -0
  28. package/lib/browser/chat-input-history.js.map +1 -0
  29. package/lib/browser/chat-input-mode-contribution.d.ts +12 -0
  30. package/lib/browser/chat-input-mode-contribution.d.ts.map +1 -0
  31. package/lib/browser/chat-input-mode-contribution.js +77 -0
  32. package/lib/browser/chat-input-mode-contribution.js.map +1 -0
  33. package/lib/browser/chat-input-widget.d.ts +118 -0
  34. package/lib/browser/chat-input-widget.d.ts.map +1 -0
  35. package/lib/browser/chat-input-widget.js +1034 -0
  36. package/lib/browser/chat-input-widget.js.map +1 -0
  37. package/lib/browser/chat-node-toolbar-action-contribution.d.ts +56 -0
  38. package/lib/browser/chat-node-toolbar-action-contribution.d.ts.map +1 -0
  39. package/lib/browser/chat-node-toolbar-action-contribution.js +92 -0
  40. package/lib/browser/chat-node-toolbar-action-contribution.js.map +1 -0
  41. package/lib/browser/chat-progress-message.d.ts +7 -0
  42. package/lib/browser/chat-progress-message.d.ts.map +1 -0
  43. package/lib/browser/chat-progress-message.js +33 -0
  44. package/lib/browser/chat-progress-message.js.map +1 -0
  45. package/lib/browser/chat-response-part-renderer.d.ts +10 -0
  46. package/lib/browser/chat-response-part-renderer.d.ts.map +1 -0
  47. package/lib/browser/chat-response-part-renderer.js +20 -0
  48. package/lib/browser/chat-response-part-renderer.js.map +1 -0
  49. package/lib/browser/chat-response-renderer/ai-selection-resolver.d.ts +23 -0
  50. package/lib/browser/chat-response-renderer/ai-selection-resolver.d.ts.map +1 -0
  51. package/lib/browser/chat-response-renderer/ai-selection-resolver.js +148 -0
  52. package/lib/browser/chat-response-renderer/ai-selection-resolver.js.map +1 -0
  53. package/lib/browser/chat-response-renderer/code-part-renderer.d.ts +73 -0
  54. package/lib/browser/chat-response-renderer/code-part-renderer.d.ts.map +1 -0
  55. package/lib/browser/chat-response-renderer/code-part-renderer.js +227 -0
  56. package/lib/browser/chat-response-renderer/code-part-renderer.js.map +1 -0
  57. package/lib/browser/chat-response-renderer/command-part-renderer.d.ts +12 -0
  58. package/lib/browser/chat-response-renderer/command-part-renderer.d.ts.map +1 -0
  59. package/lib/browser/chat-response-renderer/command-part-renderer.js +67 -0
  60. package/lib/browser/chat-response-renderer/command-part-renderer.js.map +1 -0
  61. package/lib/browser/chat-response-renderer/delegation-response-renderer.d.ts +14 -0
  62. package/lib/browser/chat-response-renderer/delegation-response-renderer.d.ts.map +1 -0
  63. package/lib/browser/chat-response-renderer/delegation-response-renderer.js +144 -0
  64. package/lib/browser/chat-response-renderer/delegation-response-renderer.js.map +1 -0
  65. package/lib/browser/chat-response-renderer/error-part-renderer.d.ts +9 -0
  66. package/lib/browser/chat-response-renderer/error-part-renderer.d.ts.map +1 -0
  67. package/lib/browser/chat-response-renderer/error-part-renderer.js +40 -0
  68. package/lib/browser/chat-response-renderer/error-part-renderer.js.map +1 -0
  69. package/lib/browser/chat-response-renderer/horizontal-layout-part-renderer.d.ts +12 -0
  70. package/lib/browser/chat-response-renderer/horizontal-layout-part-renderer.d.ts.map +1 -0
  71. package/lib/browser/chat-response-renderer/horizontal-layout-part-renderer.js +54 -0
  72. package/lib/browser/chat-response-renderer/horizontal-layout-part-renderer.js.map +1 -0
  73. package/lib/browser/chat-response-renderer/index.d.ts +13 -0
  74. package/lib/browser/chat-response-renderer/index.d.ts.map +1 -0
  75. package/lib/browser/chat-response-renderer/index.js +31 -0
  76. package/lib/browser/chat-response-renderer/index.js.map +1 -0
  77. package/lib/browser/chat-response-renderer/markdown-part-renderer.d.ts +36 -0
  78. package/lib/browser/chat-response-renderer/markdown-part-renderer.d.ts.map +1 -0
  79. package/lib/browser/chat-response-renderer/markdown-part-renderer.js +129 -0
  80. package/lib/browser/chat-response-renderer/markdown-part-renderer.js.map +1 -0
  81. package/lib/browser/chat-response-renderer/progress-part-renderer.d.ts +9 -0
  82. package/lib/browser/chat-response-renderer/progress-part-renderer.d.ts.map +1 -0
  83. package/lib/browser/chat-response-renderer/progress-part-renderer.js +39 -0
  84. package/lib/browser/chat-response-renderer/progress-part-renderer.js.map +1 -0
  85. package/lib/browser/chat-response-renderer/question-part-renderer.d.ts +10 -0
  86. package/lib/browser/chat-response-renderer/question-part-renderer.d.ts.map +1 -0
  87. package/lib/browser/chat-response-renderer/question-part-renderer.js +49 -0
  88. package/lib/browser/chat-response-renderer/question-part-renderer.js.map +1 -0
  89. package/lib/browser/chat-response-renderer/text-part-renderer.d.ts +9 -0
  90. package/lib/browser/chat-response-renderer/text-part-renderer.d.ts.map +1 -0
  91. package/lib/browser/chat-response-renderer/text-part-renderer.js +43 -0
  92. package/lib/browser/chat-response-renderer/text-part-renderer.js.map +1 -0
  93. package/lib/browser/chat-response-renderer/text-part-renderer.spec.d.ts +2 -0
  94. package/lib/browser/chat-response-renderer/text-part-renderer.spec.d.ts.map +1 -0
  95. package/lib/browser/chat-response-renderer/text-part-renderer.spec.js +46 -0
  96. package/lib/browser/chat-response-renderer/text-part-renderer.spec.js.map +1 -0
  97. package/lib/browser/chat-response-renderer/thinking-part-renderer.d.ts +9 -0
  98. package/lib/browser/chat-response-renderer/thinking-part-renderer.d.ts.map +1 -0
  99. package/lib/browser/chat-response-renderer/thinking-part-renderer.js +42 -0
  100. package/lib/browser/chat-response-renderer/thinking-part-renderer.js.map +1 -0
  101. package/lib/browser/chat-response-renderer/tool-confirmation.d.ts +17 -0
  102. package/lib/browser/chat-response-renderer/tool-confirmation.d.ts.map +1 -0
  103. package/lib/browser/chat-response-renderer/tool-confirmation.js +122 -0
  104. package/lib/browser/chat-response-renderer/tool-confirmation.js.map +1 -0
  105. package/lib/browser/chat-response-renderer/toolcall-part-renderer.d.ts +20 -0
  106. package/lib/browser/chat-response-renderer/toolcall-part-renderer.d.ts.map +1 -0
  107. package/lib/browser/chat-response-renderer/toolcall-part-renderer.js +223 -0
  108. package/lib/browser/chat-response-renderer/toolcall-part-renderer.js.map +1 -0
  109. package/lib/browser/chat-response-renderer/unknown-part-renderer.d.ts +9 -0
  110. package/lib/browser/chat-response-renderer/unknown-part-renderer.d.ts.map +1 -0
  111. package/lib/browser/chat-response-renderer/unknown-part-renderer.js +42 -0
  112. package/lib/browser/chat-response-renderer/unknown-part-renderer.js.map +1 -0
  113. package/lib/browser/chat-tree-view/chat-view-tree-container.d.ts +4 -0
  114. package/lib/browser/chat-tree-view/chat-view-tree-container.d.ts.map +1 -0
  115. package/lib/browser/chat-tree-view/chat-view-tree-container.js +33 -0
  116. package/lib/browser/chat-tree-view/chat-view-tree-container.js.map +1 -0
  117. package/lib/browser/chat-tree-view/chat-view-tree-input-widget.d.ts +38 -0
  118. package/lib/browser/chat-tree-view/chat-view-tree-input-widget.d.ts.map +1 -0
  119. package/lib/browser/chat-tree-view/chat-view-tree-input-widget.js +88 -0
  120. package/lib/browser/chat-tree-view/chat-view-tree-input-widget.js.map +1 -0
  121. package/lib/browser/chat-tree-view/chat-view-tree-widget.d.ts +120 -0
  122. package/lib/browser/chat-tree-view/chat-view-tree-widget.d.ts.map +1 -0
  123. package/lib/browser/chat-tree-view/chat-view-tree-widget.js +654 -0
  124. package/lib/browser/chat-tree-view/chat-view-tree-widget.js.map +1 -0
  125. package/lib/browser/chat-tree-view/index.d.ts +3 -0
  126. package/lib/browser/chat-tree-view/index.d.ts.map +1 -0
  127. package/lib/browser/chat-tree-view/index.js +21 -0
  128. package/lib/browser/chat-tree-view/index.js.map +1 -0
  129. package/lib/browser/chat-tree-view/sub-chat-widget.d.ts +22 -0
  130. package/lib/browser/chat-tree-view/sub-chat-widget.d.ts.map +1 -0
  131. package/lib/browser/chat-tree-view/sub-chat-widget.js +92 -0
  132. package/lib/browser/chat-tree-view/sub-chat-widget.js.map +1 -0
  133. package/lib/browser/chat-view-commands.d.ts +15 -0
  134. package/lib/browser/chat-view-commands.d.ts.map +1 -0
  135. package/lib/browser/chat-view-commands.js +76 -0
  136. package/lib/browser/chat-view-commands.js.map +1 -0
  137. package/lib/browser/chat-view-contribution.d.ts +21 -0
  138. package/lib/browser/chat-view-contribution.d.ts.map +1 -0
  139. package/lib/browser/chat-view-contribution.js +183 -0
  140. package/lib/browser/chat-view-contribution.js.map +1 -0
  141. package/lib/browser/chat-view-language-contribution.d.ts +41 -0
  142. package/lib/browser/chat-view-language-contribution.d.ts.map +1 -0
  143. package/lib/browser/chat-view-language-contribution.js +269 -0
  144. package/lib/browser/chat-view-language-contribution.js.map +1 -0
  145. package/lib/browser/chat-view-widget-toolbar-contribution.d.ts +20 -0
  146. package/lib/browser/chat-view-widget-toolbar-contribution.d.ts.map +1 -0
  147. package/lib/browser/chat-view-widget-toolbar-contribution.js +115 -0
  148. package/lib/browser/chat-view-widget-toolbar-contribution.js.map +1 -0
  149. package/lib/browser/chat-view-widget.d.ts +60 -0
  150. package/lib/browser/chat-view-widget.d.ts.map +1 -0
  151. package/lib/browser/chat-view-widget.js +243 -0
  152. package/lib/browser/chat-view-widget.js.map +1 -0
  153. package/lib/browser/context-variable-picker.d.ts +9 -0
  154. package/lib/browser/context-variable-picker.d.ts.map +1 -0
  155. package/lib/browser/context-variable-picker.js +86 -0
  156. package/lib/browser/context-variable-picker.js.map +1 -0
  157. package/lib/browser/session-settings-dialog.d.ts +35 -0
  158. package/lib/browser/session-settings-dialog.d.ts.map +1 -0
  159. package/lib/browser/session-settings-dialog.js +118 -0
  160. package/lib/browser/session-settings-dialog.js.map +1 -0
  161. package/package.json +10 -10
@@ -0,0 +1,654 @@
1
+ "use strict";
2
+ var ChatViewTreeWidget_1;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ChatViewTreeWidget = exports.ChatWelcomeMessageProvider = exports.isEnterKey = exports.isResponseNode = exports.isEditableRequestNode = exports.isRequestNode = void 0;
5
+ const tslib_1 = require("tslib");
6
+ // *****************************************************************************
7
+ // Copyright (C) 2024 EclipseSource GmbH.
8
+ //
9
+ // This program and the accompanying materials are made available under the
10
+ // terms of the Eclipse Public License v. 2.0 which is available at
11
+ // http://www.eclipse.org/legal/epl-2.0.
12
+ //
13
+ // This Source Code may also be made available under the following Secondary
14
+ // Licenses when the conditions for such availability set forth in the Eclipse
15
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
16
+ // with the GNU Classpath Exception which is available at
17
+ // https://www.gnu.org/software/classpath/license.html.
18
+ //
19
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
20
+ // *****************************************************************************
21
+ const ai_chat_1 = require("@theia/ai-chat");
22
+ const ai_core_1 = require("@theia/ai-core");
23
+ const browser_1 = require("@theia/ai-core/lib/browser");
24
+ const core_1 = require("@theia/core");
25
+ const browser_2 = require("@theia/core/lib/browser");
26
+ const nls_1 = require("@theia/core/lib/common/nls");
27
+ const inversify_1 = require("@theia/core/shared/inversify");
28
+ const React = require("@theia/core/shared/react");
29
+ const chat_node_toolbar_action_contribution_1 = require("../chat-node-toolbar-action-contribution");
30
+ const chat_response_part_renderer_1 = require("../chat-response-part-renderer");
31
+ const markdown_part_renderer_1 = require("../chat-response-renderer/markdown-part-renderer");
32
+ const chat_progress_message_1 = require("../chat-progress-message");
33
+ const chat_view_tree_input_widget_1 = require("./chat-view-tree-input-widget");
34
+ const isRequestNode = (node) => 'request' in node;
35
+ exports.isRequestNode = isRequestNode;
36
+ const isEditableRequestNode = (node) => (0, exports.isRequestNode)(node) && ai_chat_1.EditableChatRequestModel.is(node.request);
37
+ exports.isEditableRequestNode = isEditableRequestNode;
38
+ const isResponseNode = (node) => 'response' in node;
39
+ exports.isResponseNode = isResponseNode;
40
+ function isEnterKey(e) {
41
+ var _a;
42
+ return browser_2.Key.ENTER.keyCode === ((_a = browser_2.KeyCode.createKeyCode(e.nativeEvent).key) === null || _a === void 0 ? void 0 : _a.keyCode);
43
+ }
44
+ exports.isEnterKey = isEnterKey;
45
+ exports.ChatWelcomeMessageProvider = Symbol('ChatWelcomeMessageProvider');
46
+ let ChatViewTreeWidget = ChatViewTreeWidget_1 = class ChatViewTreeWidget extends browser_2.TreeWidget {
47
+ set shouldScrollToEnd(shouldScrollToEnd) {
48
+ this._shouldScrollToEnd = shouldScrollToEnd;
49
+ this.shouldScrollToRow = this._shouldScrollToEnd;
50
+ }
51
+ get shouldScrollToEnd() {
52
+ return this._shouldScrollToEnd;
53
+ }
54
+ constructor(props, model, contextMenuRenderer) {
55
+ super(props, model, contextMenuRenderer);
56
+ this.onDidSubmitEditEmitter = new core_1.Emitter();
57
+ this.onDidSubmitEdit = this.onDidSubmitEditEmitter.event;
58
+ this.chatInputs = new Map();
59
+ this._shouldScrollToEnd = true;
60
+ this.isEnabled = false;
61
+ /** Tracks if we are at the bottom for showing the scroll-to-bottom button. */
62
+ this.atBottom = true;
63
+ /**
64
+ * Track the visibility of the scroll button with debounce logic. Used to prevent flickering when streaming tokens.
65
+ */
66
+ this._showScrollButton = false;
67
+ this.lastScrollTop = 0;
68
+ this.toDisposeOnChatModelChange = new core_1.DisposableCollection();
69
+ this.id = ChatViewTreeWidget_1.ID;
70
+ this.title.closable = false;
71
+ model.root = {
72
+ id: 'ChatTree',
73
+ name: 'ChatRootNode',
74
+ parent: undefined,
75
+ visible: false,
76
+ children: [],
77
+ };
78
+ }
79
+ init() {
80
+ super.init();
81
+ this.id = ChatViewTreeWidget_1.ID + '-treeContainer';
82
+ this.addClass('treeContainer');
83
+ this.toDispose.pushAll([
84
+ this.toDisposeOnChatModelChange,
85
+ this.activationService.onDidChangeActiveStatus(change => {
86
+ this.chatInputs.forEach(widget => {
87
+ widget.setEnabled(change);
88
+ });
89
+ this.update();
90
+ }),
91
+ this.onScroll(scrollEvent => {
92
+ this.handleScrollEvent(scrollEvent);
93
+ })
94
+ ]);
95
+ // Initialize lastScrollTop with current scroll position
96
+ this.lastScrollTop = this.getCurrentScrollTop(undefined);
97
+ }
98
+ setEnabled(enabled) {
99
+ this.isEnabled = enabled;
100
+ this.update();
101
+ }
102
+ handleScrollEvent(scrollEvent) {
103
+ const currentScrollTop = this.getCurrentScrollTop(scrollEvent);
104
+ const isScrollingUp = currentScrollTop < this.lastScrollTop;
105
+ const isScrollingDown = currentScrollTop > this.lastScrollTop;
106
+ const isAtBottom = this.isScrolledToBottom();
107
+ const isAtAbsoluteBottom = this.isAtAbsoluteBottom();
108
+ // Asymmetric threshold logic to prevent jitter:
109
+ if (this.shouldScrollToEnd && isScrollingUp) {
110
+ if (!isAtAbsoluteBottom) {
111
+ this.setTemporaryScrollLock(true);
112
+ }
113
+ }
114
+ else if (!this.shouldScrollToEnd && isAtBottom && isScrollingDown) {
115
+ this.setTemporaryScrollLock(false);
116
+ }
117
+ this.updateScrollToBottomButtonState(isAtBottom);
118
+ this.lastScrollTop = currentScrollTop;
119
+ }
120
+ /** Updates the scroll-to-bottom button state and handles debounce. */
121
+ updateScrollToBottomButtonState(isAtBottom) {
122
+ const atBottomNow = isAtBottom; // Use isScrolledToBottom for threshold
123
+ if (atBottomNow !== this.atBottom) {
124
+ this.atBottom = atBottomNow;
125
+ if (this.atBottom) {
126
+ // We're at the bottom, hide the button immediately and clear any debounce timer.
127
+ this._showScrollButton = false;
128
+ if (this._scrollButtonDebounceTimer !== undefined) {
129
+ clearTimeout(this._scrollButtonDebounceTimer);
130
+ this._scrollButtonDebounceTimer = undefined;
131
+ }
132
+ this.update();
133
+ }
134
+ else {
135
+ // User scrolled up; delay showing the scroll-to-bottom button.
136
+ if (this._scrollButtonDebounceTimer !== undefined) {
137
+ clearTimeout(this._scrollButtonDebounceTimer);
138
+ }
139
+ this._scrollButtonDebounceTimer = window.setTimeout(() => {
140
+ // Re-check: only show if we're still not at bottom
141
+ if (!this.atBottom) {
142
+ this._showScrollButton = true;
143
+ this.update();
144
+ }
145
+ this._scrollButtonDebounceTimer = undefined;
146
+ }, ChatViewTreeWidget_1.SCROLL_BUTTON_GRACE_PERIOD);
147
+ }
148
+ }
149
+ }
150
+ setTemporaryScrollLock(enabled) {
151
+ var _a;
152
+ // Immediately apply scroll lock changes without delay
153
+ (_a = this.onScrollLockChange) === null || _a === void 0 ? void 0 : _a.call(this, enabled);
154
+ // Update cached scrollToRow so that outdated values do not cause unwanted scrolling on update()
155
+ this.updateScrollToRow();
156
+ }
157
+ getCurrentScrollTop(scrollEvent) {
158
+ // For virtualized trees, use the virtualized view's scroll state (most reliable)
159
+ if (this.props.virtualized !== false && this.view) {
160
+ const scrollState = this.getVirtualizedScrollState();
161
+ if (scrollState !== undefined) {
162
+ return scrollState.scrollTop;
163
+ }
164
+ }
165
+ // Try to extract scroll position from the scroll event
166
+ if (scrollEvent && typeof scrollEvent === 'object' && 'scrollTop' in scrollEvent) {
167
+ const scrollEventWithScrollTop = scrollEvent;
168
+ const scrollTop = scrollEventWithScrollTop.scrollTop;
169
+ if (typeof scrollTop === 'number' && !isNaN(scrollTop)) {
170
+ return scrollTop;
171
+ }
172
+ }
173
+ // Last resort: use DOM scroll position
174
+ if (this.node && typeof this.node.scrollTop === 'number') {
175
+ return this.node.scrollTop;
176
+ }
177
+ return 0;
178
+ }
179
+ /**
180
+ * Returns true if the scroll position is at the absolute (1px tolerance) bottom of the scroll container.
181
+ * Handles both virtualized and non-virtualized scroll containers.
182
+ * Allows for a tiny floating point epsilon (1px).
183
+ */
184
+ isAtAbsoluteBottom() {
185
+ var _a, _b;
186
+ let scrollTop = 0;
187
+ let scrollHeight = 0;
188
+ let clientHeight = 0;
189
+ const EPSILON = 1; // px
190
+ if (this.props.virtualized !== false && this.view) {
191
+ const state = this.getVirtualizedScrollState();
192
+ if (state) {
193
+ scrollTop = state.scrollTop;
194
+ scrollHeight = (_a = state.scrollHeight) !== null && _a !== void 0 ? _a : 0;
195
+ clientHeight = (_b = state.clientHeight) !== null && _b !== void 0 ? _b : 0;
196
+ }
197
+ }
198
+ else if (this.node) {
199
+ scrollTop = this.node.scrollTop;
200
+ scrollHeight = this.node.scrollHeight;
201
+ clientHeight = this.node.clientHeight;
202
+ }
203
+ const diff = Math.abs(scrollTop + clientHeight - scrollHeight);
204
+ return diff <= EPSILON;
205
+ }
206
+ renderTree(model) {
207
+ var _a;
208
+ if (!this.isEnabled) {
209
+ return this.renderDisabledMessage();
210
+ }
211
+ const tree = browser_2.CompositeTreeNode.is(model.root) && ((_a = model.root.children) === null || _a === void 0 ? void 0 : _a.length) > 0
212
+ ? super.renderTree(model)
213
+ : this.renderWelcomeMessage();
214
+ return React.createElement(React.Fragment, null,
215
+ tree,
216
+ this.renderScrollToBottomButton());
217
+ }
218
+ /** Shows the scroll to bottom button if not at the bottom (debounced). */
219
+ renderScrollToBottomButton() {
220
+ if (!this._showScrollButton) {
221
+ return undefined;
222
+ }
223
+ // Down-arrow, Theia codicon, fixed overlay on widget
224
+ return React.createElement("button", { className: "theia-ChatTree-ScrollToBottom codicon codicon-arrow-down", title: nls_1.nls.localize('theia/ai/chat-ui/chat-view-tree-widget/scrollToBottom', 'Jump to latest message'), onClick: () => this.handleScrollToBottomButtonClick() });
225
+ }
226
+ /** Scrolls to the bottom row and updates atBottom state. */
227
+ handleScrollToBottomButtonClick() {
228
+ this.scrollToRow = this.rows.size;
229
+ this.atBottom = true;
230
+ this._showScrollButton = false;
231
+ if (this._scrollButtonDebounceTimer !== undefined) {
232
+ clearTimeout(this._scrollButtonDebounceTimer);
233
+ this._scrollButtonDebounceTimer = undefined;
234
+ }
235
+ this.update();
236
+ }
237
+ renderDisabledMessage() {
238
+ var _a, _b, _c;
239
+ return (_c = (_b = (_a = this.welcomeMessageProvider) === null || _a === void 0 ? void 0 : _a.renderDisabledMessage) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : React.createElement(React.Fragment, null);
240
+ }
241
+ renderWelcomeMessage() {
242
+ var _a, _b, _c;
243
+ return (_c = (_b = (_a = this.welcomeMessageProvider) === null || _a === void 0 ? void 0 : _a.renderWelcomeMessage) === null || _b === void 0 ? void 0 : _b.call(_a)) !== null && _c !== void 0 ? _c : React.createElement(React.Fragment, null);
244
+ }
245
+ mapRequestToNode(branch) {
246
+ return {
247
+ parent: this.model.root,
248
+ get id() {
249
+ return this.request.id;
250
+ },
251
+ get request() {
252
+ return branch.get();
253
+ },
254
+ branch,
255
+ sessionId: this.chatModelId
256
+ };
257
+ }
258
+ mapResponseToNode(response) {
259
+ return {
260
+ id: response.id,
261
+ parent: this.model.root,
262
+ response,
263
+ sessionId: this.chatModelId
264
+ };
265
+ }
266
+ /**
267
+ * Tracks the ChatModel handed over.
268
+ * Tracking multiple chat models will result in a weird UI
269
+ */
270
+ trackChatModel(chatModel) {
271
+ this.toDisposeOnChatModelChange.dispose();
272
+ this.recreateModelTree(chatModel);
273
+ chatModel.getRequests().forEach(request => {
274
+ if (!request.response.isComplete) {
275
+ request.response.onDidChange(() => this.scheduleUpdateScrollToRow());
276
+ }
277
+ });
278
+ this.toDisposeOnChatModelChange.pushAll([
279
+ core_1.Disposable.create(() => {
280
+ this.chatInputs.forEach(widget => widget.dispose());
281
+ this.chatInputs.clear();
282
+ }),
283
+ chatModel.onDidChange(event => {
284
+ var _a;
285
+ if (event.kind === 'enableEdit') {
286
+ this.scrollToRow = (_a = this.rows.get(event.request.id)) === null || _a === void 0 ? void 0 : _a.index;
287
+ this.update();
288
+ return;
289
+ }
290
+ else if (event.kind === 'cancelEdit') {
291
+ this.disposeChatInputWidget(event.request);
292
+ this.scrollToRow = undefined;
293
+ this.update();
294
+ return;
295
+ }
296
+ else if (event.kind === 'changeHierarchyBranch') {
297
+ this.scrollToRow = undefined;
298
+ }
299
+ this.recreateModelTree(chatModel);
300
+ if (event.kind === 'addRequest' && !event.request.response.isComplete) {
301
+ event.request.response.onDidChange(() => this.scheduleUpdateScrollToRow());
302
+ }
303
+ else if (event.kind === 'submitEdit') {
304
+ event.branch.succeedingBranches().forEach(branch => {
305
+ this.disposeChatInputWidget(branch.get());
306
+ });
307
+ this.onDidSubmitEditEmitter.fire(event.newRequest);
308
+ }
309
+ })
310
+ ]);
311
+ }
312
+ disposeChatInputWidget(request) {
313
+ const widget = this.chatInputs.get(request.id);
314
+ if (widget) {
315
+ widget.dispose();
316
+ this.chatInputs.delete(request.id);
317
+ }
318
+ }
319
+ getScrollToRow() {
320
+ // Only scroll to end if auto-scroll is enabled (not locked)
321
+ if (this.shouldScrollToEnd) {
322
+ return this.rows.size;
323
+ }
324
+ // When auto-scroll is disabled, don't auto-scroll at all
325
+ return undefined;
326
+ }
327
+ async recreateModelTree(chatModel) {
328
+ if (browser_2.CompositeTreeNode.is(this.model.root)) {
329
+ const nodes = [];
330
+ this.chatModelId = chatModel.id;
331
+ chatModel.getBranches().forEach(branch => {
332
+ const request = branch.get();
333
+ nodes.push(this.mapRequestToNode(branch));
334
+ nodes.push(this.mapResponseToNode(request.response));
335
+ });
336
+ this.model.root.children = nodes;
337
+ this.model.refresh();
338
+ }
339
+ }
340
+ renderNode(node, props) {
341
+ if (!browser_2.TreeNode.isVisible(node)) {
342
+ return undefined;
343
+ }
344
+ if (!((0, exports.isRequestNode)(node) || (0, exports.isResponseNode)(node))) {
345
+ return super.renderNode(node, props);
346
+ }
347
+ return React.createElement(React.Fragment, { key: node.id },
348
+ React.createElement("div", { className: 'theia-ChatNode', onContextMenu: e => this.handleContextMenu(node, e) },
349
+ this.renderAgent(node),
350
+ this.renderDetail(node)));
351
+ }
352
+ renderAgent(node) {
353
+ var _a;
354
+ const inProgress = (0, exports.isResponseNode)(node) && !node.response.isComplete && !node.response.isCanceled && !node.response.isError;
355
+ const waitingForInput = (0, exports.isResponseNode)(node) && node.response.isWaitingForInput;
356
+ const toolbarContributions = !inProgress
357
+ ? this.chatNodeToolbarActionContributions.getContributions()
358
+ .flatMap(c => c.getToolbarActions(node))
359
+ .filter(action => this.commandRegistry.isEnabled(action.commandId, node))
360
+ .sort((a, b) => { var _a, _b; return ((_a = a.priority) !== null && _a !== void 0 ? _a : 0) - ((_b = b.priority) !== null && _b !== void 0 ? _b : 0); })
361
+ : [];
362
+ const agentLabel = React.createRef();
363
+ const agentDescription = (_a = this.getAgent(node)) === null || _a === void 0 ? void 0 : _a.description;
364
+ return React.createElement(React.Fragment, null,
365
+ React.createElement("div", { className: 'theia-ChatNodeHeader' },
366
+ React.createElement("div", { className: `theia-AgentAvatar ${this.getAgentIconClassName(node)}` }),
367
+ React.createElement("h3", { ref: agentLabel, className: 'theia-AgentLabel', onMouseEnter: () => {
368
+ if (agentDescription) {
369
+ this.hoverService.requestHover({
370
+ content: agentDescription,
371
+ target: agentLabel.current,
372
+ position: 'right'
373
+ });
374
+ }
375
+ } }, this.getAgentLabel(node)),
376
+ inProgress && !waitingForInput && React.createElement("span", { className: 'theia-ChatContentInProgress' }, nls_1.nls.localizeByDefault('Generating')),
377
+ inProgress && waitingForInput && React.createElement("span", { className: 'theia-ChatContentInProgress' }, nls_1.nls.localize('theia/ai/chat-ui/chat-view-tree-widget/waitingForInput', 'Waiting for input')),
378
+ React.createElement("div", { className: 'theia-ChatNodeToolbar' }, !inProgress &&
379
+ toolbarContributions.length > 0 &&
380
+ toolbarContributions.map(action => React.createElement("span", { key: action.commandId, className: `theia-ChatNodeToolbarAction ${action.icon}`, title: action.tooltip, onClick: e => {
381
+ e.stopPropagation();
382
+ this.commandRegistry.executeCommand(action.commandId, node);
383
+ }, onKeyDown: e => {
384
+ if (isEnterKey(e)) {
385
+ e.stopPropagation();
386
+ this.commandRegistry.executeCommand(action.commandId, node);
387
+ }
388
+ }, role: 'button' })))));
389
+ }
390
+ getAgentLabel(node) {
391
+ var _a, _b;
392
+ if ((0, exports.isRequestNode)(node)) {
393
+ // TODO find user name
394
+ return nls_1.nls.localize('theia/ai/chat-ui/chat-view-tree-widget/you', 'You');
395
+ }
396
+ return (_b = (_a = this.getAgent(node)) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : nls_1.nls.localize('theia/ai/chat-ui/chat-view-tree-widget/ai', 'AI');
397
+ }
398
+ getAgent(node) {
399
+ if ((0, exports.isRequestNode)(node)) {
400
+ return undefined;
401
+ }
402
+ return node.response.agentId ? this.chatAgentService.getAgent(node.response.agentId) : undefined;
403
+ }
404
+ getAgentIconClassName(node) {
405
+ var _a;
406
+ if ((0, exports.isRequestNode)(node)) {
407
+ return (0, browser_2.codicon)('account');
408
+ }
409
+ const agent = node.response.agentId ? this.chatAgentService.getAgent(node.response.agentId) : undefined;
410
+ return (_a = agent === null || agent === void 0 ? void 0 : agent.iconClass) !== null && _a !== void 0 ? _a : (0, browser_2.codicon)('copilot');
411
+ }
412
+ renderDetail(node) {
413
+ if ((0, exports.isRequestNode)(node)) {
414
+ return this.renderChatRequest(node);
415
+ }
416
+ if ((0, exports.isResponseNode)(node)) {
417
+ return this.renderChatResponse(node);
418
+ }
419
+ ;
420
+ }
421
+ renderChatRequest(node) {
422
+ return React.createElement(ChatRequestRender, { node: node, hoverService: this.hoverService, chatAgentService: this.chatAgentService, variableService: this.variableService, openerService: this.openerService, provideChatInputWidget: () => {
423
+ const editableNode = node;
424
+ if ((0, exports.isEditableRequestNode)(editableNode)) {
425
+ let widget = this.chatInputs.get(editableNode.id);
426
+ if (!widget) {
427
+ widget = this.inputWidgetFactory({
428
+ node: editableNode,
429
+ initialValue: editableNode.request.message.request.text,
430
+ onQuery: async (query) => {
431
+ editableNode.request.submitEdit({ text: query });
432
+ },
433
+ branch: editableNode.branch
434
+ });
435
+ this.chatInputs.set(editableNode.id, widget);
436
+ widget.disposed.connect(() => {
437
+ this.chatInputs.delete(editableNode.id);
438
+ editableNode.request.cancelEdit();
439
+ });
440
+ }
441
+ return widget;
442
+ }
443
+ return;
444
+ } });
445
+ }
446
+ renderChatResponse(node) {
447
+ return (React.createElement("div", { className: 'theia-ResponseNode' },
448
+ !node.response.isComplete
449
+ && node.response.response.content.length === 0
450
+ && node.response.progressMessages
451
+ .filter(c => c.show === 'untilFirstContent')
452
+ .map((c, i) => React.createElement(chat_progress_message_1.ProgressMessage, { ...c, key: `${node.id}-progress-untilFirstContent-${i}` })),
453
+ node.response.response.content.map((c, i) => React.createElement("div", { className: 'theia-ResponseNode-Content', key: `${node.id}-content-${i}` }, this.getChatResponsePartRenderer(c, node))),
454
+ !node.response.isComplete
455
+ && node.response.progressMessages
456
+ .filter(c => c.show === 'whileIncomplete')
457
+ .map((c, i) => React.createElement(chat_progress_message_1.ProgressMessage, { ...c, key: `${node.id}-progress-whileIncomplete-${i}` })),
458
+ node.response.progressMessages
459
+ .filter(c => c.show === 'forever')
460
+ .map((c, i) => React.createElement(chat_progress_message_1.ProgressMessage, { ...c, key: `${node.id}-progress-afterComplete-${i}` }))));
461
+ }
462
+ getChatResponsePartRenderer(content, node) {
463
+ const renderer = this.chatResponsePartRenderers.getContributions().reduce((prev, current) => {
464
+ const prio = current.canHandle(content);
465
+ if (prio > prev[0]) {
466
+ return [prio, current];
467
+ }
468
+ return prev;
469
+ }, [-1, undefined])[1];
470
+ if (!renderer) {
471
+ console.error('No renderer found for content', content);
472
+ return React.createElement("div", null, nls_1.nls.localize('theia/ai/chat-ui/chat-view-tree-widget/noRenderer', 'Error: No renderer found'));
473
+ }
474
+ return renderer.render(content, node);
475
+ }
476
+ handleContextMenu(node, event) {
477
+ this.contextMenuRenderer.render({
478
+ menuPath: ChatViewTreeWidget_1.CONTEXT_MENU,
479
+ anchor: { x: event.clientX, y: event.clientY },
480
+ args: [node],
481
+ context: event.currentTarget
482
+ });
483
+ event.preventDefault();
484
+ }
485
+ handleSpace(event) {
486
+ // We need to return false to prevent the handler within
487
+ // packages/core/src/browser/widgets/widget.ts
488
+ // Otherwise, the space key will never be handled by the monaco editor
489
+ return false;
490
+ }
491
+ /**
492
+ * Ensure atBottom state is correct when content grows (e.g., LLM streaming while scroll lock is enabled).
493
+ */
494
+ updateScrollToRow() {
495
+ super.updateScrollToRow();
496
+ const isAtBottom = this.isScrolledToBottom();
497
+ this.updateScrollToBottomButtonState(isAtBottom);
498
+ }
499
+ };
500
+ exports.ChatViewTreeWidget = ChatViewTreeWidget;
501
+ ChatViewTreeWidget.ID = 'chat-tree-widget';
502
+ ChatViewTreeWidget.CONTEXT_MENU = ['chat-tree-context-menu'];
503
+ /**
504
+ * Debounce period in ms before showing scroll-to-bottom button after scrolling up.
505
+ * Avoids flickering of the button during LLM token streaming.
506
+ */
507
+ ChatViewTreeWidget.SCROLL_BUTTON_GRACE_PERIOD = 100;
508
+ tslib_1.__decorate([
509
+ (0, inversify_1.inject)(core_1.ContributionProvider),
510
+ (0, inversify_1.named)(chat_response_part_renderer_1.ChatResponsePartRenderer),
511
+ tslib_1.__metadata("design:type", Object)
512
+ ], ChatViewTreeWidget.prototype, "chatResponsePartRenderers", void 0);
513
+ tslib_1.__decorate([
514
+ (0, inversify_1.inject)(core_1.ContributionProvider),
515
+ (0, inversify_1.named)(chat_node_toolbar_action_contribution_1.ChatNodeToolbarActionContribution),
516
+ tslib_1.__metadata("design:type", Object)
517
+ ], ChatViewTreeWidget.prototype, "chatNodeToolbarActionContributions", void 0);
518
+ tslib_1.__decorate([
519
+ (0, inversify_1.inject)(ai_chat_1.ChatAgentService),
520
+ tslib_1.__metadata("design:type", Object)
521
+ ], ChatViewTreeWidget.prototype, "chatAgentService", void 0);
522
+ tslib_1.__decorate([
523
+ (0, inversify_1.inject)(ai_core_1.AIVariableService),
524
+ tslib_1.__metadata("design:type", Object)
525
+ ], ChatViewTreeWidget.prototype, "variableService", void 0);
526
+ tslib_1.__decorate([
527
+ (0, inversify_1.inject)(core_1.CommandRegistry),
528
+ tslib_1.__metadata("design:type", core_1.CommandRegistry)
529
+ ], ChatViewTreeWidget.prototype, "commandRegistry", void 0);
530
+ tslib_1.__decorate([
531
+ (0, inversify_1.inject)(browser_2.OpenerService),
532
+ tslib_1.__metadata("design:type", Object)
533
+ ], ChatViewTreeWidget.prototype, "openerService", void 0);
534
+ tslib_1.__decorate([
535
+ (0, inversify_1.inject)(browser_2.HoverService),
536
+ tslib_1.__metadata("design:type", browser_2.HoverService)
537
+ ], ChatViewTreeWidget.prototype, "hoverService", void 0);
538
+ tslib_1.__decorate([
539
+ (0, inversify_1.inject)(exports.ChatWelcomeMessageProvider),
540
+ (0, inversify_1.optional)(),
541
+ tslib_1.__metadata("design:type", Object)
542
+ ], ChatViewTreeWidget.prototype, "welcomeMessageProvider", void 0);
543
+ tslib_1.__decorate([
544
+ (0, inversify_1.inject)(chat_view_tree_input_widget_1.AIChatTreeInputFactory),
545
+ tslib_1.__metadata("design:type", Function)
546
+ ], ChatViewTreeWidget.prototype, "inputWidgetFactory", void 0);
547
+ tslib_1.__decorate([
548
+ (0, inversify_1.inject)(browser_1.AIActivationService),
549
+ tslib_1.__metadata("design:type", Object)
550
+ ], ChatViewTreeWidget.prototype, "activationService", void 0);
551
+ tslib_1.__decorate([
552
+ (0, inversify_1.inject)(ai_chat_1.ChatService),
553
+ tslib_1.__metadata("design:type", Object)
554
+ ], ChatViewTreeWidget.prototype, "chatService", void 0);
555
+ tslib_1.__decorate([
556
+ (0, inversify_1.postConstruct)(),
557
+ tslib_1.__metadata("design:type", Function),
558
+ tslib_1.__metadata("design:paramtypes", []),
559
+ tslib_1.__metadata("design:returntype", void 0)
560
+ ], ChatViewTreeWidget.prototype, "init", null);
561
+ exports.ChatViewTreeWidget = ChatViewTreeWidget = ChatViewTreeWidget_1 = tslib_1.__decorate([
562
+ (0, inversify_1.injectable)(),
563
+ tslib_1.__param(0, (0, inversify_1.inject)(browser_2.TreeProps)),
564
+ tslib_1.__param(1, (0, inversify_1.inject)(browser_2.TreeModel)),
565
+ tslib_1.__param(2, (0, inversify_1.inject)(browser_2.ContextMenuRenderer)),
566
+ tslib_1.__metadata("design:paramtypes", [Object, Object, browser_2.ContextMenuRenderer])
567
+ ], ChatViewTreeWidget);
568
+ const WidgetContainer = ({ widget }) => {
569
+ // eslint-disable-next-line no-null/no-null
570
+ const containerRef = React.useRef(null);
571
+ React.useEffect(() => {
572
+ if (containerRef.current && !widget.isAttached) {
573
+ browser_2.Widget.attach(widget, containerRef.current);
574
+ }
575
+ }, [containerRef.current]);
576
+ // Clean up
577
+ React.useEffect(() => () => {
578
+ setTimeout(() => {
579
+ // Delay clean up to allow react to finish its rendering cycle
580
+ widget.clearFlag(browser_2.Widget.Flag.IsAttached);
581
+ widget.dispose();
582
+ });
583
+ }, []);
584
+ return React.createElement("div", { ref: containerRef });
585
+ };
586
+ const ChatRequestRender = ({ node, hoverService, chatAgentService, variableService, openerService, provideChatInputWidget }) => {
587
+ const parts = node.request.message.parts;
588
+ if (ai_chat_1.EditableChatRequestModel.isEditing(node.request)) {
589
+ const widget = provideChatInputWidget();
590
+ if (widget) {
591
+ return React.createElement("div", { className: "theia-RequestNode" },
592
+ React.createElement(WidgetContainer, { widget: widget }));
593
+ }
594
+ }
595
+ const renderFooter = () => {
596
+ if (node.branch.items.length < 2) {
597
+ return;
598
+ }
599
+ const isFirst = node.branch.activeBranchIndex === 0;
600
+ const isLast = node.branch.activeBranchIndex === node.branch.items.length - 1;
601
+ return (React.createElement("div", { className: 'theia-RequestNode-Footer' },
602
+ React.createElement("div", { className: `item ${isFirst ? '' : 'enabled'}` },
603
+ React.createElement("div", { className: "codicon codicon-chevron-left action-label", title: "Previous", onClick: () => {
604
+ node.branch.enablePrevious();
605
+ } })),
606
+ React.createElement("small", null,
607
+ React.createElement("span", null,
608
+ node.branch.activeBranchIndex + 1,
609
+ "/"),
610
+ React.createElement("span", null, node.branch.items.length)),
611
+ React.createElement("div", { className: `item ${isLast ? '' : 'enabled'}` },
612
+ React.createElement("div", { className: 'codicon codicon-chevron-right action-label', title: "Next", onClick: () => {
613
+ node.branch.enableNext();
614
+ } }))));
615
+ };
616
+ return (React.createElement("div", { className: "theia-RequestNode" },
617
+ React.createElement("p", null, parts.map((part, index) => {
618
+ var _a, _b;
619
+ if (part instanceof ai_chat_1.ParsedChatRequestAgentPart || part instanceof ai_chat_1.ParsedChatRequestVariablePart) {
620
+ let description = undefined;
621
+ let className = '';
622
+ if (part instanceof ai_chat_1.ParsedChatRequestAgentPart) {
623
+ description = (_a = chatAgentService.getAgent(part.agentId)) === null || _a === void 0 ? void 0 : _a.description;
624
+ className = 'theia-RequestNode-AgentLabel';
625
+ }
626
+ else if (part instanceof ai_chat_1.ParsedChatRequestVariablePart) {
627
+ description = (_b = variableService.getVariable(part.variableName)) === null || _b === void 0 ? void 0 : _b.description;
628
+ className = 'theia-RequestNode-VariableLabel';
629
+ }
630
+ return (React.createElement(HoverableLabel, { key: index, text: part.text, description: description, hoverService: hoverService, className: className }));
631
+ }
632
+ else {
633
+ const ref = (0, markdown_part_renderer_1.useMarkdownRendering)(part.text
634
+ .replace(/^[\r\n]+|[\r\n]+$/g, '') // remove excessive new lines
635
+ .replace(/(^ )/g, '&nbsp;'), // enforce keeping space before
636
+ openerService, true);
637
+ return (React.createElement("span", { key: index, ref: ref }));
638
+ }
639
+ })),
640
+ renderFooter()));
641
+ };
642
+ const HoverableLabel = ({ text, description, hoverService, className }) => {
643
+ const spanRef = React.createRef();
644
+ return (React.createElement("span", { className: className, ref: spanRef, onMouseEnter: () => {
645
+ if (description) {
646
+ hoverService.requestHover({
647
+ content: description,
648
+ target: spanRef.current,
649
+ position: 'right'
650
+ });
651
+ }
652
+ } }, text));
653
+ };
654
+ //# sourceMappingURL=chat-view-tree-widget.js.map