Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/vs/workbench/api/common/extHostEmbeddingVector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IExtensionDescription } from '../../../platform/extensions/common/exten
import { ExtHostAiEmbeddingVectorShape, IMainContext, MainContext, MainThreadAiEmbeddingVectorShape } from './extHost.protocol.js';
import type { CancellationToken, EmbeddingVectorProvider } from 'vscode';
import { Disposable } from './extHostTypes.js';
import { isFalsyOrWhitespace } from '../../../base/common/strings.js';

export class ExtHostAiEmbeddingVector implements ExtHostAiEmbeddingVectorShape {
private _AiEmbeddingVectorProviders: Map<number, EmbeddingVectorProvider> = new Map();
Expand Down Expand Up @@ -38,6 +39,10 @@ export class ExtHostAiEmbeddingVector implements ExtHostAiEmbeddingVectorShape {
}

registerEmbeddingVectorProvider(extension: IExtensionDescription, model: string, provider: EmbeddingVectorProvider): Disposable {
if (isFalsyOrWhitespace(model)) {
throw new Error('Embedding vector model must be a non-empty string.');
}

const handle = this._nextHandle;
this._nextHandle++;
this._AiEmbeddingVectorProviders.set(handle, provider);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { IDisposable } from '../../../../base/common/lifecycle.js';
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
import { StopWatch } from '../../../../base/common/stopwatch.js';
import { ILogService } from '../../../../platform/log/common/log.js';
import { isFalsyOrWhitespace } from '../../../../base/common/strings.js';

export const IAiEmbeddingVectorService = createDecorator<IAiEmbeddingVectorService>('IAiEmbeddingVectorService');

Expand Down Expand Up @@ -40,6 +41,10 @@ export class AiEmbeddingVectorService implements IAiEmbeddingVectorService {
}

registerAiEmbeddingVectorProvider(model: string, provider: IAiEmbeddingVectorProvider): IDisposable {
if (isFalsyOrWhitespace(model)) {
throw new Error('Embedding vector model must be a non-empty string.');
}

this._providers.push(provider);
return {
dispose: () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import assert from 'assert';
import { AiEmbeddingVectorService, IAiEmbeddingVectorProvider } from '../../common/aiEmbeddingVectorService.js';
import { NullLogService } from '../../../../../platform/log/common/log.js';
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';

suite('AiEmbeddingVectorService', () => {
const store = ensureNoDisposablesAreLeakedInTestSuite();
let service: AiEmbeddingVectorService;

setup(() => {
service = new AiEmbeddingVectorService(store.add(new NullLogService()));
});

test('should reject empty model when registering provider', () => {
const provider: IAiEmbeddingVectorProvider = {
provideAiEmbeddingVector: () => Promise.resolve([[1]])
};

assert.throws(
() => service.registerAiEmbeddingVectorProvider('', provider),
/Embedding vector model must be a non-empty string\./
);
});

test('should reject whitespace-only model when registering provider', () => {
const provider: IAiEmbeddingVectorProvider = {
provideAiEmbeddingVector: () => Promise.resolve([[1]])
};

assert.throws(
() => service.registerAiEmbeddingVectorProvider(' ', provider),
/Embedding vector model must be a non-empty string\./
);
});

test('should register and unregister provider with valid model', () => {
const provider: IAiEmbeddingVectorProvider = {
provideAiEmbeddingVector: () => Promise.resolve([[1]])
};

const disposable = service.registerAiEmbeddingVectorProvider('test-model', provider);
assert.strictEqual(service.isEnabled(), true);
disposable.dispose();
assert.strictEqual(service.isEnabled(), false);
});
});