Skip to content

Commit

Permalink
Telemetry for Playbook Summary API (ThumbsUp/Down) (#1301)
Browse files Browse the repository at this point in the history
* Telemetry for Playbook Summary API (ThumbsUp/Down)

* Make action/outlineId options required in PlaybookOutlineEvent
  • Loading branch information
TamiTakamiya authored May 8, 2024
1 parent 17f082c commit b74f9dc
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 58 deletions.
91 changes: 54 additions & 37 deletions packages/ansible-language-server/src/ansibleLanguageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
TextDocumentSyncKind,
} from "vscode-languageserver";
import { TextDocument } from "vscode-languageserver-textdocument";
import { v4 as uuidv4 } from "uuid";
import {
doCompletion,
doCompletionResolve,
Expand All @@ -25,6 +26,10 @@ import { WorkspaceManager } from "./services/workspaceManager";
import { getAnsibleMetaData } from "./utils/getAnsibleMetaData";
import axios from "axios";
import { getBaseUri } from "./utils/webUtils";
import {
GenerationResponse,
SummaryResponse,
} from "./interfaces/lightspeedApi";

/**
* Initializes the connection and registers all lifecycle event handlers.
Expand Down Expand Up @@ -378,53 +383,65 @@ export class AnsibleLanguageService {
return explanation;
});

this.connection.onRequest("playbook/summary", async (params) => {
const accessToken: string = params["accessToken"];
const URL: string = params["URL"];
const content: string = params["content"];

const headers = {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
};
this.connection.onRequest(
"playbook/summary",
async (params): Promise<SummaryResponse> => {
const accessToken: string = params["accessToken"];
const URL: string = params["URL"];
const content: string = params["content"];

const axiosInstance = axios.create({
baseURL: `${getBaseUri(URL)}/api/v0`,
headers: headers,
});
const headers = {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
};

const result: string = await axiosInstance
.post("/ai/summaries/", { content: content })
.then((response) => {
return response.data.content;
const axiosInstance = axios.create({
baseURL: `${getBaseUri(URL)}/api/v0`,
headers: headers,
});

return result;
});
const result: SummaryResponse = await axiosInstance
.post("/ai/summaries/", {
content: content,
summaryId: uuidv4(),
})
.then((response) => {
return response.data;
});

this.connection.onRequest("playbook/generation", async (params) => {
const accessToken: string = params["accessToken"];
const URL: string = params["URL"];
const content: string = params["content"];
return result;
},
);

const headers = {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
};
this.connection.onRequest(
"playbook/generation",
async (params): Promise<GenerationResponse> => {
const accessToken: string = params["accessToken"];
const URL: string = params["URL"];
const content: string = params["content"];

const axiosInstance = axios.create({
baseURL: `${getBaseUri(URL)}/api/v0`,
headers: headers,
});
const headers = {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
};

const result: string = await axiosInstance
.post("/ai/generations/", { content: content })
.then((response) => {
return response.data.content;
const axiosInstance = axios.create({
baseURL: `${getBaseUri(URL)}/api/v0`,
headers: headers,
});

return result;
});
const result: GenerationResponse = await axiosInstance
.post("/ai/generations/", {
content: content,
generationId: uuidv4(),
})
.then((response) => {
return response.data;
});

return result;
},
);
}

private handleError(error: unknown, contextName: string) {
Expand Down
14 changes: 14 additions & 0 deletions packages/ansible-language-server/src/interfaces/lightspeedApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Interface for Lightspeed playbook generation/explanation APIs
*/
export interface GenerationResponse {
content: string;
format: string;
generationId: string;
}

export interface SummaryResponse {
content: string;
format: string;
summaryId: string;
}
5 changes: 5 additions & 0 deletions src/definitions/lightspeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export enum UserAction {
IGNORED = 2, // ignored the suggestion or didn't wait for suggestion to be displayed
}

export enum ThumbsUpDownAction {
UP = 0, // Thumbs Up
DOWN = 1, //Thumbs Down
}

// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace LightSpeedCommands {
export const LIGHTSPEED_AUTH_REQUEST = "ansible.lightspeed.oauth";
Expand Down
15 changes: 12 additions & 3 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import {
LightspeedUser,
AuthProviderType,
} from "./features/lightspeed/lightspeedUser";
import { PlaybookOutlineEvent } from "./interfaces/lightspeed";

export let client: LanguageClient;
export let lightSpeedManager: LightSpeedManager;
Expand Down Expand Up @@ -555,9 +556,17 @@ export async function activate(context: ExtensionContext): Promise<void> {
);

context.subscriptions.push(
vscode.commands.registerCommand("ansible.lightspeed.thumbsUpDown", () => {
window.showInformationMessage("Thank you for your feedback!");
}),
vscode.commands.registerCommand(
"ansible.lightspeed.thumbsUpDown",
async (param: PlaybookOutlineEvent) => {
lightSpeedManager.apiInstance.feedbackRequest(
{ playbookOutlineFeedback: param },
true,
true,
);
window.showInformationMessage("Thank you for your feedback!");
},
),
);

context.subscriptions.push(
Expand Down
41 changes: 27 additions & 14 deletions src/features/lightspeed/playbookGeneration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { getUri } from "../utils/getUri";
import { SettingsManager } from "../../settings";
import { isLightspeedEnabled } from "../../extension";
import { LightspeedUser } from "./lightspeedUser";
import {
GenerationResponse,
SummaryResponse,
} from "@ansible/ansible-language-server/src/interfaces/lightspeedApi";

async function openNewPlaybookEditor(playbook: string) {
const options = {
Expand Down Expand Up @@ -33,18 +37,21 @@ async function generatePlaybook(
lightspeedAuthenticatedUser: LightspeedUser,
settingsManager: SettingsManager,
panel: vscode.WebviewPanel,
) {
): Promise<GenerationResponse> {
const accessToken =
await lightspeedAuthenticatedUser.getLightspeedUserAccessToken();
if (!accessToken) {
panel.webview.postMessage({ command: "exception" });
}

const playbook: string = await client.sendRequest("playbook/generation", {
accessToken,
URL: settingsManager.settings.lightSpeedService.URL,
content,
});
const playbook: GenerationResponse = await client.sendRequest(
"playbook/generation",
{
accessToken,
URL: settingsManager.settings.lightSpeedService.URL,
content,
},
);

return playbook;
}
Expand All @@ -55,18 +62,21 @@ async function summarizeInput(
lightspeedAuthenticatedUser: LightspeedUser,
settingsManager: SettingsManager,
panel: vscode.WebviewPanel,
) {
): Promise<SummaryResponse> {
const accessToken =
await lightspeedAuthenticatedUser.getLightspeedUserAccessToken();
if (!accessToken) {
panel.webview.postMessage({ command: "exception" });
}

const summary: string = await client.sendRequest("playbook/summary", {
accessToken,
URL: settingsManager.settings.lightSpeedService.URL,
content,
});
const summary: SummaryResponse = await client.sendRequest(
"playbook/summary",
{
accessToken,
URL: settingsManager.settings.lightSpeedService.URL,
content,
},
);

return summary;
}
Expand Down Expand Up @@ -112,7 +122,7 @@ export async function showPlaybookGenerationPage(
panel,
);
panel?.dispose();
await openNewPlaybookEditor(playbook);
await openNewPlaybookEditor(playbook.content);
break;
}
case "summarizeInput": {
Expand All @@ -129,7 +139,10 @@ export async function showPlaybookGenerationPage(
}
case "thumbsUp":
case "thumbsDown":
vscode.commands.executeCommand("ansible.lightspeed.thumbsUpDown");
vscode.commands.executeCommand("ansible.lightspeed.thumbsUpDown", {
action: message.action,
outlineId: message.outlineId,
});
break;
}
});
Expand Down
12 changes: 11 additions & 1 deletion src/interfaces/lightspeed.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { AuthenticationSession } from "vscode";
import { LIGHTSPEED_USER_TYPE, UserAction } from "../definitions/lightspeed";
import {
LIGHTSPEED_USER_TYPE,
ThumbsUpDownAction,
UserAction,
} from "../definitions/lightspeed";

export interface LightspeedAuthSession extends AuthenticationSession {
rhUserHasSeat: boolean;
Expand Down Expand Up @@ -67,11 +71,17 @@ export interface IssueFeedbackEvent {
description: string;
}

export interface PlaybookOutlineEvent {
action: ThumbsUpDownAction;
outlineId: string;
}

export interface FeedbackRequestParams {
inlineSuggestion?: InlineSuggestionEvent;
sentimentFeedback?: SentimentEvent;
suggestionQualityFeedback?: SuggestionQualityEvent;
issueFeedback?: IssueFeedbackEvent;
playbookOutlineFeedback?: PlaybookOutlineEvent;
model?: string;
}

Expand Down
17 changes: 14 additions & 3 deletions src/webview/apps/lightspeed/playbookGeneration/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
vsCodeTextField,
TextArea,
} from "@vscode/webview-ui-toolkit";
import { ThumbsUpDownAction } from "../../../../definitions/lightspeed";

provideVSCodeDesignSystem().register(
vsCodeButton(),
Expand All @@ -20,6 +21,7 @@ const TEXTAREA_MAX_HEIGHT = 500;
let savedInput: string;
let savedInputHeight: string | undefined;
let savedSummary: string;
let outlineId: string | undefined;

const vscode = acquireVsCodeApi();

Expand Down Expand Up @@ -58,7 +60,8 @@ window.addEventListener("message", (event) => {
changeDisplay("promptContainer", "block");

const element = document.getElementById("playbook-text-area") as TextArea;
savedSummary = element.value = message.summary;
savedSummary = element.value = message.summary.content;
outlineId = message.summary.summaryId;
resetTextAreaHeight();

const prompt = document.getElementById("prompt") as HTMLSpanElement;
Expand Down Expand Up @@ -165,7 +168,11 @@ function sendThumbsup() {
) as Button;
thumbsUpButton.setAttribute("class", "iconButtonSelected");
thumbsDownButton.setAttribute("class", "iconButton");
vscode.postMessage({ command: "thumbsUp" });
vscode.postMessage({
command: "thumbsUp",
action: ThumbsUpDownAction.UP,
outlineId,
});
}

function sendThumbsdown() {
Expand All @@ -175,7 +182,11 @@ function sendThumbsdown() {
) as Button;
thumbsUpButton.setAttribute("class", "iconButton");
thumbsDownButton.setAttribute("class", "iconButtonSelected");
vscode.postMessage({ command: "thumbsDown" });
vscode.postMessage({
command: "thumbsDown",
action: ThumbsUpDownAction.DOWN,
outlineId,
});
}

function getTextAreaInShadowDOM() {
Expand Down

0 comments on commit b74f9dc

Please sign in to comment.