@theia/ai-chat-ui 1.57.0 → 1.58.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-chat-ui-frontend-module.d.ts.map +1 -1
- package/lib/browser/ai-chat-ui-frontend-module.js +3 -0
- package/lib/browser/ai-chat-ui-frontend-module.js.map +1 -1
- package/lib/browser/chat-input-widget.d.ts +16 -6
- package/lib/browser/chat-input-widget.d.ts.map +1 -1
- package/lib/browser/chat-input-widget.js +203 -83
- package/lib/browser/chat-input-widget.js.map +1 -1
- package/lib/browser/chat-response-renderer/toolcall-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/toolcall-part-renderer.js +8 -2
- package/lib/browser/chat-response-renderer/toolcall-part-renderer.js.map +1 -1
- package/lib/browser/chat-view-language-contribution.d.ts.map +1 -1
- package/lib/browser/chat-view-language-contribution.js +0 -1
- package/lib/browser/chat-view-language-contribution.js.map +1 -1
- package/lib/browser/chat-view-widget.d.ts +2 -0
- package/lib/browser/chat-view-widget.d.ts.map +1 -1
- package/lib/browser/chat-view-widget.js +10 -4
- package/lib/browser/chat-view-widget.js.map +1 -1
- package/package.json +12 -12
- package/src/browser/ai-chat-ui-frontend-module.ts +4 -1
- package/src/browser/chat-input-widget.tsx +305 -103
- package/src/browser/chat-response-renderer/toolcall-part-renderer.tsx +8 -2
- package/src/browser/chat-view-language-contribution.ts +0 -1
- package/src/browser/chat-view-widget.tsx +13 -5
- package/src/browser/style/index.css +186 -22
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-view-widget.d.ts","sourceRoot":"","sources":["../../src/browser/chat-view-widget.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAE,cAAc,EAAa,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAe,gBAAgB,
|
|
1
|
+
{"version":3,"file":"chat-view-widget.d.ts","sourceRoot":"","sources":["../../src/browser/chat-view-widget.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAE,cAAc,EAAa,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAe,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACzF,OAAO,EAAE,UAAU,EAAW,iBAAiB,EAAE,OAAO,EAAe,iBAAiB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAG1I,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kDAAkD,CAAC;AAEvF,yBAAiB,cAAc,CAAC;IAC5B,UAAiB,KAAK;QAClB,MAAM,CAAC,EAAE,OAAO,CAAC;KACpB;CACJ;AAED,qBACa,cAAe,SAAQ,UAAW,YAAW,iBAAiB,EAAE,cAAc;IA6BnF,QAAQ,CAAC,UAAU,EAAE,kBAAkB;IAEvC,QAAQ,CAAC,WAAW,EAAE,iBAAiB;IA7B3C,OAAc,EAAE,SAAsB;IACtC,MAAM,CAAC,KAAK,SAAuD;IAGnE,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IAGnC,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC;IAGzC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAGxD,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IAGlD,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,mBAAmB,CAAC;IAE1D,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IAEnC,SAAS,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,CAAqB;IAC3D,SAAS,CAAC,QAAQ,CAAC,qBAAqB,gCAAuC;IAE/E,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;gBAIvB,UAAU,EAAE,kBAAkB,EAE9B,WAAW,EAAE,iBAAiB;IAa3C,SAAS,CAAC,IAAI,IAAI,IAAI;IAoCtB,SAAS,CAAC,aAAa,IAAI,IAAI;cAkBZ,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;IAKxD,UAAU,IAAI,MAAM;IAIpB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,IAAI;IAQpE,SAAS,KAAK,KAAK,IAAI,cAAc,CAAC,KAAK,CAE1C;IAED,SAAS,KAAK,KAAK,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,EAG9C;IAED,IAAI,cAAc,IAAI,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,CAEhD;cAEe,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBrD,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI;IAIxD,SAAS,CAAC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIpD,SAAS,CAAC,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAI1E,IAAI,IAAI,IAAI;IAIZ,MAAM,IAAI,IAAI;IAId,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,aAAa,IAAI,OAAO,CAE3B;CACJ"}
|
|
@@ -59,6 +59,8 @@ let ChatViewWidget = ChatViewWidget_1 = class ChatViewWidget extends browser_1.B
|
|
|
59
59
|
this.inputWidget.onQuery = this.onQuery.bind(this);
|
|
60
60
|
this.inputWidget.onCancel = this.onCancel.bind(this);
|
|
61
61
|
this.inputWidget.chatModel = this.chatSession.model;
|
|
62
|
+
this.inputWidget.onDeleteChangeSet = this.onDeleteChangeSet.bind(this);
|
|
63
|
+
this.inputWidget.onDeleteChangeSetElement = this.onDeleteChangeSetElement.bind(this);
|
|
62
64
|
this.treeWidget.trackChatModel(this.chatSession.model);
|
|
63
65
|
this.initListeners();
|
|
64
66
|
this.inputWidget.setEnabled(this.activationService.isActive);
|
|
@@ -120,7 +122,7 @@ let ChatViewWidget = ChatViewWidget_1 = class ChatViewWidget extends browser_1.B
|
|
|
120
122
|
requestProgress === null || requestProgress === void 0 ? void 0 : requestProgress.responseCompleted.then(responseModel => {
|
|
121
123
|
var _a, _b;
|
|
122
124
|
if (responseModel.isError) {
|
|
123
|
-
this.messageService.error((_b = (_a = responseModel.errorObject) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : 'An error occurred
|
|
125
|
+
this.messageService.error((_b = (_a = responseModel.errorObject) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : 'An error occurred during chat service invocation.');
|
|
124
126
|
}
|
|
125
127
|
});
|
|
126
128
|
if (!requestProgress) {
|
|
@@ -130,9 +132,13 @@ let ChatViewWidget = ChatViewWidget_1 = class ChatViewWidget extends browser_1.B
|
|
|
130
132
|
// Tree Widget currently tracks the ChatModel itself. Therefore no notification necessary.
|
|
131
133
|
}
|
|
132
134
|
onCancel(requestModel) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
135
|
+
this.chatService.cancelRequest(requestModel.session.id, requestModel.id);
|
|
136
|
+
}
|
|
137
|
+
onDeleteChangeSet(sessionId) {
|
|
138
|
+
this.chatService.deleteChangeSet(sessionId);
|
|
139
|
+
}
|
|
140
|
+
onDeleteChangeSetElement(sessionId, index) {
|
|
141
|
+
this.chatService.deleteChangeSetElement(sessionId, index);
|
|
136
142
|
}
|
|
137
143
|
lock() {
|
|
138
144
|
this.state = { ...(0, core_1.deepClone)(this.state), locked: true };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-view-widget.js","sourceRoot":"","sources":["../../src/browser/chat-view-widget.tsx"],"names":[],"mappings":";;;;;AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,sCAAwF;AACxF,
|
|
1
|
+
{"version":3,"file":"chat-view-widget.js","sourceRoot":"","sources":["../../src/browser/chat-view-widget.tsx"],"names":[],"mappings":";;;;;AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,sCAAwF;AACxF,4CAAyF;AACzF,qDAA0I;AAC1I,oDAAiD;AACjD,4DAAiF;AACjF,2DAAwD;AACxD,kFAA4E;AAC5E,4FAAuF;AAShF,IAAM,cAAc,sBAApB,MAAM,cAAe,SAAQ,oBAAU;IA2B1C,YAEI,UAAuC,EAEvC,WAAuC;QAEvC,KAAK,EAAE,CAAC;QAJC,eAAU,GAAV,UAAU,CAAoB;QAE9B,gBAAW,GAAX,WAAW,CAAmB;QATjC,WAAM,GAAyB,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QACxC,0BAAqB,GAAG,IAAI,cAAO,EAAwB,CAAC;QAW3E,IAAI,CAAC,EAAE,GAAG,gBAAc,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,gBAAc,CAAC,KAAK,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,gBAAc,CAAC,KAAK,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAA,iBAAO,EAAC,oBAAoB,CAAC,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;IAClB,CAAC;IAGS,IAAI;QACV,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;YACnB,IAAI,CAAC,UAAU;YACf,IAAI,CAAC,WAAW;YAChB,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE;gBAC3B,IAAI,CAAC,UAAU,CAAC,iBAAiB,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;gBACrD,IAAI,CAAC,MAAM,EAAE,CAAC;YAClB,CAAC,CAAC;SACL,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,qBAAW,EAAE,CAAC;QAE/C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QAC5D,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACzD,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC;QAEpD,IAAI,CAAC,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,WAAW,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QACpD,IAAI,CAAC,WAAW,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvE,IAAI,CAAC,WAAW,CAAC,wBAAwB,GAAG,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrF,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAEvD,IAAI,CAAC,aAAa,EAAE,CAAC;QAErB,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAC7D,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAE5D,IAAI,CAAC,iBAAiB,CAAC,uBAAuB,CAAC,MAAM,CAAC,EAAE;YACpD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACnC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,CAAC,MAAM,EAAE,CAAC;QAClB,CAAC,CAAC,CAAC;IACP,CAAC;IAES,aAAa;QACnB,IAAI,CAAC,SAAS,CAAC,IAAI,CACf,IAAI,CAAC,WAAW,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE;YAC5C,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC;YAClH,IAAI,OAAO,EAAE,CAAC;gBACV,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC;gBAC3B,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBACvD,IAAI,CAAC,WAAW,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;gBACpD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;oBACd,IAAI,CAAC,IAAI,EAAE,CAAC;gBAChB,CAAC;YACL,CAAC;iBAAM,CAAC;gBACJ,OAAO,CAAC,IAAI,CAAC,gBAAgB,KAAK,CAAC,SAAS,aAAa,CAAC,CAAC;YAC/D,CAAC;QACL,CAAC,CAAC,CACL,CAAC;IACN,CAAC;IAEkB,iBAAiB,CAAC,GAAY;QAC7C,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;IAChC,CAAC;IAED,UAAU;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,YAAY,CAAC,QAAgD;QACzD,MAAM,IAAI,GAAG,IAAA,gBAAS,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;QAClC,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,IAAc,KAAK;QACf,OAAO,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,IAAc,KAAK,CAAC,KAA2B;QAC3C,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,cAAc;QACd,OAAO,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC;IAC5C,CAAC;IAES,KAAK,CAAC,OAAO,CAAC,KAAa;QACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC;QAEnC,MAAM,WAAW,GAAgB;YAC7B,IAAI,EAAE,KAAK;SACd,CAAC;QAEF,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAC7F,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,iBAAiB,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE;;YACpD,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;gBACxB,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,MAAA,MAAA,aAAa,CAAC,WAAW,0CAAE,OAAO,mCAAI,mDAAmD,CAAC,CAAC;YACzH,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,eAAe,EAAE,CAAC;YACnB,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,iCAAiC,WAAW,CAAC,IAAI,gBAAgB,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;YAClH,OAAO;QACX,CAAC;QACD,0FAA0F;IAC9F,CAAC;IAES,QAAQ,CAAC,YAA8B;QAC7C,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC;IAC7E,CAAC;IAES,iBAAiB,CAAC,SAAiB;QACzC,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IAChD,CAAC;IAES,wBAAwB,CAAC,SAAiB,EAAE,KAAa;QAC/D,IAAI,CAAC,WAAW,CAAC,sBAAsB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI;QACA,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,IAAA,gBAAS,EAAC,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC5D,CAAC;IAED,MAAM;QACF,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,IAAA,gBAAS,EAAC,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC7D,CAAC;IAED,IAAI,QAAQ;QACR,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED,IAAI,aAAa;QACb,OAAO,IAAI,CAAC,eAAe,KAAK,SAAS,CAAC;IAC9C,CAAC;;AA9KQ,wCAAc;AAET,iBAAE,GAAG,kBAAkB,AAArB,CAAsB;AAC/B,oBAAK,GAAG,KAAK,SAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,iBAAiB,AAAtD,CAAuD;AAGzD;IADT,IAAA,kBAAM,EAAC,qBAAW,CAAC;;mDACe;AAGzB;IADT,IAAA,kBAAM,EAAC,qBAAc,CAAC;sCACG,qBAAc;sDAAC;AAGtB;IADlB,IAAA,kBAAM,EAAC,2BAAiB,CAAC;;yDAC8B;AAGrC;IADlB,IAAA,kBAAM,EAAC,qBAAc,CAAC;;sDAC2B;AAG/B;IADlB,IAAA,kBAAM,EAAC,2CAAmB,CAAC;sCACU,2CAAmB;yDAAC;AA0BhD;IADT,IAAA,yBAAa,GAAE;;;;0CAmCf;yBA9EQ,cAAc;IAD1B,IAAA,sBAAU,GAAE;IA6BJ,mBAAA,IAAA,kBAAM,EAAC,0CAAkB,CAAC,CAAA;IAE1B,mBAAA,IAAA,kBAAM,EAAC,qCAAiB,CAAC,CAAA;6CADL,0CAAkB;QAEjB,qCAAiB;GA/BlC,cAAc,CA+K1B"}
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theia/ai-chat-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.58.0",
|
|
4
4
|
"description": "Theia - AI Chat UI Extension",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@theia/ai-chat": "1.
|
|
7
|
-
"@theia/ai-core": "1.
|
|
8
|
-
"@theia/core": "1.
|
|
9
|
-
"@theia/editor": "1.
|
|
10
|
-
"@theia/editor-preview": "1.
|
|
11
|
-
"@theia/filesystem": "1.
|
|
12
|
-
"@theia/monaco": "1.
|
|
13
|
-
"@theia/monaco-editor-core": "1.
|
|
14
|
-
"@theia/workspace": "1.
|
|
6
|
+
"@theia/ai-chat": "1.58.0",
|
|
7
|
+
"@theia/ai-core": "1.58.0",
|
|
8
|
+
"@theia/core": "1.58.0",
|
|
9
|
+
"@theia/editor": "1.58.0",
|
|
10
|
+
"@theia/editor-preview": "1.58.0",
|
|
11
|
+
"@theia/filesystem": "1.58.0",
|
|
12
|
+
"@theia/monaco": "1.58.0",
|
|
13
|
+
"@theia/monaco-editor-core": "1.96.302",
|
|
14
|
+
"@theia/workspace": "1.58.0",
|
|
15
15
|
"minimatch": "^5.1.0",
|
|
16
16
|
"tslib": "^2.6.2",
|
|
17
17
|
"uuid": "^9.0.1"
|
|
@@ -50,10 +50,10 @@
|
|
|
50
50
|
"watch": "theiaext watch"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@theia/ext-scripts": "1.
|
|
53
|
+
"@theia/ext-scripts": "1.58.0"
|
|
54
54
|
},
|
|
55
55
|
"nyc": {
|
|
56
56
|
"extends": "../../configs/nyc.json"
|
|
57
57
|
},
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "6594f32b9727aea20d88934bf386dee06d08fa5e"
|
|
59
59
|
}
|
|
@@ -20,7 +20,7 @@ import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar
|
|
|
20
20
|
import { ContainerModule, interfaces } from '@theia/core/shared/inversify';
|
|
21
21
|
import { EditorManager } from '@theia/editor/lib/browser';
|
|
22
22
|
import { AIChatContribution } from './ai-chat-ui-contribution';
|
|
23
|
-
import { AIChatInputWidget } from './chat-input-widget';
|
|
23
|
+
import { AIChatInputConfiguration, AIChatInputWidget } from './chat-input-widget';
|
|
24
24
|
import { ChatNodeToolbarActionContribution } from './chat-node-toolbar-action-contribution';
|
|
25
25
|
import { ChatResponsePartRenderer } from './chat-response-part-renderer';
|
|
26
26
|
import {
|
|
@@ -60,6 +60,9 @@ export default new ContainerModule((bind, _unbind, _isBound, rebind) => {
|
|
|
60
60
|
bindChatViewWidget(bind);
|
|
61
61
|
|
|
62
62
|
bind(AIChatInputWidget).toSelf();
|
|
63
|
+
bind(AIChatInputConfiguration).toConstantValue({
|
|
64
|
+
showContext: false
|
|
65
|
+
});
|
|
63
66
|
bind(WidgetFactory).toDynamicValue(({ container }) => ({
|
|
64
67
|
id: AIChatInputWidget.ID,
|
|
65
68
|
createWidget: () => container.get(AIChatInputWidget)
|
|
@@ -13,28 +13,32 @@
|
|
|
13
13
|
//
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
|
-
import {
|
|
17
|
-
import { UntitledResourceResolver } from '@theia/core';
|
|
18
|
-
import { ContextMenuRenderer, Message, ReactWidget } from '@theia/core/lib/browser';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
16
|
+
import { ChangeSet, ChangeSetElement, ChatChangeEvent, ChatModel, ChatRequestModel } from '@theia/ai-chat';
|
|
17
|
+
import { Disposable, UntitledResourceResolver } from '@theia/core';
|
|
18
|
+
import { ContextMenuRenderer, LabelProvider, Message, ReactWidget } from '@theia/core/lib/browser';
|
|
19
|
+
import { Deferred } from '@theia/core/lib/common/promise-util';
|
|
20
|
+
import { inject, injectable, optional, postConstruct } from '@theia/core/shared/inversify';
|
|
21
21
|
import * as React from '@theia/core/shared/react';
|
|
22
|
+
import { IMouseEvent } from '@theia/monaco-editor-core';
|
|
23
|
+
import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
|
|
22
24
|
import { MonacoEditorProvider } from '@theia/monaco/lib/browser/monaco-editor-provider';
|
|
23
25
|
import { CHAT_VIEW_LANGUAGE_EXTENSION } from './chat-view-language-contribution';
|
|
24
|
-
import { IMouseEvent } from '@theia/monaco-editor-core';
|
|
25
|
-
import { Deferred } from '@theia/core/lib/common/promise-util';
|
|
26
26
|
|
|
27
27
|
type Query = (query: string) => Promise<void>;
|
|
28
28
|
type Cancel = (requestModel: ChatRequestModel) => void;
|
|
29
|
+
type DeleteChangeSet = (requestModel: ChatRequestModel) => void;
|
|
30
|
+
type DeleteChangeSetElement = (requestModel: ChatRequestModel, index: number) => void;
|
|
31
|
+
|
|
32
|
+
export const AIChatInputConfiguration = Symbol('AIChatInputConfiguration');
|
|
33
|
+
export interface AIChatInputConfiguration {
|
|
34
|
+
showContext?: boolean;
|
|
35
|
+
}
|
|
29
36
|
|
|
30
37
|
@injectable()
|
|
31
38
|
export class AIChatInputWidget extends ReactWidget {
|
|
32
39
|
public static ID = 'chat-input-widget';
|
|
33
40
|
static readonly CONTEXT_MENU = ['chat-input-context-menu'];
|
|
34
41
|
|
|
35
|
-
@inject(ChatAgentService)
|
|
36
|
-
protected readonly agentService: ChatAgentService;
|
|
37
|
-
|
|
38
42
|
@inject(MonacoEditorProvider)
|
|
39
43
|
protected readonly editorProvider: MonacoEditorProvider;
|
|
40
44
|
|
|
@@ -44,6 +48,12 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
44
48
|
@inject(ContextMenuRenderer)
|
|
45
49
|
protected readonly contextMenuRenderer: ContextMenuRenderer;
|
|
46
50
|
|
|
51
|
+
@inject(AIChatInputConfiguration) @optional()
|
|
52
|
+
protected readonly configuration: AIChatInputConfiguration | undefined;
|
|
53
|
+
|
|
54
|
+
@inject(LabelProvider)
|
|
55
|
+
protected readonly labelProvider: LabelProvider;
|
|
56
|
+
|
|
47
57
|
protected editorRef: MonacoEditor | undefined = undefined;
|
|
48
58
|
private editorReady = new Deferred<void>();
|
|
49
59
|
|
|
@@ -57,6 +67,14 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
57
67
|
set onCancel(cancel: Cancel) {
|
|
58
68
|
this._onCancel = cancel;
|
|
59
69
|
}
|
|
70
|
+
private _onDeleteChangeSet: DeleteChangeSet;
|
|
71
|
+
set onDeleteChangeSet(deleteChangeSet: DeleteChangeSet) {
|
|
72
|
+
this._onDeleteChangeSet = deleteChangeSet;
|
|
73
|
+
}
|
|
74
|
+
private _onDeleteChangeSetElement: DeleteChangeSetElement;
|
|
75
|
+
set onDeleteChangeSetElement(deleteChangeSetElement: DeleteChangeSetElement) {
|
|
76
|
+
this._onDeleteChangeSetElement = deleteChangeSetElement;
|
|
77
|
+
}
|
|
60
78
|
private _chatModel: ChatModel;
|
|
61
79
|
set chatModel(chatModel: ChatModel) {
|
|
62
80
|
this._chatModel = chatModel;
|
|
@@ -79,17 +97,14 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
79
97
|
});
|
|
80
98
|
}
|
|
81
99
|
|
|
82
|
-
protected getChatAgents(): ChatAgent[] {
|
|
83
|
-
return this.agentService.getAgents();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
100
|
protected render(): React.ReactNode {
|
|
87
101
|
return (
|
|
88
102
|
<ChatInput
|
|
89
103
|
onQuery={this._onQuery.bind(this)}
|
|
90
104
|
onCancel={this._onCancel.bind(this)}
|
|
105
|
+
onDeleteChangeSet={this._onDeleteChangeSet.bind(this)}
|
|
106
|
+
onDeleteChangeSetElement={this._onDeleteChangeSetElement.bind(this)}
|
|
91
107
|
chatModel={this._chatModel}
|
|
92
|
-
getChatAgents={this.getChatAgents.bind(this)}
|
|
93
108
|
editorProvider={this.editorProvider}
|
|
94
109
|
untitledResourceResolver={this.untitledResourceResolver}
|
|
95
110
|
contextMenuCallback={this.handleContextMenu.bind(this)}
|
|
@@ -98,6 +113,8 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
98
113
|
this.editorRef = editor;
|
|
99
114
|
this.editorReady.resolve();
|
|
100
115
|
}}
|
|
116
|
+
showContext={this.configuration?.showContext}
|
|
117
|
+
labelProvider={this.labelProvider}
|
|
101
118
|
/>
|
|
102
119
|
);
|
|
103
120
|
}
|
|
@@ -120,92 +137,102 @@ export class AIChatInputWidget extends ReactWidget {
|
|
|
120
137
|
interface ChatInputProperties {
|
|
121
138
|
onCancel: (requestModel: ChatRequestModel) => void;
|
|
122
139
|
onQuery: (query: string) => void;
|
|
140
|
+
onDeleteChangeSet: (sessionId: string) => void;
|
|
141
|
+
onDeleteChangeSetElement: (sessionId: string, index: number) => void;
|
|
123
142
|
isEnabled?: boolean;
|
|
124
143
|
chatModel: ChatModel;
|
|
125
|
-
getChatAgents: () => ChatAgent[];
|
|
126
144
|
editorProvider: MonacoEditorProvider;
|
|
127
145
|
untitledResourceResolver: UntitledResourceResolver;
|
|
128
146
|
contextMenuCallback: (event: IMouseEvent) => void;
|
|
129
147
|
setEditorRef: (editor: MonacoEditor | undefined) => void;
|
|
148
|
+
showContext?: boolean;
|
|
149
|
+
labelProvider: LabelProvider;
|
|
130
150
|
}
|
|
151
|
+
|
|
131
152
|
const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInputProperties) => {
|
|
153
|
+
const onDeleteChangeSet = () => props.onDeleteChangeSet(props.chatModel.id);
|
|
154
|
+
const onDeleteChangeSetElement = (index: number) => props.onDeleteChangeSetElement(props.chatModel.id, index);
|
|
132
155
|
|
|
133
156
|
const [inProgress, setInProgress] = React.useState(false);
|
|
157
|
+
const [isInputEmpty, setIsInputEmpty] = React.useState(true);
|
|
158
|
+
const [changeSetUI, setChangeSetUI] = React.useState(
|
|
159
|
+
() => props.chatModel.changeSet ? buildChangeSetUI(props.chatModel.changeSet, props.labelProvider, onDeleteChangeSet, onDeleteChangeSetElement) : undefined
|
|
160
|
+
);
|
|
161
|
+
|
|
134
162
|
// eslint-disable-next-line no-null/no-null
|
|
135
163
|
const editorContainerRef = React.useRef<HTMLDivElement | null>(null);
|
|
136
164
|
// eslint-disable-next-line no-null/no-null
|
|
137
165
|
const placeholderRef = React.useRef<HTMLDivElement | null>(null);
|
|
138
166
|
const editorRef = React.useRef<MonacoEditor | undefined>(undefined);
|
|
139
|
-
const allRequests = props.chatModel.getRequests();
|
|
140
|
-
const lastRequest = allRequests.length === 0 ? undefined : allRequests[allRequests.length - 1];
|
|
141
|
-
|
|
142
|
-
const createInputElement = async () => {
|
|
143
|
-
const paddingTop = 8;
|
|
144
|
-
const lineHeight = 20;
|
|
145
|
-
const maxHeight = 240;
|
|
146
|
-
const resource = await props.untitledResourceResolver.createUntitledResource('', CHAT_VIEW_LANGUAGE_EXTENSION);
|
|
147
|
-
const editor = await props.editorProvider.createInline(resource.uri, editorContainerRef.current!, {
|
|
148
|
-
language: CHAT_VIEW_LANGUAGE_EXTENSION,
|
|
149
|
-
// Disable code lens, inlay hints and hover support to avoid console errors from other contributions
|
|
150
|
-
codeLens: false,
|
|
151
|
-
inlayHints: { enabled: 'off' },
|
|
152
|
-
hover: { enabled: false },
|
|
153
|
-
autoSizing: false, // we handle the sizing ourselves
|
|
154
|
-
scrollBeyondLastLine: false,
|
|
155
|
-
scrollBeyondLastColumn: 0,
|
|
156
|
-
minHeight: 1,
|
|
157
|
-
fontFamily: 'var(--theia-ui-font-family)',
|
|
158
|
-
fontSize: 13,
|
|
159
|
-
cursorWidth: 1,
|
|
160
|
-
maxHeight: -1,
|
|
161
|
-
scrollbar: { horizontal: 'hidden' },
|
|
162
|
-
automaticLayout: true,
|
|
163
|
-
lineNumbers: 'off',
|
|
164
|
-
lineHeight,
|
|
165
|
-
padding: { top: paddingTop },
|
|
166
|
-
suggest: {
|
|
167
|
-
showIcons: true,
|
|
168
|
-
showSnippets: false,
|
|
169
|
-
showWords: false,
|
|
170
|
-
showStatusBar: false,
|
|
171
|
-
insertMode: 'replace',
|
|
172
|
-
},
|
|
173
|
-
bracketPairColorization: { enabled: false },
|
|
174
|
-
wrappingStrategy: 'advanced',
|
|
175
|
-
stickyScroll: { enabled: false },
|
|
176
|
-
});
|
|
177
167
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
168
|
+
React.useEffect(() => {
|
|
169
|
+
const createInputElement = async () => {
|
|
170
|
+
const paddingTop = 6;
|
|
171
|
+
const lineHeight = 20;
|
|
172
|
+
const maxHeight = 240;
|
|
173
|
+
const resource = await props.untitledResourceResolver.createUntitledResource('', CHAT_VIEW_LANGUAGE_EXTENSION);
|
|
174
|
+
const editor = await props.editorProvider.createInline(resource.uri, editorContainerRef.current!, {
|
|
175
|
+
language: CHAT_VIEW_LANGUAGE_EXTENSION,
|
|
176
|
+
// Disable code lens, inlay hints and hover support to avoid console errors from other contributions
|
|
177
|
+
codeLens: false,
|
|
178
|
+
inlayHints: { enabled: 'off' },
|
|
179
|
+
hover: { enabled: false },
|
|
180
|
+
autoSizing: false, // we handle the sizing ourselves
|
|
181
|
+
scrollBeyondLastLine: false,
|
|
182
|
+
scrollBeyondLastColumn: 0,
|
|
183
|
+
minHeight: 1,
|
|
184
|
+
fontFamily: 'var(--theia-ui-font-family)',
|
|
185
|
+
fontSize: 13,
|
|
186
|
+
cursorWidth: 1,
|
|
187
|
+
maxHeight: -1,
|
|
188
|
+
scrollbar: { horizontal: 'hidden' },
|
|
189
|
+
automaticLayout: true,
|
|
190
|
+
lineNumbers: 'off',
|
|
191
|
+
lineHeight,
|
|
192
|
+
padding: { top: paddingTop },
|
|
193
|
+
suggest: {
|
|
194
|
+
showIcons: true,
|
|
195
|
+
showSnippets: false,
|
|
196
|
+
showWords: false,
|
|
197
|
+
showStatusBar: false,
|
|
198
|
+
insertMode: 'replace',
|
|
199
|
+
},
|
|
200
|
+
bracketPairColorization: { enabled: false },
|
|
201
|
+
wrappingStrategy: 'advanced',
|
|
202
|
+
stickyScroll: { enabled: false },
|
|
203
|
+
});
|
|
181
204
|
|
|
182
|
-
const updateEditorHeight = () => {
|
|
183
205
|
if (editorContainerRef.current) {
|
|
184
|
-
|
|
185
|
-
editorContainerRef.current.style.height = `${Math.min(contentHeight, maxHeight)}px`;
|
|
206
|
+
editorContainerRef.current.style.height = (lineHeight + (2 * paddingTop)) + 'px';
|
|
186
207
|
}
|
|
187
|
-
};
|
|
188
|
-
editor.getControl().onDidChangeModelContent(() => {
|
|
189
|
-
updateEditorHeight();
|
|
190
|
-
handleOnChange();
|
|
191
|
-
});
|
|
192
|
-
const resizeObserver = new ResizeObserver(updateEditorHeight);
|
|
193
|
-
if (editorContainerRef.current) {
|
|
194
|
-
resizeObserver.observe(editorContainerRef.current);
|
|
195
|
-
}
|
|
196
|
-
editor.getControl().onDidDispose(() => {
|
|
197
|
-
resizeObserver.disconnect();
|
|
198
|
-
});
|
|
199
208
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
209
|
+
const updateEditorHeight = () => {
|
|
210
|
+
if (editorContainerRef.current) {
|
|
211
|
+
const contentHeight = editor.getControl().getContentHeight() + paddingTop;
|
|
212
|
+
editorContainerRef.current.style.height = `${Math.min(contentHeight, maxHeight)}px`;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
editor.getControl().onDidChangeModelContent(() => {
|
|
216
|
+
const value = editor.getControl().getValue();
|
|
217
|
+
setIsInputEmpty(!value || value.length === 0);
|
|
218
|
+
updateEditorHeight();
|
|
219
|
+
handleOnChange();
|
|
220
|
+
});
|
|
221
|
+
const resizeObserver = new ResizeObserver(updateEditorHeight);
|
|
222
|
+
if (editorContainerRef.current) {
|
|
223
|
+
resizeObserver.observe(editorContainerRef.current);
|
|
224
|
+
}
|
|
225
|
+
editor.getControl().onDidDispose(() => {
|
|
226
|
+
resizeObserver.disconnect();
|
|
227
|
+
});
|
|
203
228
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
229
|
+
editor.getControl().onContextMenu(e =>
|
|
230
|
+
props.contextMenuCallback(e.event)
|
|
231
|
+
);
|
|
207
232
|
|
|
208
|
-
|
|
233
|
+
editorRef.current = editor;
|
|
234
|
+
props.setEditorRef(editor);
|
|
235
|
+
};
|
|
209
236
|
createInputElement();
|
|
210
237
|
return () => {
|
|
211
238
|
props.setEditorRef(undefined);
|
|
@@ -215,16 +242,40 @@ const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInpu
|
|
|
215
242
|
};
|
|
216
243
|
}, []);
|
|
217
244
|
|
|
245
|
+
const responseListenerRef = React.useRef<Disposable>();
|
|
246
|
+
// track chat model updates to keep our UI in sync
|
|
247
|
+
// - keep "inProgress" in sync with the request state
|
|
248
|
+
// - keep "changeSetUI" in sync with the change set
|
|
218
249
|
React.useEffect(() => {
|
|
219
|
-
const listener =
|
|
220
|
-
if (
|
|
221
|
-
|
|
250
|
+
const listener = props.chatModel.onDidChange(event => {
|
|
251
|
+
if (event.kind === 'addRequest') {
|
|
252
|
+
if (event.request) {
|
|
253
|
+
setInProgress(ChatRequestModel.isInProgress(event.request));
|
|
254
|
+
}
|
|
255
|
+
responseListenerRef.current?.dispose();
|
|
256
|
+
responseListenerRef.current = event.request.response.onDidChange(() =>
|
|
257
|
+
setInProgress(ChatRequestModel.isInProgress(event.request))
|
|
258
|
+
);
|
|
259
|
+
} else if (ChatChangeEvent.isChangeSetEvent(event)) {
|
|
260
|
+
if (event.changeSet) {
|
|
261
|
+
setChangeSetUI(buildChangeSetUI(event.changeSet, props.labelProvider, onDeleteChangeSet, onDeleteChangeSetElement));
|
|
262
|
+
} else {
|
|
263
|
+
setChangeSetUI(undefined);
|
|
264
|
+
}
|
|
222
265
|
}
|
|
223
266
|
});
|
|
224
|
-
|
|
225
|
-
|
|
267
|
+
setChangeSetUI(props.chatModel.changeSet ? buildChangeSetUI(props.chatModel.changeSet, props.labelProvider, onDeleteChangeSet, onDeleteChangeSetElement) : undefined);
|
|
268
|
+
return () => {
|
|
269
|
+
listener?.dispose();
|
|
270
|
+
responseListenerRef.current?.dispose();
|
|
271
|
+
responseListenerRef.current = undefined;
|
|
272
|
+
};
|
|
273
|
+
}, [props.chatModel]);
|
|
226
274
|
|
|
227
275
|
function submit(value: string): void {
|
|
276
|
+
if (!value || value.trim().length === 0) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
228
279
|
setInProgress(true);
|
|
229
280
|
props.onQuery(value);
|
|
230
281
|
if (editorRef.current) {
|
|
@@ -268,30 +319,181 @@ const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInpu
|
|
|
268
319
|
}
|
|
269
320
|
};
|
|
270
321
|
|
|
322
|
+
const leftOptions = props.showContext ? [{
|
|
323
|
+
title: 'Attach elements to context',
|
|
324
|
+
handler: () => { /* TODO */ },
|
|
325
|
+
className: 'codicon-add'
|
|
326
|
+
}] : [];
|
|
327
|
+
|
|
328
|
+
const rightOptions = inProgress
|
|
329
|
+
? [{
|
|
330
|
+
title: 'Cancel (Esc)',
|
|
331
|
+
handler: () => {
|
|
332
|
+
const latestRequest = getLatestRequest(props.chatModel);
|
|
333
|
+
if (latestRequest) {
|
|
334
|
+
props.onCancel(latestRequest);
|
|
335
|
+
}
|
|
336
|
+
setInProgress(false);
|
|
337
|
+
},
|
|
338
|
+
className: 'codicon-stop-circle'
|
|
339
|
+
}]
|
|
340
|
+
: [{
|
|
341
|
+
title: 'Send (Enter)',
|
|
342
|
+
handler: () => {
|
|
343
|
+
if (props.isEnabled) {
|
|
344
|
+
submit(editorRef.current?.document.textEditorModel.getValue() || '');
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
className: 'codicon-send',
|
|
348
|
+
disabled: isInputEmpty || !props.isEnabled
|
|
349
|
+
}];
|
|
350
|
+
|
|
271
351
|
return <div className='theia-ChatInput'>
|
|
352
|
+
{changeSetUI?.elements &&
|
|
353
|
+
<ChangeSetBox changeSet={changeSetUI} />
|
|
354
|
+
}
|
|
272
355
|
<div className='theia-ChatInput-Editor-Box'>
|
|
273
356
|
<div className='theia-ChatInput-Editor' ref={editorContainerRef} onKeyDown={onKeyDown} onFocus={handleInputFocus} onBlur={handleInputBlur}>
|
|
274
357
|
<div ref={placeholderRef} className='theia-ChatInput-Editor-Placeholder'>Ask a question</div>
|
|
275
358
|
</div>
|
|
276
|
-
|
|
277
|
-
<div className="theia-ChatInputOptions">
|
|
278
|
-
{
|
|
279
|
-
inProgress ? <span
|
|
280
|
-
className="codicon codicon-stop-circle option"
|
|
281
|
-
title="Cancel (Esc)"
|
|
282
|
-
onClick={() => {
|
|
283
|
-
if (lastRequest) {
|
|
284
|
-
props.onCancel(lastRequest);
|
|
285
|
-
}
|
|
286
|
-
setInProgress(false);
|
|
287
|
-
}} /> :
|
|
288
|
-
<span
|
|
289
|
-
className="codicon codicon-send option"
|
|
290
|
-
title="Send (Enter)"
|
|
291
|
-
onClick={!props.isEnabled ? undefined : () => submit(editorRef.current?.document.textEditorModel.getValue() || '')}
|
|
292
|
-
style={{ cursor: !props.isEnabled ? 'default' : 'pointer', opacity: !props.isEnabled ? 0.5 : 1 }}
|
|
293
|
-
/>
|
|
294
|
-
}
|
|
359
|
+
<ChatInputOptions leftOptions={leftOptions} rightOptions={rightOptions} />
|
|
295
360
|
</div>
|
|
296
361
|
</div>;
|
|
297
362
|
};
|
|
363
|
+
|
|
364
|
+
const noPropagation = (handler: () => void) => (e: React.MouseEvent) => {
|
|
365
|
+
handler();
|
|
366
|
+
e.stopPropagation();
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
const buildChangeSetUI = (changeSet: ChangeSet, labelProvider: LabelProvider, onDeleteChangeSet: () => void, onDeleteChangeSetElement: (index: number) => void): ChangeSetUI => ({
|
|
370
|
+
title: changeSet.title,
|
|
371
|
+
disabled: !hasPendingElementsToAccept(changeSet),
|
|
372
|
+
acceptAllPendingElements: () => acceptAllPendingElements(changeSet),
|
|
373
|
+
delete: () => onDeleteChangeSet(),
|
|
374
|
+
elements: changeSet.getElements().map(element => ({
|
|
375
|
+
open: element?.open?.bind(element),
|
|
376
|
+
iconClass: element.icon ?? labelProvider.getIcon(element.uri) ?? labelProvider.fileIcon,
|
|
377
|
+
nameClass: `${element.type} ${element.state}`,
|
|
378
|
+
name: element.name ?? labelProvider.getName(element.uri),
|
|
379
|
+
additionalInfo: element.additionalInfo ?? labelProvider.getDetails(element.uri),
|
|
380
|
+
openChange: element?.openChange?.bind(element),
|
|
381
|
+
accept: element.state !== 'applied' ? element?.accept?.bind(element) : undefined,
|
|
382
|
+
discard: element.state === 'applied' ? element?.discard?.bind(element) : undefined,
|
|
383
|
+
delete: () => onDeleteChangeSetElement(changeSet.getElements().indexOf(element))
|
|
384
|
+
}))
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
interface ChangeSetUIElement {
|
|
388
|
+
name: string;
|
|
389
|
+
iconClass: string;
|
|
390
|
+
nameClass: string;
|
|
391
|
+
additionalInfo: string;
|
|
392
|
+
open?: () => void;
|
|
393
|
+
openChange?: () => void;
|
|
394
|
+
accept?: () => void;
|
|
395
|
+
discard?: () => void;
|
|
396
|
+
delete: () => void;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
interface ChangeSetUI {
|
|
400
|
+
title: string;
|
|
401
|
+
disabled: boolean;
|
|
402
|
+
acceptAllPendingElements: () => void;
|
|
403
|
+
delete: () => void;
|
|
404
|
+
elements: ChangeSetUIElement[];
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const ChangeSetBox: React.FunctionComponent<{ changeSet: ChangeSetUI }> = ({ changeSet }) => (
|
|
408
|
+
<div className='theia-ChatInput-ChangeSet-Box'>
|
|
409
|
+
<div className='theia-ChatInput-ChangeSet-Header'>
|
|
410
|
+
<h3>{changeSet.title}</h3>
|
|
411
|
+
<div className='theia-ChatInput-ChangeSet-Header-Actions'>
|
|
412
|
+
<button
|
|
413
|
+
className='theia-button'
|
|
414
|
+
disabled={changeSet.disabled}
|
|
415
|
+
title='Accept all pending changes'
|
|
416
|
+
onClick={() => changeSet.acceptAllPendingElements()}
|
|
417
|
+
>
|
|
418
|
+
Accept
|
|
419
|
+
</button>
|
|
420
|
+
<span className='codicon codicon-close action' title='Delete Change Set' onClick={() => changeSet.delete()} />
|
|
421
|
+
</div>
|
|
422
|
+
</div>
|
|
423
|
+
<div className='theia-ChatInput-ChangeSet-List'>
|
|
424
|
+
<ul>
|
|
425
|
+
{changeSet.elements.map((element, index) => (
|
|
426
|
+
<li key={index} title='Open Diff' onClick={() => element.openChange?.()}>
|
|
427
|
+
<div className={`theia-ChatInput-ChangeSet-Icon ${element.iconClass}`} />
|
|
428
|
+
<span className={`theia-ChatInput-ChangeSet-title ${element.nameClass}`}>
|
|
429
|
+
{element.name}
|
|
430
|
+
</span>
|
|
431
|
+
<span className='theia-ChatInput-ChangeSet-additionalInfo'>
|
|
432
|
+
{element.additionalInfo}
|
|
433
|
+
</span>
|
|
434
|
+
<div className='theia-ChatInput-ChangeSet-Actions'>
|
|
435
|
+
{element.open && (<span className='codicon codicon-file action' title='Open Original File' onClick={noPropagation(() => element.open!())} />)}
|
|
436
|
+
{element.discard && (<span className='codicon codicon-discard action' title='Undo' onClick={noPropagation(() => element.discard!())} />)}
|
|
437
|
+
{element.accept && (<span className='codicon codicon-check action' title='Accept' onClick={noPropagation(() => element.accept!())} />)}
|
|
438
|
+
<span className='codicon codicon-close action' title='Delete' onClick={noPropagation(() => element.delete())} />
|
|
439
|
+
</div>
|
|
440
|
+
</li>
|
|
441
|
+
))}
|
|
442
|
+
</ul>
|
|
443
|
+
</div>
|
|
444
|
+
</div>
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
interface ChatInputOptionsProps {
|
|
448
|
+
leftOptions: Option[];
|
|
449
|
+
rightOptions: Option[];
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
interface Option {
|
|
453
|
+
title: string;
|
|
454
|
+
handler: () => void;
|
|
455
|
+
className: string;
|
|
456
|
+
disabled?: boolean;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const ChatInputOptions: React.FunctionComponent<ChatInputOptionsProps> = ({ leftOptions, rightOptions }) => (
|
|
460
|
+
<div className="theia-ChatInputOptions">
|
|
461
|
+
<div className="theia-ChatInputOptions-left">
|
|
462
|
+
{leftOptions.map((option, index) => (
|
|
463
|
+
<span
|
|
464
|
+
key={index}
|
|
465
|
+
className={`codicon ${option.className} option ${option.disabled ? 'disabled' : ''}`}
|
|
466
|
+
title={option.title}
|
|
467
|
+
onClick={option.handler}
|
|
468
|
+
/>
|
|
469
|
+
))}
|
|
470
|
+
</div>
|
|
471
|
+
<div className="theia-ChatInputOptions-right">
|
|
472
|
+
{rightOptions.map((option, index) => (
|
|
473
|
+
<span
|
|
474
|
+
key={index}
|
|
475
|
+
className={`codicon ${option.className} option ${option.disabled ? 'disabled' : ''}`}
|
|
476
|
+
title={option.title}
|
|
477
|
+
onClick={option.handler}
|
|
478
|
+
/>
|
|
479
|
+
))}
|
|
480
|
+
</div>
|
|
481
|
+
</div>
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
function acceptAllPendingElements(changeSet: ChangeSet): void {
|
|
485
|
+
acceptablePendingElements(changeSet).forEach(e => e.accept!());
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
function hasPendingElementsToAccept(changeSet: ChangeSet): boolean | undefined {
|
|
489
|
+
return acceptablePendingElements(changeSet).length > 0;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function acceptablePendingElements(changeSet: ChangeSet): ChangeSetElement[] {
|
|
493
|
+
return changeSet.getElements().filter(e => e.accept && (e.state === undefined || e.state === 'pending'));
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function getLatestRequest(chatModel: ChatModel): ChatRequestModel | undefined {
|
|
497
|
+
const requests = chatModel.getRequests();
|
|
498
|
+
return requests.length > 0 ? requests[requests.length - 1] : undefined;
|
|
499
|
+
}
|