@theia/ai-scanoss 1.57.0-next.112

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/README.md ADDED
@@ -0,0 +1,34 @@
1
+ <div align='center'>
2
+
3
+ <br />
4
+
5
+ <img src='https://raw.githubusercontent.com/eclipse-theia/theia/master/logo/theia.svg?sanitize=true' alt='theia-ext-logo' width='100px' />
6
+
7
+ <h2>ECLIPSE THEIA - SCAN OSS AI EXTENSION</h2>
8
+
9
+ <hr />
10
+
11
+ </div>
12
+
13
+ ## Description
14
+
15
+ Integrates SCANOSS content scanning into the Chat View.
16
+ Whenever a code listing is rendered, a scan action is offered to the user.
17
+
18
+ Via the preferences the user can switch between manual and automatic scanning.
19
+
20
+ ## Additional Information
21
+
22
+ - [Theia - GitHub](https://github.com/eclipse-theia/theia)
23
+ - [Theia - Website](https://theia-ide.org/)
24
+ - [SCAN OSS Website](https://www.scanoss.com/)
25
+
26
+ ## License
27
+
28
+ - [Eclipse Public License 2.0](http://www.eclipse.org/legal/epl-2.0/)
29
+ - [一 (Secondary) GNU General Public License, version 2 with the GNU Classpath Exception](https://projects.eclipse.org/license/secondary-gpl-2.0-cp)
30
+
31
+ ## Trademark
32
+
33
+ "Theia" is a trademark of the Eclipse Foundation
34
+ <https://www.eclipse.org/theia>
@@ -0,0 +1,27 @@
1
+ /// <reference types="react" />
2
+ import { CodeChatResponseContent } from '@theia/ai-chat';
3
+ import { CodePartRendererAction } from '@theia/ai-chat-ui/lib/browser/chat-response-renderer';
4
+ import { ScanOSSResultMatch, ScanOSSService } from '@theia/scanoss';
5
+ import { PreferenceService } from '@theia/core/lib/browser';
6
+ import { ReactNode } from '@theia/core/shared/react';
7
+ import { ResponseNode } from '@theia/ai-chat-ui/lib/browser/chat-tree-view';
8
+ import * as React from '@theia/core/shared/react';
9
+ import { ReactDialog } from '@theia/core/lib/browser/dialogs/react-dialog';
10
+ export declare class ScanOSSScanButtonAction implements CodePartRendererAction {
11
+ protected readonly scanService: ScanOSSService;
12
+ protected readonly preferenceService: PreferenceService;
13
+ priority: number;
14
+ canRender(response: CodeChatResponseContent, parentNode: ResponseNode): boolean;
15
+ render(response: CodeChatResponseContent, parentNode: ResponseNode): ReactNode;
16
+ }
17
+ export declare class ScanOSSDialog extends ReactDialog<void> {
18
+ protected result: ScanOSSResultMatch;
19
+ protected readonly okButton: HTMLButtonElement;
20
+ constructor(result: ScanOSSResultMatch);
21
+ protected render(): React.ReactNode;
22
+ protected renderHeader(): React.ReactNode;
23
+ protected renderSummary(): React.ReactNode;
24
+ protected renderContent(): React.ReactNode;
25
+ get value(): undefined;
26
+ }
27
+ //# sourceMappingURL=ai-scanoss-code-scan-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-scanoss-code-scan-action.d.ts","sourceRoot":"","sources":["../../src/browser/ai-scanoss-code-scan-action.tsx"],"names":[],"mappings":";AAgBA,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sDAAsD,CAAC;AAC9F,OAAO,EAEH,kBAAkB,EAClB,cAAc,EACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAU,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,8CAA8C,CAAC;AAC5E,OAAO,KAAK,KAAK,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,8CAA8C,CAAC;AAiB3E,qBACa,uBAAwB,YAAW,sBAAsB;IAElE,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IAE/C,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAExD,QAAQ,SAAM;IAEd,SAAS,CAAC,QAAQ,EAAE,uBAAuB,EAAE,UAAU,EAAE,YAAY,GAAG,OAAO;IAkB/E,MAAM,CACF,QAAQ,EAAE,uBAAuB,EACjC,UAAU,EAAE,YAAY,GACzB,SAAS;CAcf;AAmFD,qBAAa,aAAc,SAAQ,WAAW,CAAC,IAAI,CAAC;IAGpC,SAAS,CAAC,MAAM,EAAE,kBAAkB;IAFhD,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;gBAEzB,MAAM,EAAE,kBAAkB;IAQhD,SAAS,CAAC,MAAM,IAAI,KAAK,CAAC,SAAS;IAUnC,SAAS,CAAC,YAAY,IAAI,KAAK,CAAC,SAAS;IAWzC,SAAS,CAAC,aAAa,IAAI,KAAK,CAAC,SAAS;IAc1C,SAAS,CAAC,aAAa,IAAI,KAAK,CAAC,SAAS;IAc1C,IAAI,KAAK,IAAI,SAAS,CAErB;CACJ"}
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScanOSSDialog = exports.ScanOSSScanButtonAction = void 0;
4
+ const tslib_1 = require("tslib");
5
+ // *****************************************************************************
6
+ // Copyright (C) 2024 EclipseSource GmbH.
7
+ //
8
+ // This program and the accompanying materials are made available under the
9
+ // terms of the Eclipse Public License v. 2.0 which is available at
10
+ // http://www.eclipse.org/legal/epl-2.0.
11
+ //
12
+ // This Source Code may also be made available under the following Secondary
13
+ // Licenses when the conditions for such availability set forth in the Eclipse
14
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
15
+ // with the GNU Classpath Exception which is available at
16
+ // https://www.gnu.org/software/classpath/license.html.
17
+ //
18
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
19
+ // ***
20
+ const inversify_1 = require("@theia/core/shared/inversify");
21
+ const scanoss_1 = require("@theia/scanoss");
22
+ const browser_1 = require("@theia/core/lib/browser");
23
+ const React = require("@theia/core/shared/react");
24
+ const react_dialog_1 = require("@theia/core/lib/browser/dialogs/react-dialog");
25
+ const scanoss_preferences_1 = require("@theia/scanoss/lib/browser/scanoss-preferences");
26
+ const ai_scanoss_preferences_1 = require("./ai-scanoss-preferences");
27
+ function hasScanOSSResults(data) {
28
+ return 'scanOSSResults' in data && data.scanOSSResults instanceof Map;
29
+ }
30
+ let ScanOSSScanButtonAction = class ScanOSSScanButtonAction {
31
+ constructor() {
32
+ this.priority = 30;
33
+ }
34
+ canRender(response, parentNode) {
35
+ if (!hasScanOSSResults(parentNode.response.data)) {
36
+ parentNode.response.data.scanOSSResults = new Map();
37
+ }
38
+ const results = parentNode.response.data
39
+ .scanOSSResults;
40
+ const scanOSSMode = this.preferenceService.get(ai_scanoss_preferences_1.SCANOSS_MODE_PREF, 'off');
41
+ // we mark the code for manual scanning in case it was not handled yet and the mode is manual or off.
42
+ // this prevents a possibly unexpected automatic scan of "old" snippets if automatic scan is later turned on.
43
+ if (results.get(response.code) === undefined && (scanOSSMode === 'off' || scanOSSMode === 'manual')) {
44
+ results.set(response.code, false);
45
+ }
46
+ return scanOSSMode !== 'off';
47
+ }
48
+ render(response, parentNode) {
49
+ const scanOSSResults = parentNode.response.data
50
+ .scanOSSResults;
51
+ return (React.createElement(ScanOSSIntegration, { key: 'scanoss', code: response.code, scanService: this.scanService, scanOSSResults: scanOSSResults, preferenceService: this.preferenceService }));
52
+ }
53
+ };
54
+ exports.ScanOSSScanButtonAction = ScanOSSScanButtonAction;
55
+ tslib_1.__decorate([
56
+ (0, inversify_1.inject)(scanoss_1.ScanOSSService),
57
+ tslib_1.__metadata("design:type", Object)
58
+ ], ScanOSSScanButtonAction.prototype, "scanService", void 0);
59
+ tslib_1.__decorate([
60
+ (0, inversify_1.inject)(browser_1.PreferenceService),
61
+ tslib_1.__metadata("design:type", Object)
62
+ ], ScanOSSScanButtonAction.prototype, "preferenceService", void 0);
63
+ exports.ScanOSSScanButtonAction = ScanOSSScanButtonAction = tslib_1.__decorate([
64
+ (0, inversify_1.injectable)()
65
+ ], ScanOSSScanButtonAction);
66
+ const ScanOSSIntegration = React.memo((props) => {
67
+ const [automaticCheck] = React.useState(() => props.preferenceService.get(ai_scanoss_preferences_1.SCANOSS_MODE_PREF, 'off') === 'automatic');
68
+ const [scanOSSResult, setScanOSSResult] = React.useState(props.scanOSSResults.get(props.code));
69
+ const scanCode = React.useCallback(async () => {
70
+ setScanOSSResult('pending');
71
+ const result = await props.scanService.scanContent(props.code, props.preferenceService.get(scanoss_preferences_1.SCAN_OSS_API_KEY_PREF, undefined));
72
+ setScanOSSResult(result);
73
+ props.scanOSSResults.set(props.code, result);
74
+ return result;
75
+ }, [props.code, props.scanService]);
76
+ React.useEffect(() => {
77
+ if (scanOSSResult === undefined) {
78
+ if (automaticCheck) {
79
+ scanCode();
80
+ }
81
+ else {
82
+ // sanity fallback. This codepath should already be handled via "canRender"
83
+ props.scanOSSResults.set(props.code, false);
84
+ }
85
+ }
86
+ }, []);
87
+ const scanOSSClicked = React.useCallback(async () => {
88
+ let scanResult = scanOSSResult;
89
+ if (scanResult === 'pending') {
90
+ return;
91
+ }
92
+ if (!scanResult || scanResult.type === 'error') {
93
+ scanResult = await scanCode();
94
+ }
95
+ if (scanResult && scanResult.type === 'match') {
96
+ const dialog = new ScanOSSDialog(scanResult);
97
+ dialog.open();
98
+ }
99
+ }, [scanOSSResult]);
100
+ let title = 'SCANOSS - Perform scan';
101
+ if (scanOSSResult) {
102
+ if (scanOSSResult === 'pending') {
103
+ title = 'SCANOSS - Performing scan...';
104
+ }
105
+ else if (scanOSSResult.type === 'error') {
106
+ title = `SCANOSS - Error - ${scanOSSResult.message}`;
107
+ }
108
+ else if (scanOSSResult.type === 'match') {
109
+ title = `SCANOSS - Found ${scanOSSResult.matched} match`;
110
+ }
111
+ else if (scanOSSResult.type === 'clean') {
112
+ title = 'SCANOSS - No match';
113
+ }
114
+ }
115
+ return (React.createElement(React.Fragment, null,
116
+ React.createElement("div", { className: `button scanoss-logo show-check icon-container ${scanOSSResult === 'pending'
117
+ ? 'pending'
118
+ : scanOSSResult
119
+ ? scanOSSResult.type
120
+ : ''}`, title: title, role: "button", onClick: scanOSSClicked },
121
+ React.createElement("div", { className: "codicon codicon-circle placeholder" }),
122
+ scanOSSResult && scanOSSResult !== 'pending' && (React.createElement("span", { className: "status-icon" },
123
+ scanOSSResult.type === 'clean' && React.createElement("span", { className: "codicon codicon-pass-filled" }),
124
+ scanOSSResult.type === 'match' && React.createElement("span", { className: "codicon codicon-warning" }),
125
+ scanOSSResult.type === 'error' && React.createElement("span", { className: "codicon codicon-error" }))))));
126
+ });
127
+ class ScanOSSDialog extends react_dialog_1.ReactDialog {
128
+ constructor(result) {
129
+ super({
130
+ title: 'SCANOSS Results',
131
+ });
132
+ this.result = result;
133
+ this.appendAcceptButton(browser_1.Dialog.OK);
134
+ this.update();
135
+ }
136
+ render() {
137
+ return (React.createElement("div", { className: "scanoss-dialog-container" },
138
+ this.renderHeader(),
139
+ this.renderSummary(),
140
+ this.renderContent()));
141
+ }
142
+ renderHeader() {
143
+ return (React.createElement("div", { className: "scanoss-header" },
144
+ React.createElement("div", { className: "scanoss-logo-container" },
145
+ React.createElement("div", { className: "scanoss-logo" }),
146
+ React.createElement("h2", null, "SCANOSS"))));
147
+ }
148
+ renderSummary() {
149
+ return (React.createElement("div", { className: "scanoss-summary" },
150
+ React.createElement("h3", null, "Summary"),
151
+ React.createElement("div", null,
152
+ "Found a ",
153
+ this.result.matched,
154
+ " match in",
155
+ ' ',
156
+ React.createElement("a", { href: this.result.url, target: "_blank", rel: "noopener noreferrer" }, this.result.url))));
157
+ }
158
+ renderContent() {
159
+ return (React.createElement("div", { className: "scanoss-details" },
160
+ React.createElement("h4", null, "Details"),
161
+ React.createElement("pre", null,
162
+ // eslint-disable-next-line no-null/no-null
163
+ JSON.stringify(this.result.raw, null, 2))));
164
+ }
165
+ get value() {
166
+ return undefined;
167
+ }
168
+ }
169
+ exports.ScanOSSDialog = ScanOSSDialog;
170
+ //# sourceMappingURL=ai-scanoss-code-scan-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-scanoss-code-scan-action.js","sourceRoot":"","sources":["../../src/browser/ai-scanoss-code-scan-action.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { ContainerModule } from '@theia/core/shared/inversify';
2
+ import '../../src/browser/style/index.css';
3
+ declare const _default: ContainerModule;
4
+ export default _default;
5
+ //# sourceMappingURL=ai-scanoss-frontend-module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-scanoss-frontend-module.d.ts","sourceRoot":"","sources":["../../src/browser/ai-scanoss-frontend-module.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAK/D,OAAO,mCAAmC,CAAC;;AAE3C,wBAIG"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2024 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 inversify_1 = require("@theia/core/shared/inversify");
19
+ const ai_scanoss_preferences_1 = require("./ai-scanoss-preferences");
20
+ const browser_1 = require("@theia/core/lib/browser");
21
+ const ai_scanoss_code_scan_action_1 = require("./ai-scanoss-code-scan-action");
22
+ const chat_response_renderer_1 = require("@theia/ai-chat-ui/lib/browser/chat-response-renderer");
23
+ require("../../src/browser/style/index.css");
24
+ exports.default = new inversify_1.ContainerModule(bind => {
25
+ bind(browser_1.PreferenceContribution).toConstantValue({ schema: ai_scanoss_preferences_1.AIScanOSSPreferencesSchema });
26
+ bind(ai_scanoss_code_scan_action_1.ScanOSSScanButtonAction).toSelf().inSingletonScope();
27
+ bind(chat_response_renderer_1.CodePartRendererAction).toService(ai_scanoss_code_scan_action_1.ScanOSSScanButtonAction);
28
+ });
29
+ //# sourceMappingURL=ai-scanoss-frontend-module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-scanoss-frontend-module.js","sourceRoot":"","sources":["../../src/browser/ai-scanoss-frontend-module.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;;AAEhF,4DAA+D;AAC/D,qEAAsE;AACtE,qDAAiE;AACjE,+EAAwE;AACxE,iGAA8F;AAC9F,6CAA2C;AAE3C,kBAAe,IAAI,2BAAe,CAAC,IAAI,CAAC,EAAE;IACtC,IAAI,CAAC,gCAAsB,CAAC,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,mDAA0B,EAAE,CAAC,CAAC;IACrF,IAAI,CAAC,qDAAuB,CAAC,CAAC,MAAM,EAAE,CAAC,gBAAgB,EAAE,CAAC;IAC1D,IAAI,CAAC,+CAAsB,CAAC,CAAC,SAAS,CAAC,qDAAuB,CAAC,CAAC;AACpE,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { PreferenceSchema } from '@theia/core/lib/browser/preferences';
2
+ export declare const SCANOSS_MODE_PREF = "ai-features.SCANOSS.mode";
3
+ export declare const AIScanOSSPreferencesSchema: PreferenceSchema;
4
+ //# sourceMappingURL=ai-scanoss-preferences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-scanoss-preferences.d.ts","sourceRoot":"","sources":["../../src/browser/ai-scanoss-preferences.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAGvE,eAAO,MAAM,iBAAiB,6BAA6B,CAAC;AAE5D,eAAO,MAAM,0BAA0B,EAAE,gBAiBxC,CAAC"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2024 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.AIScanOSSPreferencesSchema = exports.SCANOSS_MODE_PREF = void 0;
19
+ const ai_core_preferences_1 = require("@theia/ai-core/lib/browser/ai-core-preferences");
20
+ exports.SCANOSS_MODE_PREF = 'ai-features.SCANOSS.mode';
21
+ exports.AIScanOSSPreferencesSchema = {
22
+ type: 'object',
23
+ properties: {
24
+ [exports.SCANOSS_MODE_PREF]: {
25
+ type: 'string',
26
+ enum: ['off', 'manual', 'automatic'],
27
+ markdownEnumDescriptions: [
28
+ 'Feature is turned off completely.',
29
+ 'User can manually trigger the scan by clicking the SCANOSS item in the chat view.',
30
+ 'Enable automatic scan of code snippets in chat views.'
31
+ ],
32
+ markdownDescription: 'Configure the SCANOSS feature for analyzing code snippets in chat views. This will send a hash of suggested code snippets to the SCANOSS\n\
33
+ service hosted by the [Software Transparency foundation](https://www.softwaretransparency.org/osskb) for analysis.',
34
+ default: 'off',
35
+ title: ai_core_preferences_1.AI_CORE_PREFERENCES_TITLE
36
+ }
37
+ }
38
+ };
39
+ //# sourceMappingURL=ai-scanoss-preferences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-scanoss-preferences.js","sourceRoot":"","sources":["../../src/browser/ai-scanoss-preferences.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,wFAA2F;AAE9E,QAAA,iBAAiB,GAAG,0BAA0B,CAAC;AAE/C,QAAA,0BAA0B,GAAqB;IACxD,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACR,CAAC,yBAAiB,CAAC,EAAE;YACjB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,WAAW,CAAC;YACpC,wBAAwB,EAAE;gBACtB,mCAAmC;gBACnC,mFAAmF;gBACnF,uDAAuD;aAC1D;YACD,mBAAmB,EAAE;+HAC8F;YACnH,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,+CAAyB;SACnC;KACJ;CACJ,CAAC"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=package.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.spec.d.ts","sourceRoot":"","sources":["../src/package.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+ /* note: this bogus test file is required so that
17
+ we are able to run mocha unit tests on this
18
+ package, without having any actual unit tests in it.
19
+ This way a coverage report will be generated,
20
+ showing 0% coverage, instead of no report.
21
+ This file can be removed once we have real unit
22
+ tests in place. */
23
+ describe('ai-scanoss package', () => {
24
+ it('support code coverage statistics', () => true);
25
+ });
26
+ //# sourceMappingURL=package.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.spec.js","sourceRoot":"","sources":["../src/package.spec.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,oDAAoD;AACpD,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;AAEhF;;;;;;qBAMqB;AAErB,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAEhC,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@theia/ai-scanoss",
3
+ "version": "1.57.0-next.112+f4778c273",
4
+ "description": "Theia - SCANOSS AI Integration",
5
+ "dependencies": {
6
+ "@theia/ai-chat": "1.57.0-next.112+f4778c273",
7
+ "@theia/ai-chat-ui": "1.57.0-next.112+f4778c273",
8
+ "@theia/ai-core": "1.57.0-next.112+f4778c273",
9
+ "@theia/core": "1.57.0-next.112+f4778c273",
10
+ "@theia/scanoss": "1.57.0-next.112+f4778c273"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "theiaExtensions": [
16
+ {
17
+ "frontend": "lib/browser/ai-scanoss-frontend-module"
18
+ }
19
+ ],
20
+ "keywords": [
21
+ "theia-extension"
22
+ ],
23
+ "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/eclipse-theia/theia.git"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/eclipse-theia/theia/issues"
30
+ },
31
+ "homepage": "https://github.com/eclipse-theia/theia",
32
+ "files": [
33
+ "lib",
34
+ "src"
35
+ ],
36
+ "main": "lib/common",
37
+ "scripts": {
38
+ "build": "theiaext build",
39
+ "clean": "theiaext clean",
40
+ "compile": "theiaext compile",
41
+ "lint": "theiaext lint",
42
+ "test": "theiaext test",
43
+ "watch": "theiaext watch"
44
+ },
45
+ "devDependencies": {
46
+ "@theia/ext-scripts": "1.58.0"
47
+ },
48
+ "nyc": {
49
+ "extends": "../../configs/nyc.json"
50
+ },
51
+ "gitHead": "f4778c2737bb75613f0e1f99da8996bad91f6e17"
52
+ }
@@ -0,0 +1,235 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // ***
16
+ import { inject, injectable } from '@theia/core/shared/inversify';
17
+ import { CodeChatResponseContent } from '@theia/ai-chat';
18
+ import { CodePartRendererAction } from '@theia/ai-chat-ui/lib/browser/chat-response-renderer';
19
+ import {
20
+ ScanOSSResult,
21
+ ScanOSSResultMatch,
22
+ ScanOSSService,
23
+ } from '@theia/scanoss';
24
+ import { Dialog, PreferenceService } from '@theia/core/lib/browser';
25
+ import { ReactNode } from '@theia/core/shared/react';
26
+ import { ResponseNode } from '@theia/ai-chat-ui/lib/browser/chat-tree-view';
27
+ import * as React from '@theia/core/shared/react';
28
+ import { ReactDialog } from '@theia/core/lib/browser/dialogs/react-dialog';
29
+ import { SCAN_OSS_API_KEY_PREF } from '@theia/scanoss/lib/browser/scanoss-preferences';
30
+ import { SCANOSS_MODE_PREF } from './ai-scanoss-preferences';
31
+
32
+ // cached map of scanOSS results.
33
+ // 'false' is stored when not automatic check is off and it was not (yet) requested deliberately.
34
+ type ScanOSSResults = Map<string, ScanOSSResult | false>;
35
+ interface HasScanOSSResults {
36
+ scanOSSResults: ScanOSSResults;
37
+ [key: string]: unknown;
38
+ }
39
+ function hasScanOSSResults(data: {
40
+ [key: string]: unknown;
41
+ }): data is HasScanOSSResults {
42
+ return 'scanOSSResults' in data && data.scanOSSResults instanceof Map;
43
+ }
44
+
45
+ @injectable()
46
+ export class ScanOSSScanButtonAction implements CodePartRendererAction {
47
+ @inject(ScanOSSService)
48
+ protected readonly scanService: ScanOSSService;
49
+ @inject(PreferenceService)
50
+ protected readonly preferenceService: PreferenceService;
51
+
52
+ priority = 30;
53
+
54
+ canRender(response: CodeChatResponseContent, parentNode: ResponseNode): boolean {
55
+ if (!hasScanOSSResults(parentNode.response.data)) {
56
+ parentNode.response.data.scanOSSResults = new Map<
57
+ string,
58
+ ScanOSSResult
59
+ >();
60
+ }
61
+ const results = parentNode.response.data
62
+ .scanOSSResults as ScanOSSResults;
63
+ const scanOSSMode = this.preferenceService.get(SCANOSS_MODE_PREF, 'off');
64
+ // we mark the code for manual scanning in case it was not handled yet and the mode is manual or off.
65
+ // this prevents a possibly unexpected automatic scan of "old" snippets if automatic scan is later turned on.
66
+ if (results.get(response.code) === undefined && (scanOSSMode === 'off' || scanOSSMode === 'manual')) {
67
+ results.set(response.code, false);
68
+ }
69
+ return scanOSSMode !== 'off';
70
+ }
71
+
72
+ render(
73
+ response: CodeChatResponseContent,
74
+ parentNode: ResponseNode
75
+ ): ReactNode {
76
+ const scanOSSResults = parentNode.response.data
77
+ .scanOSSResults as ScanOSSResults;
78
+
79
+ return (
80
+ <ScanOSSIntegration
81
+ key='scanoss'
82
+ code={response.code}
83
+ scanService={this.scanService}
84
+ scanOSSResults={scanOSSResults}
85
+ preferenceService={this.preferenceService}
86
+ />
87
+ );
88
+ }
89
+ }
90
+
91
+ const ScanOSSIntegration = React.memo((props: {
92
+ code: string;
93
+ scanService: ScanOSSService;
94
+ scanOSSResults: ScanOSSResults;
95
+ preferenceService: PreferenceService;
96
+ }) => {
97
+ const [automaticCheck] = React.useState(() =>
98
+ props.preferenceService.get<string>(SCANOSS_MODE_PREF, 'off') === 'automatic'
99
+ );
100
+ const [scanOSSResult, setScanOSSResult] = React.useState<
101
+ ScanOSSResult | 'pending' | undefined | false
102
+ >(props.scanOSSResults.get(props.code));
103
+ const scanCode = React.useCallback(async () => {
104
+ setScanOSSResult('pending');
105
+ const result = await props.scanService.scanContent(props.code, props.preferenceService.get(SCAN_OSS_API_KEY_PREF, undefined));
106
+ setScanOSSResult(result);
107
+ props.scanOSSResults.set(props.code, result);
108
+ return result;
109
+ }, [props.code, props.scanService]);
110
+
111
+ React.useEffect(() => {
112
+ if (scanOSSResult === undefined) {
113
+ if (automaticCheck) {
114
+ scanCode();
115
+ } else {
116
+ // sanity fallback. This codepath should already be handled via "canRender"
117
+ props.scanOSSResults.set(props.code, false);
118
+ }
119
+ }
120
+ }, []);
121
+ const scanOSSClicked = React.useCallback(async () => {
122
+ let scanResult = scanOSSResult;
123
+ if (scanResult === 'pending') {
124
+ return;
125
+ }
126
+ if (!scanResult || scanResult.type === 'error') {
127
+ scanResult = await scanCode();
128
+ }
129
+ if (scanResult && scanResult.type === 'match') {
130
+ const dialog = new ScanOSSDialog(scanResult);
131
+ dialog.open();
132
+ }
133
+ }, [scanOSSResult]);
134
+ let title = 'SCANOSS - Perform scan';
135
+ if (scanOSSResult) {
136
+ if (scanOSSResult === 'pending') {
137
+ title = 'SCANOSS - Performing scan...';
138
+ } else if (scanOSSResult.type === 'error') {
139
+ title = `SCANOSS - Error - ${scanOSSResult.message}`;
140
+ } else if (scanOSSResult.type === 'match') {
141
+ title = `SCANOSS - Found ${scanOSSResult.matched} match`;
142
+ } else if (scanOSSResult.type === 'clean') {
143
+ title = 'SCANOSS - No match';
144
+ }
145
+ }
146
+ return (
147
+ <>
148
+ <div
149
+ className={`button scanoss-logo show-check icon-container ${scanOSSResult === 'pending'
150
+ ? 'pending'
151
+ : scanOSSResult
152
+ ? scanOSSResult.type
153
+ : ''
154
+ }`}
155
+ title={title}
156
+ role="button"
157
+ onClick={scanOSSClicked}
158
+ >
159
+ <div className="codicon codicon-circle placeholder" />
160
+ {scanOSSResult && scanOSSResult !== 'pending' && (
161
+ <span className="status-icon">
162
+ {scanOSSResult.type === 'clean' && <span className="codicon codicon-pass-filled" />}
163
+ {scanOSSResult.type === 'match' && <span className="codicon codicon-warning" />}
164
+ {scanOSSResult.type === 'error' && <span className="codicon codicon-error" />}
165
+ </span>
166
+ )}
167
+ </div>
168
+ </>
169
+ );
170
+ });
171
+
172
+ export class ScanOSSDialog extends ReactDialog<void> {
173
+ protected readonly okButton: HTMLButtonElement;
174
+
175
+ constructor(protected result: ScanOSSResultMatch) {
176
+ super({
177
+ title: 'SCANOSS Results',
178
+ });
179
+ this.appendAcceptButton(Dialog.OK);
180
+ this.update();
181
+ }
182
+
183
+ protected render(): React.ReactNode {
184
+ return (
185
+ <div className="scanoss-dialog-container">
186
+ {this.renderHeader()}
187
+ {this.renderSummary()}
188
+ {this.renderContent()}
189
+ </div>
190
+ );
191
+ }
192
+
193
+ protected renderHeader(): React.ReactNode {
194
+ return (
195
+ <div className="scanoss-header">
196
+ <div className="scanoss-logo-container">
197
+ <div className="scanoss-logo"></div>
198
+ <h2>SCANOSS</h2>
199
+ </div>
200
+ </div>
201
+ );
202
+ }
203
+
204
+ protected renderSummary(): React.ReactNode {
205
+ return (
206
+ <div className="scanoss-summary">
207
+ <h3>Summary</h3>
208
+ <div>
209
+ Found a {this.result.matched} match in{' '}
210
+ <a href={this.result.url} target="_blank" rel="noopener noreferrer">
211
+ {this.result.url}
212
+ </a>
213
+ </div>
214
+ </div>
215
+ );
216
+ }
217
+
218
+ protected renderContent(): React.ReactNode {
219
+ return (
220
+ <div className="scanoss-details">
221
+ <h4>Details</h4>
222
+ <pre>
223
+ {
224
+ // eslint-disable-next-line no-null/no-null
225
+ JSON.stringify(this.result.raw, null, 2)
226
+ }
227
+ </pre>
228
+ </div>
229
+ );
230
+ }
231
+
232
+ get value(): undefined {
233
+ return undefined;
234
+ }
235
+ }
@@ -0,0 +1,28 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { ContainerModule } from '@theia/core/shared/inversify';
18
+ import { AIScanOSSPreferencesSchema } from './ai-scanoss-preferences';
19
+ import { PreferenceContribution } from '@theia/core/lib/browser';
20
+ import { ScanOSSScanButtonAction } from './ai-scanoss-code-scan-action';
21
+ import { CodePartRendererAction } from '@theia/ai-chat-ui/lib/browser/chat-response-renderer';
22
+ import '../../src/browser/style/index.css';
23
+
24
+ export default new ContainerModule(bind => {
25
+ bind(PreferenceContribution).toConstantValue({ schema: AIScanOSSPreferencesSchema });
26
+ bind(ScanOSSScanButtonAction).toSelf().inSingletonScope();
27
+ bind(CodePartRendererAction).toService(ScanOSSScanButtonAction);
28
+ });
@@ -0,0 +1,39 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { PreferenceSchema } from '@theia/core/lib/browser/preferences';
18
+ import { AI_CORE_PREFERENCES_TITLE } from '@theia/ai-core/lib/browser/ai-core-preferences';
19
+
20
+ export const SCANOSS_MODE_PREF = 'ai-features.SCANOSS.mode';
21
+
22
+ export const AIScanOSSPreferencesSchema: PreferenceSchema = {
23
+ type: 'object',
24
+ properties: {
25
+ [SCANOSS_MODE_PREF]: {
26
+ type: 'string',
27
+ enum: ['off', 'manual', 'automatic'],
28
+ markdownEnumDescriptions: [
29
+ 'Feature is turned off completely.',
30
+ 'User can manually trigger the scan by clicking the SCANOSS item in the chat view.',
31
+ 'Enable automatic scan of code snippets in chat views.'
32
+ ],
33
+ markdownDescription: 'Configure the SCANOSS feature for analyzing code snippets in chat views. This will send a hash of suggested code snippets to the SCANOSS\n\
34
+ service hosted by the [Software Transparency foundation](https://www.softwaretransparency.org/osskb) for analysis.',
35
+ default: 'off',
36
+ title: AI_CORE_PREFERENCES_TITLE
37
+ }
38
+ }
39
+ };
@@ -0,0 +1,132 @@
1
+ .scanoss-logo {
2
+ background-image: url("scanoss_logo_dark_theme.svg");
3
+ background-repeat: no-repeat;
4
+ background-position: center;
5
+ }
6
+
7
+ .vs-light .scanoss-logo,
8
+ .theia-light .scanoss-logo,
9
+ .light-theia .scanoss-logo {
10
+ background-image: url("scanoss_logo_light_theme.svg");
11
+ }
12
+
13
+ /* We need a more detailed selector to override the default button style */
14
+ .theia-CodePartRenderer-actions .scanoss-logo {
15
+ background-size: 82% auto; /* scale the image to be a bit smaller than the button because the codicon icons are also smaller */
16
+ transition: filter 0.3s;
17
+ display: inline-block;
18
+ }
19
+
20
+ .scanoss-logo.requesting {
21
+ animation: pulse 1s infinite ease-in-out;
22
+ }
23
+
24
+ /* Use a rounded background when not hovered */
25
+ .theia-CodePartRenderer-actions .scanoss-logo:not(:hover) {
26
+ border-radius: 50%;
27
+ }
28
+
29
+ .scanoss-logo.clean {
30
+ background-color: rgba(46, 125, 50, 0.3); /* translucent green */
31
+ }
32
+
33
+ .scanoss-logo.match {
34
+ background-color: rgba(249, 215, 116, 0.3); /* translucent yellow */
35
+ }
36
+
37
+ .scanoss-logo.error {
38
+ background-color: rgba(210, 72, 72, 0.3); /* translucent red */
39
+ }
40
+
41
+ .icon-container {
42
+ position: relative;
43
+ display: inline-block;
44
+ width: 16px;
45
+ height: 16px;
46
+ }
47
+
48
+ /* The placeholder is used to align with the remaining actions, however it should not be visible*/
49
+ .scanoss-logo .placeholder {
50
+ visibility: hidden;
51
+ }
52
+
53
+ /* The status icon is used to display the result of the scan on the top right */
54
+ .scanoss-logo .status-icon {
55
+ position: absolute;
56
+ transform: translate(-4px, -5px);
57
+ }
58
+
59
+ .scanoss-logo.clean .status-icon {
60
+ color: green;
61
+ }
62
+ .scanoss-logo.match .status-icon {
63
+ color: yellow;
64
+ text-shadow: 0 0 3px rgba(0,0,0,0.9);
65
+ }
66
+ .scanoss-logo.error .status-icon {
67
+ color: red;
68
+ text-shadow: 0 0 3px currentColor
69
+ }
70
+
71
+ /* Disable the button when it's in the clean state */
72
+ .theia-CodePartRenderer-actions .scanoss-logo.clean{
73
+ pointer-events: none;
74
+ cursor: default;
75
+ }
76
+
77
+ .scanoss-dialog-container .scanoss-header {
78
+ display: flex;
79
+ flex-direction: column;
80
+ align-items: center;
81
+ margin-bottom: 20px;
82
+ }
83
+
84
+ .scanoss-dialog-container .scanoss-logo-container {
85
+ display: flex;
86
+ flex-direction: row;
87
+ align-items: center;
88
+ gap: 10px;
89
+ }
90
+
91
+ .scanoss-dialog-container .scanoss-logo {
92
+ width: 40px;
93
+ height: 40px;
94
+ background-size: contain;
95
+ }
96
+
97
+ .scanoss-dialog-container .scanoss-logo-container h2 {
98
+ font-size: 1.8em;
99
+ margin: 0;
100
+ }
101
+
102
+ .scanoss-dialog-container .scanoss-summary {
103
+ padding: 15px;
104
+ border-radius: 4px;
105
+ margin-bottom: 20px;
106
+ }
107
+
108
+ .scanoss-dialog-container .scanoss-summary h3 {
109
+ margin-top: 0;
110
+ font-size: 1.4em;
111
+ margin-bottom: 10px;
112
+ }
113
+
114
+ .scanoss-dialog-container .scanoss-details {
115
+ padding: 15px;
116
+ border-radius: 4px;
117
+ border: 1px solid var(--theia-sideBarSectionHeader-border);
118
+ }
119
+
120
+ .scanoss-dialog-container .scanoss-details h4 {
121
+ margin-top: 0;
122
+ font-size: 1.2em;
123
+ margin-bottom: 10px;
124
+ }
125
+
126
+ .scanoss-dialog-container .scanoss-details pre {
127
+ background: var(--theia-editor-background);
128
+ padding: 10px;
129
+ border-radius: 4px;
130
+ overflow: auto;
131
+ font-size: 0.9em;
132
+ }
@@ -0,0 +1,11 @@
1
+ <svg width="81" height="82" viewBox="0 0 81 82" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M18.5086 36.073H29.0966C30.2492 33.5499 32.2272 31.4981 34.7021 30.2582C37.1771 29.0184 40.0003 28.6651 42.7029 29.257C45.4056 29.8488 47.8253 31.3502 49.5603 33.512C51.2953 35.6738 52.2414 38.3659 52.2414 41.1415C52.2414 43.9171 51.2953 46.6092 49.5603 48.771C47.8253 50.9328 45.4056 52.4342 42.7029 53.0261C40.0003 53.6179 37.1771 53.2646 34.7021 52.0248C32.2272 50.7849 30.2492 48.7332 29.0966 46.21H18.5086C19.7483 51.5397 22.898 56.226 27.3581 59.3766C31.8182 62.5273 37.2773 63.9225 42.6961 63.2964C48.1149 62.6704 53.1152 60.0669 56.7449 55.9816C60.3746 51.8963 62.3804 46.6144 62.3804 41.1415C62.3804 35.6686 60.3746 30.3867 56.7449 26.3014C53.1152 22.2161 48.1149 19.6126 42.6961 18.9866C37.2773 18.3606 31.8182 19.7557 27.3581 22.9064C22.898 26.057 19.7483 30.7433 18.5086 36.073Z" fill="white"/>
3
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M40.412 10.1933C23.3992 10.1933 9.60766 24.0311 9.60766 41.101C9.60766 58.1708 23.3992 72.0086 40.412 72.0086C57.4247 72.0086 71.2163 58.1708 71.2163 41.101C71.2163 24.0311 57.4247 10.1933 40.412 10.1933ZM0.0908203 41.101C0.0908203 18.7575 18.1432 0.644531 40.412 0.644531C62.6808 0.644531 80.7332 18.7575 80.7332 41.101C80.7332 63.4444 62.6808 81.5574 40.412 81.5574C18.1432 81.5574 0.0908203 63.4444 0.0908203 41.101Z" fill="white"/>
4
+ <path d="M40.1112 46.015C42.666 46.015 44.7371 43.9737 44.7371 41.4557C44.7371 38.9377 42.666 36.8965 40.1112 36.8965C37.5564 36.8965 35.4854 38.9377 35.4854 41.4557C35.4854 43.9737 37.5564 46.015 40.1112 46.015Z" fill="url(#paint0_linear_458_1146)"/>
5
+ <defs>
6
+ <linearGradient id="paint0_linear_458_1146" x1="35.4854" y1="63.6006" x2="45.2955" y2="63.4776" gradientUnits="userSpaceOnUse">
7
+ <stop stop-color="#6366F1"/>
8
+ <stop offset="1" stop-color="#863DFF"/>
9
+ </linearGradient>
10
+ </defs>
11
+ </svg>
@@ -0,0 +1,11 @@
1
+ <svg width="82" height="82" viewBox="0 0 82 82" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M19.1814 36.073H29.7694C30.9221 33.5499 32.9 31.4981 35.375 30.2582C37.85 29.0184 40.6731 28.6651 43.3758 29.257C46.0785 29.8488 48.4981 31.3502 50.2332 33.512C51.9682 35.6738 52.9142 38.3659 52.9142 41.1415C52.9142 43.9171 51.9682 46.6092 50.2332 48.771C48.4981 50.9328 46.0785 52.4342 43.3758 53.0261C40.6731 53.6179 37.85 53.2646 35.375 52.0248C32.9 50.7849 30.9221 48.7332 29.7694 46.21H19.1814C20.4211 51.5397 23.5708 56.226 28.0309 59.3766C32.491 62.5273 37.9501 63.9225 43.3689 63.2964C48.7878 62.6704 53.788 60.0669 57.4177 55.9816C61.0475 51.8963 63.0532 46.6144 63.0532 41.1415C63.0532 35.6686 61.0475 30.3867 57.4177 26.3014C53.788 22.2161 48.7878 19.6126 43.3689 18.9866C37.9501 18.3606 32.491 19.7557 28.0309 22.9064C23.5708 26.057 20.4211 30.7433 19.1814 36.073Z" fill="#1E293B"/>
3
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M41.0848 10.1933C24.0721 10.1933 10.2805 24.0311 10.2805 41.101C10.2805 58.1708 24.072 72.0086 41.0848 72.0086C58.0976 72.0086 71.8892 58.1708 71.8892 41.101C71.8892 24.0311 58.0976 10.1933 41.0848 10.1933ZM0.763672 41.101C0.763672 18.7575 18.816 0.644531 41.0848 0.644531C63.3536 0.644531 81.406 18.7575 81.406 41.101C81.406 63.4444 63.3536 81.5574 41.0848 81.5574C18.816 81.5574 0.763672 63.4444 0.763672 41.101Z" fill="#1E293B"/>
4
+ <path d="M40.7841 46.015C43.3389 46.015 45.41 43.9737 45.41 41.4557C45.41 38.9377 43.3389 36.8965 40.7841 36.8965C38.2293 36.8965 36.1582 38.9377 36.1582 41.4557C36.1582 43.9737 38.2293 46.015 40.7841 46.015Z" fill="url(#paint0_linear_458_1134)"/>
5
+ <defs>
6
+ <linearGradient id="paint0_linear_458_1134" x1="36.1582" y1="63.6006" x2="45.9684" y2="63.4776" gradientUnits="userSpaceOnUse">
7
+ <stop stop-color="#6366F1"/>
8
+ <stop offset="1" stop-color="#863DFF"/>
9
+ </linearGradient>
10
+ </defs>
11
+ </svg>
@@ -0,0 +1,28 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ /* note: this bogus test file is required so that
18
+ we are able to run mocha unit tests on this
19
+ package, without having any actual unit tests in it.
20
+ This way a coverage report will be generated,
21
+ showing 0% coverage, instead of no report.
22
+ This file can be removed once we have real unit
23
+ tests in place. */
24
+
25
+ describe('ai-scanoss package', () => {
26
+
27
+ it('support code coverage statistics', () => true);
28
+ });