@theia/ai-chat 1.66.0-next.44 → 1.66.0-next.73
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/agent-delegation-tool.d.ts.map +1 -1
- package/lib/browser/agent-delegation-tool.js +4 -2
- package/lib/browser/agent-delegation-tool.js.map +1 -1
- package/lib/browser/ai-chat-frontend-module.d.ts.map +1 -1
- package/lib/browser/ai-chat-frontend-module.js +15 -0
- package/lib/browser/ai-chat-frontend-module.js.map +1 -1
- package/lib/browser/change-set-file-element-deserializer.d.ts +7 -0
- package/lib/browser/change-set-file-element-deserializer.d.ts.map +1 -0
- package/lib/browser/change-set-file-element-deserializer.js +61 -0
- package/lib/browser/change-set-file-element-deserializer.js.map +1 -0
- package/lib/browser/change-set-file-element.d.ts +3 -1
- package/lib/browser/change-set-file-element.d.ts.map +1 -1
- package/lib/browser/change-set-file-element.js +23 -2
- package/lib/browser/change-set-file-element.js.map +1 -1
- package/lib/browser/change-set-file-service.d.ts.map +1 -1
- package/lib/browser/change-set-file-service.js +2 -2
- package/lib/browser/change-set-file-service.js.map +1 -1
- package/lib/browser/chat-session-store-impl.d.ts +36 -0
- package/lib/browser/chat-session-store-impl.d.ts.map +1 -0
- package/lib/browser/chat-session-store-impl.js +287 -0
- package/lib/browser/chat-session-store-impl.js.map +1 -0
- package/lib/browser/file-chat-variable-contribution.d.ts.map +1 -1
- package/lib/browser/file-chat-variable-contribution.js +1 -1
- package/lib/browser/file-chat-variable-contribution.js.map +1 -1
- package/lib/browser/image-context-variable-contribution.js +1 -1
- package/lib/browser/image-context-variable-contribution.js.map +1 -1
- package/lib/browser/task-context-service.d.ts.map +1 -1
- package/lib/browser/task-context-service.js +8 -2
- package/lib/browser/task-context-service.js.map +1 -1
- package/lib/browser/task-context-variable.d.ts.map +1 -1
- package/lib/browser/task-context-variable.js +7 -3
- package/lib/browser/task-context-variable.js.map +1 -1
- package/lib/common/change-set-element-deserializer.d.ts +30 -0
- package/lib/common/change-set-element-deserializer.d.ts.map +1 -0
- package/lib/common/change-set-element-deserializer.js +81 -0
- package/lib/common/change-set-element-deserializer.js.map +1 -0
- package/lib/common/change-set.d.ts +7 -0
- package/lib/common/change-set.d.ts.map +1 -1
- package/lib/common/change-set.js +1 -1
- package/lib/common/change-set.js.map +1 -1
- package/lib/common/chat-agents-variable-contribution.d.ts.map +1 -1
- package/lib/common/chat-agents-variable-contribution.js +17 -1
- package/lib/common/chat-agents-variable-contribution.js.map +1 -1
- package/lib/common/chat-agents.d.ts.map +1 -1
- package/lib/common/chat-agents.js +3 -3
- package/lib/common/chat-agents.js.map +1 -1
- package/lib/common/chat-auto-save.spec.d.ts +2 -0
- package/lib/common/chat-auto-save.spec.d.ts.map +1 -0
- package/lib/common/chat-auto-save.spec.js +304 -0
- package/lib/common/chat-auto-save.spec.js.map +1 -0
- package/lib/common/chat-content-deserializer.d.ts +161 -0
- package/lib/common/chat-content-deserializer.d.ts.map +1 -0
- package/lib/common/chat-content-deserializer.js +166 -0
- package/lib/common/chat-content-deserializer.js.map +1 -0
- package/lib/common/chat-content-deserializer.spec.d.ts +2 -0
- package/lib/common/chat-content-deserializer.spec.d.ts.map +1 -0
- package/lib/common/chat-content-deserializer.spec.js +307 -0
- package/lib/common/chat-content-deserializer.spec.js.map +1 -0
- package/lib/common/chat-model-serialization.d.ts +110 -0
- package/lib/common/chat-model-serialization.d.ts.map +1 -0
- package/lib/common/chat-model-serialization.js +20 -0
- package/lib/common/chat-model-serialization.js.map +1 -0
- package/lib/common/chat-model-serialization.spec.d.ts +2 -0
- package/lib/common/chat-model-serialization.spec.d.ts.map +1 -0
- package/lib/common/chat-model-serialization.spec.js +278 -0
- package/lib/common/chat-model-serialization.spec.js.map +1 -0
- package/lib/common/chat-model.d.ts +163 -14
- package/lib/common/chat-model.d.ts.map +1 -1
- package/lib/common/chat-model.js +444 -36
- package/lib/common/chat-model.js.map +1 -1
- package/lib/common/chat-request-parser.d.ts +8 -1
- package/lib/common/chat-request-parser.d.ts.map +1 -1
- package/lib/common/chat-request-parser.js +29 -1
- package/lib/common/chat-request-parser.js.map +1 -1
- package/lib/common/chat-request-parser.spec.js +51 -0
- package/lib/common/chat-request-parser.spec.js.map +1 -1
- package/lib/common/chat-service-deletion.spec.d.ts +2 -0
- package/lib/common/chat-service-deletion.spec.d.ts.map +1 -0
- package/lib/common/chat-service-deletion.spec.js +221 -0
- package/lib/common/chat-service-deletion.spec.js.map +1 -0
- package/lib/common/chat-service.d.ts +30 -2
- package/lib/common/chat-service.d.ts.map +1 -1
- package/lib/common/chat-service.js +182 -10
- package/lib/common/chat-service.js.map +1 -1
- package/lib/common/chat-session-naming-service.d.ts.map +1 -1
- package/lib/common/chat-session-naming-service.js +11 -3
- package/lib/common/chat-session-naming-service.js.map +1 -1
- package/lib/common/chat-session-store.d.ts +43 -0
- package/lib/common/chat-session-store.d.ts.map +1 -0
- package/lib/common/chat-session-store.js +20 -0
- package/lib/common/chat-session-store.js.map +1 -0
- package/lib/common/chat-session-summary-agent-prompt.js +1 -1
- package/lib/common/chat-session-summary-agent-prompt.js.map +1 -1
- package/lib/common/chat-session-summary-agent.d.ts.map +1 -1
- package/lib/common/chat-session-summary-agent.js +2 -1
- package/lib/common/chat-session-summary-agent.js.map +1 -1
- package/lib/common/chat-tool-preferences.js +1 -1
- package/lib/common/chat-tool-preferences.js.map +1 -1
- package/lib/common/image-context-variable.d.ts.map +1 -1
- package/lib/common/image-context-variable.js +21 -6
- package/lib/common/image-context-variable.js.map +1 -1
- package/lib/common/index.d.ts +3 -0
- package/lib/common/index.d.ts.map +1 -1
- package/lib/common/index.js +3 -0
- package/lib/common/index.js.map +1 -1
- package/package.json +9 -9
- package/src/browser/agent-delegation-tool.ts +4 -2
- package/src/browser/ai-chat-frontend-module.ts +27 -0
- package/src/browser/change-set-file-element-deserializer.ts +62 -0
- package/src/browser/change-set-file-element.ts +29 -4
- package/src/browser/change-set-file-service.ts +3 -3
- package/src/browser/chat-session-store-impl.ts +326 -0
- package/src/browser/file-chat-variable-contribution.ts +2 -2
- package/src/browser/image-context-variable-contribution.ts +1 -1
- package/src/browser/task-context-service.ts +9 -3
- package/src/browser/task-context-variable.ts +8 -3
- package/src/common/change-set-element-deserializer.ts +90 -0
- package/src/common/change-set.ts +10 -2
- package/src/common/chat-agents-variable-contribution.ts +2 -2
- package/src/common/chat-agents.ts +4 -4
- package/src/common/chat-auto-save.spec.ts +372 -0
- package/src/common/chat-content-deserializer.spec.ts +375 -0
- package/src/common/chat-content-deserializer.ts +327 -0
- package/src/common/chat-model-serialization.spec.ts +343 -0
- package/src/common/chat-model-serialization.ts +133 -0
- package/src/common/chat-model.ts +644 -41
- package/src/common/chat-request-parser.spec.ts +61 -0
- package/src/common/chat-request-parser.ts +40 -1
- package/src/common/chat-service-deletion.spec.ts +269 -0
- package/src/common/chat-service.ts +227 -10
- package/src/common/chat-session-naming-service.ts +12 -4
- package/src/common/chat-session-store.ts +63 -0
- package/src/common/chat-session-summary-agent-prompt.ts +1 -1
- package/src/common/chat-session-summary-agent.ts +2 -1
- package/src/common/chat-tool-preferences.ts +1 -2
- package/src/common/image-context-variable.ts +21 -6
- package/src/common/index.ts +3 -0
|
@@ -0,0 +1,375 @@
|
|
|
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 { expect } from 'chai';
|
|
18
|
+
import { URI } from '@theia/core';
|
|
19
|
+
import { Position } from '@theia/core/shared/vscode-languageserver-protocol';
|
|
20
|
+
import { ILogger } from '@theia/core/lib/common';
|
|
21
|
+
import {
|
|
22
|
+
ChatContentDeserializerRegistryImpl,
|
|
23
|
+
DefaultChatContentDeserializerContribution
|
|
24
|
+
} from './chat-content-deserializer';
|
|
25
|
+
import {
|
|
26
|
+
CodeChatResponseContentImpl,
|
|
27
|
+
ErrorChatResponseContentImpl,
|
|
28
|
+
HorizontalLayoutChatResponseContentImpl,
|
|
29
|
+
InformationalChatResponseContentImpl,
|
|
30
|
+
MarkdownChatResponseContentImpl,
|
|
31
|
+
ProgressChatResponseContentImpl,
|
|
32
|
+
QuestionResponseContentImpl,
|
|
33
|
+
TextChatResponseContentImpl,
|
|
34
|
+
ThinkingChatResponseContentImpl,
|
|
35
|
+
ToolCallChatResponseContentImpl
|
|
36
|
+
} from './chat-model';
|
|
37
|
+
|
|
38
|
+
class MockLogger {
|
|
39
|
+
error(): void { }
|
|
40
|
+
warn(): void { }
|
|
41
|
+
info(): void { }
|
|
42
|
+
debug(): void { }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
describe('Chat Content Serialization', () => {
|
|
46
|
+
|
|
47
|
+
let registry: ChatContentDeserializerRegistryImpl;
|
|
48
|
+
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
registry = new ChatContentDeserializerRegistryImpl();
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
|
+
(registry as any).logger = new MockLogger() as unknown as ILogger;
|
|
53
|
+
const contribution = new DefaultChatContentDeserializerContribution();
|
|
54
|
+
contribution.registerDeserializers(registry);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('TextChatResponseContentImpl', () => {
|
|
58
|
+
it('should serialize and deserialize correctly', async () => {
|
|
59
|
+
const original = new TextChatResponseContentImpl('Hello, World!');
|
|
60
|
+
const serialized = original.toSerializable?.();
|
|
61
|
+
|
|
62
|
+
expect(serialized).to.not.be.undefined;
|
|
63
|
+
expect(serialized!.kind).to.equal('text');
|
|
64
|
+
expect(serialized!.data).to.deep.equal({ content: 'Hello, World!' });
|
|
65
|
+
|
|
66
|
+
// Simulate caller populating fallbackMessage
|
|
67
|
+
const withFallback = {
|
|
68
|
+
...serialized!,
|
|
69
|
+
fallbackMessage: original.asString?.() || original.toString()
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const deserialized = await registry.deserialize(withFallback);
|
|
73
|
+
expect(deserialized.kind).to.equal('text');
|
|
74
|
+
expect(deserialized.asString?.()).to.equal('Hello, World!');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('ThinkingChatResponseContentImpl', () => {
|
|
79
|
+
it('should serialize and deserialize correctly', async () => {
|
|
80
|
+
const original = new ThinkingChatResponseContentImpl('Thinking...', 'sig123');
|
|
81
|
+
const serialized = original.toSerializable?.();
|
|
82
|
+
|
|
83
|
+
expect(serialized).to.not.be.undefined;
|
|
84
|
+
expect(serialized!.kind).to.equal('thinking');
|
|
85
|
+
expect(serialized!.data).to.deep.equal({
|
|
86
|
+
content: 'Thinking...',
|
|
87
|
+
signature: 'sig123'
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Simulate caller populating fallbackMessage
|
|
91
|
+
const withFallback = {
|
|
92
|
+
...serialized!,
|
|
93
|
+
fallbackMessage: original.asString?.() || original.toString()
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const deserialized = await registry.deserialize(withFallback);
|
|
97
|
+
expect(deserialized.kind).to.equal('thinking');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('MarkdownChatResponseContentImpl', () => {
|
|
102
|
+
it('should serialize and deserialize correctly', async () => {
|
|
103
|
+
const original = new MarkdownChatResponseContentImpl('# Title\n\nContent');
|
|
104
|
+
const serialized = original.toSerializable?.();
|
|
105
|
+
|
|
106
|
+
expect(serialized).to.not.be.undefined;
|
|
107
|
+
expect(serialized!.kind).to.equal('markdownContent');
|
|
108
|
+
expect(serialized!.data).to.deep.equal({ content: '# Title\n\nContent' });
|
|
109
|
+
|
|
110
|
+
// Simulate caller populating fallbackMessage
|
|
111
|
+
const withFallback = {
|
|
112
|
+
...serialized!,
|
|
113
|
+
fallbackMessage: original.asString?.() || original.toString()
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const deserialized = await registry.deserialize(withFallback);
|
|
117
|
+
expect(deserialized.kind).to.equal('markdownContent');
|
|
118
|
+
expect(deserialized.asString?.()).to.equal('# Title\n\nContent');
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe('InformationalChatResponseContentImpl', () => {
|
|
123
|
+
it('should serialize and deserialize correctly', async () => {
|
|
124
|
+
const original = new InformationalChatResponseContentImpl('Info message');
|
|
125
|
+
const serialized = original.toSerializable?.();
|
|
126
|
+
|
|
127
|
+
expect(serialized).to.not.be.undefined;
|
|
128
|
+
expect(serialized!.kind).to.equal('informational');
|
|
129
|
+
expect(serialized!.data).to.deep.equal({ content: 'Info message' });
|
|
130
|
+
|
|
131
|
+
// Simulate caller populating fallbackMessage
|
|
132
|
+
const withFallback = {
|
|
133
|
+
...serialized!,
|
|
134
|
+
fallbackMessage: original.asString?.() || original.toString()
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const deserialized = await registry.deserialize(withFallback);
|
|
138
|
+
expect(deserialized.kind).to.equal('informational');
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe('CodeChatResponseContentImpl', () => {
|
|
143
|
+
it('should serialize and deserialize code without location', async () => {
|
|
144
|
+
const original = new CodeChatResponseContentImpl('console.log("test")', 'typescript');
|
|
145
|
+
const serialized = original.toSerializable?.();
|
|
146
|
+
|
|
147
|
+
expect(serialized).to.not.be.undefined;
|
|
148
|
+
expect(serialized!.kind).to.equal('code');
|
|
149
|
+
expect(serialized!.data).to.deep.equal({
|
|
150
|
+
code: 'console.log("test")',
|
|
151
|
+
language: 'typescript',
|
|
152
|
+
location: undefined
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Simulate caller populating fallbackMessage
|
|
156
|
+
const withFallback = {
|
|
157
|
+
...serialized!,
|
|
158
|
+
fallbackMessage: original.asString?.() || original.toString()
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const deserialized = await registry.deserialize(withFallback);
|
|
162
|
+
expect(deserialized.kind).to.equal('code');
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('should serialize and deserialize code with location', async () => {
|
|
166
|
+
const location = {
|
|
167
|
+
uri: new URI('file:///test.ts'),
|
|
168
|
+
position: Position.create(1, 0)
|
|
169
|
+
};
|
|
170
|
+
const original = new CodeChatResponseContentImpl('code', 'typescript', location);
|
|
171
|
+
const serialized = original.toSerializable?.();
|
|
172
|
+
|
|
173
|
+
expect(serialized).to.not.be.undefined;
|
|
174
|
+
expect(serialized!.kind).to.equal('code');
|
|
175
|
+
|
|
176
|
+
// Simulate caller populating fallbackMessage
|
|
177
|
+
const withFallback = {
|
|
178
|
+
...serialized!,
|
|
179
|
+
fallbackMessage: original.asString?.() || original.toString()
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const deserialized = await registry.deserialize(withFallback);
|
|
183
|
+
expect(deserialized.kind).to.equal('code');
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe('ToolCallChatResponseContentImpl', () => {
|
|
188
|
+
it('should serialize and deserialize correctly', async () => {
|
|
189
|
+
const original = new ToolCallChatResponseContentImpl(
|
|
190
|
+
'id123',
|
|
191
|
+
'toolName',
|
|
192
|
+
'{"arg": "value"}',
|
|
193
|
+
true,
|
|
194
|
+
'result'
|
|
195
|
+
);
|
|
196
|
+
const serialized = original.toSerializable?.();
|
|
197
|
+
|
|
198
|
+
expect(serialized).to.not.be.undefined;
|
|
199
|
+
expect(serialized!.kind).to.equal('toolCall');
|
|
200
|
+
expect(serialized!.data).to.deep.equal({
|
|
201
|
+
id: 'id123',
|
|
202
|
+
name: 'toolName',
|
|
203
|
+
arguments: '{"arg": "value"}',
|
|
204
|
+
finished: true,
|
|
205
|
+
result: 'result'
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Simulate caller populating fallbackMessage
|
|
209
|
+
const withFallback = {
|
|
210
|
+
...serialized!,
|
|
211
|
+
fallbackMessage: original.asString?.() || original.toString()
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const deserialized = await registry.deserialize(withFallback);
|
|
215
|
+
expect(deserialized.kind).to.equal('toolCall');
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
describe('ErrorChatResponseContentImpl', () => {
|
|
220
|
+
it('should serialize and deserialize correctly', async () => {
|
|
221
|
+
const error = new Error('Test error');
|
|
222
|
+
const original = new ErrorChatResponseContentImpl(error);
|
|
223
|
+
const serialized = original.toSerializable?.();
|
|
224
|
+
|
|
225
|
+
expect(serialized).to.not.be.undefined;
|
|
226
|
+
expect(serialized!.kind).to.equal('error');
|
|
227
|
+
expect(serialized!.data).to.have.property('message', 'Test error');
|
|
228
|
+
|
|
229
|
+
// Simulate caller populating fallbackMessage
|
|
230
|
+
const withFallback = {
|
|
231
|
+
...serialized!,
|
|
232
|
+
fallbackMessage: original.asString?.() || original.toString()
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
const deserialized = await registry.deserialize(withFallback);
|
|
236
|
+
expect(deserialized.kind).to.equal('error');
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe('ProgressChatResponseContentImpl', () => {
|
|
241
|
+
it('should serialize and deserialize correctly', async () => {
|
|
242
|
+
const original = new ProgressChatResponseContentImpl('Processing...');
|
|
243
|
+
const serialized = original.toSerializable?.();
|
|
244
|
+
|
|
245
|
+
expect(serialized).to.not.be.undefined;
|
|
246
|
+
expect(serialized!.kind).to.equal('progress');
|
|
247
|
+
expect(serialized!.data).to.deep.equal({ message: 'Processing...' });
|
|
248
|
+
|
|
249
|
+
// Simulate caller populating fallbackMessage
|
|
250
|
+
const withFallback = {
|
|
251
|
+
...serialized!,
|
|
252
|
+
fallbackMessage: original.asString?.() || original.toString()
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const deserialized = await registry.deserialize(withFallback);
|
|
256
|
+
expect(deserialized.kind).to.equal('progress');
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
describe('HorizontalLayoutChatResponseContentImpl', () => {
|
|
261
|
+
it('should serialize and deserialize nested content', async () => {
|
|
262
|
+
const child1 = new TextChatResponseContentImpl('Text 1');
|
|
263
|
+
const child2 = new TextChatResponseContentImpl('Text 2');
|
|
264
|
+
const original = new HorizontalLayoutChatResponseContentImpl([child1, child2]);
|
|
265
|
+
const serialized = original.toSerializable?.();
|
|
266
|
+
|
|
267
|
+
expect(serialized).to.not.be.undefined;
|
|
268
|
+
expect(serialized!.kind).to.equal('horizontal');
|
|
269
|
+
expect(serialized!.data).to.have.property('content');
|
|
270
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
271
|
+
expect((serialized!.data as any).content).to.be.an('array').with.length(2);
|
|
272
|
+
|
|
273
|
+
// Simulate caller populating fallbackMessage
|
|
274
|
+
const withFallback = {
|
|
275
|
+
...serialized!,
|
|
276
|
+
fallbackMessage: original.asString?.() || original.toString()
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const deserialized = await registry.deserialize(withFallback);
|
|
280
|
+
expect(deserialized.kind).to.equal('horizontal');
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
describe('QuestionResponseContentImpl', () => {
|
|
285
|
+
it('should serialize and deserialize question with selected option', async () => {
|
|
286
|
+
const options = [
|
|
287
|
+
{ text: 'Blue' },
|
|
288
|
+
{ text: 'Green' },
|
|
289
|
+
{ text: 'Lavender' }
|
|
290
|
+
];
|
|
291
|
+
const original = new QuestionResponseContentImpl(
|
|
292
|
+
'Which color do you find most calming?',
|
|
293
|
+
options,
|
|
294
|
+
undefined, // request
|
|
295
|
+
undefined, // handler
|
|
296
|
+
{ text: 'Blue' } // selectedOption
|
|
297
|
+
);
|
|
298
|
+
const serialized = original.toSerializable?.();
|
|
299
|
+
|
|
300
|
+
expect(serialized).to.not.be.undefined;
|
|
301
|
+
expect(serialized!.kind).to.equal('question');
|
|
302
|
+
expect(serialized!.data).to.deep.equal({
|
|
303
|
+
question: 'Which color do you find most calming?',
|
|
304
|
+
options: options,
|
|
305
|
+
selectedOption: { text: 'Blue' }
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// Simulate caller populating fallbackMessage
|
|
309
|
+
const withFallback = {
|
|
310
|
+
...serialized!,
|
|
311
|
+
fallbackMessage: original.asString?.() || original.toString()
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
const deserialized = await registry.deserialize(withFallback);
|
|
315
|
+
expect(deserialized.kind).to.equal('question');
|
|
316
|
+
expect(deserialized.asString?.()).to.include('Question: Which color do you find most calming?');
|
|
317
|
+
expect(deserialized.asString?.()).to.include('Answer: Blue');
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it('should serialize and deserialize question without selected option', async () => {
|
|
321
|
+
const options = [
|
|
322
|
+
{ text: 'Option 1' },
|
|
323
|
+
{ text: 'Option 2' }
|
|
324
|
+
];
|
|
325
|
+
const original = new QuestionResponseContentImpl(
|
|
326
|
+
'What is your choice?',
|
|
327
|
+
options,
|
|
328
|
+
undefined, // request
|
|
329
|
+
undefined // handler
|
|
330
|
+
// no selectedOption
|
|
331
|
+
);
|
|
332
|
+
const serialized = original.toSerializable?.();
|
|
333
|
+
|
|
334
|
+
expect(serialized).to.not.be.undefined;
|
|
335
|
+
expect(serialized!.kind).to.equal('question');
|
|
336
|
+
|
|
337
|
+
// Simulate caller populating fallbackMessage
|
|
338
|
+
const withFallback = {
|
|
339
|
+
...serialized!,
|
|
340
|
+
fallbackMessage: original.asString?.() || original.toString()
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
const deserialized = await registry.deserialize(withFallback);
|
|
344
|
+
expect(deserialized.kind).to.equal('question');
|
|
345
|
+
expect(deserialized.asString?.()).to.include('Question: What is your choice?');
|
|
346
|
+
expect(deserialized.asString?.()).to.include('No answer');
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
describe('ChatContentDeserializerRegistry', () => {
|
|
351
|
+
it('should handle unknown content types with fallback', async () => {
|
|
352
|
+
const unknownContent = {
|
|
353
|
+
kind: 'unknown-type',
|
|
354
|
+
fallbackMessage: 'Fallback text',
|
|
355
|
+
data: { some: 'data' }
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
const deserialized = await registry.deserialize(unknownContent);
|
|
359
|
+
expect(deserialized.kind).to.equal('unknown');
|
|
360
|
+
expect(deserialized.asString?.()).to.equal('Fallback text');
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
it('should use fallback message when deserializer not found', async () => {
|
|
364
|
+
const unknownContent = {
|
|
365
|
+
kind: 'custom-extension-type',
|
|
366
|
+
fallbackMessage: 'Custom content not available',
|
|
367
|
+
data: undefined
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const deserialized = await registry.deserialize(unknownContent);
|
|
371
|
+
expect(deserialized.asString?.()).to.equal('Custom content not available');
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
});
|