@theia/ai-chat 1.62.1 → 1.63.0-next.24

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-chat-frontend-module.d.ts.map +1 -1
  2. package/lib/browser/ai-chat-frontend-module.js +7 -1
  3. package/lib/browser/ai-chat-frontend-module.js.map +1 -1
  4. package/lib/browser/change-set-file-element.d.ts +9 -6
  5. package/lib/browser/change-set-file-element.d.ts.map +1 -1
  6. package/lib/browser/change-set-file-element.js +27 -14
  7. package/lib/browser/change-set-file-element.js.map +1 -1
  8. package/lib/browser/change-set-variable.js +1 -2
  9. package/lib/browser/change-set-variable.js.map +1 -1
  10. package/lib/browser/chat-tool-preferences.d.ts +54 -0
  11. package/lib/browser/chat-tool-preferences.d.ts.map +1 -0
  12. package/lib/browser/chat-tool-preferences.js +170 -0
  13. package/lib/browser/chat-tool-preferences.js.map +1 -0
  14. package/lib/browser/chat-tool-request-service.d.ts +20 -0
  15. package/lib/browser/chat-tool-request-service.d.ts.map +1 -0
  16. package/lib/browser/chat-tool-request-service.js +89 -0
  17. package/lib/browser/chat-tool-request-service.js.map +1 -0
  18. package/lib/browser/frontend-chat-service.d.ts.map +1 -1
  19. package/lib/browser/frontend-chat-service.js +2 -6
  20. package/lib/browser/frontend-chat-service.js.map +1 -1
  21. package/lib/common/change-set.d.ts +78 -0
  22. package/lib/common/change-set.d.ts.map +1 -0
  23. package/lib/common/change-set.js +133 -0
  24. package/lib/common/change-set.js.map +1 -0
  25. package/lib/common/chat-agents.d.ts.map +1 -1
  26. package/lib/common/chat-agents.js +4 -1
  27. package/lib/common/chat-agents.js.map +1 -1
  28. package/lib/common/chat-model.d.ts +68 -80
  29. package/lib/common/chat-model.d.ts.map +1 -1
  30. package/lib/common/chat-model.js +224 -136
  31. package/lib/common/chat-model.js.map +1 -1
  32. package/lib/common/chat-service.d.ts +3 -3
  33. package/lib/common/chat-service.d.ts.map +1 -1
  34. package/lib/common/chat-service.js +5 -8
  35. package/lib/common/chat-service.js.map +1 -1
  36. package/package.json +10 -10
  37. package/src/browser/ai-chat-frontend-module.ts +8 -1
  38. package/src/browser/change-set-file-element.ts +33 -21
  39. package/src/browser/change-set-variable.ts +1 -1
  40. package/src/browser/chat-tool-preferences.ts +178 -0
  41. package/src/browser/chat-tool-request-service.ts +93 -0
  42. package/src/browser/frontend-chat-service.ts +3 -6
  43. package/src/common/change-set.ts +197 -0
  44. package/src/common/chat-agents.ts +15 -11
  45. package/src/common/chat-model.ts +249 -207
  46. package/src/common/chat-service.ts +6 -9
@@ -20,16 +20,19 @@
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.ChangeSetImpl = exports.ChatRequestHierarchyBranchImpl = exports.ChatRequestHierarchyImpl = 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 = void 0;
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;
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");
27
27
  const vscode_languageserver_protocol_1 = require("@theia/core/shared/vscode-languageserver-protocol");
28
28
  const chat_agents_1 = require("./chat-agents");
29
+ const change_set_1 = require("./change-set");
30
+ Object.defineProperty(exports, "ChangeSetImpl", { enumerable: true, get: function () { return change_set_1.ChangeSetImpl; } });
31
+ const debounce = require("@theia/core/shared/lodash.debounce");
29
32
  var ChatChangeEvent;
30
33
  (function (ChatChangeEvent) {
31
34
  function isChangeSetEvent(event) {
32
- return event.kind === 'setChangeSet' || event.kind === 'removeChangeSet' || event.kind === 'updateChangeSet';
35
+ return event.kind === 'updateChangeSet';
33
36
  }
34
37
  ChatChangeEvent.isChangeSetEvent = isChangeSetEvent;
35
38
  })(ChatChangeEvent || (exports.ChatChangeEvent = ChatChangeEvent = {}));
@@ -252,16 +255,27 @@ class MutableChatModel {
252
255
  this._contextManager = new ChatContextManagerImpl();
253
256
  // TODO accept serialized data as a parameter to restore a previously saved ChatModel
254
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);
255
261
  this._id = (0, core_1.generateUuid)();
256
262
  this.toDispose.pushAll([
257
263
  this._onDidChangeEmitter,
258
- this._contextManager.onDidChange(e => this._onDidChangeEmitter.fire(e)),
259
- this._hierarchy.onDidChange(event => this._onDidChangeEmitter.fire({
260
- kind: 'changeHierarchyBranch',
261
- branch: event.branch,
262
- })),
264
+ this._contextManager.onDidChange(this._onDidChangeEmitter.fire, this._onDidChangeEmitter),
265
+ this._hierarchy.onDidChange(event => {
266
+ this._onDidChangeEmitter.fire({
267
+ kind: 'changeHierarchyBranch',
268
+ branch: event.branch,
269
+ });
270
+ }),
263
271
  ]);
264
272
  }
273
+ get id() {
274
+ return this._id;
275
+ }
276
+ get changeSet() {
277
+ return this._changeSet;
278
+ }
265
279
  getBranches() {
266
280
  return this._hierarchy.activeBranches();
267
281
  }
@@ -274,12 +288,6 @@ class MutableChatModel {
274
288
  getRequest(id) {
275
289
  return this.getRequests().find(request => request.id === id);
276
290
  }
277
- get id() {
278
- return this._id;
279
- }
280
- get changeSet() {
281
- return this._changeSet;
282
- }
283
291
  get suggestions() {
284
292
  return this._suggestions;
285
293
  }
@@ -292,49 +300,30 @@ class MutableChatModel {
292
300
  setSettings(settings) {
293
301
  this._settings = settings;
294
302
  }
295
- setChangeSet(changeSet) {
296
- if (!changeSet) {
297
- return this.removeChangeSet();
298
- }
299
- const oldChangeSet = this._changeSet;
300
- oldChangeSet === null || oldChangeSet === void 0 ? void 0 : oldChangeSet.dispose();
301
- this._changeSet = changeSet;
302
- this._onDidChangeEmitter.fire({
303
- kind: 'setChangeSet',
304
- changeSet,
305
- oldChangeSet,
306
- });
307
- changeSet.onDidChange(() => {
308
- this._onDidChangeEmitter.fire({
309
- kind: 'updateChangeSet',
310
- changeSet,
311
- });
312
- });
313
- }
314
- removeChangeSet() {
315
- if (this._changeSet) {
316
- const oldChangeSet = this._changeSet;
317
- this._changeSet = undefined;
318
- oldChangeSet.dispose();
319
- this._onDidChangeEmitter.fire({
320
- kind: 'removeChangeSet',
321
- changeSet: oldChangeSet,
322
- });
323
- }
324
- }
325
303
  addRequest(parsedChatRequest, agentId, context = { variables: [] }) {
326
- if (parsedChatRequest.request.referencedRequestId) {
327
- return this.applyEdit(parsedChatRequest, agentId, context);
328
- }
304
+ const add = this.getTargetForRequestAddition(parsedChatRequest);
329
305
  const requestModel = new MutableChatRequestModel(this, parsedChatRequest, agentId, context);
330
- this.toDispose.push(requestModel);
331
- this._hierarchy.append(requestModel);
306
+ requestModel.onDidChange(event => {
307
+ if (!ChatChangeEvent.isChangeSetEvent(event)) {
308
+ this._onDidChangeEmitter.fire(event);
309
+ }
310
+ }, this, this.toDispose);
311
+ add(requestModel);
312
+ this._changeSet.registerRequest(requestModel);
332
313
  this._onDidChangeEmitter.fire({
333
314
  kind: 'addRequest',
334
315
  request: requestModel,
335
316
  });
336
317
  return requestModel;
337
318
  }
319
+ getTargetForRequestAddition(request) {
320
+ const requestId = request.request.referencedRequestId;
321
+ const branch = requestId !== undefined && this._hierarchy.findBranch(requestId);
322
+ if (requestId !== undefined && !branch) {
323
+ throw new Error(`Cannot find branch for requestId: ${requestId}`);
324
+ }
325
+ return branch ? branch.add.bind(branch) : this._hierarchy.append.bind(this._hierarchy);
326
+ }
338
327
  setSuggestions(suggestions) {
339
328
  this._suggestions = Object.freeze(suggestions);
340
329
  this._onDidChangeEmitter.fire({
@@ -345,31 +334,127 @@ class MutableChatModel {
345
334
  isEmpty() {
346
335
  return this.getRequests().length === 0;
347
336
  }
348
- applyEdit(parsedChatRequest, agentId, context = { variables: [] }) {
349
- const requestId = parsedChatRequest.request.referencedRequestId;
350
- const branch = this._hierarchy.findBranch(requestId);
351
- if (!branch) {
352
- throw new Error(`Cannot find branch for requestId: ${requestId}`);
337
+ dispose() {
338
+ this.toDispose.dispose();
339
+ }
340
+ }
341
+ exports.MutableChatModel = MutableChatModel;
342
+ class ChatTreeChangeSet {
343
+ get onDidChange() {
344
+ return this.onDidChangeEmitter.event;
345
+ }
346
+ constructor(hierarchy) {
347
+ this.hierarchy = hierarchy;
348
+ this.onDidChangeEmitter = new core_1.Emitter();
349
+ this.toDispose = new core_1.DisposableCollection();
350
+ this.currentElements = [];
351
+ this.handleChangeSetChange = debounce(this.doHandleChangeSetChange.bind(this), 100, { leading: false, trailing: true });
352
+ this.toDisposeOnRequestAdded = new core_1.DisposableCollection();
353
+ hierarchy.onDidChange(this.handleChangeSetChange, this, this.toDispose);
354
+ }
355
+ get title() {
356
+ var _a, _b;
357
+ return (_b = (_a = this.getCurrentChangeSet()) === null || _a === void 0 ? void 0 : _a.title) !== null && _b !== void 0 ? _b : '';
358
+ }
359
+ removeElements(...uris) {
360
+ return this.getMutableChangeSet().removeElements(...uris);
361
+ }
362
+ addElements(...elements) {
363
+ return this.getMutableChangeSet().addElements(...elements);
364
+ }
365
+ setElements(...elements) {
366
+ this.getMutableChangeSet().setElements(...elements);
367
+ }
368
+ setTitle(title) {
369
+ this.getMutableChangeSet().setTitle(title);
370
+ }
371
+ getElementByURI(uri) {
372
+ return this.currentElements.find(candidate => candidate.uri.isEqual(uri));
373
+ }
374
+ doHandleChangeSetChange() {
375
+ var _a;
376
+ const newElements = this.computeChangeSetElements();
377
+ this.handleElementChange(newElements);
378
+ this.currentElements = newElements;
379
+ this.onDidChangeEmitter.fire({ kind: 'updateChangeSet', elements: this.currentElements, title: (_a = this.getCurrentChangeSet()) === null || _a === void 0 ? void 0 : _a.title });
380
+ }
381
+ getElements() {
382
+ return this.currentElements;
383
+ }
384
+ computeChangeSetElements() {
385
+ const allElements = change_set_1.ChangeSetImpl.combine((function* (requests) {
386
+ for (let i = requests.length - 1; i >= 0; i--) {
387
+ const changeSet = requests[i].changeSet;
388
+ if (changeSet) {
389
+ yield changeSet;
390
+ }
391
+ }
392
+ })(this.hierarchy.activeRequests()));
393
+ return core_1.ArrayUtils.coalesce(Array.from(allElements.values()));
394
+ }
395
+ handleElementChange(newElements) {
396
+ var _a, _b;
397
+ const old = new Set(this.currentElements);
398
+ for (const element of newElements) {
399
+ if (!old.delete(element)) {
400
+ (_a = element.onShow) === null || _a === void 0 ? void 0 : _a.call(element);
401
+ }
353
402
  }
354
- const requestModel = new MutableChatRequestModel(this, parsedChatRequest, agentId, context);
355
- this.toDispose.push(requestModel);
356
- branch.add(requestModel);
357
- this.removeChangeSet();
358
- this._onDidChangeEmitter.fire({
359
- kind: 'addRequest',
360
- request: requestModel,
361
- });
362
- return requestModel;
403
+ for (const element of old) {
404
+ (_b = element.onHide) === null || _b === void 0 ? void 0 : _b.call(element);
405
+ }
406
+ }
407
+ registerRequest(request) {
408
+ request.onDidChange(event => event.kind === 'updateChangeSet' && this.handleChangeSetChange(), this, this.toDispose);
409
+ if (this.localChangeSet) {
410
+ request.changeSet = this.localChangeSet;
411
+ this.localChangeSet = undefined;
412
+ }
413
+ this.toDisposeOnRequestAdded.dispose();
414
+ }
415
+ getMutableChangeSet() {
416
+ const tipRequest = this.hierarchy.activeRequests().at(-1);
417
+ const existingChangeSet = tipRequest === null || tipRequest === void 0 ? void 0 : tipRequest.changeSet;
418
+ if (existingChangeSet) {
419
+ return existingChangeSet;
420
+ }
421
+ if (this.localChangeSet && tipRequest) {
422
+ throw new Error('Non-empty chat model retained reference to own change set. This is unexpected!');
423
+ }
424
+ if (this.localChangeSet) {
425
+ return this.localChangeSet;
426
+ }
427
+ const newChangeSet = new change_set_1.ChangeSetImpl();
428
+ if (tipRequest) {
429
+ tipRequest.changeSet = newChangeSet;
430
+ }
431
+ else {
432
+ this.localChangeSet = newChangeSet;
433
+ newChangeSet.onDidChange(this.handleChangeSetChange, this, this.toDisposeOnRequestAdded);
434
+ }
435
+ return newChangeSet;
436
+ }
437
+ getCurrentChangeSet() {
438
+ var _a;
439
+ const holder = this.getBranchParent(candidate => !!candidate.get().changeSet);
440
+ return (_a = holder === null || holder === void 0 ? void 0 : holder.get().changeSet) !== null && _a !== void 0 ? _a : this.localChangeSet;
441
+ }
442
+ /** Returns the lowest node among active nodes that satisfies {@link criterion} */
443
+ getBranchParent(criterion) {
444
+ const branches = this.hierarchy.activeBranches();
445
+ for (let i = branches.length - 1; i >= 0; i--) {
446
+ const branch = branches[i];
447
+ if (criterion === null || criterion === void 0 ? void 0 : criterion(branch)) {
448
+ return branch;
449
+ }
450
+ }
451
+ return branches.at(0);
363
452
  }
364
453
  dispose() {
365
- this.removeChangeSet(); // Signal disposal of last change set.
366
454
  this.toDispose.dispose();
367
455
  }
368
- emit(event) {
369
- this._onDidChangeEmitter.fire(event);
370
- }
371
456
  }
372
- exports.MutableChatModel = MutableChatModel;
457
+ exports.ChatTreeChangeSet = ChatTreeChangeSet;
373
458
  class ChatRequestHierarchyImpl {
374
459
  constructor() {
375
460
  this.onDidChangeActiveBranchEmitter = new core_1.Emitter();
@@ -429,6 +514,10 @@ class ChatRequestHierarchyImpl {
429
514
  notifyChange(event) {
430
515
  this.onDidChangeActiveBranchEmitter.fire(event);
431
516
  }
517
+ dispose() {
518
+ this.onDidChangeActiveBranchEmitter.dispose();
519
+ this.branch.dispose();
520
+ }
432
521
  }
433
522
  exports.ChatRequestHierarchyImpl = ChatRequestHierarchyImpl;
434
523
  class ChatRequestHierarchyBranchImpl {
@@ -516,72 +605,14 @@ class ChatRequestHierarchyBranchImpl {
516
605
  }
517
606
  return branches;
518
607
  }
519
- }
520
- exports.ChatRequestHierarchyBranchImpl = ChatRequestHierarchyBranchImpl;
521
- class ChangeSetImpl {
522
- constructor(title, elements = []) {
523
- this.title = title;
524
- this._onDidChangeEmitter = new core_1.Emitter();
525
- this.onDidChange = this._onDidChangeEmitter.event;
526
- this._elements = [];
527
- this.addElements(...elements);
528
- }
529
- getElements() {
530
- return this._elements;
531
- }
532
- /**
533
- * Find an element by URI.
534
- * @param uri The URI to look for.
535
- * @returns The element with the given URI, or undefined if not found.
536
- */
537
- getElementByURI(uri) {
538
- const uriString = uri.toString();
539
- for (const element of this._elements) {
540
- if (element.uri.toString() === uriString) {
541
- return element;
542
- }
543
- }
544
- return undefined;
545
- }
546
- /** Will replace any element that is already present, using URI as identity criterion. */
547
- addElements(...elements) {
548
- const added = [];
549
- const modified = [];
550
- const toDispose = [];
551
- const current = new Map(this.getElements().map((element, index) => [element.uri.toString(), index]));
552
- elements.forEach(element => {
553
- var _a;
554
- const existingIndex = current.get(element.uri.toString());
555
- if (existingIndex !== undefined) {
556
- modified.push(element.uri);
557
- toDispose.push(this._elements[existingIndex]);
558
- this._elements[existingIndex] = element;
559
- }
560
- else {
561
- added.push(element.uri);
562
- this._elements.push(element);
563
- }
564
- (_a = element.onDidChange) === null || _a === void 0 ? void 0 : _a.call(element, () => this.notifyChange({ state: [element.uri] }));
565
- });
566
- toDispose.forEach(element => { var _a; return (_a = element.dispose) === null || _a === void 0 ? void 0 : _a.call(element); });
567
- this.notifyChange({ added, modified });
568
- }
569
- removeElements(...indices) {
570
- // From highest to lowest so that we don't affect lower indices with our splicing.
571
- const sorted = indices.slice().sort((left, right) => left - right);
572
- const deletions = sorted.flatMap(index => this._elements.splice(index, 1));
573
- deletions.forEach(deleted => { var _a; return (_a = deleted.dispose) === null || _a === void 0 ? void 0 : _a.call(deleted); });
574
- this.notifyChange({ removed: deletions.map(element => element.uri) });
575
- }
576
- notifyChange(change) {
577
- this._onDidChangeEmitter.fire(change);
578
- }
579
608
  dispose() {
580
- this._onDidChangeEmitter.dispose();
581
- this._elements.forEach(element => { var _a; return (_a = element.dispose) === null || _a === void 0 ? void 0 : _a.call(element); });
609
+ if (core_1.Disposable.is(this.get())) {
610
+ this.items.forEach(({ element }) => core_1.Disposable.is(element) && element.dispose());
611
+ }
612
+ this.items.length = 0;
582
613
  }
583
614
  }
584
- exports.ChangeSetImpl = ChangeSetImpl;
615
+ exports.ChatRequestHierarchyBranchImpl = ChatRequestHierarchyBranchImpl;
585
616
  class ChatContextManagerImpl {
586
617
  get onDidChange() {
587
618
  return this.onDidChangeEmitter.event;
@@ -641,6 +672,8 @@ exports.ChatContextManagerImpl = ChatContextManagerImpl;
641
672
  class MutableChatRequestModel {
642
673
  constructor(session, message, agentId, context = { variables: [] }, data = {}) {
643
674
  this.message = message;
675
+ this._onDidChangeEmitter = new core_1.Emitter();
676
+ this.onDidChange = this._onDidChangeEmitter.event;
644
677
  this._isEditing = false;
645
678
  this.toDispose = new core_1.DisposableCollection();
646
679
  // TODO accept serialized data as a parameter to restore a previously saved ChatRequestModel
@@ -652,9 +685,19 @@ class MutableChatRequestModel {
652
685
  this._agentId = agentId;
653
686
  this._data = data;
654
687
  this.editContextManager = new ChatContextManagerImpl(context);
655
- this.toDispose.pushAll([
656
- this.editContextManager.onDidChange(e => this.session.emit(e))
657
- ]);
688
+ this.editContextManager.onDidChange(this._onDidChangeEmitter.fire, this._onDidChangeEmitter, this.toDispose);
689
+ this.toDispose.push(this._onDidChangeEmitter);
690
+ }
691
+ get changeSet() {
692
+ return this._changeSet;
693
+ }
694
+ set changeSet(changeSet) {
695
+ var _a;
696
+ (_a = this._changeSet) === null || _a === void 0 ? void 0 : _a.dispose();
697
+ this._changeSet = changeSet;
698
+ this.toDispose.push(changeSet);
699
+ changeSet.onDidChange(() => this._onDidChangeEmitter.fire({ kind: 'updateChangeSet', elements: changeSet.getElements(), title: changeSet.title }), this, this.toDispose);
700
+ this._onDidChangeEmitter.fire({ kind: 'updateChangeSet', elements: changeSet.getElements(), title: changeSet.title });
658
701
  }
659
702
  get isEditing() {
660
703
  return this._isEditing;
@@ -727,7 +770,7 @@ class MutableChatRequestModel {
727
770
  if (!branch) {
728
771
  throw new Error(`Cannot find hierarchy for requestId: ${request.id}`);
729
772
  }
730
- this.session.emit({
773
+ this._onDidChangeEmitter.fire({
731
774
  kind: 'enableEdit',
732
775
  request,
733
776
  branch,
@@ -738,7 +781,7 @@ class MutableChatRequestModel {
738
781
  if (!branch) {
739
782
  throw new Error(`Cannot find branch for requestId: ${request.id}`);
740
783
  }
741
- this.session.emit({
784
+ this._onDidChangeEmitter.fire({
742
785
  kind: 'cancelEdit',
743
786
  request,
744
787
  branch,
@@ -749,7 +792,7 @@ class MutableChatRequestModel {
749
792
  if (!branch) {
750
793
  throw new Error(`Cannot find branch for requestId: ${request.id}`);
751
794
  }
752
- this.session.emit({
795
+ this._onDidChangeEmitter.fire({
753
796
  kind: 'submitEdit',
754
797
  request,
755
798
  branch,
@@ -914,6 +957,8 @@ class ToolCallChatResponseContentImpl {
914
957
  this._arguments = arg_string;
915
958
  this._finished = finished;
916
959
  this._result = result;
960
+ // Initialize the confirmation promise immediately
961
+ this._confirmed = this.createConfirmationPromise();
917
962
  }
918
963
  get id() {
919
964
  return this._id;
@@ -930,6 +975,48 @@ class ToolCallChatResponseContentImpl {
930
975
  get result() {
931
976
  return this._result;
932
977
  }
978
+ get confirmed() {
979
+ return this._confirmed;
980
+ }
981
+ /**
982
+ * Create a confirmation promise that can be resolved/rejected later
983
+ */
984
+ createConfirmationPromise() {
985
+ // The promise is always created, just ensure we have resolution handlers
986
+ if (!this._confirmationResolver) {
987
+ this._confirmed = new Promise((resolve, reject) => {
988
+ this._confirmationResolver = resolve;
989
+ this._confirmationRejecter = reject;
990
+ });
991
+ }
992
+ return this._confirmed;
993
+ }
994
+ /**
995
+ * Confirm the tool execution
996
+ */
997
+ confirm() {
998
+ if (this._confirmationResolver) {
999
+ this._confirmationResolver(true);
1000
+ }
1001
+ }
1002
+ /**
1003
+ * Deny the tool execution
1004
+ */
1005
+ deny() {
1006
+ if (this._confirmationResolver) {
1007
+ this._confirmationResolver(false);
1008
+ this._finished = true;
1009
+ this._result = 'Tool execution denied by user';
1010
+ }
1011
+ }
1012
+ /**
1013
+ * Cancel the confirmation (reject the promise)
1014
+ */
1015
+ cancelConfirmation(reason) {
1016
+ if (this._confirmationRejecter) {
1017
+ this._confirmationRejecter(reason);
1018
+ }
1019
+ }
933
1020
  asString() {
934
1021
  return '';
935
1022
  }
@@ -943,6 +1030,7 @@ class ToolCallChatResponseContentImpl {
943
1030
  this._result = nextChatResponseContent.result;
944
1031
  const args = nextChatResponseContent.arguments;
945
1032
  this._arguments = (args && args.length > 0) ? args : this._arguments;
1033
+ // Don't merge confirmation promises - they should be managed separately
946
1034
  return true;
947
1035
  }
948
1036
  if (nextChatResponseContent.name !== undefined) {