@theia/ai-chat 1.66.0-next.67 → 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.
Files changed (83) hide show
  1. package/lib/browser/agent-delegation-tool.d.ts.map +1 -1
  2. package/lib/browser/agent-delegation-tool.js +4 -2
  3. package/lib/browser/agent-delegation-tool.js.map +1 -1
  4. package/lib/browser/ai-chat-frontend-module.d.ts.map +1 -1
  5. package/lib/browser/ai-chat-frontend-module.js +15 -0
  6. package/lib/browser/ai-chat-frontend-module.js.map +1 -1
  7. package/lib/browser/change-set-file-element-deserializer.d.ts +7 -0
  8. package/lib/browser/change-set-file-element-deserializer.d.ts.map +1 -0
  9. package/lib/browser/change-set-file-element-deserializer.js +61 -0
  10. package/lib/browser/change-set-file-element-deserializer.js.map +1 -0
  11. package/lib/browser/change-set-file-element.d.ts +2 -0
  12. package/lib/browser/change-set-file-element.d.ts.map +1 -1
  13. package/lib/browser/change-set-file-element.js +17 -0
  14. package/lib/browser/change-set-file-element.js.map +1 -1
  15. package/lib/browser/chat-session-store-impl.d.ts +36 -0
  16. package/lib/browser/chat-session-store-impl.d.ts.map +1 -0
  17. package/lib/browser/chat-session-store-impl.js +287 -0
  18. package/lib/browser/chat-session-store-impl.js.map +1 -0
  19. package/lib/common/change-set-element-deserializer.d.ts +30 -0
  20. package/lib/common/change-set-element-deserializer.d.ts.map +1 -0
  21. package/lib/common/change-set-element-deserializer.js +81 -0
  22. package/lib/common/change-set-element-deserializer.js.map +1 -0
  23. package/lib/common/change-set.d.ts +7 -0
  24. package/lib/common/change-set.d.ts.map +1 -1
  25. package/lib/common/change-set.js.map +1 -1
  26. package/lib/common/chat-auto-save.spec.d.ts +2 -0
  27. package/lib/common/chat-auto-save.spec.d.ts.map +1 -0
  28. package/lib/common/chat-auto-save.spec.js +304 -0
  29. package/lib/common/chat-auto-save.spec.js.map +1 -0
  30. package/lib/common/chat-content-deserializer.d.ts +161 -0
  31. package/lib/common/chat-content-deserializer.d.ts.map +1 -0
  32. package/lib/common/chat-content-deserializer.js +166 -0
  33. package/lib/common/chat-content-deserializer.js.map +1 -0
  34. package/lib/common/chat-content-deserializer.spec.d.ts +2 -0
  35. package/lib/common/chat-content-deserializer.spec.d.ts.map +1 -0
  36. package/lib/common/chat-content-deserializer.spec.js +307 -0
  37. package/lib/common/chat-content-deserializer.spec.js.map +1 -0
  38. package/lib/common/chat-model-serialization.d.ts +110 -0
  39. package/lib/common/chat-model-serialization.d.ts.map +1 -0
  40. package/lib/common/chat-model-serialization.js +20 -0
  41. package/lib/common/chat-model-serialization.js.map +1 -0
  42. package/lib/common/chat-model-serialization.spec.d.ts +2 -0
  43. package/lib/common/chat-model-serialization.spec.d.ts.map +1 -0
  44. package/lib/common/chat-model-serialization.spec.js +278 -0
  45. package/lib/common/chat-model-serialization.spec.js.map +1 -0
  46. package/lib/common/chat-model.d.ts +163 -14
  47. package/lib/common/chat-model.d.ts.map +1 -1
  48. package/lib/common/chat-model.js +444 -36
  49. package/lib/common/chat-model.js.map +1 -1
  50. package/lib/common/chat-service-deletion.spec.d.ts +2 -0
  51. package/lib/common/chat-service-deletion.spec.d.ts.map +1 -0
  52. package/lib/common/chat-service-deletion.spec.js +221 -0
  53. package/lib/common/chat-service-deletion.spec.js.map +1 -0
  54. package/lib/common/chat-service.d.ts +30 -2
  55. package/lib/common/chat-service.d.ts.map +1 -1
  56. package/lib/common/chat-service.js +182 -10
  57. package/lib/common/chat-service.js.map +1 -1
  58. package/lib/common/chat-session-store.d.ts +43 -0
  59. package/lib/common/chat-session-store.d.ts.map +1 -0
  60. package/lib/common/chat-session-store.js +20 -0
  61. package/lib/common/chat-session-store.js.map +1 -0
  62. package/lib/common/index.d.ts +3 -0
  63. package/lib/common/index.d.ts.map +1 -1
  64. package/lib/common/index.js +3 -0
  65. package/lib/common/index.js.map +1 -1
  66. package/package.json +9 -9
  67. package/src/browser/agent-delegation-tool.ts +4 -2
  68. package/src/browser/ai-chat-frontend-module.ts +27 -0
  69. package/src/browser/change-set-file-element-deserializer.ts +62 -0
  70. package/src/browser/change-set-file-element.ts +19 -0
  71. package/src/browser/chat-session-store-impl.ts +326 -0
  72. package/src/common/change-set-element-deserializer.ts +90 -0
  73. package/src/common/change-set.ts +8 -0
  74. package/src/common/chat-auto-save.spec.ts +372 -0
  75. package/src/common/chat-content-deserializer.spec.ts +375 -0
  76. package/src/common/chat-content-deserializer.ts +327 -0
  77. package/src/common/chat-model-serialization.spec.ts +343 -0
  78. package/src/common/chat-model-serialization.ts +133 -0
  79. package/src/common/chat-model.ts +644 -41
  80. package/src/common/chat-service-deletion.spec.ts +269 -0
  81. package/src/common/chat-service.ts +227 -10
  82. package/src/common/chat-session-store.ts +63 -0
  83. package/src/common/index.ts +3 -0
@@ -20,7 +20,7 @@
20
20
  *--------------------------------------------------------------------------------------------*/
21
21
  // Partially copied from https://github.com/microsoft/vscode/blob/a2cab7255c0df424027be05d58e1b7b941f4ea60/src/vs/workbench/contrib/chat/common/chatModel.ts
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.ProgressChatResponseContentImpl = exports.ErrorChatResponseModel = exports.MutableChatResponseModel = exports.QuestionResponseContentImpl = exports.HorizontalLayoutChatResponseContentImpl = exports.CommandChatResponseContentImpl = exports.COMMAND_CHAT_RESPONSE_COMMAND = exports.ToolCallChatResponseContentImpl = exports.CodeChatResponseContentImpl = exports.InformationalChatResponseContentImpl = exports.MarkdownChatResponseContentImpl = exports.ThinkingChatResponseContentImpl = exports.TextChatResponseContentImpl = exports.ErrorChatResponseContentImpl = exports.MutableChatRequestModel = exports.ChatContextManagerImpl = exports.ChatRequestHierarchyBranchImpl = exports.ChatRequestHierarchyImpl = exports.ChatTreeChangeSet = exports.MutableChatModel = exports.QuestionResponseContent = exports.ProgressChatResponseContent = exports.ThinkingChatResponseContent = exports.ErrorChatResponseContent = exports.ToolCallChatResponseContent = exports.HorizontalLayoutChatResponseContent = exports.CodeChatResponseContent = exports.CommandChatResponseContent = exports.InformationalChatResponseContent = exports.MarkdownChatResponseContent = exports.TextChatResponseContent = exports.Location = exports.ChatResponseContent = exports.EditableChatRequestModel = exports.ChatRequestModel = exports.ChatSuggestionCallback = exports.ChatChangeEvent = exports.ChangeSetImpl = void 0;
23
+ exports.UnknownChatResponseContentImpl = exports.ProgressChatResponseContentImpl = exports.ErrorChatResponseModel = exports.MutableChatResponseModel = exports.QuestionResponseContentImpl = exports.HorizontalLayoutChatResponseContentImpl = exports.CommandChatResponseContentImpl = exports.COMMAND_CHAT_RESPONSE_COMMAND = exports.ToolCallChatResponseContentImpl = exports.CodeChatResponseContentImpl = exports.InformationalChatResponseContentImpl = exports.MarkdownChatResponseContentImpl = exports.ThinkingChatResponseContentImpl = exports.TextChatResponseContentImpl = exports.ErrorChatResponseContentImpl = exports.MutableChatRequestModel = exports.ChatContextManagerImpl = exports.ChatRequestHierarchyBranchImpl = exports.ChatRequestHierarchyImpl = exports.ChatTreeChangeSet = exports.MutableChatModel = exports.QuestionResponseContent = exports.ProgressChatResponseContent = exports.ThinkingChatResponseContent = exports.ErrorChatResponseContent = exports.ToolCallChatResponseContent = exports.HorizontalLayoutChatResponseContent = exports.CodeChatResponseContent = exports.CommandChatResponseContent = exports.InformationalChatResponseContent = exports.MarkdownChatResponseContent = exports.TextChatResponseContent = exports.Location = exports.ChatResponseContent = exports.EditableChatRequestModel = exports.ChatRequestModel = exports.ChatSuggestionCallback = exports.ChatChangeEvent = exports.ChangeSetImpl = void 0;
24
24
  const ai_core_1 = require("@theia/ai-core");
25
25
  const core_1 = require("@theia/core");
26
26
  const markdown_rendering_1 = require("@theia/core/lib/common/markdown-rendering");
@@ -235,10 +235,9 @@ var QuestionResponseContent;
235
235
  option && 'text' in option &&
236
236
  typeof option.text === 'string' &&
237
237
  ('value' in option ? typeof option.value === 'string' || typeof option.value === 'undefined' : true)) &&
238
- 'handler' in obj &&
239
- typeof obj.handler === 'function' &&
240
- 'request' in obj &&
241
- obj.request instanceof MutableChatRequestModel);
238
+ // handler and request are optional (undefined for restored/read-only questions)
239
+ ('handler' in obj ? obj.handler === undefined || typeof obj.handler === 'function' : true) &&
240
+ ('request' in obj ? obj.request === undefined || obj.request instanceof MutableChatRequestModel : true));
242
241
  }
243
242
  QuestionResponseContent.is = is;
244
243
  })(QuestionResponseContent || (exports.QuestionResponseContent = QuestionResponseContent = {}));
@@ -246,19 +245,28 @@ var QuestionResponseContent;
246
245
  * Implementations
247
246
  **********************/
248
247
  class MutableChatModel {
249
- constructor(location = chat_agents_1.ChatAgentLocation.Panel) {
250
- this.location = location;
248
+ get location() {
249
+ return this._location;
250
+ }
251
+ constructor(locationOrSerializedData = chat_agents_1.ChatAgentLocation.Panel) {
251
252
  this._onDidChangeEmitter = new core_1.Emitter();
252
253
  this.onDidChange = this._onDidChangeEmitter.event;
253
254
  this.toDispose = new core_1.DisposableCollection();
254
255
  this._suggestions = [];
255
256
  this._contextManager = new ChatContextManagerImpl();
256
- // TODO accept serialized data as a parameter to restore a previously saved ChatModel
257
- this._hierarchy = new ChatRequestHierarchyImpl();
258
- this._changeSet = new ChatTreeChangeSet(this._hierarchy);
259
- this.toDispose.push(this._changeSet);
260
- this._changeSet.onDidChange(this._onDidChangeEmitter.fire, this._onDidChangeEmitter, this.toDispose);
261
- this._id = (0, core_1.generateUuid)();
257
+ // Check if we're restoring from serialized data
258
+ if (this.isSerializedChatModel(locationOrSerializedData)) {
259
+ this.restoreFromSerializedData(locationOrSerializedData);
260
+ }
261
+ else {
262
+ // Normal creation path
263
+ this._location = locationOrSerializedData;
264
+ this._id = (0, core_1.generateUuid)();
265
+ this._hierarchy = new ChatRequestHierarchyImpl();
266
+ this._changeSet = new ChatTreeChangeSet(this._hierarchy);
267
+ this.toDispose.push(this._changeSet);
268
+ this._changeSet.onDidChange(this._onDidChangeEmitter.fire, this._onDidChangeEmitter, this.toDispose);
269
+ }
262
270
  this.toDispose.pushAll([
263
271
  this._onDidChangeEmitter,
264
272
  this._contextManager.onDidChange(this._onDidChangeEmitter.fire, this._onDidChangeEmitter),
@@ -270,6 +278,38 @@ class MutableChatModel {
270
278
  }),
271
279
  ]);
272
280
  }
281
+ /**
282
+ * Type guard to determine if we're receiving serialized data
283
+ */
284
+ isSerializedChatModel(data) {
285
+ return typeof data === 'object' && 'sessionId' in data && 'requests' in data && 'responses' in data;
286
+ }
287
+ /**
288
+ * Restore this chat model from serialized data
289
+ *
290
+ * Does not restore response content or changesets.
291
+ * This handled by the chat service using the deserializer registries.
292
+ */
293
+ restoreFromSerializedData(data) {
294
+ this._id = data.sessionId;
295
+ this._location = data.location;
296
+ // First, create all request models and build a map
297
+ const requestMap = new Map();
298
+ for (const reqData of data.requests) {
299
+ const respData = data.responses.find(r => r.requestId === reqData.id);
300
+ const requestModel = new MutableChatRequestModel(this, reqData, respData);
301
+ requestMap.set(requestModel.id, requestModel);
302
+ }
303
+ // Restore the hierarchy structure with all alternatives
304
+ this._hierarchy = new ChatRequestHierarchyImpl(data.hierarchy, requestMap);
305
+ // Register all requests with changeset
306
+ this._changeSet = new ChatTreeChangeSet(this._hierarchy);
307
+ this.toDispose.push(this._changeSet);
308
+ this._changeSet.onDidChange(this._onDidChangeEmitter.fire, this._onDidChangeEmitter, this.toDispose);
309
+ for (const requestModel of requestMap.values()) {
310
+ this._changeSet.registerRequest(requestModel);
311
+ }
312
+ }
273
313
  get id() {
274
314
  return this._id;
275
315
  }
@@ -334,6 +374,44 @@ class MutableChatModel {
334
374
  isEmpty() {
335
375
  return this.getRequests().length === 0;
336
376
  }
377
+ toSerializable() {
378
+ const hierarchy = this._hierarchy.toSerializable();
379
+ const allRequests = this.getAllRequests();
380
+ const serializedRequests = allRequests.map(req => req.toSerializable());
381
+ const serializedResponses = allRequests
382
+ .filter(req => req.response)
383
+ .map(req => req.response.toSerializable());
384
+ return {
385
+ sessionId: this._id,
386
+ location: this.location,
387
+ hierarchy,
388
+ requests: serializedRequests,
389
+ responses: serializedResponses
390
+ };
391
+ }
392
+ /**
393
+ * Get all requests from the hierarchy.
394
+ * This is used for operations that need to process all requests, such as serialization.
395
+ */
396
+ getAllRequests() {
397
+ const allRequests = [];
398
+ const visited = new Set();
399
+ const collectFromBranch = (branch) => {
400
+ for (const item of branch.items) {
401
+ // Avoid duplicates
402
+ if (!visited.has(item.element.id)) {
403
+ visited.add(item.element.id);
404
+ allRequests.push(item.element);
405
+ }
406
+ // Recursively collect from next branches
407
+ if (item.next) {
408
+ collectFromBranch(item.next);
409
+ }
410
+ }
411
+ };
412
+ collectFromBranch(this._hierarchy.branch);
413
+ return allRequests;
414
+ }
337
415
  dispose() {
338
416
  this.toDispose.dispose();
339
417
  }
@@ -456,10 +534,70 @@ class ChatTreeChangeSet {
456
534
  }
457
535
  exports.ChatTreeChangeSet = ChatTreeChangeSet;
458
536
  class ChatRequestHierarchyImpl {
459
- constructor() {
537
+ constructor(serializedHierarchy, requestMap) {
460
538
  this.onDidChangeActiveBranchEmitter = new core_1.Emitter();
461
539
  this.onDidChange = this.onDidChangeActiveBranchEmitter.event;
462
540
  this.branch = new ChatRequestHierarchyBranchImpl(this);
541
+ if (serializedHierarchy && requestMap) {
542
+ this.restoreFromSerialized(serializedHierarchy, requestMap);
543
+ }
544
+ }
545
+ /**
546
+ * Restore the hierarchy from serialized data.
547
+ */
548
+ restoreFromSerialized(serializedHierarchy, requestMap) {
549
+ // Build a map of branch IDs to restored branch objects
550
+ const branchMap = new Map();
551
+ // Function to restore a branch and its descendants
552
+ const restoreBranch = (branchId) => {
553
+ // Check if already restored
554
+ if (branchMap.has(branchId)) {
555
+ return branchMap.get(branchId);
556
+ }
557
+ const serializedBranch = serializedHierarchy.branches[branchId];
558
+ if (!serializedBranch) {
559
+ throw new Error(`Cannot find serialized branch with id: ${branchId}`);
560
+ }
561
+ // Restore items in this branch
562
+ const items = serializedBranch.items.map(serializedItem => {
563
+ const request = requestMap.get(serializedItem.requestId);
564
+ if (!request) {
565
+ throw new Error(`Cannot find request with id: ${serializedItem.requestId}`);
566
+ }
567
+ // Restore next branch if present
568
+ const next = serializedItem.nextBranchId
569
+ ? restoreBranch(serializedItem.nextBranchId)
570
+ : undefined;
571
+ return {
572
+ element: request,
573
+ next
574
+ };
575
+ });
576
+ // Determine if this is the root branch
577
+ const isRoot = branchId === serializedHierarchy.rootBranchId;
578
+ if (isRoot) {
579
+ // For root branch, we need to replace the existing branch's internals
580
+ // Cast is safe here as we know this.branch is a ChatRequestHierarchyBranchImpl
581
+ const rootBranch = this.branch;
582
+ // Use Object.assign to update the readonly properties
583
+ Object.assign(rootBranch, {
584
+ id: branchId,
585
+ items,
586
+ _activeIndex: serializedBranch.activeBranchIndex
587
+ });
588
+ branchMap.set(branchId, rootBranch);
589
+ return rootBranch;
590
+ }
591
+ else {
592
+ // For non-root branches, use constructor-based deserialization
593
+ const restoredBranch = new ChatRequestHierarchyBranchImpl(this, undefined, // previous will be set by parent
594
+ items, serializedBranch.activeBranchIndex, branchId);
595
+ branchMap.set(branchId, restoredBranch);
596
+ return restoredBranch;
597
+ }
598
+ };
599
+ // Start restoration from the root branch
600
+ restoreBranch(serializedHierarchy.rootBranchId);
463
601
  }
464
602
  append(request) {
465
603
  const branches = this.activeBranches();
@@ -514,6 +652,32 @@ class ChatRequestHierarchyImpl {
514
652
  notifyChange(event) {
515
653
  this.onDidChangeActiveBranchEmitter.fire(event);
516
654
  }
655
+ toSerializable() {
656
+ const branches = {};
657
+ // Recursively serialize all branches starting from the root
658
+ this.serializeBranch(this.branch, branches);
659
+ return {
660
+ rootBranchId: this.branch.id,
661
+ branches
662
+ };
663
+ }
664
+ serializeBranch(branch, branches) {
665
+ const items = branch.items.map(item => {
666
+ var _a;
667
+ if (item.next) {
668
+ this.serializeBranch(item.next, branches);
669
+ }
670
+ return {
671
+ requestId: item.element.id,
672
+ nextBranchId: (_a = item.next) === null || _a === void 0 ? void 0 : _a.id
673
+ };
674
+ });
675
+ branches[branch.id] = {
676
+ id: branch.id,
677
+ items,
678
+ activeBranchIndex: branch.activeBranchIndex
679
+ };
680
+ }
517
681
  dispose() {
518
682
  this.onDidChangeActiveBranchEmitter.dispose();
519
683
  this.branch.dispose();
@@ -521,12 +685,12 @@ class ChatRequestHierarchyImpl {
521
685
  }
522
686
  exports.ChatRequestHierarchyImpl = ChatRequestHierarchyImpl;
523
687
  class ChatRequestHierarchyBranchImpl {
524
- constructor(hierarchy, previous, items = [], _activeIndex = -1) {
688
+ constructor(hierarchy, previous, items = [], _activeIndex = -1, id) {
525
689
  this.hierarchy = hierarchy;
526
690
  this.previous = previous;
527
691
  this.items = items;
528
692
  this._activeIndex = _activeIndex;
529
- this.id = (0, core_1.generateUuid)();
693
+ this.id = id !== null && id !== void 0 ? id : (0, core_1.generateUuid)();
530
694
  }
531
695
  get activeBranchIndex() {
532
696
  return this._activeIndex;
@@ -670,24 +834,74 @@ class ChatContextManagerImpl {
670
834
  }
671
835
  exports.ChatContextManagerImpl = ChatContextManagerImpl;
672
836
  class MutableChatRequestModel {
673
- constructor(session, message, agentId, context = { variables: [] }, data = {}) {
674
- this.message = message;
837
+ constructor(session, messageOrData, agentIdOrResponseData, context = { variables: [] }, data = {}) {
675
838
  this._onDidChangeEmitter = new core_1.Emitter();
676
839
  this.onDidChange = this._onDidChangeEmitter.event;
677
840
  this._isEditing = false;
678
841
  this.toDispose = new core_1.DisposableCollection();
679
- // TODO accept serialized data as a parameter to restore a previously saved ChatRequestModel
680
- this._request = message.request;
681
- this._id = (0, core_1.generateUuid)();
682
842
  this._session = session;
683
- this._response = new MutableChatResponseModel(this._id, agentId);
684
- this._context = context;
685
- this._agentId = agentId;
686
- this._data = data;
687
- this.editContextManager = new ChatContextManagerImpl(context);
843
+ // Check if we're restoring from serialized data
844
+ if (this.isSerializedRequestData(messageOrData)) {
845
+ this.restoreFromSerializedData(messageOrData, agentIdOrResponseData);
846
+ }
847
+ else {
848
+ // Normal creation path
849
+ this._request = messageOrData.request;
850
+ this._id = (0, core_1.generateUuid)();
851
+ this._response = new MutableChatResponseModel(this._id, agentIdOrResponseData);
852
+ this._context = context;
853
+ this._agentId = agentIdOrResponseData;
854
+ this._data = data;
855
+ // Store the parsed message
856
+ this.message = messageOrData;
857
+ }
858
+ this.editContextManager = new ChatContextManagerImpl(this._context);
688
859
  this.editContextManager.onDidChange(this._onDidChangeEmitter.fire, this._onDidChangeEmitter, this.toDispose);
860
+ // Wire response changes to propagate through request to session
861
+ this._response.onDidChange(() => {
862
+ // Fire a generic addVariable event to propagate response changes
863
+ this._onDidChangeEmitter.fire({ kind: 'responseChanged' });
864
+ }, this, this.toDispose);
689
865
  this.toDispose.push(this._onDidChangeEmitter);
690
866
  }
867
+ /**
868
+ * Type guard to determine if we're receiving serialized data
869
+ */
870
+ isSerializedRequestData(data) {
871
+ return 'id' in data && 'text' in data && !('request' in data);
872
+ }
873
+ /**
874
+ * Restore this request model from serialized data
875
+ */
876
+ restoreFromSerializedData(reqData, respData) {
877
+ this._id = reqData.id;
878
+ this._request = { text: reqData.text };
879
+ this._agentId = reqData.agentId;
880
+ this._data = {};
881
+ // Create minimal context
882
+ this._context = { variables: [] };
883
+ // TODO: More sophisticated restoration?
884
+ // Casting required because 'message' is readonly
885
+ this.message = {
886
+ request: this._request,
887
+ parts: [{
888
+ kind: 'text',
889
+ text: reqData.text,
890
+ promptText: reqData.text,
891
+ range: { start: 0, endExclusive: reqData.text.length }
892
+ }],
893
+ toolRequests: new Map(),
894
+ variables: []
895
+ };
896
+ // Restore response if present
897
+ if (respData) {
898
+ this._response = new MutableChatResponseModel(this._id, this._agentId, respData);
899
+ }
900
+ else {
901
+ this._response = new MutableChatResponseModel(this._id, this._agentId);
902
+ }
903
+ // Note: ChangeSet restoration will be handled by ChatService using deserializer registry
904
+ }
691
905
  get changeSet() {
692
906
  return this._changeSet;
693
907
  }
@@ -759,6 +973,17 @@ class MutableChatRequestModel {
759
973
  cancel() {
760
974
  this.response.cancel();
761
975
  }
976
+ toSerializable() {
977
+ return {
978
+ id: this.id,
979
+ text: this.request.text,
980
+ agentId: this.agentId,
981
+ changeSet: this._changeSet ? {
982
+ title: this._changeSet.title,
983
+ elements: this._changeSet.getElements().map(elem => { var _a; return (_a = elem.toSerializable) === null || _a === void 0 ? void 0 : _a.call(elem); }).filter((elem) => elem !== undefined)
984
+ } : undefined
985
+ };
986
+ }
762
987
  dispose() {
763
988
  this.toDispose.dispose();
764
989
  }
@@ -812,6 +1037,15 @@ class ErrorChatResponseContentImpl {
812
1037
  asString() {
813
1038
  return undefined;
814
1039
  }
1040
+ toSerializable() {
1041
+ return {
1042
+ kind: 'error',
1043
+ data: {
1044
+ message: this._error.message,
1045
+ stack: this._error.stack
1046
+ }
1047
+ };
1048
+ }
815
1049
  }
816
1050
  exports.ErrorChatResponseContentImpl = ErrorChatResponseContentImpl;
817
1051
  class TextChatResponseContentImpl {
@@ -839,6 +1073,12 @@ class TextChatResponseContentImpl {
839
1073
  text: this.content
840
1074
  };
841
1075
  }
1076
+ toSerializable() {
1077
+ return {
1078
+ kind: 'text',
1079
+ data: { content: this._content }
1080
+ };
1081
+ }
842
1082
  }
843
1083
  exports.TextChatResponseContentImpl = TextChatResponseContentImpl;
844
1084
  class ThinkingChatResponseContentImpl {
@@ -876,6 +1116,15 @@ class ThinkingChatResponseContentImpl {
876
1116
  signature: this.signature
877
1117
  };
878
1118
  }
1119
+ toSerializable() {
1120
+ return {
1121
+ kind: 'thinking',
1122
+ data: {
1123
+ content: this._content,
1124
+ signature: this._signature
1125
+ }
1126
+ };
1127
+ }
879
1128
  }
880
1129
  exports.ThinkingChatResponseContentImpl = ThinkingChatResponseContentImpl;
881
1130
  class MarkdownChatResponseContentImpl {
@@ -904,6 +1153,12 @@ class MarkdownChatResponseContentImpl {
904
1153
  text: this.content.value
905
1154
  };
906
1155
  }
1156
+ toSerializable() {
1157
+ return {
1158
+ kind: 'markdownContent',
1159
+ data: { content: this._content.value }
1160
+ };
1161
+ }
907
1162
  }
908
1163
  exports.MarkdownChatResponseContentImpl = MarkdownChatResponseContentImpl;
909
1164
  class InformationalChatResponseContentImpl {
@@ -921,6 +1176,12 @@ class InformationalChatResponseContentImpl {
921
1176
  this._content.appendMarkdown(nextChatResponseContent.content.value);
922
1177
  return true;
923
1178
  }
1179
+ toSerializable() {
1180
+ return {
1181
+ kind: 'informational',
1182
+ data: { content: this._content.value }
1183
+ };
1184
+ }
924
1185
  }
925
1186
  exports.InformationalChatResponseContentImpl = InformationalChatResponseContentImpl;
926
1187
  class CodeChatResponseContentImpl {
@@ -947,6 +1208,16 @@ class CodeChatResponseContentImpl {
947
1208
  this._code += `${nextChatResponseContent.code}`;
948
1209
  return true;
949
1210
  }
1211
+ toSerializable() {
1212
+ return {
1213
+ kind: 'code',
1214
+ data: {
1215
+ code: this._code,
1216
+ language: this._language,
1217
+ location: this._location
1218
+ }
1219
+ };
1220
+ }
950
1221
  }
951
1222
  exports.CodeChatResponseContentImpl = CodeChatResponseContentImpl;
952
1223
  class ToolCallChatResponseContentImpl {
@@ -1058,6 +1329,18 @@ class ToolCallChatResponseContentImpl {
1058
1329
  name: (_d = this.name) !== null && _d !== void 0 ? _d : ''
1059
1330
  }];
1060
1331
  }
1332
+ toSerializable() {
1333
+ return {
1334
+ kind: 'toolCall',
1335
+ data: {
1336
+ id: this._id,
1337
+ name: this._name,
1338
+ arguments: this._arguments,
1339
+ finished: this._finished,
1340
+ result: this._result
1341
+ }
1342
+ };
1343
+ }
1061
1344
  }
1062
1345
  exports.ToolCallChatResponseContentImpl = ToolCallChatResponseContentImpl;
1063
1346
  exports.COMMAND_CHAT_RESPONSE_COMMAND = {
@@ -1078,6 +1361,17 @@ class CommandChatResponseContentImpl {
1078
1361
  var _a, _b;
1079
1362
  return ((_a = this.command) === null || _a === void 0 ? void 0 : _a.id) || ((_b = this.customCallback) === null || _b === void 0 ? void 0 : _b.label) || 'command';
1080
1363
  }
1364
+ toSerializable() {
1365
+ var _a, _b;
1366
+ return {
1367
+ kind: 'command',
1368
+ data: {
1369
+ commandId: (_a = this.command) === null || _a === void 0 ? void 0 : _a.id,
1370
+ commandLabel: (_b = this.customCallback) === null || _b === void 0 ? void 0 : _b.label,
1371
+ arguments: this.args
1372
+ }
1373
+ };
1374
+ }
1081
1375
  }
1082
1376
  exports.CommandChatResponseContentImpl = CommandChatResponseContentImpl;
1083
1377
  class HorizontalLayoutChatResponseContentImpl {
@@ -1103,22 +1397,52 @@ class HorizontalLayoutChatResponseContentImpl {
1103
1397
  }
1104
1398
  return true;
1105
1399
  }
1400
+ toSerializable() {
1401
+ return {
1402
+ kind: 'horizontal',
1403
+ data: {
1404
+ content: this._content.map(child => {
1405
+ var _a, _b, _c;
1406
+ const serialized = (_a = child.toSerializable) === null || _a === void 0 ? void 0 : _a.call(child);
1407
+ if (!serialized) {
1408
+ return {
1409
+ kind: child.kind,
1410
+ fallbackMessage: (_b = child.asString) === null || _b === void 0 ? void 0 : _b.call(child),
1411
+ data: undefined
1412
+ };
1413
+ }
1414
+ return {
1415
+ ...serialized,
1416
+ fallbackMessage: (_c = child.asString) === null || _c === void 0 ? void 0 : _c.call(child)
1417
+ };
1418
+ })
1419
+ }
1420
+ };
1421
+ }
1106
1422
  }
1107
1423
  exports.HorizontalLayoutChatResponseContentImpl = HorizontalLayoutChatResponseContentImpl;
1108
1424
  /**
1109
1425
  * Default implementation for the QuestionResponseContent.
1426
+ * Can be created with or without handler/request for read-only (restored) mode.
1110
1427
  */
1111
1428
  class QuestionResponseContentImpl {
1112
- constructor(question, options, request, handler) {
1429
+ constructor(question, options, request, handler, selectedOption) {
1113
1430
  this.question = question;
1114
1431
  this.options = options;
1115
1432
  this.request = request;
1116
1433
  this.handler = handler;
1117
1434
  this.kind = 'question';
1435
+ this._selectedOption = selectedOption;
1436
+ }
1437
+ get isReadOnly() {
1438
+ return !this.handler || !this.request;
1118
1439
  }
1119
1440
  set selectedOption(option) {
1120
1441
  this._selectedOption = option;
1121
- this.request.response.response.responseContentChanged();
1442
+ // Only trigger change notification if request is available (not in read-only mode)
1443
+ if (this.request) {
1444
+ this.request.response.response.responseContentChanged();
1445
+ }
1122
1446
  }
1123
1447
  get selectedOption() {
1124
1448
  return this._selectedOption;
@@ -1131,13 +1455,22 @@ ${this.selectedOption ? `Answer: ${(_a = this.selectedOption) === null || _a ===
1131
1455
  merge() {
1132
1456
  return false;
1133
1457
  }
1458
+ toSerializable() {
1459
+ return {
1460
+ kind: 'question',
1461
+ data: {
1462
+ question: this.question,
1463
+ options: this.options,
1464
+ selectedOption: this._selectedOption
1465
+ }
1466
+ };
1467
+ }
1134
1468
  }
1135
1469
  exports.QuestionResponseContentImpl = QuestionResponseContentImpl;
1136
1470
  class ChatResponseImpl {
1137
1471
  constructor() {
1138
1472
  this._onDidChangeEmitter = new core_1.Emitter();
1139
1473
  this.onDidChange = this._onDidChangeEmitter.event;
1140
- // TODO accept serialized data as a parameter to restore a previously saved ChatResponse
1141
1474
  this._content = [];
1142
1475
  }
1143
1476
  get content() {
@@ -1222,21 +1555,46 @@ class ChatResponseImpl {
1222
1555
  }
1223
1556
  }
1224
1557
  class MutableChatResponseModel {
1225
- constructor(requestId, agentId) {
1558
+ constructor(requestId, agentId, serializedData) {
1226
1559
  this._onDidChangeEmitter = new core_1.Emitter();
1227
1560
  this.onDidChange = this._onDidChangeEmitter.event;
1228
1561
  this.data = {};
1229
- // TODO accept serialized data as a parameter to restore a previously saved ChatResponseModel
1230
1562
  this._requestId = requestId;
1231
- this._id = (0, core_1.generateUuid)();
1232
- this._progressMessages = [];
1563
+ this._agentId = agentId;
1564
+ this._cancellationToken = new core_1.CancellationTokenSource();
1565
+ // Check if we're restoring from serialized data
1566
+ if (serializedData) {
1567
+ this.restoreFromSerializedData(serializedData);
1568
+ }
1569
+ else {
1570
+ // Normal creation path
1571
+ this._id = (0, core_1.generateUuid)();
1572
+ this._progressMessages = [];
1573
+ this._isComplete = false;
1574
+ this._isWaitingForInput = false;
1575
+ this._isError = false;
1576
+ }
1233
1577
  const response = new ChatResponseImpl();
1234
1578
  response.onDidChange(() => this._onDidChangeEmitter.fire());
1235
1579
  this._response = response;
1236
- this._isComplete = false;
1580
+ }
1581
+ /**
1582
+ * Restore this response model from serialized data
1583
+ */
1584
+ restoreFromSerializedData(data) {
1585
+ this._id = data.id;
1586
+ // Always mark restored responses as complete since there's no active agent
1587
+ this._isComplete = true;
1588
+ this._isError = data.isError;
1589
+ // Do not restore waitingForInput state - when a session is restored,
1590
+ // the agent that was waiting for input is no longer running
1237
1591
  this._isWaitingForInput = false;
1238
- this._agentId = agentId;
1239
- this._cancellationToken = new core_1.CancellationTokenSource();
1592
+ // TODO: Restore progressMessages?
1593
+ this._progressMessages = [];
1594
+ if (data.errorMessage) {
1595
+ this._errorObject = new Error(data.errorMessage);
1596
+ }
1597
+ // Note: Content restoration will be handled by ChatService using deserializer registry
1240
1598
  }
1241
1599
  get id() {
1242
1600
  return this._id;
@@ -1341,6 +1699,32 @@ class MutableChatResponseModel {
1341
1699
  get isError() {
1342
1700
  return this._isError;
1343
1701
  }
1702
+ toSerializable() {
1703
+ var _a;
1704
+ return {
1705
+ id: this.id,
1706
+ requestId: this.requestId,
1707
+ isComplete: this.isComplete,
1708
+ isError: this.isError,
1709
+ errorMessage: (_a = this.errorObject) === null || _a === void 0 ? void 0 : _a.message,
1710
+ content: this.response.content.map(c => {
1711
+ var _a, _b, _c;
1712
+ const serialized = (_a = c.toSerializable) === null || _a === void 0 ? void 0 : _a.call(c);
1713
+ if (!serialized) {
1714
+ // Fallback if toSerializable not implemented
1715
+ return {
1716
+ kind: c.kind,
1717
+ fallbackMessage: (_b = c.asString) === null || _b === void 0 ? void 0 : _b.call(c),
1718
+ data: undefined
1719
+ };
1720
+ }
1721
+ return {
1722
+ ...serialized,
1723
+ fallbackMessage: (_c = c.asString) === null || _c === void 0 ? void 0 : _c.call(c)
1724
+ };
1725
+ })
1726
+ };
1727
+ }
1344
1728
  }
1345
1729
  exports.MutableChatResponseModel = MutableChatResponseModel;
1346
1730
  class ErrorChatResponseModel extends MutableChatResponseModel {
@@ -1378,6 +1762,30 @@ class ProgressChatResponseContentImpl {
1378
1762
  text: this.message
1379
1763
  };
1380
1764
  }
1765
+ toSerializable() {
1766
+ return {
1767
+ kind: 'progress',
1768
+ data: { message: this._message }
1769
+ };
1770
+ }
1381
1771
  }
1382
1772
  exports.ProgressChatResponseContentImpl = ProgressChatResponseContentImpl;
1773
+ class UnknownChatResponseContentImpl {
1774
+ constructor(originalKind, fallbackMessage, data) {
1775
+ this.originalKind = originalKind;
1776
+ this.fallbackMessage = fallbackMessage;
1777
+ this.data = data;
1778
+ this.kind = 'unknown';
1779
+ }
1780
+ asString() {
1781
+ return this.fallbackMessage;
1782
+ }
1783
+ toSerializable() {
1784
+ return {
1785
+ kind: 'unknown',
1786
+ data: this.data
1787
+ };
1788
+ }
1789
+ }
1790
+ exports.UnknownChatResponseContentImpl = UnknownChatResponseContentImpl;
1383
1791
  //# sourceMappingURL=chat-model.js.map