Skip to content

Commit

Permalink
AAP-19001: No training matches found for the latest accepted suggestion.
Browse files Browse the repository at this point in the history
  • Loading branch information
manstis committed Mar 29, 2024
1 parent 60ef443 commit f99821f
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 132 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ coverage
*.pyc

test/testFixtures/.vscode/
examples/.vscode/
18 changes: 12 additions & 6 deletions src/features/lightspeed/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
FeedbackResponseParams,
ContentMatchesRequestParams,
ContentMatchesResponseParams,
IError,
} from "../../interfaces/lightspeed";
import {
LIGHTSPEED_SUGGESTION_CONTENT_MATCHES_URL,
Expand All @@ -20,9 +21,11 @@ import { LightSpeedAuthenticationProvider } from "./lightSpeedOAuthProvider";
import { getBaseUri } from "./utils/webUtils";
import { ANSIBLE_LIGHTSPEED_API_TIMEOUT } from "../../definitions/constants";
import { UserAction } from "../../definitions/lightspeed";
import { retrieveError } from "./handleApiError";
import { mapError } from "./handleApiError";
import { lightSpeedManager } from "../../extension";

const UNKNOWN_ERROR: string = "An unknown error occurred.";

export class LightSpeedAPI {
private axiosInstance: AxiosInstance | undefined;
private settingsManager: SettingsManager;
Expand Down Expand Up @@ -142,7 +145,8 @@ export class LightSpeedAPI {
} catch (error) {
this._inlineSuggestionFeedbackIgnoredPending = false;
const err = error as AxiosError;
vscode.window.showErrorMessage(retrieveError(err));
const mappedError: IError = mapError(err);
vscode.window.showErrorMessage(mappedError.message ?? UNKNOWN_ERROR);
return {} as CompletionResponseParams;
} finally {
if (this._inlineSuggestionFeedbackIgnoredPending) {
Expand Down Expand Up @@ -215,14 +219,15 @@ export class LightSpeedAPI {
return response.data;
} catch (error) {
const err = error as AxiosError;
vscode.window.showErrorMessage(retrieveError(err));
const mappedError: IError = mapError(err);
vscode.window.showErrorMessage(mappedError.message ?? UNKNOWN_ERROR);
return {} as FeedbackResponseParams;
}
}

public async contentMatchesRequest(
inputData: ContentMatchesRequestParams
): Promise<ContentMatchesResponseParams> {
): Promise<ContentMatchesResponseParams | IError> {
// return early if the user is not authenticated
if (!(await this.lightSpeedAuthProvider.isAuthenticated())) {
vscode.window.showErrorMessage(
Expand Down Expand Up @@ -256,8 +261,9 @@ export class LightSpeedAPI {
return response.data;
} catch (error) {
const err = error as AxiosError;
vscode.window.showErrorMessage(retrieveError(err));
return {} as ContentMatchesResponseParams;
const mappedError: IError = mapError(err);
vscode.window.showErrorMessage(mappedError.message ?? UNKNOWN_ERROR);
return mappedError;
}
}
}
76 changes: 69 additions & 7 deletions src/features/lightspeed/contentMatchesWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
IContentMatch,
IContentMatchParams,
ISuggestionDetails,
IError,
} from "../../interfaces/lightspeed";
import { getCurrentUTCDateTime } from "../utils/dateTime";
import * as yaml from "yaml";
Expand Down Expand Up @@ -61,7 +62,7 @@ export class ContentMatchesWebview implements vscode.WebviewViewProvider {
async requestInlineSuggestContentMatches(
suggestion: string,
suggestionId: string
): Promise<ContentMatchesResponseParams> {
): Promise<ContentMatchesResponseParams | IError> {
const taskArray = suggestion
.trim()
.split(/\n\s*\n/)
Expand All @@ -83,7 +84,7 @@ export class ContentMatchesWebview implements vscode.WebviewViewProvider {
)}`
);

const outputData: ContentMatchesResponseParams =
const outputData: ContentMatchesResponseParams | IError =
await this.apiInstance.contentMatchesRequest(contentMatchesRequestData);
this.log(
`${getCurrentUTCDateTime().toISOString()}: response data from Ansible lightspeed:\n${JSON.stringify(
Expand All @@ -107,22 +108,82 @@ export class ContentMatchesWebview implements vscode.WebviewViewProvider {
this._view.webview.html = "";
}

public isError(
contentMatchResponses: ContentMatchesResponseParams | IError
): contentMatchResponses is IError {
return (contentMatchResponses as IError).code !== undefined;
}

private async getWebviewContent(): Promise<string> {
const noContentMatchesFoundHtml = `<html><body>No training matches found for the latest accepted suggestion.</body></html>`;
const noActiveSuggestionHtml = `
<html>
<body>
<p>Training matches cannot be retrieved. No active suggestion found.</p>
</body>
</html>`;
if (
this.suggestionDetails.length === 0 ||
!this.suggestionDetails[0].suggestion
) {
return noContentMatchesFoundHtml;
return noActiveSuggestionHtml;
}

const suggestion = this.suggestionDetails[0].suggestion;
const suggestionId = this.suggestionDetails[0].suggestionId;

const contentMatchResponses = await this.requestInlineSuggestContentMatches(
suggestion,
suggestionId
);
this.log(contentMatchResponses);

if (this.isError(contentMatchResponses)) {
return this.getErrorWebviewContent(contentMatchResponses);
} else {
return this.getContentMatchWebviewContent(
suggestion,
contentMatchResponses
);
}
}

private async getErrorWebviewContent(error: IError) {
let detail: unknown = error.detail;
if (typeof error.detail === "string") {
detail = error.detail as string;
} else if (typeof error.detail === "object") {
detail = JSON.stringify(error.detail, undefined, " ");
}

const errorHtml = `
<html>
<head>
<!-- https://code.visualstudio.com/api/extension-guides/webview#content-security-policy -->
<meta http-equiv="Content-Security-Policy" content="default-src 'none';">
</head>
<body>
<p>An error occurred trying to retrieve the training matches.</p>
<p><b>Message:</b> ${error.message}</p>
<details>
<summary><b>Detail:</b></summary>
<p>${detail}</p>
</details>
</body>
</html>
`;
return errorHtml;
}

private async getContentMatchWebviewContent(
suggestion: string,
contentMatchResponses: ContentMatchesResponseParams
) {
const noContentMatchesFoundHtml = `
<html>
<body>
<p>No training matches found for the latest accepted suggestion.</p>
</body>
</html>
`;
if (
Object.keys(contentMatchResponses).length === 0 ||
contentMatchResponses.contentmatches.length === 0
Expand Down Expand Up @@ -168,12 +229,13 @@ export class ContentMatchesWebview implements vscode.WebviewViewProvider {
rhUserHasSeat === true
);
}
const html = `<html>
const html = `
<html>
<body>
${contentMatchesHtml}
</body>
</html>
`;
`;
return html;
}

Expand Down
Loading

0 comments on commit f99821f

Please sign in to comment.