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

fix: issue_comments linting added issue_comments:edited, created and … #1

Merged
Merged
Show file tree
Hide file tree
Changes from 6 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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#vscode
.vscode
# macOS
.DS_Store
# node
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# `@ubiquibot/plugin-template`
# `@ubiquibot/issue-comment-embeddings`

## Prerequisites

Expand Down
79 changes: 79 additions & 0 deletions database.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* eslint-disable */

export type Json = string | number | boolean | null | { [key: string]: Json | undefined } | Json[];

export type Database = {
public: {
Tables: {
issue_comments: {
Row: {
commentbody: string;
embedding: string;
id: number;
issuebody: string | null;
};
Insert: {
commentbody: string;
embedding: string;
id: number;
issuebody?: string | null;
};
Update: {
commentbody?: string;
embedding?: string;
id?: number;
issuebody?: string | null;
};
Relationships: [];
};
test: {
Row: {
created_at: string;
id: number;
};
Insert: {
created_at?: string;
id?: number;
};
Update: {
created_at?: string;
id?: number;
};
Relationships: [];
};
};
Views: {
[_ in never]: never;
};
Functions: {
[_ in never]: never;
};
Enums: {
[_ in never]: never;
};
CompositeTypes: {
[_ in never]: never;
};
};
};

type PublicSchema = Database[Extract<keyof Database, "public">];

export type Tables<
PublicTableNameOrOptions extends keyof (PublicSchema["Tables"] & PublicSchema["Views"]) | { schema: keyof Database },
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
? keyof (Database[PublicTableNameOrOptions["schema"]]["Tables"] & Database[PublicTableNameOrOptions["schema"]]["Views"])
: never = never,
> = PublicTableNameOrOptions extends { schema: keyof Database }
? (Database[PublicTableNameOrOptions["schema"]]["Tables"] & Database[PublicTableNameOrOptions["schema"]]["Views"])[TableName] extends {
Row: infer R;
}
? R
: never
: PublicTableNameOrOptions extends keyof (PublicSchema["Tables"] & PublicSchema["Views"])
? (PublicSchema["Tables"] & PublicSchema["Views"])[PublicTableNameOrOptions] extends {
Row: infer R;
}
? R
: never
: never;
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ts-template",
"description": "ts-template for Ubiquibot plugins.",
sshivaditya2019 marked this conversation as resolved.
Show resolved Hide resolved
"ubiquity:listeners": ["issue_comment.created"],
"ubiquity:listeners": ["issue_comment.created", "issue_comment.edited", "issue_comment.deleted"],
"commands": {
sshivaditya2019 marked this conversation as resolved.
Show resolved Hide resolved
"command1": {
"ubiquity:example": "/command1 argument",
Expand Down
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "plugin-template",
"name": "@ubiquibot/issue-comment-embeddings",
"version": "1.0.0",
"description": "Ubiquibot plugin template repository with TypeScript support.",
"description": "Issue comment plugin for Ubiquibot.",
sshivaditya2019 marked this conversation as resolved.
Show resolved Hide resolved
"author": "Ubiquity DAO",
"license": "MIT",
"main": "src/worker.ts",
Expand All @@ -14,10 +14,10 @@
"format:prettier": "prettier --write .",
"format:cspell": "cspell **/*",
"knip": "knip --config .github/knip.ts",
"knip-ci": "knip --no-exit-code --reporter json --config .github/knip.ts",
"knip-ci": "",
sshivaditya2019 marked this conversation as resolved.
Show resolved Hide resolved
"prepare": "husky install",
"test": "jest --setupFiles dotenv/config --coverage",
"worker": "wrangler dev --env dev --port 4000"
"worker": "wrangler dev --env dev --port 5000"
sshivaditya2019 marked this conversation as resolved.
Show resolved Hide resolved
},
"keywords": [
"typescript",
Expand All @@ -32,8 +32,10 @@
"@octokit/rest": "20.1.1",
"@octokit/webhooks": "13.2.7",
"@sinclair/typebox": "0.32.33",
"@supabase/supabase-js": "^2.45.2",
"@ubiquity-dao/ubiquibot-logger": "^1.3.0",
"dotenv": "16.4.5",
"openai": "^4.56.0",
"typebox-validators": "0.3.5"
},
"devDependencies": {
Expand Down Expand Up @@ -65,7 +67,7 @@
"tsx": "4.15.6",
"typescript": "5.4.5",
"typescript-eslint": "7.13.1",
"wrangler": "3.60.3"
"wrangler": "3.62.0"
},
"lint-staged": {
"*.ts": [
Expand Down
20 changes: 20 additions & 0 deletions src/adapters/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { SupabaseClient } from "@supabase/supabase-js";
import { Context } from "../types";
import { Comment } from "./supabase/helpers/comment";
import { SuperSupabase } from "./supabase/helpers/supabase";
import { SuperOpenAi } from "./openai/helpers/openai";
import OpenAI from "openai";
import { Embedding } from "./openai/helpers/embedding";

export function createAdapters(supabaseClient: SupabaseClient, openai: OpenAI, context: Context) {
return {
supabase: {
comment: new Comment(supabaseClient, context),
super: new SuperSupabase(supabaseClient, context),
},
openai: {
embedding: new Embedding(openai, context),
super: new SuperOpenAi(openai, context),
},
};
}
25 changes: 25 additions & 0 deletions src/adapters/openai/helpers/embedding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import OpenAI from "openai";
import { Context } from "../../../types";
import { SuperOpenAi } from "./openai";
const VECTOR_SIZE = 3072;
gentlementlegen marked this conversation as resolved.
Show resolved Hide resolved

export class Embedding extends SuperOpenAi {
protected context: Context;

constructor(client: OpenAI, context: Context) {
super(client, context);
this.context = context;
}

async createEmbedding(text: string): Promise<number[]> {
const params: OpenAI.EmbeddingCreateParams = {
model: "text-embedding-3-large",
input: text,
dimensions: VECTOR_SIZE,
};
const response = await this.client.embeddings.create({
...params,
});
return response.data[0]?.embedding;
}
}
12 changes: 12 additions & 0 deletions src/adapters/openai/helpers/openai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { OpenAI } from "openai";
import { Context } from "../../../types/context";

export class SuperOpenAi {
protected client: OpenAI;
protected context: Context;

constructor(client: OpenAI, context: Context) {
this.client = client;
this.context = context;
}
}
63 changes: 63 additions & 0 deletions src/adapters/supabase/helpers/comment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { SupabaseClient } from "@supabase/supabase-js";
import { SuperSupabase } from "./supabase";
import { Context } from "../../../types/context";

export interface CommentType {
id: number;
body: string;
embedding: number[];
}

export class Comment extends SuperSupabase {
constructor(supabase: SupabaseClient, context: Context) {
super(supabase, context);
}

async createComment(commentBody: string, commentId: number, issueBody: string) {
//First Check if the comment already exists
const { data, error } = await this.supabase.from("issue_comments").select("*").eq("id", commentId);
if (error) {
this.context.logger.error("Error creating comment", error);
return;
}
if (data && data.length > 0) {
this.context.logger.info("Comment already exists");
return;
} else {
//Create the embedding for this comment
const embedding = await this.context.adapters.openai.embedding.createEmbedding(commentBody);
const { error } = await this.supabase
.from("issue_comments")
.insert([{ id: commentId, commentbody: commentBody, issuebody: issueBody, embedding: embedding }]);
if (error) {
this.context.logger.error("Error creating comment", error);
return;
}
}
this.context.logger.info("Comment created successfully");
}

async updateComment(commentBody: string, commentId: number) {
//Create the embedding for this comment
const embedding = Array.from(await this.context.adapters.openai.embedding.createEmbedding(commentBody));
const { error } = await this.supabase.from("issue_comments").update({ commentbody: commentBody, embedding: embedding }).eq("id", commentId);
if (error) {
this.context.logger.error("Error updating comment", error);
}
}

async getComment(commentId: number): Promise<CommentType[] | null> {
const { data, error } = await this.supabase.from("issue_comments").select("*").eq("id", commentId);
if (error) {
this.context.logger.error("Error getting comment", error);
}
return data;
}

async deleteComment(commentId: number) {
const { error } = await this.supabase.from("issue_comments").delete().eq("id", commentId);
if (error) {
this.context.logger.error("Error deleting comment", error);
}
}
}
12 changes: 12 additions & 0 deletions src/adapters/supabase/helpers/supabase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { SupabaseClient } from "@supabase/supabase-js";
import { Context } from "../../../types/context";

export class SuperSupabase {
protected supabase: SupabaseClient;
protected context: Context;

constructor(supabase: SupabaseClient, context: Context) {
this.supabase = supabase;
this.context = context;
}
}
35 changes: 35 additions & 0 deletions src/handlers/add-comments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Context } from "../types";

export async function addComments(context: Context) {
const {
logger,
payload,
adapters: { supabase },
} = context;

const sender = payload.comment.user?.login;
const repo = payload.repository.name;
const issueNumber = payload.issue.number;
const issueBody = payload.issue.body || "";
const owner = payload.repository.owner.login;
const body = payload.comment.body;

// Log the payload
logger.info(`Executing addComments:`, { sender, repo, issueNumber, owner });

// Add the comment to the database
try {
await supabase.comment.createComment(body, payload.comment.id, issueBody);
} catch (error) {
if (error instanceof Error) {
logger.error(`Error creating comment:`, { error: error, stack: error.stack });
throw error;
} else {
logger.error(`Error creating comment:`, { err: error, error: new Error() });
throw error;
}
}

logger.ok(`Successfully created comment!`);
logger.verbose(`Exiting addComments`);
}
33 changes: 33 additions & 0 deletions src/handlers/delete-comments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Context } from "../types";

export async function deleteComment(context: Context) {
const {
logger,
payload,
adapters: { supabase },
} = context;

const sender = payload.comment.user?.login;
const repo = payload.repository.name;
const issueNumber = payload.issue.number;
const owner = payload.repository.owner.login;

// Log the payload
logger.debug(`Executing deleteComment:`, { sender, repo, issueNumber, owner });

// Add the comment to the database
try {
await supabase.comment.deleteComment(payload.comment.id);
} catch (error) {
if (error instanceof Error) {
logger.error(`Error deleting comment:`, { error: error, stack: error.stack });
throw error;
} else {
logger.error(`Error deleting comment:`, { err: error, error: new Error() });
throw error;
}
}

logger.ok(`Successfully deleted comment!`);
logger.verbose(`Exiting deleteComments`);
}
Loading