@theia/ai-chat-ui 1.68.0-next.8 → 1.68.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 (132) hide show
  1. package/README.md +33 -0
  2. package/lib/browser/ai-chat-ui-contribution.d.ts +2 -1
  3. package/lib/browser/ai-chat-ui-contribution.d.ts.map +1 -1
  4. package/lib/browser/ai-chat-ui-contribution.js +41 -32
  5. package/lib/browser/ai-chat-ui-contribution.js.map +1 -1
  6. package/lib/browser/ai-chat-ui-frontend-module.d.ts.map +1 -1
  7. package/lib/browser/ai-chat-ui-frontend-module.js +15 -6
  8. package/lib/browser/ai-chat-ui-frontend-module.js.map +1 -1
  9. package/lib/browser/change-set-actions/change-set-accept-action.d.ts +0 -1
  10. package/lib/browser/change-set-actions/change-set-accept-action.d.ts.map +1 -1
  11. package/lib/browser/change-set-actions/change-set-action-service.d.ts +0 -1
  12. package/lib/browser/change-set-actions/change-set-action-service.d.ts.map +1 -1
  13. package/lib/browser/change-set-actions/change-set-action-service.js +2 -2
  14. package/lib/browser/change-set-actions/change-set-action-service.js.map +1 -1
  15. package/lib/browser/chat-focus-contribution.d.ts +14 -0
  16. package/lib/browser/chat-focus-contribution.d.ts.map +1 -0
  17. package/lib/browser/chat-focus-contribution.js +102 -0
  18. package/lib/browser/chat-focus-contribution.js.map +1 -0
  19. package/lib/browser/chat-input-agent-suggestions.d.ts +0 -1
  20. package/lib/browser/chat-input-agent-suggestions.d.ts.map +1 -1
  21. package/lib/browser/chat-input-agent-suggestions.js +1 -1
  22. package/lib/browser/chat-input-agent-suggestions.js.map +1 -1
  23. package/lib/browser/chat-input-history-contribution.js +6 -10
  24. package/lib/browser/chat-input-history-contribution.js.map +1 -1
  25. package/lib/browser/chat-input-mode-contribution.js +1 -2
  26. package/lib/browser/chat-input-mode-contribution.js.map +1 -1
  27. package/lib/browser/chat-input-widget.d.ts +0 -1
  28. package/lib/browser/chat-input-widget.d.ts.map +1 -1
  29. package/lib/browser/chat-input-widget.js +106 -96
  30. package/lib/browser/chat-input-widget.js.map +1 -1
  31. package/lib/browser/chat-progress-message.d.ts +0 -1
  32. package/lib/browser/chat-progress-message.d.ts.map +1 -1
  33. package/lib/browser/chat-response-part-renderer.d.ts +0 -1
  34. package/lib/browser/chat-response-part-renderer.d.ts.map +1 -1
  35. package/lib/browser/chat-response-renderer/ai-selection-resolver.js +4 -5
  36. package/lib/browser/chat-response-renderer/ai-selection-resolver.js.map +1 -1
  37. package/lib/browser/chat-response-renderer/code-part-renderer.d.ts +0 -1
  38. package/lib/browser/chat-response-renderer/code-part-renderer.d.ts.map +1 -1
  39. package/lib/browser/chat-response-renderer/code-part-renderer.js +6 -9
  40. package/lib/browser/chat-response-renderer/code-part-renderer.js.map +1 -1
  41. package/lib/browser/chat-response-renderer/command-part-renderer.d.ts +0 -1
  42. package/lib/browser/chat-response-renderer/command-part-renderer.d.ts.map +1 -1
  43. package/lib/browser/chat-response-renderer/command-part-renderer.js +7 -4
  44. package/lib/browser/chat-response-renderer/command-part-renderer.js.map +1 -1
  45. package/lib/browser/chat-response-renderer/delegation-response-renderer.d.ts +0 -1
  46. package/lib/browser/chat-response-renderer/delegation-response-renderer.d.ts.map +1 -1
  47. package/lib/browser/chat-response-renderer/delegation-response-renderer.js +3 -4
  48. package/lib/browser/chat-response-renderer/delegation-response-renderer.js.map +1 -1
  49. package/lib/browser/chat-response-renderer/error-part-renderer.d.ts +0 -1
  50. package/lib/browser/chat-response-renderer/error-part-renderer.d.ts.map +1 -1
  51. package/lib/browser/chat-response-renderer/horizontal-layout-part-renderer.d.ts +0 -1
  52. package/lib/browser/chat-response-renderer/horizontal-layout-part-renderer.d.ts.map +1 -1
  53. package/lib/browser/chat-response-renderer/index.d.ts +1 -0
  54. package/lib/browser/chat-response-renderer/index.d.ts.map +1 -1
  55. package/lib/browser/chat-response-renderer/index.js +1 -0
  56. package/lib/browser/chat-response-renderer/index.js.map +1 -1
  57. package/lib/browser/chat-response-renderer/markdown-part-renderer.d.ts +0 -1
  58. package/lib/browser/chat-response-renderer/markdown-part-renderer.d.ts.map +1 -1
  59. package/lib/browser/chat-response-renderer/markdown-part-renderer.js +7 -9
  60. package/lib/browser/chat-response-renderer/markdown-part-renderer.js.map +1 -1
  61. package/lib/browser/chat-response-renderer/not-available-toolcall-renderer.d.ts +17 -0
  62. package/lib/browser/chat-response-renderer/not-available-toolcall-renderer.d.ts.map +1 -0
  63. package/lib/browser/chat-response-renderer/not-available-toolcall-renderer.js +56 -0
  64. package/lib/browser/chat-response-renderer/not-available-toolcall-renderer.js.map +1 -0
  65. package/lib/browser/chat-response-renderer/progress-part-renderer.d.ts +0 -1
  66. package/lib/browser/chat-response-renderer/progress-part-renderer.d.ts.map +1 -1
  67. package/lib/browser/chat-response-renderer/question-part-renderer.d.ts +0 -1
  68. package/lib/browser/chat-response-renderer/question-part-renderer.d.ts.map +1 -1
  69. package/lib/browser/chat-response-renderer/question-part-renderer.js +6 -9
  70. package/lib/browser/chat-response-renderer/question-part-renderer.js.map +1 -1
  71. package/lib/browser/chat-response-renderer/text-part-renderer.d.ts +0 -1
  72. package/lib/browser/chat-response-renderer/text-part-renderer.d.ts.map +1 -1
  73. package/lib/browser/chat-response-renderer/thinking-part-renderer.d.ts +0 -1
  74. package/lib/browser/chat-response-renderer/thinking-part-renderer.d.ts.map +1 -1
  75. package/lib/browser/chat-response-renderer/tool-confirmation.d.ts +29 -10
  76. package/lib/browser/chat-response-renderer/tool-confirmation.d.ts.map +1 -1
  77. package/lib/browser/chat-response-renderer/tool-confirmation.js +219 -65
  78. package/lib/browser/chat-response-renderer/tool-confirmation.js.map +1 -1
  79. package/lib/browser/chat-response-renderer/tool-confirmation.spec.d.ts +2 -0
  80. package/lib/browser/chat-response-renderer/tool-confirmation.spec.d.ts.map +1 -0
  81. package/lib/browser/chat-response-renderer/tool-confirmation.spec.js +100 -0
  82. package/lib/browser/chat-response-renderer/tool-confirmation.spec.js.map +1 -0
  83. package/lib/browser/chat-response-renderer/toolcall-part-renderer.d.ts +5 -3
  84. package/lib/browser/chat-response-renderer/toolcall-part-renderer.d.ts.map +1 -1
  85. package/lib/browser/chat-response-renderer/toolcall-part-renderer.js +21 -11
  86. package/lib/browser/chat-response-renderer/toolcall-part-renderer.js.map +1 -1
  87. package/lib/browser/chat-response-renderer/unknown-part-renderer.d.ts +0 -1
  88. package/lib/browser/chat-response-renderer/unknown-part-renderer.d.ts.map +1 -1
  89. package/lib/browser/chat-response-renderer/unknown-part-renderer.js +1 -2
  90. package/lib/browser/chat-response-renderer/unknown-part-renderer.js.map +1 -1
  91. package/lib/browser/chat-tree-view/chat-view-tree-container.js +1 -2
  92. package/lib/browser/chat-tree-view/chat-view-tree-container.js.map +1 -1
  93. package/lib/browser/chat-tree-view/chat-view-tree-input-widget.js +2 -3
  94. package/lib/browser/chat-tree-view/chat-view-tree-input-widget.js.map +1 -1
  95. package/lib/browser/chat-tree-view/chat-view-tree-widget.d.ts +3 -1
  96. package/lib/browser/chat-tree-view/chat-view-tree-widget.d.ts.map +1 -1
  97. package/lib/browser/chat-tree-view/chat-view-tree-widget.js +49 -42
  98. package/lib/browser/chat-tree-view/chat-view-tree-widget.js.map +1 -1
  99. package/lib/browser/chat-tree-view/prompt-variant-badge.d.ts +0 -1
  100. package/lib/browser/chat-tree-view/prompt-variant-badge.d.ts.map +1 -1
  101. package/lib/browser/chat-tree-view/sub-chat-widget.d.ts +0 -1
  102. package/lib/browser/chat-tree-view/sub-chat-widget.d.ts.map +1 -1
  103. package/lib/browser/chat-view-commands.d.ts.map +1 -1
  104. package/lib/browser/chat-view-commands.js +2 -2
  105. package/lib/browser/chat-view-commands.js.map +1 -1
  106. package/lib/browser/chat-view-contribution.js +7 -7
  107. package/lib/browser/chat-view-contribution.js.map +1 -1
  108. package/lib/browser/chat-view-language-contribution.js +3 -4
  109. package/lib/browser/chat-view-language-contribution.js.map +1 -1
  110. package/lib/browser/chat-view-widget.js +9 -10
  111. package/lib/browser/chat-view-widget.js.map +1 -1
  112. package/lib/browser/context-variable-picker.js +9 -13
  113. package/lib/browser/context-variable-picker.js.map +1 -1
  114. package/lib/browser/session-storage-preference-renderer.d.ts +127 -0
  115. package/lib/browser/session-storage-preference-renderer.d.ts.map +1 -0
  116. package/lib/browser/session-storage-preference-renderer.js +490 -0
  117. package/lib/browser/session-storage-preference-renderer.js.map +1 -0
  118. package/package.json +12 -11
  119. package/src/browser/ai-chat-ui-contribution.ts +19 -7
  120. package/src/browser/ai-chat-ui-frontend-module.ts +13 -0
  121. package/src/browser/chat-focus-contribution.ts +102 -0
  122. package/src/browser/chat-input-widget.tsx +99 -27
  123. package/src/browser/chat-response-renderer/index.ts +1 -0
  124. package/src/browser/chat-response-renderer/not-available-toolcall-renderer.tsx +57 -0
  125. package/src/browser/chat-response-renderer/tool-confirmation.spec.ts +108 -0
  126. package/src/browser/chat-response-renderer/tool-confirmation.tsx +379 -95
  127. package/src/browser/chat-response-renderer/toolcall-part-renderer.tsx +27 -13
  128. package/src/browser/chat-tree-view/chat-view-tree-widget.tsx +33 -5
  129. package/src/browser/chat-view-commands.ts +2 -2
  130. package/src/browser/session-storage-preference-renderer.ts +657 -0
  131. package/src/browser/style/index.css +73 -26
  132. package/src/browser/style/session-storage-preference.css +134 -0
@@ -38,7 +38,7 @@ const task_context_variable_1 = require("@theia/ai-chat/lib/browser/task-context
38
38
  const chat_input_history_1 = require("./chat-input-history");
39
39
  const context_file_validation_service_1 = require("@theia/ai-chat/lib/browser/context-file-validation-service");
40
40
  exports.AIChatInputConfiguration = Symbol('AIChatInputConfiguration');
41
- let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends browser_2.ReactWidget {
41
+ let AIChatInputWidget = class AIChatInputWidget extends browser_2.ReactWidget {
42
42
  constructor() {
43
43
  super(...arguments);
44
44
  this.fileValidationState = new Map();
@@ -56,6 +56,9 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
56
56
  this.onDidResizeEmitter = new core_1.Emitter();
57
57
  this.onDidResize = this.onDidResizeEmitter.event;
58
58
  }
59
+ static { AIChatInputWidget_1 = this; }
60
+ static { this.ID = 'chat-input-widget'; }
61
+ static { this.CONTEXT_MENU = ['chat-input-context-menu']; }
59
62
  get editor() {
60
63
  return this.editorRef;
61
64
  }
@@ -94,8 +97,7 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
94
97
  }
95
98
  set onQuery(query) {
96
99
  this._onQuery = (prompt, mode) => {
97
- var _a;
98
- if (((_a = this.configuration) === null || _a === void 0 ? void 0 : _a.enablePromptHistory) !== false && prompt.trim()) {
100
+ if (this.configuration?.enablePromptHistory !== false && prompt.trim()) {
99
101
  this.historyService.addToHistory(prompt);
100
102
  this.navigationState.stopNavigation();
101
103
  }
@@ -219,7 +221,6 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
219
221
  }, 200);
220
222
  }
221
223
  async updateReceivingAgent() {
222
- var _a, _b, _c;
223
224
  if (!this.editorRef || !this._chatModel) {
224
225
  if (this.receivingAgent !== undefined) {
225
226
  this.chatInputReceivingAgentKey.set('');
@@ -237,15 +238,18 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
237
238
  const session = this.chatService.getSessions().find(s => s.model.id === this._chatModel.id);
238
239
  if (session) {
239
240
  const agent = this.chatService.getAgent(parsedRequest, session);
240
- const agentId = (_a = agent === null || agent === void 0 ? void 0 : agent.id) !== null && _a !== void 0 ? _a : '';
241
- const previousAgentId = (_b = this.receivingAgent) === null || _b === void 0 ? void 0 : _b.agentId;
241
+ const agentId = agent?.id ?? '';
242
+ const previousAgentId = this.receivingAgent?.agentId;
242
243
  this.chatInputReceivingAgentKey.set(agentId);
243
244
  // Only update and re-render when the agent changes
244
245
  if (agent && agentId !== previousAgentId) {
245
- const modes = (_c = agent.modes) !== null && _c !== void 0 ? _c : [];
246
+ const modes = agent.modes ?? [];
247
+ const defaultMode = modes.find(m => m.isDefault);
248
+ const initialModeId = defaultMode?.id;
246
249
  this.receivingAgent = {
247
250
  agentId: agentId,
248
- modes
251
+ modes,
252
+ currentModeId: initialModeId
249
253
  };
250
254
  this.chatInputHasModesKey.set(modes.length > 1);
251
255
  this.update();
@@ -326,13 +330,12 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
326
330
  return new core_1.URI(`ai-chat:/input.${chat_view_language_contribution_1.CHAT_VIEW_LANGUAGE_EXTENSION}`);
327
331
  }
328
332
  render() {
329
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
330
333
  const branch = this._branch;
331
334
  const chatModel = this._chatModel;
332
335
  // State of the input widget's action buttons depends on the state of the currently active or last processed
333
336
  // request, if there is one. If the chat model has branched, then the current request is the last on the
334
337
  // branch. Otherwise, it's the last request in the chat model.
335
- const currentRequest = (_c = (_b = (_a = branch === null || branch === void 0 ? void 0 : branch.items) === null || _a === void 0 ? void 0 : _a.at(-1)) === null || _b === void 0 ? void 0 : _b.element) !== null && _c !== void 0 ? _c : chatModel.getRequests().at(-1);
338
+ const currentRequest = branch?.items?.at(-1)?.element ?? chatModel.getRequests().at(-1);
336
339
  const isEditing = !!(currentRequest && (ai_chat_1.EditableChatRequestModel.isEditing(currentRequest)));
337
340
  const isPending = () => !!(currentRequest && !isEditing && ai_chat_1.ChatRequestModel.isInProgress(currentRequest));
338
341
  const pending = isPending();
@@ -340,22 +343,22 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
340
343
  this.editorRef = editor;
341
344
  this.setupEditorEventListeners();
342
345
  this.editorReady.resolve();
343
- }, showContext: (_d = this.configuration) === null || _d === void 0 ? void 0 : _d.showContext, showPinnedAgent: (_e = this.configuration) === null || _e === void 0 ? void 0 : _e.showPinnedAgent, showChangeSet: (_f = this.configuration) === null || _f === void 0 ? void 0 : _f.showChangeSet, showSuggestions: (_g = this.configuration) === null || _g === void 0 ? void 0 : _g.showSuggestions, hasPromptHistory: (_h = this.configuration) === null || _h === void 0 ? void 0 : _h.enablePromptHistory, labelProvider: this.labelProvider, actionService: this.changeSetActionService, decoratorService: this.changeSetDecoratorService, initialValue: this._initialValue, openerService: this.openerService, suggestions: this._chatModel.suggestions, currentRequest: currentRequest, isEditing: isEditing, pending: pending, heightInLines: this.heightInLines, onResponseChanged: () => {
346
+ this.scheduleUpdateReceivingAgent();
347
+ }, showContext: this.configuration?.showContext, showPinnedAgent: this.configuration?.showPinnedAgent, showChangeSet: this.configuration?.showChangeSet, showSuggestions: this.configuration?.showSuggestions, hasPromptHistory: this.configuration?.enablePromptHistory, labelProvider: this.labelProvider, actionService: this.changeSetActionService, decoratorService: this.changeSetDecoratorService, initialValue: this._initialValue, openerService: this.openerService, suggestions: this._chatModel.suggestions, currentRequest: currentRequest, isEditing: isEditing, pending: pending, heightInLines: this.heightInLines, onResponseChanged: () => {
344
348
  if (isPending() !== pending) {
345
349
  this.update();
346
350
  }
347
351
  }, onResize: () => this.onDidResizeEmitter.fire(), modeSelectorProps: {
348
- receivingAgentModes: (_j = this.receivingAgent) === null || _j === void 0 ? void 0 : _j.modes,
349
- currentMode: (_k = this.receivingAgent) === null || _k === void 0 ? void 0 : _k.currentModeId,
352
+ receivingAgentModes: this.receivingAgent?.modes,
353
+ currentMode: this.receivingAgent?.currentModeId,
350
354
  onModeChange: this.handleModeChange,
351
355
  } }));
352
356
  }
353
357
  onDragOver(event) {
354
- var _a;
355
358
  event.preventDefault();
356
359
  event.stopPropagation();
357
360
  this.node.classList.add('drag-over');
358
- if ((_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.types.includes('text/plain')) {
361
+ if (event.dataTransfer?.types.includes('text/plain')) {
359
362
  event.dataTransfer.dropEffect = 'copy';
360
363
  }
361
364
  else {
@@ -363,18 +366,16 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
363
366
  }
364
367
  }
365
368
  onDrop(event) {
366
- var _a, _b, _c;
367
369
  event.preventDefault();
368
370
  event.stopPropagation();
369
371
  this.node.classList.remove('drag-over');
370
- const dataTransferText = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.getData('text/plain');
371
- const position = (_c = (_b = this.editorRef) === null || _b === void 0 ? void 0 : _b.getControl().getTargetAtClientPoint(event.clientX, event.clientY)) === null || _c === void 0 ? void 0 : _c.position;
372
+ const dataTransferText = event.dataTransfer?.getData('text/plain');
373
+ const position = this.editorRef?.getControl().getTargetAtClientPoint(event.clientX, event.clientY)?.position;
372
374
  this.variableService.getDropResult(event.nativeEvent, { type: 'ai-chat-input-widget' }).then(result => {
373
- var _a, _b;
374
375
  result.variables.forEach(variable => this.addContext(variable));
375
- const text = (_a = result.text) !== null && _a !== void 0 ? _a : dataTransferText;
376
+ const text = result.text ?? dataTransferText;
376
377
  if (position && text) {
377
- (_b = this.editorRef) === null || _b === void 0 ? void 0 : _b.getControl().executeEdits('drag-and-drop', [{
378
+ this.editorRef?.getControl().executeEdits('drag-and-drop', [{
378
379
  range: {
379
380
  startLineNumber: position.lineNumber,
380
381
  startColumn: position.column,
@@ -388,12 +389,11 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
388
389
  }
389
390
  onPaste(event) {
390
391
  this.variableService.getPasteResult(event, { type: 'ai-chat-input-widget' }).then(result => {
391
- var _a, _b;
392
392
  result.variables.forEach(variable => this.addContext(variable));
393
393
  if (result.text) {
394
- const position = (_a = this.editorRef) === null || _a === void 0 ? void 0 : _a.getControl().getPosition();
394
+ const position = this.editorRef?.getControl().getPosition();
395
395
  if (position && result.text) {
396
- (_b = this.editorRef) === null || _b === void 0 ? void 0 : _b.getControl().executeEdits('paste', [{
396
+ this.editorRef?.getControl().executeEdits('paste', [{
397
397
  range: {
398
398
  startLineNumber: position.lineNumber,
399
399
  startColumn: position.column,
@@ -407,8 +407,7 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
407
407
  });
408
408
  }
409
409
  onEscape() {
410
- var _a, _b, _c, _d;
411
- const currentRequest = (_d = (_c = (_b = (_a = this._branch) === null || _a === void 0 ? void 0 : _a.items) === null || _b === void 0 ? void 0 : _b.at(-1)) === null || _c === void 0 ? void 0 : _c.element) !== null && _d !== void 0 ? _d : this._chatModel.getRequests().at(-1);
410
+ const currentRequest = this._branch?.items?.at(-1)?.element ?? this._chatModel.getRequests().at(-1);
412
411
  if (currentRequest && !ai_chat_1.EditableChatRequestModel.isEditing(currentRequest) && ai_chat_1.ChatRequestModel.isInProgress(currentRequest)) {
413
412
  this._onCancel(currentRequest);
414
413
  }
@@ -458,8 +457,6 @@ let AIChatInputWidget = AIChatInputWidget_1 = class AIChatInputWidget extends br
458
457
  }
459
458
  };
460
459
  exports.AIChatInputWidget = AIChatInputWidget;
461
- AIChatInputWidget.ID = 'chat-input-widget';
462
- AIChatInputWidget.CONTEXT_MENU = ['chat-input-context-menu'];
463
460
  tslib_1.__decorate([
464
461
  (0, inversify_1.inject)(monaco_editor_provider_1.MonacoEditorProvider),
465
462
  tslib_1.__metadata("design:type", monaco_editor_provider_1.MonacoEditorProvider)
@@ -540,9 +537,8 @@ exports.AIChatInputWidget = AIChatInputWidget = AIChatInputWidget_1 = tslib_1.__
540
537
  (0, inversify_1.injectable)()
541
538
  ], AIChatInputWidget);
542
539
  // Utility to check if we have task context in the chat model
543
- const hasTaskContext = (chatModel) => chatModel.context.getVariables().some(variable => { var _a; return ((_a = variable.variable) === null || _a === void 0 ? void 0 : _a.id) === task_context_variable_1.TASK_CONTEXT_VARIABLE.id; });
540
+ const hasTaskContext = (chatModel) => chatModel.context.getVariables().some(variable => variable.variable?.id === task_context_variable_1.TASK_CONTEXT_VARIABLE.id);
544
541
  const ChatInput = (props) => {
545
- var _a, _b;
546
542
  const onDeleteChangeSet = () => props.onDeleteChangeSet(props.chatModel.id);
547
543
  const onDeleteChangeSetElement = (uri) => props.onDeleteChangeSetElement(props.chatModel.id, uri);
548
544
  const [isInputEmpty, setIsInputEmpty] = React.useState(true);
@@ -589,10 +585,9 @@ const ChatInput = (props) => {
589
585
  React.useEffect(() => {
590
586
  const uri = props.uri;
591
587
  const createInputElement = async () => {
592
- var _a, _b;
593
588
  const paddingTop = 6;
594
589
  const lineHeight = 20;
595
- const maxHeightPx = ((_a = props.heightInLines) !== null && _a !== void 0 ? _a : 12) * lineHeight;
590
+ const maxHeightPx = (props.heightInLines ?? 12) * lineHeight;
596
591
  const editor = await props.editorProvider.createSimpleInline(uri, editorContainerRef.current, {
597
592
  language: chat_view_language_contribution_1.CHAT_VIEW_LANGUAGE_EXTENSION,
598
593
  // Disable code lens, inlay hints and hover support to avoid console errors from other contributions
@@ -622,6 +617,7 @@ const ChatInput = (props) => {
622
617
  bracketPairColorization: { enabled: false },
623
618
  wrappingStrategy: 'advanced',
624
619
  stickyScroll: { enabled: false },
620
+ ariaLabel: core_1.nls.localize('theia/ai/chat-ui/chatInputAriaLabel', 'Type your message here'),
625
621
  });
626
622
  if (editorContainerRef.current) {
627
623
  editorContainerRef.current.style.overflowY = 'auto'; // ensure vertical scrollbar
@@ -669,18 +665,17 @@ const ChatInput = (props) => {
669
665
  }
670
666
  });
671
667
  }
672
- const lineNumbers = model.getAllDecorations().filter(predicate => { var _a; return (_a = predicate.options.description) === null || _a === void 0 ? void 0 : _a.startsWith('line-number-'); });
668
+ const lineNumbers = model.getAllDecorations().filter(predicate => predicate.options.description?.startsWith('line-number-'));
673
669
  editor.getControl().removeDecorations(lineNumbers.map(d => d.id));
674
670
  editor.getControl().createDecorationsCollection(decorations);
675
671
  };
676
- (_b = editor.getControl().getModel()) === null || _b === void 0 ? void 0 : _b.onDidChangeContent(() => {
672
+ editor.getControl().getModel()?.onDidChangeContent(() => {
677
673
  updateLineCounts();
678
674
  });
679
675
  editor.getControl().onDidChangeCursorPosition(e => {
680
- var _a;
681
676
  const lineNumber = e.position.lineNumber;
682
- const line = (_a = editor.getControl().getDomNode()) === null || _a === void 0 ? void 0 : _a.querySelector(`.line-number-${lineNumber}`);
683
- line === null || line === void 0 ? void 0 : line.scrollIntoView({ behavior: 'instant', block: 'nearest' });
677
+ const line = editor.getControl().getDomNode()?.querySelector(`.line-number-${lineNumber}`);
678
+ line?.scrollIntoView({ behavior: 'instant', block: 'nearest' });
684
679
  });
685
680
  editorRef.current = editor;
686
681
  props.setEditorRef(editor);
@@ -748,17 +743,17 @@ const ChatInput = (props) => {
748
743
  setValue('');
749
744
  if (editorRef.current && !editorRef.current.document.textEditorModel.isDisposed()) {
750
745
  editorRef.current.document.textEditorModel.setValue('');
746
+ editorRef.current.focus();
751
747
  }
752
748
  }, [props.context, props.onQuery, props.modeSelectorProps.currentMode, setValue, shouldUseTaskPlaceholder, taskPlaceholder]);
753
749
  const onKeyDown = React.useCallback((event) => {
754
- var _a;
755
750
  if (!props.isEnabled) {
756
751
  return;
757
752
  }
758
753
  if (event.key === 'Enter' && !event.shiftKey) {
759
754
  event.preventDefault();
760
755
  // On Enter, read input and submit (handles task context)
761
- const currentValue = ((_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.document.textEditorModel.getValue()) || '';
756
+ const currentValue = editorRef.current?.document.textEditorModel.getValue() || '';
762
757
  submit(currentValue);
763
758
  }
764
759
  else if (event.key === 'Escape') {
@@ -779,22 +774,19 @@ const ChatInput = (props) => {
779
774
  showPlaceholderIfEditorEmpty();
780
775
  };
781
776
  const showPlaceholderIfEditorEmpty = () => {
782
- var _a, _b;
783
- if (!((_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.getControl().getValue())) {
784
- (_b = placeholderRef.current) === null || _b === void 0 ? void 0 : _b.classList.remove('hidden');
777
+ if (!editorRef.current?.getControl().getValue()) {
778
+ placeholderRef.current?.classList.remove('hidden');
785
779
  }
786
780
  };
787
781
  const hidePlaceholderIfEditorFilled = () => {
788
- var _a, _b;
789
- const value = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.getControl().getValue();
782
+ const value = editorRef.current?.getControl().getValue();
790
783
  if (value && value.length > 0) {
791
- (_b = placeholderRef.current) === null || _b === void 0 ? void 0 : _b.classList.add('hidden');
784
+ placeholderRef.current?.classList.add('hidden');
792
785
  }
793
786
  };
794
787
  const handlePin = () => {
795
- var _a, _b;
796
788
  if (editorRef.current) {
797
- (_a = editorRef.current.getControl().getModel()) === null || _a === void 0 ? void 0 : _a.applyEdits([{
789
+ editorRef.current.getControl().getModel()?.applyEdits([{
798
790
  range: {
799
791
  startLineNumber: 1,
800
792
  startColumn: 1,
@@ -804,7 +796,7 @@ const ChatInput = (props) => {
804
796
  text: '@',
805
797
  }]);
806
798
  editorRef.current.getControl().setPosition({ lineNumber: 1, column: 2 });
807
- (_b = editorRef.current.getControl().getAction('editor.action.triggerSuggest')) === null || _b === void 0 ? void 0 : _b.run();
799
+ editorRef.current.getControl().getAction('editor.action.triggerSuggest')?.run();
808
800
  }
809
801
  };
810
802
  const leftOptions = [
@@ -842,9 +834,8 @@ const ChatInput = (props) => {
842
834
  rightOptions = [{
843
835
  title: core_1.nls.localize('theia/ai/chat-ui/send', 'Send (Enter)'),
844
836
  handler: () => {
845
- var _a;
846
837
  if (props.isEnabled) {
847
- submit(((_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.document.textEditorModel.getValue()) || '');
838
+ submit(editorRef.current?.document.textEditorModel.getValue() || '');
848
839
  }
849
840
  },
850
841
  className: 'codicon-send',
@@ -866,9 +857,8 @@ const ChatInput = (props) => {
866
857
  rightOptions = [{
867
858
  title: core_1.nls.localize('theia/ai/chat-ui/send', 'Send (Enter)'),
868
859
  handler: () => {
869
- var _a;
870
860
  if (props.isEnabled) {
871
- submit(((_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.document.textEditorModel.getValue()) || '');
861
+ submit(editorRef.current?.document.textEditorModel.getValue() || '');
872
862
  }
873
863
  },
874
864
  className: 'codicon-send',
@@ -877,10 +867,10 @@ const ChatInput = (props) => {
877
867
  }
878
868
  const contextUI = buildContextUI(props.context, props.labelProvider, props.onDeleteContextElement, props.onOpenContextElement, props.fileValidationState);
879
869
  // Show mode selector if agent has multiple modes
880
- const showModeSelector = ((_b = (_a = props.modeSelectorProps.receivingAgentModes) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 1;
870
+ const showModeSelector = (props.modeSelectorProps.receivingAgentModes?.length ?? 0) > 1;
881
871
  return (React.createElement("div", { className: 'theia-ChatInput', "data-ai-disabled": !props.isEnabled, onDragOver: props.onDragOver, onDrop: props.onDrop, ref: containerRef },
882
872
  props.showSuggestions !== false && React.createElement(chat_input_agent_suggestions_1.ChatInputAgentSuggestions, { suggestions: props.suggestions, opener: props.openerService }),
883
- props.showChangeSet && (changeSetUI === null || changeSetUI === void 0 ? void 0 : changeSetUI.elements) &&
873
+ props.showChangeSet && changeSetUI?.elements &&
884
874
  React.createElement(ChangeSetBox, { changeSet: changeSetUI }),
885
875
  React.createElement("div", { className: 'theia-ChatInput-Editor-Box' },
886
876
  React.createElement("div", { className: 'theia-ChatInput-Editor', ref: editorContainerRef, onKeyDown: onKeyDown, onFocus: handleInputFocus, onBlur: handleInputBlur },
@@ -894,25 +884,29 @@ const ChatInput = (props) => {
894
884
  onModeChange: props.modeSelectorProps.onModeChange,
895
885
  } }))));
896
886
  };
897
- const ChatInputOptions = ({ leftOptions, rightOptions, isEnabled, modeSelectorProps }) => (React.createElement("div", { className: "theia-ChatInputOptions" },
887
+ const ChatInputOptions = ({ leftOptions, rightOptions, isEnabled, modeSelectorProps }) => (
888
+ // Right options are rendered first in DOM for tab order (send button first when enabled)
889
+ // CSS order property positions them visually (left on left, right on right)
890
+ React.createElement("div", { className: "theia-ChatInputOptions" },
891
+ React.createElement("div", { className: "theia-ChatInputOptions-right" }, rightOptions.map((option, index) => (React.createElement("span", { key: index, className: `option${option.disabled ? ' disabled' : ''}${option.text?.align === 'right' ? ' reverse' : ''}`, title: option.title, "aria-label": option.title, role: 'button', tabIndex: option.disabled ? -1 : 0, onClick: option.handler, onKeyDown: e => {
892
+ if (e.key === 'Enter' || e.key === ' ') {
893
+ e.preventDefault();
894
+ option.handler();
895
+ }
896
+ } },
897
+ React.createElement("span", null, option.text?.content),
898
+ React.createElement("span", { className: `codicon ${option.className}` }))))),
898
899
  React.createElement("div", { className: "theia-ChatInputOptions-left" },
899
- leftOptions.map((option, index) => {
900
- var _a, _b;
901
- return (React.createElement("span", { key: index, className: `option${option.disabled ? ' disabled' : ''}${((_a = option.text) === null || _a === void 0 ? void 0 : _a.align) === 'right' ? ' reverse' : ''}`, title: option.title, onClick: option.handler },
902
- React.createElement("span", null, (_b = option.text) === null || _b === void 0 ? void 0 : _b.content),
903
- React.createElement("span", { className: `codicon ${option.className}` })));
904
- }),
905
- modeSelectorProps.show && modeSelectorProps.modes && (React.createElement(ChatModeSelector, { modes: modeSelectorProps.modes, currentMode: modeSelectorProps.currentMode, onModeChange: modeSelectorProps.onModeChange, disabled: !isEnabled }))),
906
- React.createElement("div", { className: "theia-ChatInputOptions-right" }, rightOptions.map((option, index) => {
907
- var _a, _b;
908
- return (React.createElement("span", { key: index, className: `option${option.disabled ? ' disabled' : ''}${((_a = option.text) === null || _a === void 0 ? void 0 : _a.align) === 'right' ? ' reverse' : ''}`, title: option.title, onClick: option.handler },
909
- React.createElement("span", null, (_b = option.text) === null || _b === void 0 ? void 0 : _b.content),
910
- React.createElement("span", { className: `codicon ${option.className}` })));
911
- }))));
912
- const ChatModeSelector = React.memo(({ modes, currentMode, onModeChange, disabled }) => {
913
- var _a, _b, _c;
914
- return (React.createElement("select", { className: "theia-ChatInput-ModeSelector", value: (_b = currentMode !== null && currentMode !== void 0 ? currentMode : (_a = modes[0]) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : '', onChange: e => onModeChange(e.target.value), disabled: disabled, title: (_c = modes.find(m => { var _a; return m.id === (currentMode !== null && currentMode !== void 0 ? currentMode : (_a = modes[0]) === null || _a === void 0 ? void 0 : _a.id); })) === null || _c === void 0 ? void 0 : _c.name }, modes.map(mode => (React.createElement("option", { key: mode.id, value: mode.id, title: mode.name }, mode.name)))));
915
- });
900
+ leftOptions.map((option, index) => (React.createElement("span", { key: index, className: `option${option.disabled ? ' disabled' : ''}${option.text?.align === 'right' ? ' reverse' : ''}`, title: option.title, "aria-label": option.title, role: 'button', tabIndex: option.disabled ? -1 : 0, onClick: option.handler, onKeyDown: e => {
901
+ if (e.key === 'Enter' || e.key === ' ') {
902
+ e.preventDefault();
903
+ option.handler();
904
+ }
905
+ } },
906
+ React.createElement("span", null, option.text?.content),
907
+ React.createElement("span", { className: `codicon ${option.className}` })))),
908
+ modeSelectorProps.show && modeSelectorProps.modes && (React.createElement(ChatModeSelector, { modes: modeSelectorProps.modes, currentMode: modeSelectorProps.currentMode, onModeChange: modeSelectorProps.onModeChange, disabled: !isEnabled })))));
909
+ const ChatModeSelector = React.memo(({ modes, currentMode, onModeChange, disabled }) => (React.createElement("select", { className: "theia-ChatInput-ModeSelector", value: currentMode ?? modes[0]?.id ?? '', onChange: e => onModeChange(e.target.value), disabled: disabled, title: modes.find(m => m.id === (currentMode ?? modes[0]?.id))?.name }, modes.map(mode => (React.createElement("option", { key: mode.id, value: mode.id, title: mode.name }, mode.name))))));
916
910
  const noPropagation = (handler) => (e) => {
917
911
  handler();
918
912
  e.stopPropagation();
@@ -928,31 +922,48 @@ const buildChangeSetUI = (changeSet, labelProvider, decoratorService, actions, o
928
922
  }) : undefined;
929
923
  };
930
924
  /** Memo because the parent element rerenders on every key press in the chat widget. */
931
- const ChangeSetBox = React.memo(({ changeSet: { changeSet, title, deleteChangeSet, elements, actions } }) => (React.createElement("div", { className: 'theia-ChatInput-ChangeSet-Box' },
932
- React.createElement("div", { className: 'theia-ChatInput-ChangeSet-Header' },
933
- React.createElement("h3", null, title),
934
- React.createElement("div", { className: 'theia-ChatInput-ChangeSet-Header-Actions' },
935
- actions.map(action => React.createElement("div", { key: action.id, className: 'theia-changeSet-Action' }, action.render(changeSet))),
936
- React.createElement("span", { className: 'codicon codicon-close action', title: core_1.nls.localize('theia/ai/chat-ui/deleteChangeSet', 'Delete Change Set'), onClick: () => deleteChangeSet() }))),
937
- React.createElement("div", { className: 'theia-ChatInput-ChangeSet-List' },
938
- React.createElement("ul", null, elements.map(element => ChangeSetElement(element)))))));
925
+ const ChangeSetBox = React.memo(({ changeSet: { changeSet, title, deleteChangeSet, elements, actions } }) => {
926
+ const [isCollapsed, setIsCollapsed] = React.useState(false);
927
+ const toggleCollapse = React.useCallback(() => {
928
+ setIsCollapsed(prev => !prev);
929
+ }, []);
930
+ const handleToggleKeyDown = React.useCallback((e) => {
931
+ if (e.key === 'Enter' || e.key === ' ') {
932
+ e.preventDefault();
933
+ toggleCollapse();
934
+ }
935
+ }, [toggleCollapse]);
936
+ return (React.createElement("div", { className: 'theia-ChatInput-ChangeSet-Box' },
937
+ React.createElement("div", { className: 'theia-ChatInput-ChangeSet-Header' },
938
+ React.createElement("div", { className: 'theia-ChatInput-ChangeSet-Header-Title' },
939
+ React.createElement("span", { className: `codicon ${isCollapsed ? 'codicon-chevron-right' : 'codicon-chevron-down'} theia-ChatInput-ChangeSet-Toggle`, onClick: toggleCollapse, onKeyDown: handleToggleKeyDown, role: 'button', tabIndex: 0, "aria-expanded": !isCollapsed, "aria-label": isCollapsed
940
+ ? core_1.nls.localize('theia/ai/chat-ui/expandChangeSet', 'Expand Change Set')
941
+ : core_1.nls.localize('theia/ai/chat-ui/collapseChangeSet', 'Collapse Change Set'), title: isCollapsed
942
+ ? core_1.nls.localize('theia/ai/chat-ui/expandChangeSet', 'Expand Change Set')
943
+ : core_1.nls.localize('theia/ai/chat-ui/collapseChangeSet', 'Collapse Change Set') }),
944
+ React.createElement("h3", null, title)),
945
+ React.createElement("div", { className: 'theia-ChatInput-ChangeSet-Header-Actions' },
946
+ actions.map(action => (React.createElement("div", { key: action.id, className: 'theia-changeSet-Action' }, action.render(changeSet)))),
947
+ React.createElement("span", { className: 'codicon codicon-close action', title: core_1.nls.localize('theia/ai/chat-ui/deleteChangeSet', 'Delete Change Set'), onClick: () => deleteChangeSet() }))),
948
+ React.createElement("div", { className: `theia-ChatInput-ChangeSet-List ${isCollapsed ? 'collapsed' : 'expanded'}` },
949
+ React.createElement("ul", null, elements.map(element => ChangeSetElement(element))))));
950
+ });
939
951
  function toUiElement(element, onDeleteChangeSetElement, labelProvider, decoratorService) {
940
- var _a, _b, _c, _d, _e, _f, _g, _h;
941
- return ({
942
- open: (_a = element.open) === null || _a === void 0 ? void 0 : _a.bind(element),
952
+ return {
953
+ open: element.open?.bind(element),
943
954
  uri: element.uri.toString(),
944
- iconClass: (_c = (_b = element.icon) !== null && _b !== void 0 ? _b : labelProvider.getIcon(element.uri)) !== null && _c !== void 0 ? _c : labelProvider.fileIcon,
955
+ iconClass: element.icon ?? labelProvider.getIcon(element.uri) ?? labelProvider.fileIcon,
945
956
  nameClass: `${element.type} ${element.state}`,
946
- name: (_d = element.name) !== null && _d !== void 0 ? _d : labelProvider.getName(element.uri),
947
- additionalInfo: (_e = element.additionalInfo) !== null && _e !== void 0 ? _e : labelProvider.getDetails(element.uri),
957
+ name: element.name ?? labelProvider.getName(element.uri),
958
+ additionalInfo: element.additionalInfo ?? labelProvider.getDetails(element.uri),
948
959
  additionalInfoSuffixIcon: decoratorService.getAdditionalInfoSuffixIcon(element),
949
- openChange: (_f = element === null || element === void 0 ? void 0 : element.openChange) === null || _f === void 0 ? void 0 : _f.bind(element),
950
- apply: element.state !== 'applied' ? (_g = element === null || element === void 0 ? void 0 : element.apply) === null || _g === void 0 ? void 0 : _g.bind(element) : undefined,
951
- revert: element.state === 'applied' || element.state === 'stale' ? (_h = element === null || element === void 0 ? void 0 : element.revert) === null || _h === void 0 ? void 0 : _h.bind(element) : undefined,
960
+ openChange: element?.openChange?.bind(element),
961
+ apply: element.state !== 'applied' ? element?.apply?.bind(element) : undefined,
962
+ revert: element.state === 'applied' || element.state === 'stale' ? element?.revert?.bind(element) : undefined,
952
963
  delete: () => onDeleteChangeSetElement(element.uri)
953
- });
964
+ };
954
965
  }
955
- const ChangeSetElement = element => (React.createElement("li", { key: element.uri, title: core_1.nls.localize('theia/ai/chat-ui/openDiff', 'Open Diff'), onClick: () => { var _a; return (_a = element.openChange) === null || _a === void 0 ? void 0 : _a.call(element); } },
966
+ const ChangeSetElement = element => (React.createElement("li", { key: element.uri, title: core_1.nls.localize('theia/ai/chat-ui/openDiff', 'Open Diff'), onClick: () => element.openChange?.() },
956
967
  React.createElement("div", { className: `theia-ChatInput-ChangeSet-Icon ${element.iconClass}` }),
957
968
  React.createElement("div", { className: 'theia-ChatInput-ChangeSet-labelParts' },
958
969
  React.createElement("span", { className: `theia-ChatInput-ChangeSet-title ${element.nameClass}` }, element.name),
@@ -1005,14 +1016,13 @@ function buildContextUI(context, labelProvider, onDeleteContextElement, onOpen,
1005
1016
  }
1006
1017
  const ChatContext = ({ context }) => (React.createElement("div", { className: "theia-ChatInput-ChatContext" },
1007
1018
  React.createElement("ul", null, context.map((element, index) => {
1008
- var _a, _b, _c, _d;
1009
1019
  if (image_context_variable_1.ImageContextVariable.isImageContextRequest(element.variable)) {
1010
1020
  const variable = image_context_variable_1.ImageContextVariable.parseRequest(element.variable);
1011
- return React.createElement("li", { key: index, className: "theia-ChatInput-ChatContext-Element theia-ChatInput-ImageContext-Element", title: (_a = variable.name) !== null && _a !== void 0 ? _a : variable.wsRelativePath, onClick: () => { var _a; return (_a = element.open) === null || _a === void 0 ? void 0 : _a.call(element); } },
1021
+ return React.createElement("li", { key: index, className: "theia-ChatInput-ChatContext-Element theia-ChatInput-ImageContext-Element", title: variable.name ?? variable.wsRelativePath, onClick: () => element.open?.() },
1012
1022
  React.createElement("div", { className: "theia-ChatInput-ChatContext-Row" },
1013
1023
  React.createElement("div", { className: `theia-ChatInput-ChatContext-Icon ${element.iconClass}` }),
1014
1024
  React.createElement("div", { className: "theia-ChatInput-ChatContext-labelParts" },
1015
- React.createElement("span", { className: `theia-ChatInput-ChatContext-title ${element.nameClass}` }, (_b = variable.name) !== null && _b !== void 0 ? _b : (_c = variable.wsRelativePath) === null || _c === void 0 ? void 0 : _c.split('/').pop()),
1025
+ React.createElement("span", { className: `theia-ChatInput-ChatContext-title ${element.nameClass}` }, variable.name ?? variable.wsRelativePath?.split('/').pop()),
1016
1026
  React.createElement("span", { className: 'theia-ChatInput-ChatContext-additionalInfo' }, element.additionalInfo)),
1017
1027
  React.createElement("span", { className: "codicon codicon-close action", title: core_1.nls.localizeByDefault('Delete'), onClick: e => { e.stopPropagation(); element.delete(); } })),
1018
1028
  React.createElement("div", { className: "theia-ChatInput-ChatContext-ImageRow" },
@@ -1021,8 +1031,8 @@ const ChatContext = ({ context }) => (React.createElement("div", { className: "t
1021
1031
  }
1022
1032
  const isWarning = element.className === 'warning-file';
1023
1033
  const isInvalid = element.className === 'invalid-file';
1024
- const tooltipTitle = (_d = element.validationMessage) !== null && _d !== void 0 ? _d : element.details;
1025
- return React.createElement("li", { key: index, className: `theia-ChatInput-ChatContext-Element ${element.className || ''}`, title: tooltipTitle, onClick: () => { var _a; return (_a = element.open) === null || _a === void 0 ? void 0 : _a.call(element); } },
1034
+ const tooltipTitle = element.validationMessage ?? element.details;
1035
+ return React.createElement("li", { key: index, className: `theia-ChatInput-ChatContext-Element ${element.className || ''}`, title: tooltipTitle, onClick: () => element.open?.() },
1026
1036
  React.createElement("div", { className: "theia-ChatInput-ChatContext-Row" },
1027
1037
  isWarning && React.createElement("span", { className: "codicon codicon-warning warning-file-icon" }),
1028
1038
  isInvalid && React.createElement("span", { className: "codicon codicon-error invalid-file-icon" }),