Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional context for lightspeed suggestions #970

Closed
wants to merge 1 commit into from
Closed
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
1 change: 1 addition & 0 deletions .config/dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ untildify
userdata
usermod
uuidv4
varInfiles
venvs
vscoss
vsix
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -680,15 +680,18 @@
"@vscode/webview-ui-toolkit": "^1.2.2",
"axios": "^1.3.4",
"ini": "^4.0.0",
"minimatch": "^9.0.3",
"untildify": "^4.0.0",
"uuid": "^9.0.0",
"vscode-languageclient": "^8.1.0",
"vscode-uri": "^3.0.7",
"yaml": "^2.2.2"
},
"description": "Ansible language support",
"devDependencies": {
"@types/chai": "^4.3.5",
"@types/glob": "^8.1.0",
"@types/minimatch": "^5.1.2",
"@types/mocha": "^10.0.1",
"@types/node": "^18.16.3",
"@types/sinon": "^10.0.14",
Expand Down
56 changes: 26 additions & 30 deletions src/definitions/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* eslint-disable @typescript-eslint/no-namespace */

import { IAnsibleFileTypes } from "../interfaces/lightspeed";

export namespace AnsibleCommands {
export const ANSIBLE_VAULT = "extension.ansible.vault";
export const ANSIBLE_INVENTORY_RESYNC = "extension.resync-ansible-inventory";
Expand All @@ -9,36 +11,30 @@ export namespace AnsibleCommands {
"ansible.python.set.interpreter";
}

// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace LightSpeedCommands {
export const LIGHTSPEED_AUTH_REQUEST = "ansible.lightspeed.oauth";
export const LIGHTSPEED_SUGGESTION_COMMIT =
"ansible.lightspeed.inlineSuggest.accept";
export const LIGHTSPEED_SUGGESTION_HIDE =
"ansible.lightspeed.inlineSuggest.hide";
export const LIGHTSPEED_SUGGESTION_TRIGGER =
"ansible.lightspeed.inlineSuggest.trigger";
export const LIGHTSPEED_STATUS_BAR_CLICK =
"ansible.lightspeed.statusBar.click";
export const LIGHTSPEED_FETCH_TRAINING_MATCHES =
"ansible.lightspeed.fetchTrainingMatches";
export const LIGHTSPEED_CLEAR_TRAINING_MATCHES =
"ansible.lightspeed.clearTrainingMatches";
export const LIGHTSPEED_FEEDBACK = "ansible.lightspeed.feedback";
}

export const LIGHTSPEED_API_VERSION = "v0";
export const LIGHTSPEED_SUGGESTION_COMPLETION_URL = `${LIGHTSPEED_API_VERSION}/ai/completions/`;
export const LIGHTSPEED_SUGGESTION_FEEDBACK_URL = `${LIGHTSPEED_API_VERSION}/ai/feedback/`;
export const LIGHTSPEED_SUGGESTION_ATTRIBUTIONS_URL = `${LIGHTSPEED_API_VERSION}/ai/attributions/`;
export const LIGHTSPEED_ME_AUTH_URL = `/api/${LIGHTSPEED_API_VERSION}/me/`;
export const AnsibleFileTypes: IAnsibleFileTypes = {
"**/playbooks/*.{yml,yaml}": "playbook",
"**/*playbook*.{yml,yaml}": "playbook",
"**/roles/**/tasks/**/*.{yml,yaml}": "tasks_in_role",
"**/tasks/**/*.{yaml,yml}": "tasks",
};

export const LIGHTSPEED_FEEDBACK_FORM_URL =
"https://red.ht/ansible-ai-feedback";
export const PlaybookKeywords = [
"hosts",
"tasks",
"vars_files",
"roles",
"pre_tasks",
"post_tasks",
];

export const LIGHTSPEED_REPORT_EMAIL_ADDRESS = "[email protected]";
export const LIGHTSPEED_STATUS_BAR_CLICK_HANDLER =
"ansible.lightspeed.statusBar.clickHandler";
export const StandardRolePaths = [
"~/.ansible/roles",
"/usr/share/ansible/roles",
"/etc/ansible/roles",
];

export const LIGHTSPEED_CLIENT_ID = "Vu2gClkeR5qUJTUGHoFAePmBznd6RZjDdy5FW2wy";
export const LIGHTSPEED_SERVICE_LOGIN_TIMEOUT = 120000;
export const IncludeVarValidTaskName = [
"include_vars",
"ansible.builtin.include_vars",
"ansible.legacy.include_vars",
];
110 changes: 33 additions & 77 deletions src/definitions/lightspeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,80 +24,36 @@ export enum AnsibleContentUploadTrigger {
TAB_CHANGE = 2,
}

export interface FeedbackResponseParams {
message: string;
}

export interface InlineSuggestionEvent {
latency?: number;
userActionTime?: number;
documentUri?: string;
action?: UserAction;
error?: string;
suggestionId?: string;
activityId?: string;
}

export interface AnsibleContentEvent {
content: string;
documentUri: string;
trigger: AnsibleContentUploadTrigger;
activityId: string | undefined;
}
export interface SentimentEvent {
value: number;
feedback: string;
}

export interface SuggestionQualityEvent {
prompt: string;
providedSuggestion: string;
expectedSuggestion: string;
additionalComment: string;
}
export interface IssueFeedbackEvent {
type: "bug-report" | "feature-request";
title: string;
description: string;
}

export interface FeedbackRequestParams {
inlineSuggestion?: InlineSuggestionEvent;
ansibleContent?: AnsibleContentEvent;
sentimentFeedback?: SentimentEvent;
suggestionQualityFeedback?: SuggestionQualityEvent;
issueFeedback?: IssueFeedbackEvent;
}

export interface IDocumentTrackerFields {
activityId: string;
content: string;
}

export interface IDocumentTracker {
[key: string]: IDocumentTrackerFields;
}

export interface AttributionsRequestParams {
suggestion: string;
suggestionId: string;
}

export interface IAttributionsParams {
repo_name: string;
repo_url: string;
path: string;
license: string;
data_source: string;
ansible_type: string;
score: number;
}

export interface AttributionsResponseParams {
attributions: IAttributionsParams[];
}

export interface ISuggestionDetails {
suggestion: string;
suggestionId: string;
}
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace LightSpeedCommands {
export const LIGHTSPEED_AUTH_REQUEST = "ansible.lightspeed.oauth";
export const LIGHTSPEED_SUGGESTION_COMMIT =
"ansible.lightspeed.inlineSuggest.accept";
export const LIGHTSPEED_SUGGESTION_HIDE =
"ansible.lightspeed.inlineSuggest.hide";
export const LIGHTSPEED_SUGGESTION_TRIGGER =
"ansible.lightspeed.inlineSuggest.trigger";
export const LIGHTSPEED_STATUS_BAR_CLICK =
"ansible.lightspeed.statusBar.click";
export const LIGHTSPEED_FETCH_TRAINING_MATCHES =
"ansible.lightspeed.fetchTrainingMatches";
export const LIGHTSPEED_CLEAR_TRAINING_MATCHES =
"ansible.lightspeed.clearTrainingMatches";
export const LIGHTSPEED_FEEDBACK = "ansible.lightspeed.feedback";
}

export const LIGHTSPEED_API_VERSION = "v0";
export const LIGHTSPEED_SUGGESTION_COMPLETION_URL = `${LIGHTSPEED_API_VERSION}/ai/completions/`;
export const LIGHTSPEED_SUGGESTION_FEEDBACK_URL = `${LIGHTSPEED_API_VERSION}/ai/feedback/`;
export const LIGHTSPEED_SUGGESTION_ATTRIBUTIONS_URL = `${LIGHTSPEED_API_VERSION}/ai/attributions/`;
export const LIGHTSPEED_ME_AUTH_URL = `/api/${LIGHTSPEED_API_VERSION}/me/`;

export const LIGHTSPEED_FEEDBACK_FORM_URL =
"https://red.ht/ansible-ai-feedback";

export const LIGHTSPEED_REPORT_EMAIL_ADDRESS = "[email protected]";
export const LIGHTSPEED_STATUS_BAR_CLICK_HANDLER =
"ansible.lightspeed.statusBar.clickHandler";

export const LIGHTSPEED_CLIENT_ID = "Vu2gClkeR5qUJTUGHoFAePmBznd6RZjDdy5FW2wy";
export const LIGHTSPEED_SERVICE_LOGIN_TIMEOUT = 120000;
6 changes: 5 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
workspace,
} from "vscode";
import { toggleEncrypt } from "./features/vault";
import { AnsibleCommands, LightSpeedCommands } from "./definitions/constants";
import { AnsibleCommands } from "./definitions/constants";
import { LightSpeedCommands } from "./definitions/lightspeed";
import {
TelemetryErrorHandler,
TelemetryOutputChannel,
Expand Down Expand Up @@ -60,9 +61,12 @@ import { AnsibleToxProvider } from "./features/ansibleTox/provider";
import { findProjectDir } from "./features/ansibleTox/utils";
import { LightspeedFeedbackWebviewViewProvider } from "./features/lightspeed/feedbackWebviewViewProvider";
import { LightspeedFeedbackWebviewProvider } from "./features/lightspeed/feedbackWebviewProvider";
import { IFileSystemWatchers } from "./interfaces/watchers";

export let client: LanguageClient;
export let lightSpeedManager: LightSpeedManager;
export const globalFileSystemWatcher: IFileSystemWatchers = {};

const lsName = "Ansible Support";

export async function activate(context: ExtensionContext): Promise<void> {
Expand Down
4 changes: 2 additions & 2 deletions src/features/lightspeed/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import {
FeedbackResponseParams,
AttributionsRequestParams,
AttributionsResponseParams,
} from "../../definitions/lightspeed";
} from "../../interfaces/lightspeed";
import {
LIGHTSPEED_SUGGESTION_ATTRIBUTIONS_URL,
LIGHTSPEED_SUGGESTION_COMPLETION_URL,
LIGHTSPEED_SUGGESTION_FEEDBACK_URL,
} from "../../definitions/constants";
} from "../../definitions/lightspeed";
import { LightSpeedAuthenticationProvider } from "./lightSpeedOAuthProvider";
import { getBaseUri } from "./utils/webUtils";

Expand Down
2 changes: 1 addition & 1 deletion src/features/lightspeed/attributionsWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
AttributionsResponseParams,
IAttributionsParams,
ISuggestionDetails,
} from "../../definitions/lightspeed";
} from "../../interfaces/lightspeed";
import { getCurrentUTCDateTime } from "../utils/dateTime";

export class AttributionsWebview implements vscode.WebviewViewProvider {
Expand Down
38 changes: 36 additions & 2 deletions src/features/lightspeed/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@ import { TelemetryManager } from "../../utils/telemetryUtils";
import { SettingsManager } from "../../settings";
import { LightSpeedAuthenticationProvider } from "./lightSpeedOAuthProvider";
import {
AnsibleContentUploadTrigger,
FeedbackRequestParams,
IDocumentTracker,
} from "../../definitions/lightspeed";
IIncludeVarsContext,
IWorkSpaceRolesContext,
} from "../../interfaces/lightspeed";
import { AnsibleContentUploadTrigger } from "../../definitions/lightspeed";
import { AttributionsWebview } from "./attributionsWebview";
import {
ANSIBLE_LIGHTSPEED_AUTH_ID,
ANSIBLE_LIGHTSPEED_AUTH_NAME,
} from "./utils/webUtils";
import { LightspeedStatusBar } from "./statusBar";
import { IVarsFileContext } from "../../interfaces/lightspeed";
import { getCustomRolePaths, getCommonRoles } from "../utils/ansible";
import { watchRolesDirectory } from "./utils/watchers";

export class LightSpeedManager {
private context;
Expand All @@ -27,6 +32,9 @@ export class LightSpeedManager {
public lightSpeedActivityTracker: IDocumentTracker;
public attributionsProvider: AttributionsWebview;
public statusBarProvider: LightspeedStatusBar;
public ansibleVarFilesCache: IVarsFileContext = {};
public ansibleRolesCache: IWorkSpaceRolesContext = {};
public ansibleIncludeVarsCache: IIncludeVarsContext = {};

constructor(
context: vscode.ExtensionContext,
Expand Down Expand Up @@ -68,6 +76,9 @@ export class LightSpeedManager {
client,
settingsManager
);

// create workspace context for ansible roles
this.setContext();
}

public async reInitialize(): Promise<void> {
Expand All @@ -76,14 +87,37 @@ export class LightSpeedManager {
.get("lightspeed.enabled");

if (!lightspeedEnabled) {
await this.resetContext();
await this.lightSpeedAuthenticationProvider.dispose();
this.statusBarProvider.statusBar.hide();
return;
} else {
this.lightSpeedAuthenticationProvider.initialize();
this.setContext();
}
}

private async resetContext(): Promise<void> {
this.ansibleVarFilesCache = {};
this.ansibleRolesCache = {};
}

private setContext(): void {
const workspaceFolders = vscode.workspace.workspaceFolders;
if (workspaceFolders) {
for (const workspaceFolder of workspaceFolders) {
const workSpaceRoot = workspaceFolder.uri.fsPath;
const rolesPath = getCustomRolePaths(workSpaceRoot);
for (const rolePath of rolesPath) {
watchRolesDirectory(this, rolePath, workSpaceRoot);
}
}
}
const commonRolesPath = getCommonRoles() || [];
for (const rolePath of commonRolesPath) {
watchRolesDirectory(this, rolePath);
}
}
public ansibleContentFeedback(
document: vscode.TextDocument,
trigger: AnsibleContentUploadTrigger
Expand Down
Loading
Loading