mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-20 02:34:37 +01:00
inline chat and replace-tool (#1827)
* `detectIntent` shouldn't make a request when there is no metadata to pick from https://github.com/microsoft/vscode/issues/275818 * add unit test for https://github.com/microsoft/vscode/issues/275824
This commit is contained in:
@@ -17,6 +17,7 @@ import { ITabsAndEditorsService } from '../../../platform/tabs/common/tabsAndEdi
|
||||
import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService';
|
||||
import { ITelemetryService } from '../../../platform/telemetry/common/telemetry';
|
||||
import { isNotebookCellOrNotebookChatInput } from '../../../util/common/notebooks';
|
||||
import { isFalsyOrEmpty } from '../../../util/vs/base/common/arrays';
|
||||
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
|
||||
import { Position, Range } from '../../../vscodeTypes';
|
||||
import { getAgentForIntent, GITHUB_PLATFORM_AGENT, Intent } from '../../common/constants';
|
||||
@@ -181,6 +182,11 @@ export class IntentDetector implements ChatParticipantDetectionProvider {
|
||||
|
||||
this.logService.trace('Building intent detector');
|
||||
|
||||
if (builtinParticipants.length === 0 && (isFalsyOrEmpty(thirdPartyParticipants))) {
|
||||
this.logService.trace('No participants available for intent detection');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const endpoint = await this.endpointProvider.getChatEndpoint('copilot-fast');
|
||||
|
||||
const preferredIntent = await this.getPreferredIntent(location, documentContext, history, messageText);
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference path="./math.test.js" />
|
||||
|
||||
console.log("foobar");
|
||||
|
||||
// one
|
||||
// two
|
||||
// three
|
||||
|
||||
logwo
|
||||
|
||||
// * merge/re-use modified file entries
|
||||
// * no accept/disacrd on new session
|
||||
// * accept all hunks
|
||||
|
||||
export function fib(nth) {
|
||||
if (nth <= 0) return 0;
|
||||
if (nth === 1) return 0;
|
||||
if (nth === 2) return 1;
|
||||
return fib(nth - 1) + fib(nth - 2);
|
||||
}
|
||||
|
||||
///-///-////---
|
||||
|
||||
const r = /hello/gim;
|
||||
|
||||
export function sum(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
export function sub(a, b) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
export function sumArray(a) {
|
||||
return a.reduce((sum, num) => sum + num, 0);
|
||||
}
|
||||
|
||||
export function div(a, b) {
|
||||
// console.log fff fff
|
||||
return a / b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function mul(a, b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
export function sumThreeFloats(a, b, c) {
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given number is a prime number.
|
||||
*
|
||||
* @param {number} number - The number to check for primality.
|
||||
* @returns {boolean} - Returns true if the number is prime, otherwise false.
|
||||
*/
|
||||
export function isPrime(number) {
|
||||
if (number <= 1) return false;
|
||||
for (let i = 2; i <= Math.sqrt(number); i++) {
|
||||
if (number % i === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
export function isEven(n) {
|
||||
return n % 2 === 0;
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference path="./math.test.js" />
|
||||
|
||||
console.log("foobar");
|
||||
|
||||
// one
|
||||
// two
|
||||
// three
|
||||
|
||||
logwo
|
||||
|
||||
// * merge/re-use modified file entries
|
||||
// * no accept/disacrd on new session
|
||||
// * accept all hunks
|
||||
|
||||
export function fib(nth) {
|
||||
if (nth <= 0) return 0;
|
||||
if (nth === 1) return 0;
|
||||
if (nth === 2) return 1;
|
||||
return fib(nth - 1) + fib(nth - 2);
|
||||
}
|
||||
|
||||
///-///-////---
|
||||
|
||||
const r = /hello/gim;
|
||||
|
||||
export function sum(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
export function sub(a, b) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
export function sumArray(a) {
|
||||
return a.reduce((sum, num) => sum + num, 0);
|
||||
}
|
||||
|
||||
export function div(A, b) {
|
||||
// console.log fff fff
|
||||
return A / b;
|
||||
}
|
||||
|
||||
export function mul(a, b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
export function sumThreeFloats(a, b, c) {
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given number is a prime number.
|
||||
*
|
||||
* @param {number} number - The number to check for primality.
|
||||
* @returns {boolean} - Returns true if the number is prime, otherwise false.
|
||||
*/
|
||||
export function isPrime(number) {
|
||||
if (number <= 1) return false;
|
||||
for (let i = 2; i <= Math.sqrt(number); i++) {
|
||||
if (number % i === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
export function isEven(n) {
|
||||
return n % 2 === 0;
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { beforeEach, expect, it, suite } from 'vitest';
|
||||
import { ITestingServicesAccessor } from '../../../../../platform/test/node/services';
|
||||
import { TestWorkspaceService } from '../../../../../platform/test/node/testWorkspaceService';
|
||||
import { IWorkspaceService } from '../../../../../platform/workspace/common/workspaceService';
|
||||
import { ChatResponseStreamImpl } from '../../../../../util/common/chatResponseStreamImpl';
|
||||
import { createTextDocumentData } from '../../../../../util/common/test/shims/textDocument';
|
||||
import { CancellationToken } from '../../../../../util/vs/base/common/cancellation';
|
||||
import { assertType } from '../../../../../util/vs/base/common/types';
|
||||
import { URI } from '../../../../../util/vs/base/common/uri';
|
||||
import { SyncDescriptor } from '../../../../../util/vs/platform/instantiation/common/descriptors';
|
||||
import { IInstantiationService } from '../../../../../util/vs/platform/instantiation/common/instantiation';
|
||||
import { ChatResponseTextEditPart } from '../../../../../vscodeTypes';
|
||||
import { ChatVariablesCollection } from '../../../../prompt/common/chatVariablesCollection';
|
||||
import { WorkingCopyOriginalDocument } from '../../../../prompts/node/inline/workingCopies';
|
||||
import { createExtensionUnitTestingServices } from '../../../../test/node/services';
|
||||
import { IReplaceStringToolParams, ReplaceStringTool } from '../../../node/replaceStringTool';
|
||||
|
||||
|
||||
suite('ReplaceString Tool', () => {
|
||||
|
||||
let accessor: ITestingServicesAccessor;
|
||||
|
||||
const path = join(__dirname, 'fixtures/math.js.txt');
|
||||
const fileTsUri = URI.file(path);
|
||||
|
||||
beforeEach(function () {
|
||||
const services = createExtensionUnitTestingServices();
|
||||
|
||||
const content = String(readFileSync(path));
|
||||
|
||||
const testDoc = createTextDocumentData(fileTsUri, content, 'ts').document;
|
||||
services.define(IWorkspaceService, new SyncDescriptor(
|
||||
TestWorkspaceService, [[fileTsUri], [testDoc]]
|
||||
));
|
||||
|
||||
accessor = services.createTestingAccessor();
|
||||
});
|
||||
|
||||
it('whitespace change everywhere', async () => {
|
||||
|
||||
const input: IReplaceStringToolParams = JSON.parse(`{
|
||||
"filePath": "${path.replaceAll('\\', '\\\\')}",
|
||||
"oldString": "export function div(a, b) {\\n // console.log fff fff\\n return a / b;\\n}",
|
||||
"newString": "export function div(A, b) {\\n // console.log fff fff\\n return A / b;\\n}"
|
||||
}`);
|
||||
|
||||
const tool = accessor.get(IInstantiationService).createInstance(ReplaceStringTool);
|
||||
|
||||
expect(tool).toBeDefined();
|
||||
|
||||
const document = accessor.get(IWorkspaceService).textDocuments.find(doc => doc.uri.toString() === fileTsUri.toString());
|
||||
assertType(document);
|
||||
|
||||
const workingCopyDocument = new WorkingCopyOriginalDocument(document.getText());
|
||||
|
||||
expect(document.getText().includes(input.oldString)).toBe(false); // TAB vs SPACES
|
||||
|
||||
let seenEdits = 0;
|
||||
|
||||
const stream = new ChatResponseStreamImpl((part) => {
|
||||
|
||||
if (part instanceof ChatResponseTextEditPart) {
|
||||
const offsetEdits = workingCopyDocument.transformer.toOffsetEdit(part.edits);
|
||||
|
||||
if (!workingCopyDocument.isNoop(offsetEdits)) {
|
||||
seenEdits++;
|
||||
workingCopyDocument.applyOffsetEdits(offsetEdits);
|
||||
}
|
||||
}
|
||||
|
||||
}, () => { }, () => { });
|
||||
|
||||
const input2 = await tool.resolveInput(input, {
|
||||
history: [],
|
||||
stream,
|
||||
query: 'change a to A',
|
||||
chatVariables: new ChatVariablesCollection([]),
|
||||
});
|
||||
|
||||
await tool.invoke({ input: input2, toolInvocationToken: undefined }, CancellationToken.None);
|
||||
|
||||
expect(seenEdits).toBe(1);
|
||||
expect(workingCopyDocument.text).toMatchFileSnapshot('fixtures/math.js.txt.expected');
|
||||
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user