Skip to content

Commit

Permalink
Merge pull request #696 from polywrap/release/staging
Browse files Browse the repository at this point in the history
Release Jan 24th
  • Loading branch information
dOrgJelli authored Jan 24, 2024
2 parents 2139d45 + 97017be commit 2dde2e1
Show file tree
Hide file tree
Showing 5 changed files with 535 additions and 69 deletions.
2 changes: 1 addition & 1 deletion apps/browser/lib/hooks/useEvoService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export const useEvoService = (
const workspace = (() => {
if (session?.supabaseAccessToken) {
const supabase = createSupabaseBrowserClient(session.supabaseAccessToken)
return new SupabaseWorkspace(chatId, supabase.storage)
return new SupabaseWorkspace(chatId, supabase)
} else {
return new InMemoryWorkspace()
}
Expand Down
170 changes: 103 additions & 67 deletions apps/browser/lib/supabase/SupabaseWorkspace.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,25 @@
import { DirectoryEntry, Workspace } from "@evo-ninja/agent-utils";
import { StorageClient } from "@supabase/storage-js";
import { SupabaseClient } from "@supabase/supabase-js";
import { Database } from "./dbTypes";
import * as path from "path-browserify";

const BUCKET_NAME = "workspaces";

export class SupabaseWorkspace implements Workspace {
constructor(
public readonly chatId: string,
public readonly supabaseStorage: StorageClient
public readonly supabase: SupabaseClient<Database>
) {}

async writeFile(subpath: string, data: string): Promise<void> {
const path = this.toWorkspacePath(subpath);

const { error } = await this.supabaseStorage
.from(BUCKET_NAME)
.upload(path, data, { upsert: true });

if (error) {
throw error;
}

return;
await this.uploadWorkspaceFile(path, data);
}

async readFile(subpath: string): Promise<string> {
const path = this.toWorkspacePath(subpath);

const { data, error } = await this.supabaseStorage
const { data, error } = await this.supabase.storage
.from(BUCKET_NAME)
.download(path);

Expand All @@ -45,7 +37,7 @@ export class SupabaseWorkspace implements Workspace {
async exists(subpath: string): Promise<boolean> {
const path = this.toWorkspacePath(subpath);

const { data, error } = await this.supabaseStorage
const { data, error } = await this.supabase.storage
.from(BUCKET_NAME)
.download(path);

Expand All @@ -60,13 +52,10 @@ export class SupabaseWorkspace implements Workspace {
const absOldPath = this.toWorkspacePath(oldPath);
const absNewPath = this.toWorkspacePath(newPath);

const { error } = await this.supabaseStorage
.from(BUCKET_NAME)
.move(absOldPath, absNewPath);

if (error) {
throw error;
}
await this.renameWorkspaceFile(
absOldPath,
absNewPath
);
}

async mkdir(_subpath: string): Promise<void> {}
Expand All @@ -77,56 +66,36 @@ export class SupabaseWorkspace implements Workspace {
}

const path = this.toWorkspacePath(subpath);

const { data: list, error: listError } = await this.supabaseStorage
.from(BUCKET_NAME)
.list(path);

if (listError) {
throw listError;
}
const filesToRemove = list.map((x) => `${path}/${x.name}`);
const filesToRemove = await this.listWorkspaceFiles(path);

if (filesToRemove.length === 0) {
return;
}

const { error: removeError } = await this.supabaseStorage
.from(BUCKET_NAME)
.remove(filesToRemove);
await this.removeWorkspaceFiles(filesToRemove);

if (removeError) {
throw removeError;
if (path === this.toWorkspacePath("")) {
await this.supabase.storage.deleteBucket(this.chatId);
}
}

async readdir(subpath: string): Promise<DirectoryEntry[]> {
const path = this.toWorkspacePath(subpath);
const fileNames = (await this.listWorkspaceFiles(path))
.map((file) => file.replace(`${path}/`, ""));

const { data, error } = await this.supabaseStorage
.from(BUCKET_NAME)
.list(path);

if (error) {
throw error;
}

if (!data) {
throw new Error("Directory not found");
}

return data
.filter((x) => !x.name.startsWith("."))
return fileNames
.filter((x) => !x.startsWith("."))
.map((x) => ({
name: x.name,
name: x,
type: "file",
}));
}

async appendFile(subpath: string, data: string): Promise<void> {
const path = this.toWorkspacePath(subpath);

const { data: existingData, error: readError } = await this.supabaseStorage
const { data: existingData, error: readError } = await this.supabase.storage
.from(BUCKET_NAME)
.download(path);

Expand All @@ -136,25 +105,12 @@ export class SupabaseWorkspace implements Workspace {

const newData = existingData ? existingData.text() + data : data;

const { error: writeError } = await this.supabaseStorage
.from(BUCKET_NAME)
.upload(path, newData, { upsert: true });

if (writeError) {
throw writeError;
}
await this.uploadWorkspaceFile(path, newData);
}

async rm(subpath: string): Promise<void> {
const path = this.toWorkspacePath(subpath);

const { error } = await this.supabaseStorage
.from(BUCKET_NAME)
.remove([path]);

if (error) {
throw error;
}
await this.removeWorkspaceFiles([path]);
}

async exec(
Expand All @@ -168,6 +124,86 @@ export class SupabaseWorkspace implements Workspace {
}

private toWorkspacePath(subpath: string): string {
return path.resolve("/", this.chatId, subpath).slice(1);
const result = path.resolve(path.join(this.chatId, subpath));
return result.replace(/^\/+/, "");
}

private async listWorkspaceFiles(path: string): Promise<string[]> {
const { data: list, error: listError } = await this.supabase
.from("workspace_files")
.select("path, chat_id")
.eq("chat_id", this.chatId);

if (listError) {
throw listError;
}

return list
.filter((x) => x)
.filter((x) => x.path.includes(path))
.map((x) => x.path) as string[];
}

private async uploadWorkspaceFile(path: string, data: string): Promise<void> {
const { error: storageError } = await this.supabase.storage
.from(BUCKET_NAME)
.upload(path, data, { upsert: true });

if (storageError) {
throw storageError;
}

const { error: indexError } = await this.supabase
.from("workspace_files")
.upsert({
chat_id: this.chatId,
path: path
}, {
onConflict: "chat_id, path"
});

if (indexError) {
throw indexError;
}
}

private async removeWorkspaceFiles(paths: string[]): Promise<void> {
const { error: storageError } = await this.supabase.storage
.from(BUCKET_NAME)
.remove(paths);

if (storageError) {
throw storageError;
}

const { error: indexError } = await this.supabase
.from("workspace_files")
.delete()
.eq("chat_id", this.chatId)
.in("path", paths);

if (indexError) {
throw indexError;
}
}

private async renameWorkspaceFile(oldPath: string, newPath: string): Promise<void> {
const { error: storageError } = await this.supabase.storage
.from(BUCKET_NAME)
.move(oldPath, newPath);

if (storageError) {
throw storageError;
}

const { error: indexError } = await this.supabase
.from("workspace_files")
.update({ path: newPath })
.eq("chat_id", this.chatId)
.eq("path", oldPath)

if (indexError) {
throw indexError;
}
}
}
Loading

0 comments on commit 2dde2e1

Please sign in to comment.