Skip to content

Commit

Permalink
feat: copilot plugin debugger (#12876)
Browse files Browse the repository at this point in the history
* feat: copilot plugin debugger initial changes

* fix: compile error

* feat: clean up cdp

* feat: use short telemetry event name

* feat: collect and clean cdp clients

* feat: telemetry + error handling + feature flag + templates

* fix: connection check

* refactor: revert telemetry event

* refactor: clean

* refactor: clean

* refactor: clean

* test: ut

* feat: version

* feat: revert

* fix: isM365CopilotChatDebugSession

* test: ut

* test: ut

* refactor: update ui to success driven

* test: ut

* test: ut

* test: ut for cdpClient

* fix: ut

* fix: m365 compabible

* fix: both url works

* fix: ut

* fix: log

* feat: support multiple api debug sessions

* test: add unit tests for copilot debug log output

* test: ut

* test: ut

* test: ut

---------

Co-authored-by: samwelkanda <[email protected]>
  • Loading branch information
jayzhang and samwelkanda authored Dec 17, 2024
1 parent 7ab47da commit 8f0fc45
Show file tree
Hide file tree
Showing 18 changed files with 1,691 additions and 107 deletions.
5 changes: 5 additions & 0 deletions packages/fx-core/src/common/featureFlags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export class FeatureFlagName {
static readonly ApiPluginAAD = "TEAMSFX_API_PLUGIN_AAD";
static readonly CEAEnabled = "TEAMSFX_CEA_ENABLED";
static readonly MultiTenant = "TEAMSFX_MULTI_TENANT";
static readonly ApiPluginDebug = "TEAMSFX_API_PLUGIN_DEBUG";
}

export interface FeatureFlag {
Expand Down Expand Up @@ -99,6 +100,10 @@ export class FeatureFlags {
name: FeatureFlagName.MultiTenant,
defaultValue: "false",
};
static readonly ApiPluginDebug = {
name: FeatureFlagName.ApiPluginDebug,
defaultValue: "false",
};
}

export class FeatureFlagManager {
Expand Down
5 changes: 5 additions & 0 deletions packages/vscode-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1656,6 +1656,7 @@
"watch:vite": "vite build --config vite.config.mts --watch",
"build:test": "tsc --project tsconfig.test.json --incremental",
"test:unit": "npm run build:test && nyc mocha --config .mocharc.json \"test/**/*.test.ts\"",
"test:debug": "npm run build:test && nyc mocha --config .mocharc.json \"test/pluginDebugger/*.test.ts\"",
"test:integration": "echo 'to be implementd'",
"test:e2e": "echo 'to be implementd'",
"check-format": "prettier --list-different --config .prettierrc.js --ignore-path .prettierignore \"src/**/*.ts\" \"test/**/*.ts\" \"*.{js,json}\"",
Expand All @@ -1678,6 +1679,7 @@
"@types/chai": "^4.2.14",
"@types/chai-as-promised": "^7.1.3",
"@types/chai-spies": "^1.0.3",
"@types/chrome-remote-interface": "^0.31.14",
"@types/express": "^4.17.14",
"@types/fs-extra": "^9.0.5",
"@types/jscodeshift": "^0.11.2",
Expand Down Expand Up @@ -1762,9 +1764,12 @@
"@vscode/webview-ui-toolkit": "^1.2.2",
"async-mutex": "^0.3.1",
"axios": "^1.7.5",
"chrome-remote-interface": "^0.33.2",
"detect-port": "^1.3.0",
"devtools-protocol": "^0.0.1387316",
"dotenv": "^8.2.0",
"dree": "^4.7.0",
"edge-paths": "^3.0.5",
"express": "^4.21.1",
"find-process": "^1.4.4",
"fuse.js": "^6.6.2",
Expand Down
68 changes: 66 additions & 2 deletions packages/vscode-extension/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions packages/vscode-extension/src/debug/common/debugConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ export enum Host {
office = "www.office.com",
}

export enum ANSIColors {
RED = "\u001b[31m",
GREEN = "\u001b[32m",
YELLOW = "\u001b[33m",
BLUE = "\u001b[34m",
MAGENTA = "\u001b[35m",
WHITE = "\u001b[37m",
GRAY = "\u001b[38;5;244m",
}

export const accountHintPlaceholder = "${account-hint}";
export const agentHintPlaceholder = "${agent-hint}";
export const m365AppIdEnv = "M365_APP_ID";
Expand Down Expand Up @@ -254,6 +264,14 @@ export const launchingTeamsClientDisplayMessages = Object.freeze({
"The app supports hot reloading. If you have any code changes in the project, the app will be reloaded.",
});

export const connectToExistingBrowserDebugSessionForCopilot = Object.freeze({
title: "Connecting to Existing Browser Debug Session for Copilot.",
successfulConnectionMessage: (port: number) =>
`Connected to DevTools Protocol in existing debug session on port: ${port}.`,
unsuccessfulConnectionMessage: (error: string) =>
`Failed to connect to Chrome DevTools Protocol: ${error}.`,
});

export const DebugSessionExists = "Debug session exists";

export const RecommendedOperations = Object.freeze({
Expand Down
35 changes: 26 additions & 9 deletions packages/vscode-extension/src/debug/teamsfxTaskHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import * as vscode from "vscode";
import { ProductName, UserError } from "@microsoft/teamsfx-api";
import {
Correlator,
featureFlagManager,
FeatureFlags,
getHashedEnv,
Hub,
isValidProject,
Expand All @@ -17,15 +19,16 @@ import {

import VsCodeLogInstance from "../commonlib/log";
import { ExtensionErrors, ExtensionSource } from "../error/error";
import { VS_CODE_UI } from "../qm/vsc_ui";
import * as globalVariables from "../globalVariables";
import { VS_CODE_UI } from "../qm/vsc_ui";
import {
TelemetryEvent,
TelemetryMeasurements,
TelemetryProperty,
} from "../telemetry/extTelemetryEvents";
import { localize } from "../utils/localizeUtils";
import { getNpmInstallLogInfo, getTestToolLogInfo } from "../utils/localEnvManagerUtils";
import { localize } from "../utils/localizeUtils";
import { processUtil } from "../utils/processUtil";
import {
clearAADAfterLocalDebugHelpLink,
DebugNoSessionId,
Expand All @@ -35,18 +38,18 @@ import {
issueTemplate,
m365AppsPrerequisitesHelpLink,
} from "./common/debugConstants";
import { localTelemetryReporter, sendDebugAllEvent } from "./localTelemetryReporter";
import { BaseTunnelTaskTerminal } from "./taskTerminal/baseTunnelTaskTerminal";
import { TeamsfxDebugConfiguration } from "./common/teamsfxDebugConfiguration";
import { allRunningTeamsfxTasks } from "./common/globalVariables";
import {
getLocalDebugSession,
endLocalDebugSession,
getLocalDebugSession,
getLocalDebugSessionId,
} from "./common/localDebugSession";
import { allRunningDebugSessions } from "./officeTaskHandler";
import { TeamsfxDebugConfiguration } from "./common/teamsfxDebugConfiguration";
import { deleteAad } from "./deleteAadHelper";
import { processUtil } from "../utils/processUtil";
import { localTelemetryReporter, sendDebugAllEvent } from "./localTelemetryReporter";
import { allRunningDebugSessions } from "./officeTaskHandler";
import { BaseTunnelTaskTerminal } from "./taskTerminal/baseTunnelTaskTerminal";
import { cdpClientManager, isM365CopilotChatDebugConfiguration } from "../pluginDebugger/cdpClient";

class NpmInstallTaskInfo {
private startTime: number;
Expand Down Expand Up @@ -453,6 +456,14 @@ async function onDidEndTaskProcessHandler(event: vscode.TaskProcessEndEvent): Pr
}

async function onDidStartDebugSessionHandler(event: vscode.DebugSession): Promise<void> {
if (featureFlagManager.getBooleanValue(FeatureFlags.ApiPluginDebug)) {
const port = isM365CopilotChatDebugConfiguration(event.configuration);
if (port) {
const url = event.configuration.url;
const name = event.configuration.name;
cdpClientManager.start(url, port, name);
}
}
if (globalVariables.workspaceUri && isValidProject(globalVariables.workspaceUri.fsPath)) {
const debugConfig = event.configuration as TeamsfxDebugConfiguration;
if (
Expand Down Expand Up @@ -540,11 +551,17 @@ export async function terminateAllRunningTeamsfxTasks(): Promise<void> {
}
}
allRunningTeamsfxTasks.clear();
BaseTunnelTaskTerminal.stopAll();
void deleteAad();
BaseTunnelTaskTerminal.stopAll();
}

async function onDidTerminateDebugSessionHandler(event: vscode.DebugSession): Promise<void> {
if (featureFlagManager.getBooleanValue(FeatureFlags.ApiPluginDebug)) {
const port = isM365CopilotChatDebugConfiguration(event.configuration);
if (port) {
await cdpClientManager.stop(port);
}
}
if (allRunningDebugSessions.has(event.id)) {
// a valid debug session
// send stop-debug event telemetry
Expand Down
Loading

0 comments on commit 8f0fc45

Please sign in to comment.