Skip to content
Draft
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
40 changes: 40 additions & 0 deletions src/@types/vscode.proposed.chatParticipantPrivate.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ declare module 'vscode' {
*/
readonly hasHooksEnabled: boolean;

/**
* Whether this request was submitted through Agents Voice Mode.
*/
readonly isVoiceModeInput?: boolean;

/**
* When true, this request was initiated by the system (e.g. a terminal
* command completion notification) rather than by the user typing a
Expand All @@ -135,6 +140,41 @@ declare module 'vscode' {
readonly isSystemInitiated?: boolean;
}

/**
* A transient progress update intended for Voice Mode narration.
*/
export type ChatResponseVoiceProgressStage = 'investigating' | 'planning' | 'editing' | 'validating' | 'recovering';

export class ChatResponseVoiceProgressPart {
/**
* A stable identifier used to de-duplicate the progress update.
*/
readonly id: ChatResponseVoiceProgressStage;
/**
* The concise text to narrate.
*/
readonly value: string;
/**
* Creates a Voice Mode progress update.
* @param id A stable identifier used to de-duplicate the update.
* @param value The concise text to narrate.
*/
constructor(id: ChatResponseVoiceProgressStage, value: string);
}

export interface ExtendedChatResponseParts {
ChatResponseVoiceProgressPart: ChatResponseVoiceProgressPart;
}

export interface ChatResponseStream {
/**
* Reports transient progress for Voice Mode narration.
* @param id A stable identifier used to de-duplicate the update.
* @param value The concise text to narrate.
*/
voiceProgress(id: ChatResponseVoiceProgressStage, value: string): void;
}

export enum ChatRequestEditedFileEventKind {
Keep = 1,
Undo = 2,
Expand Down
2 changes: 1 addition & 1 deletion src/@types/vscode.proposed.chatSessionsProvider.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,7 @@ declare module 'vscode' {
readonly promo?: {
readonly id: string;
readonly discountPercent: number;
readonly endsAt: string;
readonly endsAt?: string;
readonly message: string;
};
readonly maxInputTokens?: number;
Expand Down
5 changes: 4 additions & 1 deletion src/github/folderRepositoryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ export class FolderRepositoryManager extends Disposable {
}

const activeRemotes = await this.getActiveRemotes();
const isAuthenticated = this.checkForAuthMatch(activeRemotes);
let isAuthenticated = this.checkForAuthMatch(activeRemotes);
if (this.credentialStore.isAnyAuthenticated() && (activeRemotes.length === 0)) {
const allUnknownRemotes = await this.computeAllUnknownRemotes();
const areAllNeverGitHub = allUnknownRemotes.every(remote => GitHubManager.isNeverGitHub(vscode.Uri.parse(remote.normalizedHost).authority));
Expand All @@ -504,6 +504,9 @@ export class FolderRepositoryManager extends Disposable {
this.state = ReposManagerState.RepositoriesLoaded;
return true;
}
if (allUnknownRemotes.length > 0) {
isAuthenticated = false;
}
}
const repositories: GitHubRepository[] = [];
const resolveRemotePromises: Promise<boolean>[] = [];
Expand Down
18 changes: 16 additions & 2 deletions src/test/github/folderRepositoryManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { default as assert } from 'assert';
import { createSandbox, SinonSandbox } from 'sinon';

import { FolderRepositoryManager, titleAndBodyFrom } from '../../github/folderRepositoryManager';
import { FolderRepositoryManager, ReposManagerState, titleAndBodyFrom } from '../../github/folderRepositoryManager';
import { MockRepository } from '../mocks/mockRepository';
import { MockTelemetry } from '../mocks/mockTelemetry';
import { MockCommandRegistry } from '../mocks/mockCommandRegistry';
Expand All @@ -20,7 +20,7 @@ import { GitApiImpl } from '../../api/api1';
import { CredentialStore } from '../../github/credentials';
import { MockExtensionContext } from '../mocks/mockExtensionContext';
import { Uri } from 'vscode';
import { GitHubServerType } from '../../common/authentication';
import { AuthProvider, GitHubServerType } from '../../common/authentication';
import { CreatePullRequestHelper } from '../../view/createPullRequestHelper';
import { RepositoriesManager } from '../../github/repositoriesManager';
import { MockThemeWatcher } from '../mocks/mockThemeWatcher';
Expand Down Expand Up @@ -53,6 +53,20 @@ describe('PullRequestManager', function () {
sinon.restore();
});

describe('updateRepositories', function () {
it('requires authentication for an unknown remote with an existing GitHub.com session', async function () {
const url = 'ssh://git@ghe.example.com/org/repo.git';
const remote = new Remote('origin', url, new Protocol(url));
sinon.stub(manager, 'computeAllGitHubRemotes').resolves([]);
sinon.stub(manager, 'computeAllUnknownRemotes').resolves([remote]);
sinon.stub(manager.credentialStore, 'isAuthenticated').callsFake(provider => provider === AuthProvider.github);

await manager.updateRepositories();

assert.strictEqual(manager.state, ReposManagerState.NeedsAuthentication);
});
});

describe('activePullRequest', function () {
it('gets and sets the active pull request', function () {
assert.strictEqual(manager.activePullRequest, undefined);
Expand Down