@theia/ai-chat-ui 1.74.0-next.8 → 1.74.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-contribution.d.ts.map +1 -1
- package/lib/browser/ai-chat-ui-contribution.js +54 -31
- package/lib/browser/ai-chat-ui-contribution.js.map +1 -1
- package/lib/browser/ai-chat-ui-frontend-module.d.ts.map +1 -1
- package/lib/browser/ai-chat-ui-frontend-module.js +11 -3
- package/lib/browser/ai-chat-ui-frontend-module.js.map +1 -1
- package/lib/browser/chat-banner-provider.d.ts +20 -0
- package/lib/browser/chat-banner-provider.d.ts.map +1 -0
- package/lib/browser/chat-banner-provider.js +28 -0
- package/lib/browser/chat-banner-provider.js.map +1 -0
- package/lib/browser/chat-banner-widget.d.ts +20 -0
- package/lib/browser/chat-banner-widget.d.ts.map +1 -0
- package/lib/browser/chat-banner-widget.js +81 -0
- package/lib/browser/chat-banner-widget.js.map +1 -0
- package/lib/browser/chat-input-widget.d.ts +34 -15
- package/lib/browser/chat-input-widget.d.ts.map +1 -1
- package/lib/browser/chat-input-widget.js +166 -60
- package/lib/browser/chat-input-widget.js.map +1 -1
- package/lib/browser/chat-response-renderer/block-external-resources.d.ts +22 -0
- package/lib/browser/chat-response-renderer/block-external-resources.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/block-external-resources.js +331 -0
- package/lib/browser/chat-response-renderer/block-external-resources.js.map +1 -0
- package/lib/browser/chat-response-renderer/block-external-resources.spec.d.ts +2 -0
- package/lib/browser/chat-response-renderer/block-external-resources.spec.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/block-external-resources.spec.js +351 -0
- package/lib/browser/chat-response-renderer/block-external-resources.spec.js.map +1 -0
- package/lib/browser/chat-response-renderer/blocked-resource-placeholder.d.ts +7 -0
- package/lib/browser/chat-response-renderer/blocked-resource-placeholder.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/blocked-resource-placeholder.js +39 -0
- package/lib/browser/chat-response-renderer/blocked-resource-placeholder.js.map +1 -0
- package/lib/browser/chat-response-renderer/compaction-part-renderer.d.ts +8 -0
- package/lib/browser/chat-response-renderer/compaction-part-renderer.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/compaction-part-renderer.js +47 -0
- package/lib/browser/chat-response-renderer/compaction-part-renderer.js.map +1 -0
- package/lib/browser/chat-response-renderer/delegation-tool-renderer.js +1 -1
- package/lib/browser/chat-response-renderer/delegation-tool-renderer.js.map +1 -1
- package/lib/browser/chat-response-renderer/external-resource-allowlist-contribution.d.ts +11 -0
- package/lib/browser/chat-response-renderer/external-resource-allowlist-contribution.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/external-resource-allowlist-contribution.js +47 -0
- package/lib/browser/chat-response-renderer/external-resource-allowlist-contribution.js.map +1 -0
- package/lib/browser/chat-response-renderer/index.d.ts +1 -0
- package/lib/browser/chat-response-renderer/index.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/index.js +1 -0
- package/lib/browser/chat-response-renderer/index.js.map +1 -1
- package/lib/browser/chat-response-renderer/markdown-part-renderer.d.ts +4 -1
- package/lib/browser/chat-response-renderer/markdown-part-renderer.d.ts.map +1 -1
- package/lib/browser/chat-response-renderer/markdown-part-renderer.js +41 -10
- package/lib/browser/chat-response-renderer/markdown-part-renderer.js.map +1 -1
- package/lib/browser/chat-response-renderer/markdown-part-renderer.spec.d.ts +2 -0
- package/lib/browser/chat-response-renderer/markdown-part-renderer.spec.d.ts.map +1 -0
- package/lib/browser/chat-response-renderer/markdown-part-renderer.spec.js +167 -0
- package/lib/browser/chat-response-renderer/markdown-part-renderer.spec.js.map +1 -0
- package/lib/browser/chat-session-notification-contribution.d.ts +36 -0
- package/lib/browser/chat-session-notification-contribution.d.ts.map +1 -0
- package/lib/browser/chat-session-notification-contribution.js +128 -0
- package/lib/browser/chat-session-notification-contribution.js.map +1 -0
- package/lib/browser/chat-session-notification-contribution.spec.d.ts +2 -0
- package/lib/browser/chat-session-notification-contribution.spec.d.ts.map +1 -0
- package/lib/browser/chat-session-notification-contribution.spec.js +233 -0
- package/lib/browser/chat-session-notification-contribution.spec.js.map +1 -0
- package/lib/browser/chat-token-usage-indicator-util.d.ts +8 -1
- package/lib/browser/chat-token-usage-indicator-util.d.ts.map +1 -1
- package/lib/browser/chat-token-usage-indicator-util.js +50 -5
- package/lib/browser/chat-token-usage-indicator-util.js.map +1 -1
- package/lib/browser/chat-token-usage-indicator-util.spec.js +86 -2
- package/lib/browser/chat-token-usage-indicator-util.spec.js.map +1 -1
- package/lib/browser/chat-tree-view/chat-view-tree-widget.d.ts +12 -27
- package/lib/browser/chat-tree-view/chat-view-tree-widget.d.ts.map +1 -1
- package/lib/browser/chat-tree-view/chat-view-tree-widget.js +39 -127
- package/lib/browser/chat-tree-view/chat-view-tree-widget.js.map +1 -1
- package/lib/browser/chat-tree-view/chat-view-tree-widget.spec.d.ts +2 -0
- package/lib/browser/chat-tree-view/chat-view-tree-widget.spec.d.ts.map +1 -0
- package/lib/browser/chat-tree-view/chat-view-tree-widget.spec.js +83 -0
- package/lib/browser/chat-tree-view/chat-view-tree-widget.spec.js.map +1 -0
- package/lib/browser/chat-tree-view/model-badge.d.ts +13 -0
- package/lib/browser/chat-tree-view/model-badge.d.ts.map +1 -0
- package/lib/browser/chat-tree-view/model-badge.js +41 -0
- package/lib/browser/chat-tree-view/model-badge.js.map +1 -0
- package/lib/browser/chat-view-commands.d.ts +1 -0
- package/lib/browser/chat-view-commands.d.ts.map +1 -1
- package/lib/browser/chat-view-commands.js +6 -1
- package/lib/browser/chat-view-commands.js.map +1 -1
- package/lib/browser/chat-view-preferences.d.ts +2 -0
- package/lib/browser/chat-view-preferences.d.ts.map +1 -1
- package/lib/browser/chat-view-preferences.js +13 -1
- package/lib/browser/chat-view-preferences.js.map +1 -1
- package/lib/browser/chat-view-widget.d.ts +3 -1
- package/lib/browser/chat-view-widget.d.ts.map +1 -1
- package/lib/browser/chat-view-widget.js +8 -2
- package/lib/browser/chat-view-widget.js.map +1 -1
- package/lib/browser/session-settings-dialog.d.ts +5 -0
- package/lib/browser/session-settings-dialog.d.ts.map +1 -1
- package/lib/browser/session-settings-dialog.js +61 -2
- package/lib/browser/session-settings-dialog.js.map +1 -1
- package/package.json +13 -13
- package/src/browser/ai-chat-ui-contribution.ts +64 -36
- package/src/browser/ai-chat-ui-frontend-module.ts +12 -3
- package/src/browser/chat-banner-provider.ts +36 -0
- package/src/browser/chat-banner-widget.tsx +69 -0
- package/src/browser/chat-input-widget.tsx +222 -62
- package/src/browser/chat-response-renderer/block-external-resources.spec.ts +449 -0
- package/src/browser/chat-response-renderer/block-external-resources.ts +370 -0
- package/src/browser/chat-response-renderer/blocked-resource-placeholder.tsx +44 -0
- package/src/browser/chat-response-renderer/compaction-part-renderer.tsx +52 -0
- package/src/browser/chat-response-renderer/delegation-tool-renderer.tsx +1 -1
- package/src/browser/chat-response-renderer/external-resource-allowlist-contribution.ts +42 -0
- package/src/browser/chat-response-renderer/index.ts +1 -0
- package/src/browser/chat-response-renderer/markdown-part-renderer.spec.tsx +203 -0
- package/src/browser/chat-response-renderer/markdown-part-renderer.tsx +47 -10
- package/src/browser/chat-session-notification-contribution.spec.ts +314 -0
- package/src/browser/chat-session-notification-contribution.ts +132 -0
- package/src/browser/chat-token-usage-indicator-util.spec.ts +100 -2
- package/src/browser/chat-token-usage-indicator-util.ts +52 -5
- package/src/browser/chat-tree-view/chat-view-tree-widget.spec.tsx +117 -0
- package/src/browser/chat-tree-view/chat-view-tree-widget.tsx +53 -153
- package/src/browser/chat-tree-view/model-badge.tsx +52 -0
- package/src/browser/chat-view-commands.ts +6 -0
- package/src/browser/chat-view-preferences.ts +16 -0
- package/src/browser/chat-view-widget.tsx +6 -1
- package/src/browser/session-settings-dialog.tsx +140 -1
- package/src/browser/style/index.css +195 -34
- package/lib/browser/chat-input-needed-notification-contribution.d.ts +0 -28
- package/lib/browser/chat-input-needed-notification-contribution.d.ts.map +0 -1
- package/lib/browser/chat-input-needed-notification-contribution.js +0 -104
- package/lib/browser/chat-input-needed-notification-contribution.js.map +0 -1
- package/lib/browser/chat-input-needed-notification-contribution.spec.d.ts +0 -2
- package/lib/browser/chat-input-needed-notification-contribution.spec.d.ts.map +0 -1
- package/lib/browser/chat-input-needed-notification-contribution.spec.js +0 -171
- package/lib/browser/chat-input-needed-notification-contribution.spec.js.map +0 -1
- package/src/browser/chat-input-needed-notification-contribution.spec.ts +0 -223
- package/src/browser/chat-input-needed-notification-contribution.ts +0 -103
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// *****************************************************************************
|
|
3
|
+
// Copyright (C) 2026 EclipseSource GmbH.
|
|
4
|
+
//
|
|
5
|
+
// This program and the accompanying materials are made available under the
|
|
6
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
+
//
|
|
9
|
+
// This Source Code may also be made available under the following Secondary
|
|
10
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
+
// with the GNU Classpath Exception which is available at
|
|
13
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
|
+
// *****************************************************************************
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.ExternalResourceAllowlistContribution = void 0;
|
|
19
|
+
const tslib_1 = require("tslib");
|
|
20
|
+
const inversify_1 = require("@theia/core/shared/inversify");
|
|
21
|
+
const chat_view_preferences_1 = require("../chat-view-preferences");
|
|
22
|
+
const block_external_resources_1 = require("./block-external-resources");
|
|
23
|
+
/**
|
|
24
|
+
* Keeps the resource allowlist used by {@link blockExternalResources} in sync with the
|
|
25
|
+
* `ai-features.chat.allowedResourceUrls` preference.
|
|
26
|
+
*/
|
|
27
|
+
let ExternalResourceAllowlistContribution = class ExternalResourceAllowlistContribution {
|
|
28
|
+
onStart() {
|
|
29
|
+
this.preferences.ready.then(() => {
|
|
30
|
+
(0, block_external_resources_1.setAllowedResourceUrls)(this.preferences[chat_view_preferences_1.CHAT_VIEW_ALLOWED_RESOURCE_URLS] ?? []);
|
|
31
|
+
});
|
|
32
|
+
this.preferences.onPreferenceChanged(event => {
|
|
33
|
+
if (event.preferenceName === chat_view_preferences_1.CHAT_VIEW_ALLOWED_RESOURCE_URLS) {
|
|
34
|
+
(0, block_external_resources_1.setAllowedResourceUrls)(this.preferences[chat_view_preferences_1.CHAT_VIEW_ALLOWED_RESOURCE_URLS] ?? []);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
exports.ExternalResourceAllowlistContribution = ExternalResourceAllowlistContribution;
|
|
40
|
+
tslib_1.__decorate([
|
|
41
|
+
(0, inversify_1.inject)(chat_view_preferences_1.ChatViewPreferences),
|
|
42
|
+
tslib_1.__metadata("design:type", Object)
|
|
43
|
+
], ExternalResourceAllowlistContribution.prototype, "preferences", void 0);
|
|
44
|
+
exports.ExternalResourceAllowlistContribution = ExternalResourceAllowlistContribution = tslib_1.__decorate([
|
|
45
|
+
(0, inversify_1.injectable)()
|
|
46
|
+
], ExternalResourceAllowlistContribution);
|
|
47
|
+
//# sourceMappingURL=external-resource-allowlist-contribution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-resource-allowlist-contribution.js","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/external-resource-allowlist-contribution.ts"],"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;;;;AAGhF,4DAAkE;AAClE,oEAAgG;AAChG,yEAAoE;AAEpE;;;GAGG;AAEI,IAAM,qCAAqC,GAA3C,MAAM,qCAAqC;IAK9C,OAAO;QACH,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;YAC7B,IAAA,iDAAsB,EAAC,IAAI,CAAC,WAAW,CAAC,uDAA+B,CAAC,IAAI,EAAE,CAAC,CAAC;QACpF,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE;YACzC,IAAI,KAAK,CAAC,cAAc,KAAK,uDAA+B,EAAE,CAAC;gBAC3D,IAAA,iDAAsB,EAAC,IAAI,CAAC,WAAW,CAAC,uDAA+B,CAAC,IAAI,EAAE,CAAC,CAAC;YACpF,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC;CACJ,CAAA;AAfY,sFAAqC;AAG3B;IADlB,IAAA,kBAAM,EAAC,2CAAmB,CAAC;;0EACwB;gDAH3C,qCAAqC;IADjD,IAAA,sBAAU,GAAE;GACA,qCAAqC,CAejD"}
|
|
@@ -11,6 +11,7 @@ export * from './toolcall-part-renderer';
|
|
|
11
11
|
export * from './server-toolcall-part-renderer';
|
|
12
12
|
export * from './not-available-toolcall-renderer';
|
|
13
13
|
export * from './thinking-part-renderer';
|
|
14
|
+
export * from './compaction-part-renderer';
|
|
14
15
|
export * from './progress-part-renderer';
|
|
15
16
|
export * from './tool-confirmation';
|
|
16
17
|
export * from './delegation-tool-renderer';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/index.ts"],"names":[],"mappings":"AAeA,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/index.ts"],"names":[],"mappings":"AAeA,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC"}
|
|
@@ -29,6 +29,7 @@ tslib_1.__exportStar(require("./toolcall-part-renderer"), exports);
|
|
|
29
29
|
tslib_1.__exportStar(require("./server-toolcall-part-renderer"), exports);
|
|
30
30
|
tslib_1.__exportStar(require("./not-available-toolcall-renderer"), exports);
|
|
31
31
|
tslib_1.__exportStar(require("./thinking-part-renderer"), exports);
|
|
32
|
+
tslib_1.__exportStar(require("./compaction-part-renderer"), exports);
|
|
32
33
|
tslib_1.__exportStar(require("./progress-part-renderer"), exports);
|
|
33
34
|
tslib_1.__exportStar(require("./tool-confirmation"), exports);
|
|
34
35
|
tslib_1.__exportStar(require("./delegation-tool-renderer"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/index.ts"],"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,kEAAwC;AACxC,+DAAqC;AACrC,kEAAwC;AACxC,gEAAsC;AACtC,4EAAkD;AAClD,mEAAyC;AACzC,kEAAwC;AACxC,8DAAoC;AACpC,+DAAqC;AACrC,mEAAyC;AACzC,0EAAgD;AAChD,4EAAkD;AAClD,mEAAyC;AACzC,mEAAyC;AACzC,8DAAoC;AACpC,qEAA2C;AAC3C,gEAAsC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/index.ts"],"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,kEAAwC;AACxC,+DAAqC;AACrC,kEAAwC;AACxC,gEAAsC;AACtC,4EAAkD;AAClD,mEAAyC;AACzC,kEAAwC;AACxC,8DAAoC;AACpC,+DAAqC;AACrC,mEAAyC;AACzC,0EAAgD;AAChD,4EAAkD;AAClD,mEAAyC;AACzC,qEAA2C;AAC3C,mEAAyC;AACzC,8DAAoC;AACpC,qEAA2C;AAC3C,gEAAsC"}
|
|
@@ -39,7 +39,10 @@ export interface DeclaredEventsEventListenerObject extends EventListenerObject {
|
|
|
39
39
|
* @param eventHandler `handleEvent` will be called by default for `click` events and additionally
|
|
40
40
|
* for all events enumerated in {@link DeclaredEventsEventListenerObject.handledEvents}. If `handleEvent` returns `true`,
|
|
41
41
|
* no additional handlers will be run for the event.
|
|
42
|
+
* @param blockExternalResourceLoading whether external URL resources should be blocked until explicitly allowed (default: true).
|
|
43
|
+
* Trusted content authored by the user (e.g. their own chat requests) can pass `false` to render such resources directly.
|
|
44
|
+
* Active embedded content (iframes, frames, objects, embeds) is always blocked regardless of this flag.
|
|
42
45
|
* @returns the ref to use in an element to render the markdown
|
|
43
46
|
*/
|
|
44
|
-
export declare const useMarkdownRendering: (markdown: string | MarkdownString, openerService: OpenerService, skipSurroundingParagraph?: boolean, eventHandler?: DeclaredEventsEventListenerObject) => React.MutableRefObject<HTMLDivElement | null>;
|
|
47
|
+
export declare const useMarkdownRendering: (markdown: string | MarkdownString, openerService: OpenerService, skipSurroundingParagraph?: boolean, eventHandler?: DeclaredEventsEventListenerObject, blockExternalResourceLoading?: boolean) => React.MutableRefObject<HTMLDivElement | null>;
|
|
45
48
|
//# sourceMappingURL=markdown-part-renderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-part-renderer.d.ts","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/markdown-part-renderer.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE1E,OAAO,EACH,mBAAmB,EACnB,gCAAgC,EAChC,2BAA2B,EAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,SAAS,EAAqB,MAAM,0BAA0B,CAAC;AACxE,OAAO,KAAK,KAAK,MAAM,0BAA0B,CAAC;AAClD,OAAO,KAAK,UAAU,MAAM,gCAAgC,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAQ,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"markdown-part-renderer.d.ts","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/markdown-part-renderer.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAE1E,OAAO,EACH,mBAAmB,EACnB,gCAAgC,EAChC,2BAA2B,EAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,SAAS,EAAqB,MAAM,0BAA0B,CAAC;AACxE,OAAO,KAAK,KAAK,MAAM,0BAA0B,CAAC;AAClD,OAAO,KAAK,UAAU,MAAM,gCAAgC,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAQ,MAAM,yBAAyB,CAAC;AAU9D,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC;IAC9B,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAGxD,CAAC;AAEF,qBACa,oBAAqB,YAAW,wBAAwB,CAAC,2BAA2B,GAAG,gCAAgC,CAAC;IAC1G,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IACvE,SAAS,CAAC,QAAQ,CAAC,UAAU,aAA0C;IACvE,SAAS,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM;IAShD,MAAM,CAAC,QAAQ,EAAE,2BAA2B,GAAG,gCAAgC,GAAG,SAAS;CAU9F;AAED,MAAM,WAAW,iCAAkC,SAAQ,mBAAmB;IAC1E,aAAa,CAAC,EAAE,CAAC,MAAM,mBAAmB,CAAC,EAAE,CAAC;CACjD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,oBAAoB,GAC7B,UAAU,MAAM,GAAG,cAAc,EACjC,eAAe,aAAa,EAC5B,2BAA0B,OAAe,EACzC,eAAe,iCAAiC,EAChD,+BAA8B,OAAc,kDA0E/C,CAAC"}
|
|
@@ -26,6 +26,7 @@ const markdownitemoji = require("@theia/core/shared/markdown-it-emoji");
|
|
|
26
26
|
const DOMPurify = require("@theia/core/shared/dompurify");
|
|
27
27
|
const browser_1 = require("@theia/core/lib/browser");
|
|
28
28
|
const core_1 = require("@theia/core");
|
|
29
|
+
const block_external_resources_1 = require("./block-external-resources");
|
|
29
30
|
/**
|
|
30
31
|
* Renders the given markdown via {@link useMarkdownRendering} into a `<div>`.
|
|
31
32
|
* Shared component for use across chat response renderers.
|
|
@@ -81,38 +82,68 @@ exports.MarkdownPartRenderer = MarkdownPartRenderer = tslib_1.__decorate([
|
|
|
81
82
|
* @param eventHandler `handleEvent` will be called by default for `click` events and additionally
|
|
82
83
|
* for all events enumerated in {@link DeclaredEventsEventListenerObject.handledEvents}. If `handleEvent` returns `true`,
|
|
83
84
|
* no additional handlers will be run for the event.
|
|
85
|
+
* @param blockExternalResourceLoading whether external URL resources should be blocked until explicitly allowed (default: true).
|
|
86
|
+
* Trusted content authored by the user (e.g. their own chat requests) can pass `false` to render such resources directly.
|
|
87
|
+
* Active embedded content (iframes, frames, objects, embeds) is always blocked regardless of this flag.
|
|
84
88
|
* @returns the ref to use in an element to render the markdown
|
|
85
89
|
*/
|
|
86
|
-
const useMarkdownRendering = (markdown, openerService, skipSurroundingParagraph = false, eventHandler) => {
|
|
90
|
+
const useMarkdownRendering = (markdown, openerService, skipSurroundingParagraph = false, eventHandler, blockExternalResourceLoading = true) => {
|
|
87
91
|
// null is valid in React
|
|
88
92
|
// eslint-disable-next-line no-null/no-null
|
|
89
93
|
const ref = (0, react_1.useRef)(null);
|
|
90
94
|
const markdownString = typeof markdown === 'string' ? markdown : markdown.value;
|
|
91
95
|
(0, react_1.useEffect)(() => {
|
|
92
|
-
const markdownIt = markdownit().use(markdownitemoji.full);
|
|
96
|
+
const markdownIt = markdownit({ html: true }).use(markdownitemoji.full);
|
|
93
97
|
const host = document.createElement('div');
|
|
98
|
+
const template = document.createElement('template');
|
|
94
99
|
// markdownIt always puts the content in a paragraph element, so we remove it if we don't want that
|
|
95
100
|
const html = skipSurroundingParagraph ? markdownIt.render(markdownString).replace(/^<p>|<\/p>|<p><\/p>$/g, '') : markdownIt.render(markdownString);
|
|
96
|
-
|
|
101
|
+
template.innerHTML = DOMPurify.sanitize(html, {
|
|
97
102
|
// DOMPurify usually strips non http(s) links from hrefs
|
|
98
103
|
// but we want to allow them (see handleClick via OpenerService below)
|
|
99
|
-
ALLOW_UNKNOWN_PROTOCOLS: true
|
|
104
|
+
ALLOW_UNKNOWN_PROTOCOLS: true,
|
|
105
|
+
ADD_TAGS: ['iframe', 'frame'],
|
|
106
|
+
ADD_ATTR: ['src', 'srcset', 'srcdoc', 'poster', 'href', 'xlink:href', 'data']
|
|
100
107
|
});
|
|
108
|
+
// Active embedded content is always blocked; trusted content (blockExternalResourceLoading=false)
|
|
109
|
+
// still renders its external URL resources directly.
|
|
110
|
+
(0, block_external_resources_1.blockExternalResources)(template.content, blockExternalResourceLoading);
|
|
111
|
+
host.appendChild(template.content);
|
|
101
112
|
while (ref?.current?.firstChild) {
|
|
102
113
|
ref.current.removeChild(ref.current.firstChild);
|
|
103
114
|
}
|
|
104
115
|
ref?.current?.appendChild(host);
|
|
105
116
|
// intercept link clicks to use the Theia OpenerService instead of the default browser behavior
|
|
106
117
|
const handleClick = (event) => {
|
|
118
|
+
let target = event.target instanceof Element ? event.target : event.target instanceof Node ? event.target.parentElement : undefined;
|
|
119
|
+
const allowButton = target?.closest(`.${block_external_resources_1.BLOCKED_RESOURCE_ALLOW_CLASS}`);
|
|
120
|
+
if (allowButton) {
|
|
121
|
+
const placeholder = allowButton.closest(`.${block_external_resources_1.BLOCKED_RESOURCE_CLASS}`);
|
|
122
|
+
const restored = placeholder ? (0, block_external_resources_1.restoreBlockedResource)(placeholder) : undefined;
|
|
123
|
+
if (placeholder && restored) {
|
|
124
|
+
const wrapper = placeholder.parentElement?.classList.contains(block_external_resources_1.BLOCKED_RESOURCE_WRAPPER_CLASS)
|
|
125
|
+
? placeholder.parentElement
|
|
126
|
+
: undefined;
|
|
127
|
+
if (wrapper) {
|
|
128
|
+
wrapper.replaceWith(restored);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
placeholder.replaceWith(restored);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
event.preventDefault();
|
|
135
|
+
event.stopPropagation();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
107
138
|
if (eventHandler?.handleEvent(event) === true) {
|
|
108
139
|
return;
|
|
109
140
|
}
|
|
110
|
-
|
|
111
|
-
while (target && target.tagName !== 'A') {
|
|
112
|
-
target = target.parentElement;
|
|
141
|
+
// SVG anchors keep their lower-case tag name, so normalize before comparing
|
|
142
|
+
while (target && target.tagName.toUpperCase() !== 'A') {
|
|
143
|
+
target = target.parentElement ?? undefined;
|
|
113
144
|
}
|
|
114
|
-
if (target && target.tagName === 'A') {
|
|
115
|
-
const href = target.getAttribute('href');
|
|
145
|
+
if (target && target.tagName.toUpperCase() === 'A') {
|
|
146
|
+
const href = target.getAttribute('href') ?? target.getAttribute('xlink:href');
|
|
116
147
|
if (href) {
|
|
117
148
|
(0, browser_1.open)(openerService, new core_1.URI(href));
|
|
118
149
|
event.preventDefault();
|
|
@@ -125,7 +156,7 @@ const useMarkdownRendering = (markdown, openerService, skipSurroundingParagraph
|
|
|
125
156
|
ref.current?.removeEventListener('click', handleClick);
|
|
126
157
|
eventHandler?.handledEvents?.forEach(eventType => eventType !== 'click' && ref?.current?.removeEventListener(eventType, eventHandler));
|
|
127
158
|
};
|
|
128
|
-
}, [markdownString, skipSurroundingParagraph, openerService]);
|
|
159
|
+
}, [markdownString, skipSurroundingParagraph, openerService, blockExternalResourceLoading]);
|
|
129
160
|
return ref;
|
|
130
161
|
};
|
|
131
162
|
exports.useMarkdownRendering = useMarkdownRendering;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-part-renderer.js","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/markdown-part-renderer.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;;;;AAGhF,4DAAkE;AAClE,sDAImC;AACnC,oDAAwE;AACxE,kDAAkD;AAClD,6DAA6D;AAC7D,wEAAwE;AACxE,0DAA0D;AAE1D,qDAA8D;AAC9D,sCAAkC;
|
|
1
|
+
{"version":3,"file":"markdown-part-renderer.js","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/markdown-part-renderer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-part-renderer.spec.d.ts","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/markdown-part-renderer.spec.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// *****************************************************************************
|
|
3
|
+
// Copyright (C) 2026 EclipseSource GmbH.
|
|
4
|
+
//
|
|
5
|
+
// This program and the accompanying materials are made available under the
|
|
6
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
+
//
|
|
9
|
+
// This Source Code may also be made available under the following Secondary
|
|
10
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
+
// with the GNU Classpath Exception which is available at
|
|
13
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
|
+
// *****************************************************************************
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const jsdom_1 = require("@theia/core/lib/browser/test/jsdom");
|
|
19
|
+
let disableJSDOM = (0, jsdom_1.enableJSDOM)();
|
|
20
|
+
const chai_1 = require("chai");
|
|
21
|
+
const React = require("@theia/core/shared/react");
|
|
22
|
+
const client_1 = require("@theia/core/shared/react-dom/client");
|
|
23
|
+
const markdown_part_renderer_1 = require("./markdown-part-renderer");
|
|
24
|
+
const block_external_resources_1 = require("./block-external-resources");
|
|
25
|
+
disableJSDOM();
|
|
26
|
+
describe('useMarkdownRendering', () => {
|
|
27
|
+
let container;
|
|
28
|
+
let root;
|
|
29
|
+
const openerService = {
|
|
30
|
+
getOpener: async () => ({ open: async () => undefined }),
|
|
31
|
+
getOpeners: async () => [],
|
|
32
|
+
open: async () => undefined
|
|
33
|
+
};
|
|
34
|
+
const Markdown = ({ markdown, eventHandler }) => {
|
|
35
|
+
const ref = (0, markdown_part_renderer_1.useMarkdownRendering)(markdown, openerService, false, eventHandler);
|
|
36
|
+
return React.createElement("div", { ref: ref });
|
|
37
|
+
};
|
|
38
|
+
const TrustedMarkdown = ({ markdown }) => {
|
|
39
|
+
const ref = (0, markdown_part_renderer_1.useMarkdownRendering)(markdown, openerService, false, undefined, false);
|
|
40
|
+
return React.createElement("div", { ref: ref });
|
|
41
|
+
};
|
|
42
|
+
before(() => disableJSDOM = (0, jsdom_1.enableJSDOM)());
|
|
43
|
+
after(() => disableJSDOM());
|
|
44
|
+
beforeEach(() => {
|
|
45
|
+
container = document.createElement('div');
|
|
46
|
+
document.body.appendChild(container);
|
|
47
|
+
root = (0, client_1.createRoot)(container);
|
|
48
|
+
});
|
|
49
|
+
afterEach(() => {
|
|
50
|
+
root.unmount();
|
|
51
|
+
document.body.removeChild(container);
|
|
52
|
+
});
|
|
53
|
+
it('blocks external markdown images before they are mounted', done => {
|
|
54
|
+
root.render(React.createElement(Markdown, { markdown: "" }));
|
|
55
|
+
setTimeout(() => {
|
|
56
|
+
(0, chai_1.expect)(container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_CLASS}`)).to.exist;
|
|
57
|
+
(0, chai_1.expect)(container.querySelector('img')).to.be.null;
|
|
58
|
+
done();
|
|
59
|
+
}, 50);
|
|
60
|
+
});
|
|
61
|
+
it('allows a blocked resource after explicit user action', done => {
|
|
62
|
+
root.render(React.createElement(Markdown, { markdown: "" }));
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
const allow = container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_ALLOW_CLASS}`);
|
|
65
|
+
(0, chai_1.expect)(allow).to.exist;
|
|
66
|
+
allow.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
67
|
+
const image = container.querySelector('img');
|
|
68
|
+
(0, chai_1.expect)(container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_CLASS}`)).to.be.null;
|
|
69
|
+
(0, chai_1.expect)(image?.getAttribute('src')).to.equal('https://evil.com/x.gif');
|
|
70
|
+
done();
|
|
71
|
+
}, 50);
|
|
72
|
+
});
|
|
73
|
+
it('handles allow clicks before custom event handlers', done => {
|
|
74
|
+
let handled = false;
|
|
75
|
+
const eventHandler = {
|
|
76
|
+
handleEvent: () => {
|
|
77
|
+
handled = true;
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
root.render(React.createElement(Markdown, { markdown: "", eventHandler: eventHandler }));
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
const allow = container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_ALLOW_CLASS}`);
|
|
84
|
+
(0, chai_1.expect)(allow).to.exist;
|
|
85
|
+
allow.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
86
|
+
const image = container.querySelector('img');
|
|
87
|
+
(0, chai_1.expect)(handled).to.be.false;
|
|
88
|
+
(0, chai_1.expect)(container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_CLASS}`)).to.be.null;
|
|
89
|
+
(0, chai_1.expect)(image?.getAttribute('src')).to.equal('https://evil.com/x.gif');
|
|
90
|
+
done();
|
|
91
|
+
}, 50);
|
|
92
|
+
});
|
|
93
|
+
it('does not restore forged blocked-resource placeholders', done => {
|
|
94
|
+
const forgedPlaceholder = '<span class="theia-blocked-resource" data-blocked-html="<img src=x onerror=alert(1)>">'
|
|
95
|
+
+ '<button class="theia-blocked-resource-allow">Allow this resource</button></span>';
|
|
96
|
+
root.render(React.createElement(Markdown, { markdown: forgedPlaceholder }));
|
|
97
|
+
setTimeout(() => {
|
|
98
|
+
const allow = container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_ALLOW_CLASS}`);
|
|
99
|
+
(0, chai_1.expect)(allow).to.exist;
|
|
100
|
+
allow.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
101
|
+
(0, chai_1.expect)(container.querySelector('img')).to.be.null;
|
|
102
|
+
(0, chai_1.expect)(container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_CLASS}`)).to.exist;
|
|
103
|
+
done();
|
|
104
|
+
}, 50);
|
|
105
|
+
});
|
|
106
|
+
it('renders external resources directly when blocking is disabled', done => {
|
|
107
|
+
root.render(React.createElement(TrustedMarkdown, { markdown: "" }));
|
|
108
|
+
setTimeout(() => {
|
|
109
|
+
(0, chai_1.expect)(container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_CLASS}`)).to.be.null;
|
|
110
|
+
(0, chai_1.expect)(container.querySelector('img')?.getAttribute('src')).to.equal('https://evil.com/x.gif');
|
|
111
|
+
done();
|
|
112
|
+
}, 50);
|
|
113
|
+
});
|
|
114
|
+
it('shows blocked placeholders for iframe markdown', done => {
|
|
115
|
+
root.render(React.createElement(Markdown, { markdown: '<iframe src="https://evil.com"></iframe>' }));
|
|
116
|
+
setTimeout(() => {
|
|
117
|
+
const placeholder = container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_CLASS}`);
|
|
118
|
+
(0, chai_1.expect)(placeholder).to.exist;
|
|
119
|
+
(0, chai_1.expect)(placeholder?.textContent).to.contain('https://evil.com');
|
|
120
|
+
(0, chai_1.expect)(container.querySelector('iframe')).to.be.null;
|
|
121
|
+
done();
|
|
122
|
+
}, 50);
|
|
123
|
+
});
|
|
124
|
+
it('sandboxes allowed iframes with inline content', done => {
|
|
125
|
+
root.render(React.createElement(Markdown, { markdown: '<iframe srcdoc="<img src=x onerror=alert(1)>"></iframe>' }));
|
|
126
|
+
setTimeout(() => {
|
|
127
|
+
const allow = container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_ALLOW_CLASS}`);
|
|
128
|
+
(0, chai_1.expect)(allow).to.exist;
|
|
129
|
+
allow.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
130
|
+
const iframe = container.querySelector('iframe');
|
|
131
|
+
(0, chai_1.expect)(iframe).to.exist;
|
|
132
|
+
(0, chai_1.expect)(iframe?.getAttribute('sandbox')).to.equal('');
|
|
133
|
+
done();
|
|
134
|
+
}, 50);
|
|
135
|
+
});
|
|
136
|
+
it('shows blocked placeholders for SVG resource markdown', done => {
|
|
137
|
+
root.render(React.createElement(Markdown, { markdown: '<svg><image href="https://evil.com/x.png"></image></svg>' }));
|
|
138
|
+
setTimeout(() => {
|
|
139
|
+
const placeholder = container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_CLASS}`);
|
|
140
|
+
(0, chai_1.expect)(placeholder).to.exist;
|
|
141
|
+
(0, chai_1.expect)(placeholder?.textContent).to.contain('https://evil.com/x.png');
|
|
142
|
+
(0, chai_1.expect)(container.querySelector('image')).to.be.null;
|
|
143
|
+
done();
|
|
144
|
+
}, 50);
|
|
145
|
+
});
|
|
146
|
+
it('shows blocked placeholders for style sheets importing external CSS', done => {
|
|
147
|
+
root.render(React.createElement(Markdown, { markdown: 'some text\n\n<style>@import url("https://evil.com/main.css");</style>\n<div class="App">content</div>' }));
|
|
148
|
+
setTimeout(() => {
|
|
149
|
+
const placeholder = container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_CLASS}`);
|
|
150
|
+
(0, chai_1.expect)(placeholder).to.exist;
|
|
151
|
+
(0, chai_1.expect)(placeholder?.textContent).to.contain('https://evil.com/main.css');
|
|
152
|
+
(0, chai_1.expect)(container.querySelector('style')).to.be.null;
|
|
153
|
+
done();
|
|
154
|
+
}, 50);
|
|
155
|
+
});
|
|
156
|
+
it('shows blocked placeholders for SVG filter image markdown', done => {
|
|
157
|
+
root.render(React.createElement(Markdown, { markdown: '<svg><filter><feImage href="https://evil.com/filter.png"></feImage></filter></svg>' }));
|
|
158
|
+
setTimeout(() => {
|
|
159
|
+
const placeholder = container.querySelector(`.${block_external_resources_1.BLOCKED_RESOURCE_CLASS}`);
|
|
160
|
+
(0, chai_1.expect)(placeholder).to.exist;
|
|
161
|
+
(0, chai_1.expect)(placeholder?.textContent).to.contain('https://evil.com/filter.png');
|
|
162
|
+
(0, chai_1.expect)(container.querySelector('feImage')).to.be.null;
|
|
163
|
+
done();
|
|
164
|
+
}, 50);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
//# sourceMappingURL=markdown-part-renderer.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-part-renderer.spec.js","sourceRoot":"","sources":["../../../src/browser/chat-response-renderer/markdown-part-renderer.spec.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ChatService, ChatSession, ChatSessionStatus } from '@theia/ai-chat';
|
|
2
|
+
import { DisposableCollection } from '@theia/core';
|
|
3
|
+
import { ApplicationShell, FrontendApplicationContribution } from '@theia/core/lib/browser';
|
|
4
|
+
import { AgentNotificationKind } from '@theia/ai-core';
|
|
5
|
+
import { AgentNotificationService } from '@theia/ai-core/lib/browser';
|
|
6
|
+
interface SessionNotificationState {
|
|
7
|
+
/** Whether the session status required user action at the last observed status change. */
|
|
8
|
+
waiting: boolean;
|
|
9
|
+
/** Whether a request was in progress at the last observed status change. */
|
|
10
|
+
inProgress: boolean;
|
|
11
|
+
listener: DisposableCollection;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Fires agent notifications on chat session status transitions: when a session starts waiting
|
|
15
|
+
* for user action (a tool approval or another input) and when a session finishes its request
|
|
16
|
+
* (successfully or with an error). Watches all sessions, not just the active one, so that
|
|
17
|
+
* background sessions still reach the user.
|
|
18
|
+
*
|
|
19
|
+
* Delegated sessions (created by the agent delegation tool on behalf of a parent session) are
|
|
20
|
+
* excluded: their interactions bubble into the parent session's UI, so they must not produce
|
|
21
|
+
* their own notifications.
|
|
22
|
+
*/
|
|
23
|
+
export declare class ChatSessionNotificationContribution implements FrontendApplicationContribution {
|
|
24
|
+
protected readonly chatService: ChatService;
|
|
25
|
+
protected readonly notificationService: AgentNotificationService;
|
|
26
|
+
protected readonly shell: ApplicationShell;
|
|
27
|
+
protected readonly states: Map<string, SessionNotificationState>;
|
|
28
|
+
onStart(): void;
|
|
29
|
+
protected watchSession(session: ChatSession): void;
|
|
30
|
+
protected handleStatusChanged(session: ChatSession, state: SessionNotificationState, status: ChatSessionStatus): void;
|
|
31
|
+
protected isDelegatedSession(session: ChatSession): boolean;
|
|
32
|
+
protected notify(session: ChatSession, kind: AgentNotificationKind): void;
|
|
33
|
+
protected unwatchSession(sessionId: string): void;
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=chat-session-notification-contribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-session-notification-contribution.d.ts","sourceRoot":"","sources":["../../src/browser/chat-session-notification-contribution.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAmB,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC9F,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,+BAA+B,EAAE,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EAAE,qBAAqB,EAA2E,MAAM,gBAAgB,CAAC;AAChI,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAItE,UAAU,wBAAwB;IAC9B,0FAA0F;IAC1F,OAAO,EAAE,OAAO,CAAC;IACjB,4EAA4E;IAC5E,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,oBAAoB,CAAC;CAClC;AAED;;;;;;;;;GASG;AACH,qBACa,mCAAoC,YAAW,+BAA+B;IAGvF,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAG5C,SAAS,CAAC,QAAQ,CAAC,mBAAmB,EAAE,wBAAwB,CAAC;IAGjE,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IAE3C,SAAS,CAAC,QAAQ,CAAC,MAAM,wCAA+C;IAExE,OAAO,IAAI,IAAI;IAcf,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAiBlD,SAAS,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,wBAAwB,EAAE,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAoBrH,SAAS,CAAC,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO;IAI3D,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,qBAAqB,GAAG,IAAI;IAazE,SAAS,CAAC,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CAOpD"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// *****************************************************************************
|
|
3
|
+
// Copyright (C) 2026 EclipseSource GmbH.
|
|
4
|
+
//
|
|
5
|
+
// This program and the accompanying materials are made available under the
|
|
6
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
+
//
|
|
9
|
+
// This Source Code may also be made available under the following Secondary
|
|
10
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
+
// with the GNU Classpath Exception which is available at
|
|
13
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
|
+
// *****************************************************************************
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.ChatSessionNotificationContribution = void 0;
|
|
19
|
+
const tslib_1 = require("tslib");
|
|
20
|
+
const ai_chat_1 = require("@theia/ai-chat");
|
|
21
|
+
const core_1 = require("@theia/core");
|
|
22
|
+
const browser_1 = require("@theia/core/lib/browser");
|
|
23
|
+
const ai_core_1 = require("@theia/ai-core");
|
|
24
|
+
const browser_2 = require("@theia/ai-core/lib/browser");
|
|
25
|
+
const inversify_1 = require("@theia/core/shared/inversify");
|
|
26
|
+
const chat_session_focus_1 = require("./chat-session-focus");
|
|
27
|
+
/**
|
|
28
|
+
* Fires agent notifications on chat session status transitions: when a session starts waiting
|
|
29
|
+
* for user action (a tool approval or another input) and when a session finishes its request
|
|
30
|
+
* (successfully or with an error). Watches all sessions, not just the active one, so that
|
|
31
|
+
* background sessions still reach the user.
|
|
32
|
+
*
|
|
33
|
+
* Delegated sessions (created by the agent delegation tool on behalf of a parent session) are
|
|
34
|
+
* excluded: their interactions bubble into the parent session's UI, so they must not produce
|
|
35
|
+
* their own notifications.
|
|
36
|
+
*/
|
|
37
|
+
let ChatSessionNotificationContribution = class ChatSessionNotificationContribution {
|
|
38
|
+
constructor() {
|
|
39
|
+
this.states = new Map();
|
|
40
|
+
}
|
|
41
|
+
onStart() {
|
|
42
|
+
this.chatService.getSessions().forEach(session => this.watchSession(session));
|
|
43
|
+
this.chatService.onSessionEvent(event => {
|
|
44
|
+
if (event.type === 'created') {
|
|
45
|
+
const session = this.chatService.getSession(event.sessionId);
|
|
46
|
+
if (session) {
|
|
47
|
+
this.watchSession(session);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (event.type === 'deleted') {
|
|
51
|
+
this.unwatchSession(event.sessionId);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
watchSession(session) {
|
|
56
|
+
if (this.states.has(session.id)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const state = {
|
|
60
|
+
waiting: ai_chat_1.ChatSessionStatus.requiresUserAction(session.model.status),
|
|
61
|
+
inProgress: ai_chat_1.ChatSessionStatus.isInProgress(session.model.status),
|
|
62
|
+
listener: new core_1.DisposableCollection()
|
|
63
|
+
};
|
|
64
|
+
this.states.set(session.id, state);
|
|
65
|
+
session.model.onDidChange(event => {
|
|
66
|
+
if (ai_chat_1.ChatChangeEvent.isStatusChangedEvent(event)) {
|
|
67
|
+
this.handleStatusChanged(session, state, event.status);
|
|
68
|
+
}
|
|
69
|
+
}, undefined, state.listener);
|
|
70
|
+
}
|
|
71
|
+
handleStatusChanged(session, state, status) {
|
|
72
|
+
const nowWaiting = ai_chat_1.ChatSessionStatus.requiresUserAction(status);
|
|
73
|
+
const nowInProgress = ai_chat_1.ChatSessionStatus.isInProgress(status);
|
|
74
|
+
const startedWaiting = nowWaiting && !state.waiting;
|
|
75
|
+
const completed = !nowInProgress && state.inProgress;
|
|
76
|
+
state.waiting = nowWaiting;
|
|
77
|
+
state.inProgress = nowInProgress;
|
|
78
|
+
// We do not want to notify for delegated sessions
|
|
79
|
+
if (this.isDelegatedSession(session)) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (startedWaiting) {
|
|
83
|
+
this.notify(session, ai_core_1.AGENT_NOTIFICATION_KIND_INPUT_NEEDED);
|
|
84
|
+
}
|
|
85
|
+
else if (completed) {
|
|
86
|
+
this.notify(session, ai_core_1.AGENT_NOTIFICATION_KIND_COMPLETED);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
isDelegatedSession(session) {
|
|
90
|
+
return session.model.rootSessionId !== undefined;
|
|
91
|
+
}
|
|
92
|
+
notify(session, kind) {
|
|
93
|
+
// The session status is derived from the last request, so that is the one to report.
|
|
94
|
+
const lastRequest = session.model.getRequests().at(-1);
|
|
95
|
+
const agentId = lastRequest?.agentId ?? lastRequest?.response.agentId;
|
|
96
|
+
if (agentId) {
|
|
97
|
+
this.notificationService.showNotification(agentId, kind, {
|
|
98
|
+
shouldSuppress: () => (0, chat_session_focus_1.isChatSessionFocused)(this.shell, this.chatService, session.id),
|
|
99
|
+
onActivate: () => this.chatService.setActiveSession(session.id, { focus: true }),
|
|
100
|
+
sessionTitle: session.title
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
unwatchSession(sessionId) {
|
|
105
|
+
const state = this.states.get(sessionId);
|
|
106
|
+
if (state) {
|
|
107
|
+
state.listener.dispose();
|
|
108
|
+
this.states.delete(sessionId);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
exports.ChatSessionNotificationContribution = ChatSessionNotificationContribution;
|
|
113
|
+
tslib_1.__decorate([
|
|
114
|
+
(0, inversify_1.inject)(ai_chat_1.ChatService),
|
|
115
|
+
tslib_1.__metadata("design:type", Object)
|
|
116
|
+
], ChatSessionNotificationContribution.prototype, "chatService", void 0);
|
|
117
|
+
tslib_1.__decorate([
|
|
118
|
+
(0, inversify_1.inject)(browser_2.AgentNotificationService),
|
|
119
|
+
tslib_1.__metadata("design:type", browser_2.AgentNotificationService)
|
|
120
|
+
], ChatSessionNotificationContribution.prototype, "notificationService", void 0);
|
|
121
|
+
tslib_1.__decorate([
|
|
122
|
+
(0, inversify_1.inject)(browser_1.ApplicationShell),
|
|
123
|
+
tslib_1.__metadata("design:type", browser_1.ApplicationShell)
|
|
124
|
+
], ChatSessionNotificationContribution.prototype, "shell", void 0);
|
|
125
|
+
exports.ChatSessionNotificationContribution = ChatSessionNotificationContribution = tslib_1.__decorate([
|
|
126
|
+
(0, inversify_1.injectable)()
|
|
127
|
+
], ChatSessionNotificationContribution);
|
|
128
|
+
//# sourceMappingURL=chat-session-notification-contribution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-session-notification-contribution.js","sourceRoot":"","sources":["../../src/browser/chat-session-notification-contribution.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-session-notification-contribution.spec.d.ts","sourceRoot":"","sources":["../../src/browser/chat-session-notification-contribution.spec.ts"],"names":[],"mappings":"AAuBA,OAAO,kBAAkB,CAAC"}
|