@theia/ai-history 1.61.0 → 1.62.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 (46) hide show
  1. package/lib/browser/ai-history-contribution.d.ts +9 -1
  2. package/lib/browser/ai-history-contribution.d.ts.map +1 -1
  3. package/lib/browser/ai-history-contribution.js +102 -4
  4. package/lib/browser/ai-history-contribution.js.map +1 -1
  5. package/lib/browser/ai-history-exchange-card.d.ts +11 -0
  6. package/lib/browser/ai-history-exchange-card.d.ts.map +1 -0
  7. package/lib/browser/ai-history-exchange-card.js +132 -0
  8. package/lib/browser/ai-history-exchange-card.js.map +1 -0
  9. package/lib/browser/ai-history-frontend-module.d.ts.map +1 -1
  10. package/lib/browser/ai-history-frontend-module.js +0 -4
  11. package/lib/browser/ai-history-frontend-module.js.map +1 -1
  12. package/lib/browser/ai-history-widget.d.ts +17 -5
  13. package/lib/browser/ai-history-widget.d.ts.map +1 -1
  14. package/lib/browser/ai-history-widget.js +50 -30
  15. package/lib/browser/ai-history-widget.js.map +1 -1
  16. package/lib/common/index.d.ts +0 -1
  17. package/lib/common/index.d.ts.map +1 -1
  18. package/lib/common/index.js +0 -4
  19. package/lib/common/index.js.map +1 -1
  20. package/lib/package.spec.d.ts +1 -0
  21. package/lib/package.spec.d.ts.map +1 -0
  22. package/lib/package.spec.js +26 -0
  23. package/lib/package.spec.js.map +1 -0
  24. package/package.json +9 -8
  25. package/src/browser/ai-history-contribution.ts +107 -3
  26. package/src/browser/ai-history-exchange-card.tsx +243 -0
  27. package/src/browser/ai-history-frontend-module.ts +0 -5
  28. package/src/browser/ai-history-widget.tsx +74 -31
  29. package/src/browser/style/ai-history.css +145 -60
  30. package/src/common/index.ts +0 -1
  31. package/src/package.spec.ts +28 -0
  32. package/lib/browser/ai-history-communication-card.d.ts +0 -8
  33. package/lib/browser/ai-history-communication-card.d.ts.map +0 -1
  34. package/lib/browser/ai-history-communication-card.js +0 -71
  35. package/lib/browser/ai-history-communication-card.js.map +0 -1
  36. package/lib/common/communication-recording-service.d.ts +0 -18
  37. package/lib/common/communication-recording-service.d.ts.map +0 -1
  38. package/lib/common/communication-recording-service.js +0 -74
  39. package/lib/common/communication-recording-service.js.map +0 -1
  40. package/lib/common/communication-recording-service.spec.d.ts +0 -2
  41. package/lib/common/communication-recording-service.spec.d.ts.map +0 -1
  42. package/lib/common/communication-recording-service.spec.js +0 -43
  43. package/lib/common/communication-recording-service.spec.js.map +0 -1
  44. package/src/browser/ai-history-communication-card.tsx +0 -103
  45. package/src/common/communication-recording-service.spec.ts +0 -63
  46. package/src/common/communication-recording-service.ts +0 -97
@@ -13,33 +13,35 @@
13
13
  //
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
- import { Agent, AgentService, CommunicationRecordingService, CommunicationRequestEntry, CommunicationResponseEntry } from '@theia/ai-core';
16
+ import { Agent, AgentService, LanguageModelService, SessionEvent } from '@theia/ai-core';
17
+ import { LanguageModelExchange } from '@theia/ai-core/lib/common/language-model-interaction-model';
17
18
  import { codicon, ReactWidget, StatefulWidget } from '@theia/core/lib/browser';
18
19
  import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
19
20
  import * as React from '@theia/core/shared/react';
20
- import { CommunicationCard } from './ai-history-communication-card';
21
+ import { ExchangeCard } from './ai-history-exchange-card';
21
22
  import { SelectComponent, SelectOption } from '@theia/core/lib/browser/widgets/select-component';
22
23
  import { deepClone, nls } from '@theia/core';
23
24
 
24
25
  namespace AIHistoryView {
25
26
  export interface State {
26
27
  chronological: boolean;
28
+ compactView: boolean;
29
+ renderNewlines: boolean;
30
+ selectedAgentId?: string;
27
31
  }
28
32
  }
29
33
 
30
34
  @injectable()
31
35
  export class AIHistoryView extends ReactWidget implements StatefulWidget {
32
- @inject(CommunicationRecordingService)
33
- protected recordingService: CommunicationRecordingService;
36
+ @inject(LanguageModelService)
37
+ protected languageModelService: LanguageModelService;
34
38
  @inject(AgentService)
35
39
  protected readonly agentService: AgentService;
36
40
 
37
41
  public static ID = 'ai-history-widget';
38
42
  static LABEL = nls.localize('theia/ai/history/view/label', 'AI Agent History [Alpha]');
39
43
 
40
- protected selectedAgent?: Agent;
41
-
42
- protected _state: AIHistoryView.State = { chronological: false };
44
+ protected _state: AIHistoryView.State = { chronological: false, compactView: true, renderNewlines: true };
43
45
 
44
46
  constructor() {
45
47
  super();
@@ -65,36 +67,36 @@ export class AIHistoryView extends ReactWidget implements StatefulWidget {
65
67
 
66
68
  restoreState(oldState: object & Partial<AIHistoryView.State>): void {
67
69
  const copy = deepClone(this.state);
68
- if (oldState.chronological) {
70
+ if (oldState.chronological !== undefined) {
69
71
  copy.chronological = oldState.chronological;
70
72
  }
73
+ if (oldState.compactView !== undefined) {
74
+ copy.compactView = oldState.compactView;
75
+ }
76
+ if (oldState.renderNewlines !== undefined) {
77
+ copy.renderNewlines = oldState.renderNewlines;
78
+ }
71
79
  this.state = copy;
72
80
  }
73
81
 
74
82
  @postConstruct()
75
83
  protected init(): void {
76
84
  this.update();
77
- this.toDispose.push(this.recordingService.onDidRecordRequest(entry => this.historyContentUpdated(entry)));
78
- this.toDispose.push(this.recordingService.onDidRecordResponse(entry => this.historyContentUpdated(entry)));
79
- this.toDispose.push(this.recordingService.onStructuralChange(() => this.update()));
85
+ this.toDispose.push(this.languageModelService.onSessionChanged((event: SessionEvent) => this.historyContentUpdated(event)));
80
86
  this.selectAgent(this.agentService.getAllAgents()[0]);
81
87
  }
82
88
 
83
89
  protected selectAgent(agent: Agent | undefined): void {
84
- this.selectedAgent = agent;
85
- this.update();
90
+ this.state = { ...this.state, selectedAgentId: agent?.id };
86
91
  }
87
92
 
88
- protected historyContentUpdated(entry: CommunicationRequestEntry | CommunicationResponseEntry): void {
89
- if (entry.agentId === this.selectedAgent?.id) {
90
- this.update();
91
- }
93
+ protected historyContentUpdated(event: SessionEvent): void {
94
+ this.update();
92
95
  }
93
96
 
94
97
  render(): React.ReactNode {
95
98
  const selectionChange = (value: SelectOption) => {
96
- this.selectedAgent = this.agentService.getAllAgents().find(agent => agent.id === value.value);
97
- this.update();
99
+ this.selectAgent(this.agentService.getAllAgents().find(agent => agent.id === value.value));
98
100
  };
99
101
  const agents = this.agentService.getAllAgents();
100
102
  if (agents.length === 0) {
@@ -112,7 +114,7 @@ export class AIHistoryView extends ReactWidget implements StatefulWidget {
112
114
  description: agent.description || ''
113
115
  }))}
114
116
  onChange={selectionChange}
115
- defaultValue={this.selectedAgent?.id} />
117
+ defaultValue={this.state.selectedAgentId} />
116
118
  <div className='agent-history'>
117
119
  {this.renderHistory()}
118
120
  </div>
@@ -121,31 +123,72 @@ export class AIHistoryView extends ReactWidget implements StatefulWidget {
121
123
  }
122
124
 
123
125
  protected renderHistory(): React.ReactNode {
124
- if (!this.selectedAgent) {
126
+ if (!this.state.selectedAgentId) {
125
127
  return <div className='theia-card no-content'>{nls.localize('theia/ai/history/view/noAgentSelected', 'No agent selected.')}</div>;
126
128
  }
127
- const history = [...this.recordingService.getHistory(this.selectedAgent.id)];
128
- if (history.length === 0) {
129
+
130
+ const exchanges = this.getExchangesByAgent(this.state.selectedAgentId);
131
+
132
+ if (exchanges.length === 0) {
133
+ const selectedAgent = this.agentService.getAllAgents().find(agent => agent.id === this.state.selectedAgentId);
129
134
  return <div className='theia-card no-content'>
130
- {nls.localize('theia/ai/history/view/noHistoryForAgent', 'No history available for the selected agent \'{0}\'', this.selectedAgent.name)}
135
+ {nls.localize('theia/ai/history/view/noHistoryForAgent', 'No history available for the selected agent \'{0}\'', selectedAgent?.name || this.state.selectedAgentId)}
131
136
  </div>;
132
137
  }
133
- if (!this.state.chronological) {
134
- history.reverse();
135
- }
136
- return history.map(entry => <CommunicationCard key={entry.requestId} entry={entry} />);
138
+
139
+ // Sort exchanges by timestamp (using the first sub-request's timestamp)
140
+ const sortedExchanges = [...exchanges].sort((a, b) => {
141
+ const aTimestamp = a.requests[0]?.metadata.timestamp as number || 0;
142
+ const bTimestamp = b.requests[0]?.metadata.timestamp as number || 0;
143
+ return this.state.chronological ? aTimestamp - bTimestamp : bTimestamp - aTimestamp;
144
+ });
145
+
146
+ return sortedExchanges.map(exchange => (
147
+ <ExchangeCard
148
+ key={exchange.id}
149
+ exchange={exchange}
150
+ selectedAgentId={this.state.selectedAgentId}
151
+ compactView={this.state.compactView}
152
+ renderNewlines={this.state.renderNewlines}
153
+ />
154
+ ));
137
155
  }
138
156
 
139
- protected onClick(e: React.MouseEvent<HTMLDivElement>, agent: Agent): void {
140
- e.stopPropagation();
141
- this.selectAgent(agent);
157
+ /**
158
+ * Get all exchanges for a specific agent.
159
+ * Includes all exchanges in which the agent is involved, either as the main exchange or as a sub-request.
160
+ * @param agentId The agent ID to filter by
161
+ */
162
+ protected getExchangesByAgent(agentId: string): LanguageModelExchange[] {
163
+ return this.languageModelService.sessions.flatMap(session =>
164
+ session.exchanges.filter(exchange =>
165
+ exchange.metadata.agent === agentId ||
166
+ exchange.requests.some(request => request.metadata.agent === agentId)
167
+ )
168
+ );
142
169
  }
143
170
 
144
171
  public sortHistory(chronological: boolean): void {
145
172
  this.state = { ...deepClone(this.state), chronological: chronological };
146
173
  }
147
174
 
175
+ public toggleCompactView(): void {
176
+ this.state = { ...deepClone(this.state), compactView: !this.state.compactView };
177
+ }
178
+
179
+ public toggleRenderNewlines(): void {
180
+ this.state = { ...deepClone(this.state), renderNewlines: !this.state.renderNewlines };
181
+ }
182
+
148
183
  get isChronological(): boolean {
149
184
  return this.state.chronological === true;
150
185
  }
186
+
187
+ get isCompactView(): boolean {
188
+ return this.state.compactView === true;
189
+ }
190
+
191
+ get isRenderNewlines(): boolean {
192
+ return this.state.renderNewlines === true;
193
+ }
151
194
  }
@@ -38,10 +38,6 @@
38
38
  margin-bottom: 10px;
39
39
  }
40
40
 
41
- .theia-card-content h2 {
42
- font-size: var(--theia-ui-font-size2);
43
- }
44
-
45
41
  .theia-card-content h3 {
46
42
  font-size: var(--theia-ui-font-size1);
47
43
  font-weight: bold;
@@ -51,95 +47,184 @@
51
47
  border-radius: 4px;
52
48
  border: 1px solid var(--theia-sideBarSectionHeader-border);
53
49
  background-color: var(--theia-terminal-background);
54
- overflow: auto;
50
+ overflow: visible;
55
51
  padding: 10px;
56
52
  margin: 5px 0;
57
53
  }
58
54
 
59
- /* Common styles for request and response sections */
60
- .theia-card-request details,
61
- .theia-card-response details {
62
- margin: 10px 0;
55
+ .theia-card-request-id,
56
+ .theia-card-timestamp {
57
+ flex: 1;
58
+ text-align: left;
59
+ }
60
+
61
+ .exchange-card {
62
+ border-radius: 6px;
63
+ transition: box-shadow 0.3s ease;
64
+ }
65
+
66
+ .requests-container {
67
+ display: flex;
68
+ flex-direction: column;
69
+ gap: 15px;
70
+ width: 100%;
71
+ overflow: visible;
72
+ }
73
+
74
+ /* Request Card Styles */
75
+ .request-card {
76
+ background-color: var(--theia-editor-background);
77
+ border: 1px solid var(--theia-sideBarSectionHeader-border);
78
+ border-radius: 4px;
79
+ padding: 12px;
80
+ margin-bottom: 15px;
81
+ transition: box-shadow 0.3s ease;
82
+ }
83
+
84
+ .request-header {
85
+ display: flex;
86
+ flex-direction: column;
87
+ margin-bottom: 10px;
88
+ padding-bottom: 8px;
89
+ border-bottom: 1px solid var(--theia-sideBarSectionHeader-border);
90
+ }
91
+
92
+ .request-header h3 {
93
+ margin: 0 0 8px 0;
94
+ }
95
+
96
+ .request-info {
97
+ display: flex;
98
+ flex-wrap: wrap;
99
+ gap: 12px;
100
+ align-items: center;
101
+ }
102
+
103
+ .request-id,
104
+ .request-agent,
105
+ .request-model {
106
+ font-size: 0.9em;
107
+ color: var(--theia-descriptionForeground);
108
+ white-space: nowrap;
109
+ padding: 2px 6px;
110
+ background-color: var(--theia-editor-inactiveSelectionBackground);
111
+ border-radius: 3px;
112
+ }
113
+
114
+ .request-content-container {
115
+ width: 100%;
116
+ overflow: visible;
117
+ }
118
+
119
+ .request-content-container details {
120
+ margin-bottom: 10px;
63
121
  border: 1px solid var(--theia-editorWidget-border);
64
122
  border-radius: 4px;
65
- overflow: hidden;
66
123
  }
67
124
 
68
- .theia-card-request summary,
69
- .theia-card-response summary {
70
- padding: 10px;
125
+ .request-content-container summary {
126
+ padding: 8px 12px;
71
127
  background-color: var(--theia-editorWidget-background);
72
128
  cursor: pointer;
73
- transition: background-color 0.2s;
129
+ font-weight: bold;
130
+ display: block; /* Make the entire summary clickable */
74
131
  }
75
132
 
76
- .theia-card-request summary:hover,
77
- .theia-card-response summary:hover {
133
+ .request-content-container summary:hover {
78
134
  background-color: var(--theia-list-hoverBackground);
79
135
  }
80
136
 
81
- .theia-card-request summary h3,
82
- .theia-card-response summary h3 {
83
- display: inline;
84
- margin: 0;
137
+ .request-content,
138
+ .response-content {
139
+ padding: 10px;
140
+ overflow: visible;
85
141
  }
86
142
 
87
- .theia-card-request details > div,
88
- .theia-card-response details > div {
89
- padding: 0 10px 10px 10px;
90
- border-top: 1px solid var(--theia-editorWidget-border);
91
- background-color: var(--theia-editor-background);
92
- position: relative;
143
+ .request-content-container details {
144
+ margin-bottom: 15px;
93
145
  }
94
146
 
95
- .theia-card-request h4,
96
- .theia-card-response h4 {
97
- margin-top: 12px;
98
- color: var(--theia-editor-foreground);
99
- font-size: var(--theia-ui-font-size1);
100
- border-bottom: 1px solid var(--theia-sideBarSectionHeader-border);
101
- padding-bottom: 5px;
147
+ .request-content-container summary {
148
+ padding: 10px 15px;
149
+ font-size: 1em;
150
+ transition: background-color 0.2s ease;
151
+ }
152
+
153
+ .stream-part {
154
+ margin-bottom: 8px;
155
+ padding-bottom: 8px;
156
+ border-bottom: 1px dashed var(--theia-sideBarSectionHeader-border);
102
157
  }
103
158
 
104
- .theia-card-request ul,
105
- .theia-card-response ul {
106
- list-style: none;
107
- padding-inline-start: 0;
159
+ .stream-part:last-child {
160
+ border-bottom: none;
108
161
  }
109
162
 
110
- .theia-card-request pre,
111
- .theia-card-response pre {
163
+ .compact-response {
164
+ padding: 8px;
112
165
  background-color: var(--theia-editor-background);
113
- text-wrap: wrap;
166
+ border-radius: 4px;
114
167
  }
115
168
 
116
- .theia-card-request,
117
- .theia-card-response {
118
- margin-bottom: 10px;
169
+ .formatted-json {
170
+ white-space: pre-wrap;
171
+ word-break: break-word;
172
+ font-family: var(--theia-ui-font-family-monospace);
173
+ font-size: var(--theia-code-font-size);
174
+ line-height: var(--theia-code-line-height);
175
+ color: var(--theia-editor-foreground);
119
176
  }
120
177
 
121
- /* Message lists styling */
122
- .theia-card-request-messages-list li,
123
- .theia-card-response-messages-list li {
124
- margin-bottom: 15px;
125
- position: relative;
126
- padding-left: 0;
178
+ .formatted-json.render-newlines {
179
+ white-space: pre-wrap;
127
180
  }
128
181
 
129
- /* Meta information styling */
130
- .theia-card-request-id,
131
- .theia-card-session-id,
132
- .theia-card-timestamp,
133
- .theia-card-response-time {
134
- flex: 1;
182
+ .request-content-container summary::before {
183
+ content: '▶';
184
+ display: inline-block;
185
+ margin-right: 8px;
186
+ transition: transform 0.2s;
187
+ font-size: 0.8em;
135
188
  }
136
189
 
137
- .theia-card-request-id,
138
- .theia-card-timestamp {
139
- text-align: left;
190
+ .request-content-container details[open] summary::before {
191
+ transform: rotate(90deg);
140
192
  }
141
193
 
142
- .theia-card-session-id,
143
- .theia-card-response-time {
194
+ .theia-card-agent-id {
195
+ flex: 1;
144
196
  text-align: right;
197
+ font-weight: bold;
198
+ }
199
+
200
+ .request-card.different-agent-opacity {
201
+ opacity: 0.7;
202
+ }
203
+
204
+ .request-agent.different-agent-name {
205
+ font-style: italic;
206
+ color: var(--theia-notificationsWarningIcon-foreground);
207
+ }
208
+
209
+ /* Request meta information */
210
+ .request-meta {
211
+ display: flex;
212
+ justify-content: space-between;
213
+ font-size: 0.85em;
214
+ color: var(--theia-descriptionForeground);
215
+ margin-top: 10px;
216
+ padding-top: 8px;
217
+ border-top: 1px solid var(--theia-sideBarSectionHeader-border);
218
+ }
219
+
220
+ .no-content {
221
+ padding: 15px;
222
+ color: var(--theia-descriptionForeground);
223
+ text-align: center;
224
+ font-style: italic;
225
+ }
226
+
227
+ .request-timestamp {
228
+ font-size: 0.85em;
229
+ color: var(--theia-descriptionForeground);
145
230
  }
@@ -14,4 +14,3 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- export * from './communication-recording-service';
@@ -0,0 +1,28 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 EclipseSource GmbH and others.
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
+ /* note: this bogus test file is required so that
18
+ we are able to run mocha unit tests on this
19
+ package, without having any actual unit tests in it.
20
+ This way a coverage report will be generated,
21
+ showing 0% coverage, instead of no report.
22
+ This file can be removed once we have real unit
23
+ tests in place. */
24
+
25
+ describe('ai-history package', () => {
26
+
27
+ it('support code coverage statistics', () => true);
28
+ });
@@ -1,8 +0,0 @@
1
- /// <reference types="react" />
2
- import { CommunicationHistoryEntry } from '@theia/ai-core';
3
- import * as React from '@theia/core/shared/react';
4
- export interface CommunicationCardProps {
5
- entry: CommunicationHistoryEntry;
6
- }
7
- export declare const CommunicationCard: React.FC<CommunicationCardProps>;
8
- //# sourceMappingURL=ai-history-communication-card.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-history-communication-card.d.ts","sourceRoot":"","sources":["../../src/browser/ai-history-communication-card.tsx"],"names":[],"mappings":";AAeA,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAE3D,OAAO,KAAK,KAAK,MAAM,0BAA0B,CAAC;AAElD,MAAM,WAAW,sBAAsB;IACnC,KAAK,EAAE,yBAAyB,CAAC;CACpC;AAsBD,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CA2D1D,CAAC"}
@@ -1,71 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CommunicationCard = void 0;
4
- const core_1 = require("@theia/core");
5
- const React = require("@theia/core/shared/react");
6
- // Format JSON with error handling
7
- const formatJson = (data) => {
8
- try {
9
- return JSON.stringify(data, undefined, 2).split(/(?:\\r)?\\n/).flatMap((stringChunk, i) => [stringChunk, React.createElement("br", { key: stringChunk + i })]);
10
- }
11
- catch (error) {
12
- console.error('Error formatting JSON:', error);
13
- return 'Error formatting data';
14
- }
15
- };
16
- // Format the timestamp for better readability
17
- const formatTimestamp = (timestamp) => new Date(timestamp).toLocaleString(undefined, {
18
- year: 'numeric',
19
- month: 'short',
20
- day: 'numeric',
21
- hour: '2-digit',
22
- minute: '2-digit',
23
- second: '2-digit'
24
- });
25
- const CommunicationCard = ({ entry }) => (React.createElement("div", { className: 'theia-card', role: "article", "aria-label": `Communication log for request ${entry.requestId}` },
26
- React.createElement("div", { className: 'theia-card-meta' },
27
- React.createElement("span", { className: 'theia-card-request-id' },
28
- core_1.nls.localize('theia/ai/history/communication-card/requestId', 'Request ID'),
29
- ": ",
30
- entry.requestId),
31
- React.createElement("span", { className: 'theia-card-session-id' },
32
- core_1.nls.localize('theia/ai/history/communication-card/sessionId', 'Session ID'),
33
- ": ",
34
- entry.sessionId)),
35
- React.createElement("div", { className: 'theia-card-content' },
36
- entry.request && (React.createElement("div", { className: 'theia-card-request' },
37
- React.createElement("h2", null, core_1.nls.localize('theia/ai/history/communication-card/request', 'Request')),
38
- React.createElement("details", { key: `request-${entry.requestId}` },
39
- React.createElement("summary", null,
40
- React.createElement("h3", null,
41
- core_1.nls.localize('theia/ai/history/communication-card/request/summary', 'Request'),
42
- " ",
43
- entry.requestId)),
44
- React.createElement("div", { className: 'theia-card-request-messages' },
45
- React.createElement("h4", null, core_1.nls.localize('theia/ai/history/communication-card/request/messages', 'Messages')),
46
- React.createElement("ul", { className: 'theia-card-request-messages-list' }, entry.request.map((message, index) => (React.createElement("li", { key: `message-${entry.requestId}-${index}`, className: "message-item" },
47
- React.createElement("pre", { className: "message-content" }, formatJson(message)))))))))),
48
- entry.response && (React.createElement("div", { className: 'theia-card-response' },
49
- React.createElement("h2", null, core_1.nls.localize('theia/ai/history/communication-card/response', 'Response')),
50
- React.createElement("details", { key: `response-${entry.requestId}` },
51
- React.createElement("summary", null,
52
- React.createElement("h3", null,
53
- core_1.nls.localize('theia/ai/history/communication-card/response/summary', 'Response'),
54
- " ",
55
- entry.requestId)),
56
- React.createElement("div", { className: 'theia-card-response-messages' },
57
- React.createElement("h4", null, core_1.nls.localize('theia/ai/history/communication-card/response/messages', 'Messages')),
58
- React.createElement("ul", { className: 'theia-card-response-messages-list' }, entry.response.map((message, index) => (React.createElement("li", { key: `message-${entry.requestId}-${index}`, className: "message-item" },
59
- React.createElement("pre", { className: "message-content" }, formatJson(message))))))))))),
60
- React.createElement("div", { className: 'theia-card-meta' },
61
- React.createElement("span", { className: 'theia-card-timestamp' },
62
- core_1.nls.localize('theia/ai/history/communication-card/timestamp', 'Timestamp'),
63
- ": ",
64
- formatTimestamp(entry.timestamp)),
65
- entry.responseTime !== undefined && (React.createElement("span", { className: 'theia-card-response-time' },
66
- core_1.nls.localize('theia/ai/history/communication-card/responseTime', 'Response Time'),
67
- ": ",
68
- entry.responseTime,
69
- "ms")))));
70
- exports.CommunicationCard = CommunicationCard;
71
- //# sourceMappingURL=ai-history-communication-card.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-history-communication-card.js","sourceRoot":"","sources":["../../src/browser/ai-history-communication-card.tsx"],"names":[],"mappings":";;;AAgBA,sCAAkC;AAClC,kDAAkD;AAKlD,kCAAkC;AAClC,MAAM,UAAU,GAAG,CAAC,IAAa,EAAmB,EAAE;IAClD,IAAI,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,4BAAI,GAAG,EAAE,WAAW,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3I,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;QAC/C,OAAO,uBAAuB,CAAC;IACnC,CAAC;AACL,CAAC,CAAC;AAEF,8CAA8C;AAC9C,MAAM,eAAe,GAAG,CAAC,SAAiB,EAAU,EAAE,CAClD,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,SAAS,EAAE;IAC1C,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,OAAO;IACd,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;CACpB,CAAC,CAAC;AAEA,MAAM,iBAAiB,GAAqC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAC1E,6BAAK,SAAS,EAAC,YAAY,EAAC,IAAI,EAAC,SAAS,gBAAa,iCAAiC,KAAK,CAAC,SAAS,EAAE;IACrG,6BAAK,SAAS,EAAC,iBAAiB;QAC5B,8BAAM,SAAS,EAAC,uBAAuB;YAAE,UAAG,CAAC,QAAQ,CAAC,+CAA+C,EAAE,YAAY,CAAC;;YAAI,KAAK,CAAC,SAAS,CAAQ;QAC/I,8BAAM,SAAS,EAAC,uBAAuB;YAAE,UAAG,CAAC,QAAQ,CAAC,+CAA+C,EAAE,YAAY,CAAC;;YAAI,KAAK,CAAC,SAAS,CAAQ,CAC7I;IACN,6BAAK,SAAS,EAAC,oBAAoB;QAC9B,KAAK,CAAC,OAAO,IAAI,CACd,6BAAK,SAAS,EAAC,oBAAoB;YAC/B,gCAAK,UAAG,CAAC,QAAQ,CAAC,6CAA6C,EAAE,SAAS,CAAC,CAAM;YACjF,iCAAS,GAAG,EAAE,WAAW,KAAK,CAAC,SAAS,EAAE;gBACtC;oBACI;wBAAK,UAAG,CAAC,QAAQ,CAAC,qDAAqD,EAAE,SAAS,CAAC;;wBAAG,KAAK,CAAC,SAAS,CAAM,CACrG;gBACV,6BAAK,SAAS,EAAC,6BAA6B;oBACxC,gCAAK,UAAG,CAAC,QAAQ,CAAC,sDAAsD,EAAE,UAAU,CAAC,CAAM;oBAC3F,4BAAI,SAAS,EAAC,kCAAkC,IAC3C,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CACnC,4BAAI,GAAG,EAAE,WAAW,KAAK,CAAC,SAAS,IAAI,KAAK,EAAE,EAAE,SAAS,EAAC,cAAc;wBACpE,6BAAK,SAAS,EAAC,iBAAiB,IAAE,UAAU,CAAC,OAAO,CAAC,CAAO,CAC3D,CACR,CAAC,CACD,CACH,CACA,CACR,CACT;QACA,KAAK,CAAC,QAAQ,IAAI,CACf,6BAAK,SAAS,EAAC,qBAAqB;YAChC,gCAAK,UAAG,CAAC,QAAQ,CAAC,8CAA8C,EAAE,UAAU,CAAC,CAAM;YACnF,iCAAS,GAAG,EAAE,YAAY,KAAK,CAAC,SAAS,EAAE;gBACvC;oBACI;wBAAK,UAAG,CAAC,QAAQ,CAAC,sDAAsD,EAAE,UAAU,CAAC;;wBAAG,KAAK,CAAC,SAAS,CAAM,CACvG;gBACV,6BAAK,SAAS,EAAC,8BAA8B;oBACzC,gCAAK,UAAG,CAAC,QAAQ,CAAC,uDAAuD,EAAE,UAAU,CAAC,CAAM;oBAC5F,4BAAI,SAAS,EAAC,mCAAmC,IAC5C,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,CACpC,4BAAI,GAAG,EAAE,WAAW,KAAK,CAAC,SAAS,IAAI,KAAK,EAAE,EAAE,SAAS,EAAC,cAAc;wBACpE,6BAAK,SAAS,EAAC,iBAAiB,IAAE,UAAU,CAAC,OAAO,CAAC,CAAO,CAC3D,CACR,CAAC,CACD,CACH,CACA,CACR,CACT,CACC;IACN,6BAAK,SAAS,EAAC,iBAAiB;QAC5B,8BAAM,SAAS,EAAC,sBAAsB;YACjC,UAAG,CAAC,QAAQ,CAAC,+CAA+C,EAAE,WAAW,CAAC;;YAAI,eAAe,CAAC,KAAK,CAAC,SAAS,CAAC,CAC5G;QACN,KAAK,CAAC,YAAY,KAAK,SAAS,IAAI,CACjC,8BAAM,SAAS,EAAC,0BAA0B;YACrC,UAAG,CAAC,QAAQ,CAAC,kDAAkD,EAAE,eAAe,CAAC;;YAAI,KAAK,CAAC,YAAY;iBACrG,CACV,CACC,CACJ,CACT,CAAC;AA3DO,QAAA,iBAAiB,qBA2DxB"}
@@ -1,18 +0,0 @@
1
- import { CommunicationHistory, CommunicationRecordingService, CommunicationRequestEntry, CommunicationRequestEntryParam, CommunicationResponseEntry, CommunicationResponseEntryParam } from '@theia/ai-core';
2
- import { Emitter, Event, ILogger } from '@theia/core';
3
- export declare class DefaultCommunicationRecordingService implements CommunicationRecordingService {
4
- protected logger: ILogger;
5
- protected onDidRecordRequestEmitter: Emitter<CommunicationRequestEntry>;
6
- readonly onDidRecordRequest: Event<CommunicationRequestEntry>;
7
- protected onDidRecordResponseEmitter: Emitter<CommunicationResponseEntry>;
8
- readonly onDidRecordResponse: Event<CommunicationResponseEntry>;
9
- protected onStructuralChangeEmitter: Emitter<void>;
10
- readonly onStructuralChange: Event<void>;
11
- protected history: Map<string, CommunicationHistory>;
12
- getHistory(agentId: string): CommunicationHistory;
13
- getSessionHistory(sessionId: string): CommunicationHistory;
14
- recordRequest(requestEntry: CommunicationRequestEntryParam): void;
15
- recordResponse(responseEntry: CommunicationResponseEntryParam): void;
16
- clearHistory(): void;
17
- }
18
- //# sourceMappingURL=communication-recording-service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"communication-recording-service.d.ts","sourceRoot":"","sources":["../../src/common/communication-recording-service.ts"],"names":[],"mappings":"AAeA,OAAO,EACH,oBAAoB,EACpB,6BAA6B,EAC7B,yBAAyB,EACzB,8BAA8B,EAC9B,0BAA0B,EAC1B,+BAA+B,EAClC,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtD,qBACa,oCAAqC,YAAW,6BAA6B;IAGtF,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC;IAE1B,SAAS,CAAC,yBAAyB,qCAA4C;IAC/E,QAAQ,CAAC,kBAAkB,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAwC;IAErG,SAAS,CAAC,0BAA0B,sCAA6C;IACjF,QAAQ,CAAC,mBAAmB,EAAE,KAAK,CAAC,0BAA0B,CAAC,CAAyC;IAExG,SAAS,CAAC,yBAAyB,gBAAuB;IAC1D,QAAQ,CAAC,kBAAkB,EAAE,KAAK,CAAC,IAAI,CAAC,CAAwC;IAEhF,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAa;IAEjE,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,oBAAoB;IAIjD,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,oBAAoB;IAQ1D,aAAa,CAAC,YAAY,EAAE,8BAA8B,GAAG,IAAI;IAoBjE,cAAc,CAAC,aAAa,EAAE,+BAA+B,GAAG,IAAI;IAiBpE,YAAY,IAAI,IAAI;CAIvB"}
@@ -1,74 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DefaultCommunicationRecordingService = void 0;
4
- const tslib_1 = require("tslib");
5
- const core_1 = require("@theia/core");
6
- const inversify_1 = require("@theia/core/shared/inversify");
7
- let DefaultCommunicationRecordingService = class DefaultCommunicationRecordingService {
8
- constructor() {
9
- this.onDidRecordRequestEmitter = new core_1.Emitter();
10
- this.onDidRecordRequest = this.onDidRecordRequestEmitter.event;
11
- this.onDidRecordResponseEmitter = new core_1.Emitter();
12
- this.onDidRecordResponse = this.onDidRecordResponseEmitter.event;
13
- this.onStructuralChangeEmitter = new core_1.Emitter();
14
- this.onStructuralChange = this.onStructuralChangeEmitter.event;
15
- this.history = new Map();
16
- }
17
- getHistory(agentId) {
18
- return this.history.get(agentId) || [];
19
- }
20
- getSessionHistory(sessionId) {
21
- return Array.from(this.history.values()).reduce((acc, current) => acc.concat(current.filter(entry => entry.sessionId === sessionId)), []);
22
- }
23
- recordRequest(requestEntry) {
24
- this.logger.debug('Recording request:', requestEntry.request);
25
- const completedEntry = { timestamp: Date.now(), ...requestEntry };
26
- if (!this.history.has(requestEntry.agentId)) {
27
- this.history.set(requestEntry.agentId, [completedEntry]);
28
- }
29
- else {
30
- const agentHistory = this.history.get(requestEntry.agentId);
31
- const existingEntryIndex = agentHistory.findIndex(e => e.requestId === requestEntry.requestId);
32
- if (existingEntryIndex !== -1) {
33
- agentHistory[existingEntryIndex] = {
34
- ...agentHistory[existingEntryIndex],
35
- ...completedEntry
36
- };
37
- }
38
- else {
39
- agentHistory.push(completedEntry);
40
- }
41
- }
42
- this.onDidRecordRequestEmitter.fire(completedEntry);
43
- }
44
- recordResponse(responseEntry) {
45
- this.logger.debug('Recording response:', responseEntry.response);
46
- const completedEntry = { timestamp: Date.now(), ...responseEntry };
47
- if (this.history.has(completedEntry.agentId)) {
48
- const agentHistory = this.history.get(completedEntry.agentId);
49
- if (agentHistory) {
50
- const matchingRequest = agentHistory.find(e => e.requestId === completedEntry.requestId);
51
- if (!matchingRequest) {
52
- throw Error('No matching request found for response');
53
- }
54
- matchingRequest.response = completedEntry.response;
55
- matchingRequest.responseTime = completedEntry.timestamp - matchingRequest.timestamp;
56
- this.onDidRecordResponseEmitter.fire(completedEntry);
57
- }
58
- }
59
- }
60
- clearHistory() {
61
- this.history.clear();
62
- this.onStructuralChangeEmitter.fire(undefined);
63
- }
64
- };
65
- exports.DefaultCommunicationRecordingService = DefaultCommunicationRecordingService;
66
- tslib_1.__decorate([
67
- (0, inversify_1.inject)(core_1.ILogger),
68
- (0, inversify_1.named)('llm-communication-recorder'),
69
- tslib_1.__metadata("design:type", Object)
70
- ], DefaultCommunicationRecordingService.prototype, "logger", void 0);
71
- exports.DefaultCommunicationRecordingService = DefaultCommunicationRecordingService = tslib_1.__decorate([
72
- (0, inversify_1.injectable)()
73
- ], DefaultCommunicationRecordingService);
74
- //# sourceMappingURL=communication-recording-service.js.map