diff --git a/packages/analysis-engine/src/engine.ts b/packages/analysis-engine/src/engine.ts new file mode 100644 index 00000000..110b6416 --- /dev/null +++ b/packages/analysis-engine/src/engine.ts @@ -0,0 +1,119 @@ +import "reflect-metadata"; + +import { container } from "tsyringe"; + +import { buildCommitDict } from "./commit.util"; +import { buildCSMDict } from "./csm"; +import getCommitRaws from "./parser"; +import { PluginOctokit } from "./pluginOctokit"; +import { buildStemDict } from "./stem"; +import { getSummary } from "./summary"; +import type { CommitNode } from "./types"; + +export type AnalysisEngineArgs = { + isDebugMode?: boolean; + gitLog: string; + owner: string; + repo: string; + baseBranchName: string; + auth?: string; +}; + +export class AnalysisEngine { + private static instance: AnalysisEngine | null = null; + private gitLog!: string; + private isDebugMode?: boolean; + private octokit!: PluginOctokit; + private baseBranchName!: string; + private nodes?: CommitNode[]; + private isInitialized: boolean = false; + + private constructor() {} + + public static getInstance(): AnalysisEngine { + if (!AnalysisEngine.instance) { + AnalysisEngine.instance = new AnalysisEngine(); + } + return AnalysisEngine.instance; + } + + public initialize(args: AnalysisEngineArgs): void { + const { isDebugMode, gitLog, owner, repo, auth, baseBranchName } = args; + this.gitLog = gitLog; + this.baseBranchName = baseBranchName; + this.isDebugMode = isDebugMode; + container.register("OctokitOptions", { + useValue: { + owner, + repo, + options: { + auth, + }, + }, + }); + this.octokit = container.resolve(PluginOctokit); + this.isInitialized = true; + } + + private checkInitialization() { + if (!this.isInitialized) { + throw new Error("AnalysisEngine is not initialized. Call initialize() first."); + } + } + + public async analyzeGit() { + this.checkInitialization(); + + if (!this.gitLog) { + throw new Error("AnalysisEngine is not initialized. Call initialize() first."); + } + + let isPRSuccess = true; + if (this.isDebugMode) console.log("baseBranchName: ", this.baseBranchName); + + const commitRaws = getCommitRaws(this.gitLog); + if (this.isDebugMode) console.log("commitRaws: ", commitRaws); + + const commitDict = buildCommitDict(commitRaws); + if (this.isDebugMode) console.log("commitDict: ", commitDict); + + const pullRequests = await this.octokit + .getPullRequests() + .catch((err) => { + console.error(err); + isPRSuccess = false; + return []; + }) + .then((pullRequests) => { + console.log("success, pr = ", pullRequests); + return pullRequests; + }); + if (this.isDebugMode) console.log("pullRequests: ", pullRequests); + + const stemDict = buildStemDict(commitDict, this.baseBranchName); + if (this.isDebugMode) console.log("stemDict: ", stemDict); + const csmDict = buildCSMDict(commitDict, stemDict, this.baseBranchName, pullRequests); + if (this.isDebugMode) console.log("csmDict: ", csmDict); + this.nodes = stemDict.get(this.baseBranchName)?.nodes; + + return { + isPRSuccess, + csmDict, + }; + } + + public updateArgs(args: AnalysisEngineArgs) { + if (container.isRegistered("OctokitOptions")) container.clearInstances(); + this.initialize(args); + } + + public async geminiCommitSummary() { + this.checkInitialization(); + if (!this.nodes) { + throw new Error("No commits available. Run analyzeGit() first."); + } + return await getSummary(this.nodes.slice(-10).map(({ commit }) => commit)); + } +} + +export default AnalysisEngine; diff --git a/packages/analysis-engine/src/index.ts b/packages/analysis-engine/src/index.ts index 1149d621..0755f0f7 100644 --- a/packages/analysis-engine/src/index.ts +++ b/packages/analysis-engine/src/index.ts @@ -1,96 +1,2 @@ -import "reflect-metadata"; - -import { container } from "tsyringe"; - -import { buildCommitDict } from "./commit.util"; -import { buildCSMDict } from "./csm"; -import getCommitRaws from "./parser"; -import { PluginOctokit } from "./pluginOctokit"; -import { buildStemDict } from "./stem"; -import { getCurrentUserCommitSummary, getLatestCommitSummary } from "./summary"; - -type AnalysisEngineArgs = { - isDebugMode?: boolean; - gitLog: string; - owner: string; - repo: string; - baseBranchName: string; - auth?: string; -}; - -export class AnalysisEngine { - private gitLog!: string; - - private isDebugMode?: boolean; - - private octokit!: PluginOctokit; - - private baseBranchName!: string; - - constructor(args: AnalysisEngineArgs) { - this.insertArgs(args); - } - - private insertArgs = (args: AnalysisEngineArgs) => { - const { isDebugMode, gitLog, owner, repo, auth, baseBranchName } = args; - this.gitLog = gitLog; - this.baseBranchName = baseBranchName; - this.isDebugMode = isDebugMode; - container.register("OctokitOptions", { - useValue: { - owner, - repo, - options: { - auth, - }, - }, - }); - this.octokit = container.resolve(PluginOctokit); - }; - - public analyzeGit = async () => { - let isPRSuccess = true; - if (this.isDebugMode) console.log("baseBranchName: ", this.baseBranchName); - - const commitRaws = getCommitRaws(this.gitLog); - if (this.isDebugMode) console.log("commitRaws: ", commitRaws); - - const commitDict = buildCommitDict(commitRaws); - if (this.isDebugMode) console.log("commitDict: ", commitDict); - - const pullRequests = await this.octokit - .getPullRequests() - .catch((err) => { - console.error(err); - isPRSuccess = false; - return []; - }) - .then((pullRequests) => { - console.log("success, pr = ", pullRequests); - return pullRequests; - }); - if (this.isDebugMode) console.log("pullRequests: ", pullRequests); - - const stemDict = buildStemDict(commitDict, this.baseBranchName); - if (this.isDebugMode) console.log("stemDict: ", stemDict); - const csmDict = buildCSMDict(commitDict, stemDict, this.baseBranchName, pullRequests); - if (this.isDebugMode) console.log("csmDict: ", csmDict); - const latestCommitSummary = await getLatestCommitSummary(stemDict, this.baseBranchName); - if (this.isDebugMode) console.log("latestCommitSummary: ", latestCommitSummary); - - const currentUserCommitSummary = await getCurrentUserCommitSummary(stemDict, this.baseBranchName, this.octokit); - if (this.isDebugMode) console.log("currentUserCommitSummary: ", currentUserCommitSummary); - - return { - isPRSuccess, - csmDict, - }; - }; - - public updateArgs = (args: AnalysisEngineArgs) => { - if (container.isRegistered("OctokitOptions")) container.clearInstances(); - this.insertArgs(args); - }; -} - -export default AnalysisEngine; +export type { AnalysisEngineArgs } from "./engine"; +export { AnalysisEngine } from "./engine"; diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 4f383b53..9b21f085 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -28,7 +28,8 @@ "visual analytics" ], "activationEvents": [ - "*" + "*", + "onView:githruSidebar" ], "main": "./dist/extension.js", "contributes": { @@ -68,6 +69,24 @@ "description": "Insert your primary color." } } + }, + "viewsContainers": { + "activitybar": [ + { + "id": "githruSidebarView", + "title": "Githru Sidebar", + "icon": "images/logo.png" + } + ] + }, + "views": { + "githruSidebarView": [ + { + "type": "webview", + "id": "githruSidebar", + "name": "Githru Sidebar" + } + ] } }, "scripts": { diff --git a/packages/vscode/src/extension.ts b/packages/vscode/src/extension.ts index e1c6357f..866e94e6 100644 --- a/packages/vscode/src/extension.ts +++ b/packages/vscode/src/extension.ts @@ -5,6 +5,7 @@ import { COMMAND_LAUNCH, COMMAND_LOGIN_WITH_GITHUB, COMMAND_RESET_GITHUB_AUTH } import { Credentials } from "./credentials"; import { GithubTokenUndefinedError, WorkspacePathUndefinedError } from "./errors/ExtensionError"; import { deleteGithubToken, getGithubToken, setGithubToken } from "./setting-repository"; +import { SidebarProvider } from "./sidebar"; import { mapClusterNodesFrom } from "./utils/csm.mapper"; import { findGit, @@ -25,6 +26,10 @@ function normalizeFsPath(fsPath: string) { } export async function activate(context: vscode.ExtensionContext) { + const provider = new SidebarProvider(context.extensionUri); + + context.subscriptions.push(vscode.window.registerWebviewViewProvider("githruSidebar", provider)); + const { subscriptions, extensionPath, secrets } = context; const credentials = new Credentials(); let currentPanel: vscode.WebviewPanel | undefined = undefined; @@ -82,7 +87,8 @@ export async function activate(context: vscode.ExtensionContext) { const { owner, repo: initialRepo } = getRepo(gitConfig); webLoader.setGlobalOwnerAndRepo(owner, initialRepo); const repo = initialRepo[0]; - const engine = new AnalysisEngine({ + const engine = AnalysisEngine.getInstance(); + engine.initialize({ isDebugMode: true, gitLog, owner, diff --git a/packages/vscode/src/sidebar.ts b/packages/vscode/src/sidebar.ts new file mode 100644 index 00000000..4da291f0 --- /dev/null +++ b/packages/vscode/src/sidebar.ts @@ -0,0 +1,66 @@ +import { AnalysisEngine } from "@githru-vscode-ext/analysis-engine"; +import type * as vscode from "vscode"; + +export class SidebarProvider implements vscode.WebviewViewProvider { + constructor(private readonly _extensionUri: vscode.Uri) {} + + resolveWebviewView(webviewView: vscode.WebviewView) { + webviewView.webview.options = { + enableScripts: true, + }; + + webviewView.webview.html = this._getHtmlForWebview(webviewView.webview); + + webviewView.webview.onDidReceiveMessage(async (data) => { + const result = await this.callApi(data.apiNumber); + webviewView.webview.postMessage({ type: "apiResult", result }); + }); + } + + private async callApi(apiNumber: number): Promise { + const engine = AnalysisEngine.getInstance(); + try { + const summary = await engine.geminiCommitSummary(); + console.log("Commit summary:", summary); + } catch (error) { + console.error("Error getting commit summary:", error); + } + return `API ${apiNumber} 호출 결과`; + } + + private _getHtmlForWebview(webview: vscode.Webview) { + return ` + + + + + + API Caller + + + + + +
+ + + + + `; + } +}