@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.
- package/lib/browser/ai-history-contribution.d.ts +9 -1
- package/lib/browser/ai-history-contribution.d.ts.map +1 -1
- package/lib/browser/ai-history-contribution.js +102 -4
- package/lib/browser/ai-history-contribution.js.map +1 -1
- package/lib/browser/ai-history-exchange-card.d.ts +11 -0
- package/lib/browser/ai-history-exchange-card.d.ts.map +1 -0
- package/lib/browser/ai-history-exchange-card.js +132 -0
- package/lib/browser/ai-history-exchange-card.js.map +1 -0
- package/lib/browser/ai-history-frontend-module.d.ts.map +1 -1
- package/lib/browser/ai-history-frontend-module.js +0 -4
- package/lib/browser/ai-history-frontend-module.js.map +1 -1
- package/lib/browser/ai-history-widget.d.ts +17 -5
- package/lib/browser/ai-history-widget.d.ts.map +1 -1
- package/lib/browser/ai-history-widget.js +50 -30
- package/lib/browser/ai-history-widget.js.map +1 -1
- package/lib/common/index.d.ts +0 -1
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +0 -4
- package/lib/common/index.js.map +1 -1
- package/lib/package.spec.d.ts +1 -0
- package/lib/package.spec.d.ts.map +1 -0
- package/lib/package.spec.js +26 -0
- package/lib/package.spec.js.map +1 -0
- package/package.json +9 -8
- package/src/browser/ai-history-contribution.ts +107 -3
- package/src/browser/ai-history-exchange-card.tsx +243 -0
- package/src/browser/ai-history-frontend-module.ts +0 -5
- package/src/browser/ai-history-widget.tsx +74 -31
- package/src/browser/style/ai-history.css +145 -60
- package/src/common/index.ts +0 -1
- package/src/package.spec.ts +28 -0
- package/lib/browser/ai-history-communication-card.d.ts +0 -8
- package/lib/browser/ai-history-communication-card.d.ts.map +0 -1
- package/lib/browser/ai-history-communication-card.js +0 -71
- package/lib/browser/ai-history-communication-card.js.map +0 -1
- package/lib/common/communication-recording-service.d.ts +0 -18
- package/lib/common/communication-recording-service.d.ts.map +0 -1
- package/lib/common/communication-recording-service.js +0 -74
- package/lib/common/communication-recording-service.js.map +0 -1
- package/lib/common/communication-recording-service.spec.d.ts +0 -2
- package/lib/common/communication-recording-service.spec.d.ts.map +0 -1
- package/lib/common/communication-recording-service.spec.js +0 -43
- package/lib/common/communication-recording-service.spec.js.map +0 -1
- package/src/browser/ai-history-communication-card.tsx +0 -103
- package/src/common/communication-recording-service.spec.ts +0 -63
- 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,
|
|
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 {
|
|
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(
|
|
33
|
-
protected
|
|
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
|
|
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.
|
|
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.
|
|
85
|
-
this.update();
|
|
90
|
+
this.state = { ...this.state, selectedAgentId: agent?.id };
|
|
86
91
|
}
|
|
87
92
|
|
|
88
|
-
protected historyContentUpdated(
|
|
89
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
128
|
-
|
|
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.
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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:
|
|
50
|
+
overflow: visible;
|
|
55
51
|
padding: 10px;
|
|
56
52
|
margin: 5px 0;
|
|
57
53
|
}
|
|
58
54
|
|
|
59
|
-
|
|
60
|
-
.theia-card-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
.
|
|
69
|
-
|
|
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
|
-
|
|
129
|
+
font-weight: bold;
|
|
130
|
+
display: block; /* Make the entire summary clickable */
|
|
74
131
|
}
|
|
75
132
|
|
|
76
|
-
.
|
|
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
|
-
.
|
|
82
|
-
.
|
|
83
|
-
|
|
84
|
-
|
|
137
|
+
.request-content,
|
|
138
|
+
.response-content {
|
|
139
|
+
padding: 10px;
|
|
140
|
+
overflow: visible;
|
|
85
141
|
}
|
|
86
142
|
|
|
87
|
-
.
|
|
88
|
-
|
|
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
|
-
.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
.
|
|
105
|
-
|
|
106
|
-
list-style: none;
|
|
107
|
-
padding-inline-start: 0;
|
|
159
|
+
.stream-part:last-child {
|
|
160
|
+
border-bottom: none;
|
|
108
161
|
}
|
|
109
162
|
|
|
110
|
-
.
|
|
111
|
-
|
|
163
|
+
.compact-response {
|
|
164
|
+
padding: 8px;
|
|
112
165
|
background-color: var(--theia-editor-background);
|
|
113
|
-
|
|
166
|
+
border-radius: 4px;
|
|
114
167
|
}
|
|
115
168
|
|
|
116
|
-
.
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
122
|
-
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
.
|
|
134
|
-
|
|
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
|
-
.
|
|
138
|
-
|
|
139
|
-
text-align: left;
|
|
190
|
+
.request-content-container details[open] summary::before {
|
|
191
|
+
transform: rotate(90deg);
|
|
140
192
|
}
|
|
141
193
|
|
|
142
|
-
.theia-card-
|
|
143
|
-
|
|
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
|
}
|
package/src/common/index.ts
CHANGED
|
@@ -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":"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"}
|
|
@@ -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
|