@theia/ai-chat-ui 1.60.0-next.47 → 1.61.0-next.8

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 (61) hide show
  1. package/lib/browser/ai-chat-ui-contribution.d.ts +1 -0
  2. package/lib/browser/ai-chat-ui-contribution.d.ts.map +1 -1
  3. package/lib/browser/ai-chat-ui-contribution.js +46 -7
  4. package/lib/browser/ai-chat-ui-contribution.js.map +1 -1
  5. package/lib/browser/ai-chat-ui-frontend-module.d.ts.map +1 -1
  6. package/lib/browser/ai-chat-ui-frontend-module.js +2 -0
  7. package/lib/browser/ai-chat-ui-frontend-module.js.map +1 -1
  8. package/lib/browser/chat-progress-message.d.ts +7 -0
  9. package/lib/browser/chat-progress-message.d.ts.map +1 -0
  10. package/lib/browser/chat-progress-message.js +33 -0
  11. package/lib/browser/chat-progress-message.js.map +1 -0
  12. package/lib/browser/chat-response-renderer/index.d.ts +2 -0
  13. package/lib/browser/chat-response-renderer/index.d.ts.map +1 -1
  14. package/lib/browser/chat-response-renderer/index.js +2 -0
  15. package/lib/browser/chat-response-renderer/index.js.map +1 -1
  16. package/lib/browser/chat-response-renderer/progress-part-renderer.d.ts +9 -0
  17. package/lib/browser/chat-response-renderer/progress-part-renderer.d.ts.map +1 -0
  18. package/lib/browser/chat-response-renderer/progress-part-renderer.js +39 -0
  19. package/lib/browser/chat-response-renderer/progress-part-renderer.js.map +1 -0
  20. package/lib/browser/chat-response-renderer/thinking-part-renderer.d.ts +9 -0
  21. package/lib/browser/chat-response-renderer/thinking-part-renderer.d.ts.map +1 -0
  22. package/lib/browser/chat-response-renderer/thinking-part-renderer.js +42 -0
  23. package/lib/browser/chat-response-renderer/thinking-part-renderer.js.map +1 -0
  24. package/lib/browser/chat-tree-view/chat-view-tree-widget.d.ts +25 -18
  25. package/lib/browser/chat-tree-view/chat-view-tree-widget.d.ts.map +1 -1
  26. package/lib/browser/chat-tree-view/chat-view-tree-widget.js +23 -73
  27. package/lib/browser/chat-tree-view/chat-view-tree-widget.js.map +1 -1
  28. package/lib/browser/chat-view-commands.d.ts +1 -0
  29. package/lib/browser/chat-view-commands.d.ts.map +1 -1
  30. package/lib/browser/chat-view-commands.js +5 -0
  31. package/lib/browser/chat-view-commands.js.map +1 -1
  32. package/lib/browser/chat-view-language-contribution.d.ts +1 -0
  33. package/lib/browser/chat-view-language-contribution.d.ts.map +1 -1
  34. package/lib/browser/chat-view-language-contribution.js +3 -1
  35. package/lib/browser/chat-view-language-contribution.js.map +1 -1
  36. package/lib/browser/chat-view-widget-toolbar-contribution.d.ts +8 -1
  37. package/lib/browser/chat-view-widget-toolbar-contribution.d.ts.map +1 -1
  38. package/lib/browser/chat-view-widget-toolbar-contribution.js +42 -0
  39. package/lib/browser/chat-view-widget-toolbar-contribution.js.map +1 -1
  40. package/lib/browser/chat-view-widget.d.ts +6 -0
  41. package/lib/browser/chat-view-widget.d.ts.map +1 -1
  42. package/lib/browser/chat-view-widget.js +14 -2
  43. package/lib/browser/chat-view-widget.js.map +1 -1
  44. package/lib/browser/session-settings-dialog.d.ts +35 -0
  45. package/lib/browser/session-settings-dialog.d.ts.map +1 -0
  46. package/lib/browser/session-settings-dialog.js +118 -0
  47. package/lib/browser/session-settings-dialog.js.map +1 -0
  48. package/package.json +13 -12
  49. package/src/browser/ai-chat-ui-contribution.ts +42 -8
  50. package/src/browser/ai-chat-ui-frontend-module.ts +4 -0
  51. package/src/browser/chat-progress-message.tsx +40 -0
  52. package/src/browser/chat-response-renderer/index.ts +2 -0
  53. package/src/browser/chat-response-renderer/progress-part-renderer.tsx +40 -0
  54. package/src/browser/chat-response-renderer/thinking-part-renderer.tsx +44 -0
  55. package/src/browser/chat-tree-view/chat-view-tree-widget.tsx +34 -101
  56. package/src/browser/chat-view-commands.ts +6 -0
  57. package/src/browser/chat-view-language-contribution.ts +2 -0
  58. package/src/browser/chat-view-widget-toolbar-contribution.tsx +47 -1
  59. package/src/browser/chat-view-widget.tsx +17 -3
  60. package/src/browser/session-settings-dialog.tsx +144 -0
  61. package/src/browser/style/index.css +31 -16
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2024 EclipseSource GmbH.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.SessionSettingsDialog = void 0;
19
+ const core_1 = require("@theia/core");
20
+ const dialogs_1 = require("@theia/core/lib/browser/dialogs");
21
+ class SessionSettingsDialog extends dialogs_1.AbstractDialog {
22
+ constructor(editorProvider, resources, uri, options) {
23
+ super({
24
+ title: core_1.nls.localize('theia/ai/session-settings-dialog/title', 'Set Session Settings')
25
+ });
26
+ this.editorProvider = editorProvider;
27
+ this.resources = resources;
28
+ this.uri = uri;
29
+ this.options = options;
30
+ this.settings = {};
31
+ const initialSettings = options.initialSettings;
32
+ this.initialSettingsString = JSON.stringify(initialSettings, undefined, 2) || '{}';
33
+ this.contentNode.classList.add('monaco-session-settings-dialog');
34
+ this.dialogContent = document.createElement('div');
35
+ this.dialogContent.className = 'session-settings-container';
36
+ this.contentNode.appendChild(this.dialogContent);
37
+ this.errorMessageDiv = document.createElement('div');
38
+ this.errorMessageDiv.className = 'session-settings-error';
39
+ this.contentNode.appendChild(this.errorMessageDiv);
40
+ this.appendCloseButton(core_1.nls.localizeByDefault('Cancel'));
41
+ this.appendAcceptButton(core_1.nls.localizeByDefault('Apply'));
42
+ this.createJsonEditor();
43
+ this.validateJson();
44
+ }
45
+ onAfterAttach(msg) {
46
+ super.onAfterAttach(msg);
47
+ this.update();
48
+ }
49
+ onActivateRequest(msg) {
50
+ super.onActivateRequest(msg);
51
+ if (this.jsonEditor) {
52
+ this.jsonEditor.focus();
53
+ }
54
+ }
55
+ async createJsonEditor() {
56
+ this.resources.update(this.uri, this.initialSettingsString);
57
+ try {
58
+ const editor = await this.editorProvider.createInline(this.uri, this.dialogContent, {
59
+ language: 'json',
60
+ automaticLayout: true,
61
+ minimap: {
62
+ enabled: false
63
+ },
64
+ scrollBeyondLastLine: false,
65
+ folding: true,
66
+ lineNumbers: 'on',
67
+ fontSize: 13,
68
+ wordWrap: 'on',
69
+ renderValidationDecorations: 'on',
70
+ scrollbar: {
71
+ vertical: 'auto',
72
+ horizontal: 'auto'
73
+ }
74
+ });
75
+ editor.getControl().onDidChangeModelContent(() => {
76
+ this.validateJson();
77
+ });
78
+ editor.document.textEditorModel.setValue(this.initialSettingsString);
79
+ this.jsonEditor = editor;
80
+ this.validateJson();
81
+ }
82
+ catch (error) {
83
+ console.error('Failed to create JSON editor:', error);
84
+ }
85
+ }
86
+ validateJson() {
87
+ if (!this.jsonEditor) {
88
+ return;
89
+ }
90
+ const jsonContent = this.jsonEditor.getControl().getValue();
91
+ try {
92
+ this.settings = JSON.parse(jsonContent);
93
+ this.errorMessageDiv.textContent = '';
94
+ this.setErrorButtonState(false);
95
+ }
96
+ catch (error) {
97
+ this.errorMessageDiv.textContent = `${error}`;
98
+ this.setErrorButtonState(true);
99
+ }
100
+ }
101
+ setErrorButtonState(isError) {
102
+ const acceptButton = this.acceptButton;
103
+ if (acceptButton) {
104
+ acceptButton.disabled = isError;
105
+ if (isError) {
106
+ acceptButton.classList.add('disabled');
107
+ }
108
+ else {
109
+ acceptButton.classList.remove('disabled');
110
+ }
111
+ }
112
+ }
113
+ get value() {
114
+ return this.settings;
115
+ }
116
+ }
117
+ exports.SessionSettingsDialog = SessionSettingsDialog;
118
+ //# sourceMappingURL=session-settings-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-settings-dialog.js","sourceRoot":"","sources":["../../src/browser/session-settings-dialog.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,18 +1,19 @@
1
1
  {
2
2
  "name": "@theia/ai-chat-ui",
3
- "version": "1.60.0-next.47+9332521b9",
3
+ "version": "1.61.0-next.8+436de3c45",
4
4
  "description": "Theia - AI Chat UI Extension",
5
5
  "dependencies": {
6
- "@theia/ai-chat": "1.60.0-next.47+9332521b9",
7
- "@theia/ai-core": "1.60.0-next.47+9332521b9",
8
- "@theia/ai-history": "1.60.0-next.47+9332521b9",
9
- "@theia/core": "1.60.0-next.47+9332521b9",
10
- "@theia/editor": "1.60.0-next.47+9332521b9",
11
- "@theia/editor-preview": "1.60.0-next.47+9332521b9",
12
- "@theia/filesystem": "1.60.0-next.47+9332521b9",
13
- "@theia/monaco": "1.60.0-next.47+9332521b9",
6
+ "@theia/ai-chat": "1.61.0-next.8+436de3c45",
7
+ "@theia/ai-core": "1.61.0-next.8+436de3c45",
8
+ "@theia/ai-history": "1.61.0-next.8+436de3c45",
9
+ "@theia/core": "1.61.0-next.8+436de3c45",
10
+ "@theia/editor": "1.61.0-next.8+436de3c45",
11
+ "@theia/editor-preview": "1.61.0-next.8+436de3c45",
12
+ "@theia/filesystem": "1.61.0-next.8+436de3c45",
13
+ "@theia/monaco": "1.61.0-next.8+436de3c45",
14
14
  "@theia/monaco-editor-core": "1.96.302",
15
- "@theia/workspace": "1.60.0-next.47+9332521b9",
15
+ "@theia/workspace": "1.61.0-next.8+436de3c45",
16
+ "date-fns": "^4.1.0",
16
17
  "minimatch": "^5.1.0",
17
18
  "tslib": "^2.6.2",
18
19
  "uuid": "^9.0.1"
@@ -51,10 +52,10 @@
51
52
  "watch": "theiaext watch"
52
53
  },
53
54
  "devDependencies": {
54
- "@theia/ext-scripts": "1.59.0"
55
+ "@theia/ext-scripts": "1.60.0"
55
56
  },
56
57
  "nyc": {
57
58
  "extends": "../../configs/nyc.json"
58
59
  },
59
- "gitHead": "9332521b9aa74bf534d45968905d37e30a13c3b5"
60
+ "gitHead": "436de3c4571e0000fdcbbf2e94ddfc992f38ccb2"
60
61
  }
@@ -24,6 +24,8 @@ import { TabBarToolbarContribution, TabBarToolbarRegistry } from '@theia/core/li
24
24
  import { ChatViewWidget } from './chat-view-widget';
25
25
  import { Deferred } from '@theia/core/lib/common/promise-util';
26
26
  import { SecondaryWindowHandler } from '@theia/core/lib/browser/secondary-window-handler';
27
+ import { formatDistance } from 'date-fns';
28
+ import * as locales from 'date-fns/locale';
27
29
  import { AI_SHOW_SETTINGS_COMMAND } from '@theia/ai-core/lib/browser';
28
30
  import { OPEN_AI_HISTORY_VIEW } from '@theia/ai-history/lib/browser/ai-history-contribution';
29
31
 
@@ -37,6 +39,10 @@ export class AIChatContribution extends AbstractViewContribution<ChatViewWidget>
37
39
  @inject(QuickInputService)
38
40
  protected readonly quickInputService: QuickInputService;
39
41
 
42
+ protected static readonly RENAME_CHAT_BUTTON: QuickInputButton = {
43
+ iconClass: 'codicon-edit',
44
+ tooltip: nls.localize('theia/ai/chat-ui/renameChat', 'Rename Chat'),
45
+ };
40
46
  protected static readonly REMOVE_CHAT_BUTTON: QuickInputButton = {
41
47
  iconClass: 'codicon-remove-close',
42
48
  tooltip: nls.localize('theia/ai/chat-ui/removeChat', 'Remove Chat'),
@@ -135,11 +141,20 @@ export class AIChatContribution extends AbstractViewContribution<ChatViewWidget>
135
141
 
136
142
  protected askForChatSession(): Promise<QuickPickItem | undefined> {
137
143
  const getItems = () =>
138
- this.chatService.getSessions().filter(session => !session.isActive).map(session => <QuickPickItem>({
139
- label: session.title ?? nls.localizeByDefault('New Chat'),
140
- id: session.id,
141
- buttons: [AIChatContribution.REMOVE_CHAT_BUTTON]
142
- })).reverse();
144
+ this.chatService.getSessions()
145
+ .filter(session => !session.isActive && session.title)
146
+ .sort((a, b) => {
147
+ if (!a.lastInteraction) { return 1; }
148
+ if (!b.lastInteraction) { return -1; }
149
+ return b.lastInteraction.getTime() - a.lastInteraction.getTime();
150
+ })
151
+ .map(session => <QuickPickItem>({
152
+ label: session.title,
153
+ description: session.lastInteraction ? formatDistance(session.lastInteraction, new Date(), { addSuffix: false, locale: getDateFnsLocale() }) : undefined,
154
+ detail: session.model.getRequests().at(0)?.request.text,
155
+ id: session.id,
156
+ buttons: [AIChatContribution.RENAME_CHAT_BUTTON, AIChatContribution.REMOVE_CHAT_BUTTON]
157
+ }));
143
158
 
144
159
  const defer = new Deferred<QuickPickItem | undefined>();
145
160
  const quickPick = this.quickInputService.createQuickPick();
@@ -148,10 +163,24 @@ export class AIChatContribution extends AbstractViewContribution<ChatViewWidget>
148
163
  quickPick.items = getItems();
149
164
 
150
165
  quickPick.onDidTriggerItemButton(async context => {
151
- this.chatService.deleteSession(context.item.id!);
152
- quickPick.items = getItems();
153
- if (this.chatService.getSessions().length <= 1) {
166
+ if (context.button === AIChatContribution.RENAME_CHAT_BUTTON) {
154
167
  quickPick.hide();
168
+ this.quickInputService.input({
169
+ placeHolder: nls.localize('theia/ai/chat-ui/enterChatName', 'Enter chat name')
170
+ }).then(name => {
171
+ if (name && name.length > 0) {
172
+ const session = this.chatService.getSession(context.item.id!);
173
+ if (session) {
174
+ session.title = name;
175
+ }
176
+ }
177
+ });
178
+ } else if (context.button === AIChatContribution.REMOVE_CHAT_BUTTON) {
179
+ this.chatService.deleteSession(context.item.id!);
180
+ quickPick.items = getItems();
181
+ if (this.chatService.getSessions().length <= 1) {
182
+ quickPick.hide();
183
+ }
155
184
  }
156
185
  });
157
186
 
@@ -183,3 +212,8 @@ export class AIChatContribution extends AbstractViewContribution<ChatViewWidget>
183
212
  return !chatView.secondaryWindow;
184
213
  }
185
214
  }
215
+
216
+ function getDateFnsLocale(): locales.Locale {
217
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
218
+ return nls.locale ? (locales as any)[nls.locale] ?? locales.enUS : locales.enUS;
219
+ }
@@ -34,6 +34,8 @@ import {
34
34
  InsertCodeAtCursorButtonAction,
35
35
  MarkdownPartRenderer,
36
36
  ToolCallPartRenderer,
37
+ ThinkingPartRenderer,
38
+ ProgressPartRenderer,
37
39
  } from './chat-response-renderer';
38
40
  import {
39
41
  GitHubSelectionResolver,
@@ -86,7 +88,9 @@ export default new ContainerModule((bind, _unbind, _isBound, rebind) => {
86
88
  bind(ChatResponsePartRenderer).to(CommandPartRenderer).inSingletonScope();
87
89
  bind(ChatResponsePartRenderer).to(ToolCallPartRenderer).inSingletonScope();
88
90
  bind(ChatResponsePartRenderer).to(ErrorPartRenderer).inSingletonScope();
91
+ bind(ChatResponsePartRenderer).to(ThinkingPartRenderer).inSingletonScope();
89
92
  bind(ChatResponsePartRenderer).to(QuestionPartRenderer).inSingletonScope();
93
+ bind(ChatResponsePartRenderer).to(ProgressPartRenderer).inSingletonScope();
90
94
  [CommandContribution, MenuContribution].forEach(serviceIdentifier =>
91
95
  bind(serviceIdentifier).to(ChatViewMenuContribution).inSingletonScope()
92
96
  );
@@ -0,0 +1,40 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { ChatProgressMessage } from '@theia/ai-chat';
18
+ import * as React from '@theia/core/shared/react';
19
+
20
+ export type ProgressMessageProps = Omit<ChatProgressMessage, 'kind' | 'id' | 'show'>;
21
+
22
+ export const ProgressMessage = (c: ProgressMessageProps) => (
23
+ <div className='theia-ResponseNode-ProgressMessage'>
24
+ <Indicator {...c} /> {c.content}
25
+ </div>
26
+ );
27
+
28
+ export const Indicator = (progressMessage: ProgressMessageProps) => (
29
+ <span className='theia-ResponseNode-ProgressMessage-Indicator'>
30
+ {progressMessage.status === 'inProgress' &&
31
+ <i className={'fa fa-spinner fa-spin ' + progressMessage.status}></i>
32
+ }
33
+ {progressMessage.status === 'completed' &&
34
+ <i className={'fa fa-check ' + progressMessage.status}></i>
35
+ }
36
+ {progressMessage.status === 'failed' &&
37
+ <i className={'fa fa-warning ' + progressMessage.status}></i>
38
+ }
39
+ </span>
40
+ );
@@ -21,3 +21,5 @@ export * from './horizontal-layout-part-renderer';
21
21
  export * from './markdown-part-renderer';
22
22
  export * from './text-part-renderer';
23
23
  export * from './toolcall-part-renderer';
24
+ export * from './thinking-part-renderer';
25
+ export * from './progress-part-renderer';
@@ -0,0 +1,40 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { ChatResponsePartRenderer } from '../chat-response-part-renderer';
18
+ import { injectable } from '@theia/core/shared/inversify';
19
+ import { ChatResponseContent, ProgressChatResponseContent } from '@theia/ai-chat/lib/common';
20
+ import { ReactNode } from '@theia/core/shared/react';
21
+ import * as React from '@theia/core/shared/react';
22
+ import { ProgressMessage } from '../chat-progress-message';
23
+
24
+ @injectable()
25
+ export class ProgressPartRenderer implements ChatResponsePartRenderer<ProgressChatResponseContent> {
26
+
27
+ canHandle(response: ChatResponseContent): number {
28
+ if (ProgressChatResponseContent.is(response)) {
29
+ return 10;
30
+ }
31
+ return -1;
32
+ }
33
+
34
+ render(response: ProgressChatResponseContent): ReactNode {
35
+ return (
36
+ <ProgressMessage content={response.message} status='inProgress' />
37
+ );
38
+ }
39
+
40
+ }
@@ -0,0 +1,44 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { ChatResponsePartRenderer } from '../chat-response-part-renderer';
18
+ import { injectable } from '@theia/core/shared/inversify';
19
+ import { ChatResponseContent, ThinkingChatResponseContent } from '@theia/ai-chat/lib/common';
20
+ import { ReactNode } from '@theia/core/shared/react';
21
+ import { nls } from '@theia/core/lib/common/nls';
22
+ import * as React from '@theia/core/shared/react';
23
+
24
+ @injectable()
25
+ export class ThinkingPartRenderer implements ChatResponsePartRenderer<ThinkingChatResponseContent> {
26
+
27
+ canHandle(response: ChatResponseContent): number {
28
+ if (ThinkingChatResponseContent.is(response)) {
29
+ return 10;
30
+ }
31
+ return -1;
32
+ }
33
+
34
+ render(response: ThinkingChatResponseContent): ReactNode {
35
+ return (
36
+ <div className='theia-thinking'>
37
+ <details>
38
+ <summary>{nls.localize('theia/ai/chat-ui/thinking-part-renderer/thinking', 'Thinking')}</summary>
39
+ <pre>{response.content}</pre>
40
+ </details>
41
+ </div>
42
+ );
43
+ }
44
+ }