Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into chat-app-4
Browse files Browse the repository at this point in the history
  • Loading branch information
kaizu-xyz committed Nov 2, 2023
2 parents 2e884d9 + 66379d9 commit c3e1521
Show file tree
Hide file tree
Showing 11 changed files with 177 additions and 7 deletions.
3 changes: 2 additions & 1 deletion vsce/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@
"pako": "^2.1.0",
"rimraf": "^5.0.1",
"uuid": "^9.0.1",
"ws": "^8.13.0"
"ws": "^8.13.0",
"mixpanel": "^0.18.0"
}
}
4 changes: 4 additions & 0 deletions vsce/src/chat/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ export async function initChat(
chat.setMessages(message.msgs); // TODO: Move to addMessage to reduce communication overhead
storeChat(chat);
break;
case "getUserId":
const userId = vscode.workspace.getConfiguration().get<string>('NeatworkAi.neatcoder.userId');
panel.webview.postMessage({ command: 'userId', userId: userId });
break;
}
},
undefined,
Expand Down
3 changes: 3 additions & 0 deletions vsce/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const CONFIG = {
mixpanelToken: 'fad3409b4b79d03a837adc7db17f0e97',
};
4 changes: 4 additions & 0 deletions vsce/src/core/workflows/initCodeBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as wasm from "../../../pkg/neatcoder";
import { appDataManager } from "../appData";
import { addLanguage } from "../commands/addLanguage";
import { startLoading, stopLoading } from "../../utils/statusBar";
import MixpanelHelper from "../../utils/mixpanelHelper";

/**
* Asynchronously initiates a prompt to gather user input and starts processing based on the input.
Expand Down Expand Up @@ -34,6 +35,9 @@ export async function initCodeBase(
});

if (userInput !== undefined) {
let mixpanel = MixpanelHelper.getInstance();
mixpanel.trackEvent('initCodeBase', { userInput: userInput });

startLoading("Prompting the LLM..");
await appManager.initCodeBase(llmParams, userInput);
stopLoading();
Expand Down
24 changes: 23 additions & 1 deletion vsce/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { initCodeBase, appDataManager, setupDotNeatWatcher } from "./core";
import { getOrSetApiKey, initStatusBar, initLogger, logger } from "./utils";
import { ChatProvider, initChat, setupChatWatcher } from "./chat";
import { getOrSetModelVersion, setModelVersion } from "./utils/utils";
import MixpanelHelper from "./utils/mixpanelHelper";

// Declare activePanels at the top-level to make it accessible throughout your extension's main script.
let configWatcher: fs.FSWatcher | undefined; // TODO: remove, not being used.
Expand Down Expand Up @@ -54,6 +55,10 @@ export async function activate(context: vscode.ExtensionContext) {
const interfacesProvider = new InterfacesProvider();
const chatProvider = new ChatProvider();

// init Mixpanel
let mixpanel = MixpanelHelper.getInstance();
mixpanel.trackEvent("activate");

// Read or Initialize Application state

let appManager = new appDataManager(jobQueueProvider, auditTrailProvider);
Expand Down Expand Up @@ -102,6 +107,7 @@ export async function activate(context: vscode.ExtensionContext) {

// Register the Chat command
vscode.commands.registerCommand("extension.createChat", () => {
mixpanel.trackEvent('createChat');
initChat(context);
});

Expand All @@ -114,24 +120,30 @@ export async function activate(context: vscode.ExtensionContext) {

context.subscriptions.push(
vscode.commands.registerCommand("extension.addDatastore", async () => {
mixpanel.trackEvent('addDatastore');
addInterface(wasm.InterfaceType.Database, interfacesProvider);
})
);

context.subscriptions.push(
vscode.commands.registerCommand("extension.addApi", async () => {
mixpanel.trackEvent('addApi');
addInterface(wasm.InterfaceType.Api, interfacesProvider);
})
);

context.subscriptions.push(
vscode.commands.registerCommand("extension.addSchema", addSchema)
vscode.commands.registerCommand("extension.addSchema", async (item: InterfaceItem) => {
mixpanel.trackEvent('addSchema');
await addSchema(item);
})
);

context.subscriptions.push(
vscode.commands.registerCommand(
"extension.removeInterface",
(item: InterfaceItem) => {
mixpanel.trackEvent('removeInterface');
removeInterface(item);
}
)
Expand All @@ -141,6 +153,7 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand(
"extension.removeSchema",
(item: InterfaceItem) => {
mixpanel.trackEvent('removeSchema');
removeSchema(item);
}
)
Expand All @@ -150,6 +163,7 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand(
"extension.runTask",
async (taskView: TaskView) => {
mixpanel.trackEvent('runTask');
let llmParams = await getLLMParams();
await runTask(taskView, llmParams, appManager);
}
Expand All @@ -160,25 +174,29 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand(
"extension.removeTask",
(taskView: TaskView) => {
mixpanel.trackEvent('removeTask');
removeTask(taskView, appManager);
}
)
);

context.subscriptions.push(
vscode.commands.registerCommand("extension.removeAllTasks", () => {
mixpanel.trackEvent('removeAllTasks');
removeAllTasks(appManager);
})
);

context.subscriptions.push(
vscode.commands.registerCommand("extension.chooseModel", async () => {
mixpanel.trackEvent('chooseModel');
await setModelVersion();
})
);

context.subscriptions.push(
vscode.commands.registerCommand("extension.runAllTasks", async () => {
mixpanel.trackEvent('runAllTasks');
let llmParams = await getLLMParams();
runAllTasks(llmParams, appManager);
})
Expand All @@ -188,6 +206,7 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand(
"extension.retryTask",
async (taskView: TaskView) => {
mixpanel.trackEvent('retryTask');
let llmParams = await getLLMParams();
await retryTask(taskView, llmParams, appManager);
}
Expand All @@ -208,6 +227,9 @@ async function getLLMParams(): Promise<wasm.OpenAIParams> {

// This method is called when the extension is deactivated
export function deactivate() {
let mixpanel = MixpanelHelper.getInstance();
mixpanel.trackEvent("deactivate");

if (configWatcher) {
configWatcher.close();
}
Expand Down
63 changes: 63 additions & 0 deletions vsce/src/utils/mixpanelHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as mixpanel from 'mixpanel';
import * as vscode from 'vscode';
import { v4 as uuidv4 } from 'uuid';
import { CONFIG } from '../config';
import * as os from 'os';

class MixpanelHelper {
private static instance: MixpanelHelper;
private mixpanelInstance: mixpanel.Mixpanel;
private userId: string;

private constructor(token: string, config?: mixpanel.InitConfig) {
const defaultConfig = {
geolocate: true
};

// If there's any user-provided config, it will overwrite the defaults
const finalConfig = { ...defaultConfig, ...config };

this.mixpanelInstance = mixpanel.init(token, finalConfig);

// Retrieve or generate the userId
this.userId = this.getUserId();
}

static getInstance(config?: mixpanel.InitConfig): MixpanelHelper {
if (!MixpanelHelper.instance) {
MixpanelHelper.instance = new MixpanelHelper(CONFIG.mixpanelToken, config);
}
return MixpanelHelper.instance;
}

private getUserId(): string {
const userId = vscode.workspace.getConfiguration().get<string>('NeatworkAi.neatcoder.userId');
if (userId) {
return userId;
}

const newUserId = uuidv4();
vscode.workspace.getConfiguration().update('NeatworkAi.neatcoder.userId', newUserId, vscode.ConfigurationTarget.Global);
return newUserId;
}

private getExtensionVersion(): string {
const extension = vscode.extensions.getExtension('NeatworkAi.neatcoder');
return extension?.packageJSON.version || 'unknown';
}

trackEvent(eventName: string, properties: mixpanel.PropertyDict = {}): void {
properties.distinct_id = this.userId;
properties.$os = os.type();
properties.extensionVersion = this.getExtensionVersion();
properties.moduleName = 'VSCodeExtension';

this.mixpanelInstance.track(eventName, properties, (err) => {
if (err) {
console.error('Error sending event to Mixpanel:', err);
}
});
}
}

export default MixpanelHelper;
4 changes: 3 additions & 1 deletion webview/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"font-awesome": "^4.7.0",
"highlight.js": "^11.9.0",
"marked": "^9.1.2",
"mixpanel-browser": "^2.47.0",
"quill": "^1.3.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down Expand Up @@ -51,6 +52,7 @@
"devDependencies": {
"@types/marked": "^6.0.0",
"@types/quill": "^2.0.13",
"@types/turndown": "^5.0.3"
"@types/turndown": "^5.0.3",
"@types/mixpanel-browser": "^2.47.4"
}
}
11 changes: 11 additions & 0 deletions webview/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
// import React from 'react';
import './App.css';
import ChatContainer from './ components/chatContainer';
import { useEffect } from 'react';
import MixpanelWebviewHelper from './mixpanel-webview-helper';
// import 'highlight.js/styles/atom-one-dark.css';

function App() {
useEffect(() => {
try {
const mixpanelWebview = MixpanelWebviewHelper.getInstance();
console.log("MixpanelWebviewHelper initialized", mixpanelWebview);
} catch (error) {
console.error("Error initializing MixpanelWebviewHelper:", error);
}
}, []);
return (
<div className="App">
<header>
Expand Down
3 changes: 3 additions & 0 deletions webview/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const CONFIG = {
mixpanelToken: 'fad3409b4b79d03a837adc7db17f0e97',
};
20 changes: 16 additions & 4 deletions webview/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import MixpanelWebviewHelper from './mixpanel-webview-helper';
import { Metric } from 'web-vitals';

const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
Expand All @@ -13,7 +15,17 @@ root.render(
</React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
function sendToMixpanel(metric: Metric) {
const mixpanelWebview = MixpanelWebviewHelper.getInstance();

const eventData = {
id: metric.id,
name: metric.name,
value: metric.value,
delta: metric.delta,
};

mixpanelWebview.trackEvent('WebVitals', eventData);
}

reportWebVitals(sendToMixpanel);
45 changes: 45 additions & 0 deletions webview/src/mixpanel-webview-helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import mixpanel, { Dict } from 'mixpanel-browser';
import { CONFIG } from './config';

class MixpanelWebviewHelper {
private static instance: MixpanelWebviewHelper;
private userId: string | undefined;

private constructor() {
mixpanel.init(CONFIG.mixpanelToken);
this.initializeUserId();
}

private async initializeUserId() {
this.userId = await this.getUserIdFromExtension();
mixpanel.identify(this.userId);
}

static getInstance(): MixpanelWebviewHelper {
if (!MixpanelWebviewHelper.instance) {
MixpanelWebviewHelper.instance = new MixpanelWebviewHelper();
}
return MixpanelWebviewHelper.instance;
}

private getUserIdFromExtension(): Promise<string> {
return new Promise((resolve) => {
const vscode = acquireVsCodeApi();
vscode.postMessage({ command: 'getUserId' });

window.addEventListener('message', event => {
const message = event.data;
if (message.command === 'userId') {
resolve(message.userId);
}
});
});
}

trackEvent(eventName: string, properties: Dict = {}): void {
properties.moduleName = 'Webview';
mixpanel.track(eventName, properties);
}
}

export default MixpanelWebviewHelper;

0 comments on commit c3e1521

Please sign in to comment.