Skip to content

Commit

Permalink
feat: add workspace API
Browse files Browse the repository at this point in the history
Signed-off-by: Donnie Adams <[email protected]>
  • Loading branch information
thedadams committed Oct 24, 2024
1 parent 96d3724 commit ce1d9f1
Show file tree
Hide file tree
Showing 2 changed files with 211 additions and 14 deletions.
90 changes: 89 additions & 1 deletion src/gptscript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface GlobalOpts {
DefaultModel?: string
DefaultModelProvider?: string
DatasetToolRepo?: string
WorkspaceTool?: string
Env?: string[]
}

Expand Down Expand Up @@ -140,9 +141,12 @@ export class GPTScript {
if (!this.opts.URL) {
this.opts.URL = GPTScript.serverURL
}
if (this.opts.URL !== "" && !this.opts.URL.startsWith("http://") && !this.opts.URL.startsWith("https://")) {
this.opts.URL = "http://" + this.opts.URL
}

if (!this.opts.Env) {
this.opts.Env = []
this.opts.Env = Object.entries(process.env).map(([k, v]) => `${k}=${v}`)
}
if (this.opts.URL) {
this.opts.Env.push(`GPTSCRIPT_URL=${this.opts.URL}`)
Expand Down Expand Up @@ -469,6 +473,90 @@ export class GPTScript {
return JSON.parse(result) as DatasetElement
}

async createWorkspace(providerType: string, ...fromWorkspaces: string[]): Promise<string> {
const out = await this.runBasicCommand("workspaces/create", {
providerType: providerType,
fromWorkspaceIDs: fromWorkspaces,
workspaceTool: this.opts.WorkspaceTool,
env: this.opts.Env,
})
return out.trim()
}

async deleteWorkspace(workspaceID?: string): Promise<void> {
if (!workspaceID) {
workspaceID = process.env.GPTSCRIPT_WORKSPACE_ID ?? ""
}
await this.runBasicCommand("workspaces/delete", {
id: workspaceID,
workspaceTool: this.opts.WorkspaceTool,
env: this.opts.Env,
})
}

async listFilesInWorkspace(prefix?: string, workspaceID?: string): Promise<Array<string>> {
if (!workspaceID) {
workspaceID = process.env.GPTSCRIPT_WORKSPACE_ID ?? ""
}
const out = await this.runBasicCommand("workspaces/list", {
id: workspaceID,
prefix: prefix,
workspaceTool: this.opts.WorkspaceTool,
env: this.opts.Env,
})
return JSON.parse(out)
}

async removeAll(withPrefix?: string, workspaceID?: string): Promise<void> {
if (!workspaceID) {
workspaceID = process.env.GPTSCRIPT_WORKSPACE_ID ?? ""
}
await this.runBasicCommand("workspaces/remove-all-with-prefix", {
id: workspaceID,
prefix: withPrefix,
workspaceTool: this.opts.WorkspaceTool,
env: this.opts.Env,
})
}

async writeFileInWorkspace(filePath: string, content: ArrayBuffer, workspaceID?: string): Promise<void> {
if (!workspaceID) {
workspaceID = process.env.GPTSCRIPT_WORKSPACE_ID ?? ""
}
await this.runBasicCommand("workspaces/write-file", {
id: workspaceID,
filePath: filePath,
contents: Buffer.from(content).toString("base64"),
workspaceTool: this.opts.WorkspaceTool,
env: this.opts.Env,
})
}

async deleteFileInWorkspace(filePath: string, workspaceID?: string): Promise<void> {
if (!workspaceID) {
workspaceID = process.env.GPTSCRIPT_WORKSPACE_ID ?? ""
}
await this.runBasicCommand("workspaces/delete-file", {
id: workspaceID,
filePath: filePath,
workspaceTool: this.opts.WorkspaceTool,
env: this.opts.Env,
})
}

async readFileInWorkspace(filePath: string, workspaceID?: string): Promise<ArrayBuffer> {
if (!workspaceID) {
workspaceID = process.env.GPTSCRIPT_WORKSPACE_ID ?? ""
}
const out = await this.runBasicCommand("workspaces/read-file", {
id: workspaceID,
filePath: filePath,
workspaceTool: this.opts.WorkspaceTool,
env: this.opts.Env,
})
return Buffer.from(out.trim(), "base64")
}

/**
* Helper method to handle the common logic for loading.
*
Expand Down
135 changes: 122 additions & 13 deletions tests/gptscript.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as gptscript from "../src/gptscript"
import {
ArgumentSchemaType,
CredentialType, Dataset,
CredentialType,
getEnv,
PropertyType,
RunEventType,
Expand All @@ -13,7 +13,7 @@ import path from "path"
import {fileURLToPath} from "url"
import * as fs from "node:fs"
import {randomBytes} from "node:crypto"
import {tmpdir} from "node:os";
import {tmpdir} from "node:os"

let gFirst: gptscript.GPTScript
let g: gptscript.GPTScript
Expand Down Expand Up @@ -908,21 +908,21 @@ describe("gptscript module", () => {
// Add elements
try {
const e1 = await g.addDatasetElement(
workspace,
datasetID,
"element1",
"",
"this is element 1 contents"
workspace,
datasetID,
"element1",
"",
"this is element 1 contents"
)
expect(e1.name).toEqual("element1")
expect(e1.description).toEqual("")

const e2 = await g.addDatasetElement(
workspace,
datasetID,
"element2",
"a description",
"this is element 2 contents"
workspace,
datasetID,
"element2",
"a description",
"this is element 2 contents"
)
expect(e2.name).toEqual("element2")
expect(e2.description).toEqual("a description")
Expand Down Expand Up @@ -963,5 +963,114 @@ describe("gptscript module", () => {
} catch (e) {
throw new Error("failed to list datasets: " + e)
}
}, 20000)
}, 60000)

test("create and delete workspace", async () => {
if (!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY) {
console.log("AWS credentials not set, skipping test")
return
}

const workspaceID = await g.createWorkspace("directory")
expect(workspaceID).toBeDefined()
await g.deleteWorkspace(workspaceID)
}, 60000)

test("write, read, and delete file", async () => {
if (!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY) {
console.log("AWS credentials not set, skipping test")
return
}

const workspaceID = await g.createWorkspace("directory")
expect(workspaceID).toBeDefined()

await g.writeFileInWorkspace("test.txt", Buffer.from("test"), workspaceID)
const content = await g.readFileInWorkspace("test.txt", workspaceID)
expect(content.toString()).toEqual("test")
await g.deleteWorkspace(workspaceID)
}, 60000)

test("test complex ls", async () => {
if (!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY) {
console.log("AWS credentials not set, skipping test")
return
}

const workspaceID = await g.createWorkspace("directory")

// Write files in the workspace
await g.writeFileInWorkspace("test/test1.txt", Buffer.from("hello1"), workspaceID)
await g.writeFileInWorkspace("test1/test2.txt", Buffer.from("hello2"), workspaceID)
await g.writeFileInWorkspace("test1/test3.txt", Buffer.from("hello3"), workspaceID)
await g.writeFileInWorkspace(".hidden.txt", Buffer.from("hidden"), workspaceID)

let content = await g.listFilesInWorkspace(undefined, workspaceID)
expect(content.length).toEqual(4)
expect(content).toContain("test1/test2.txt")
expect(content).toContain("test1/test3.txt")
expect(content).toContain("test/test1.txt")
expect(content).toContain(".hidden.txt")

content = await g.listFilesInWorkspace("test1", workspaceID)
expect(content.length).toEqual(2)
expect(content).toContain("test1/test2.txt")
expect(content).toContain("test1/test3.txt")

await g.removeAll("test1", workspaceID)

content = await g.listFilesInWorkspace("", workspaceID)
expect(content.length).toEqual(2)
expect(content).toContain("test/test1.txt")
expect(content).toContain(".hidden.txt")

await g.deleteWorkspace(workspaceID)
}, 60000)

test("create and delete workspace in s3", async () => {
const workspaceID = await g.createWorkspace("s3")
expect(workspaceID).toBeDefined()
await g.deleteWorkspace(workspaceID)
}, 60000)

test("write, read, and delete file in s3", async () => {
const workspaceID = await g.createWorkspace("s3")
expect(workspaceID).toBeDefined()

await g.writeFileInWorkspace("test.txt", Buffer.from("test"), workspaceID)
const content = await g.readFileInWorkspace("test.txt", workspaceID)
expect(content.toString()).toEqual("test")
await g.deleteWorkspace(workspaceID)
}, 60000)

test("test complex ls in s3", async () => {
const workspaceID = await g.createWorkspace("s3")

// Write files in the workspace
await g.writeFileInWorkspace("test/test1.txt", Buffer.from("hello1"), workspaceID)
await g.writeFileInWorkspace("test1/test2.txt", Buffer.from("hello2"), workspaceID)
await g.writeFileInWorkspace("test1/test3.txt", Buffer.from("hello3"), workspaceID)
await g.writeFileInWorkspace(".hidden.txt", Buffer.from("hidden"), workspaceID)

let content = await g.listFilesInWorkspace(undefined, workspaceID)
expect(content.length).toEqual(4)
expect(content).toContain("test1/test2.txt")
expect(content).toContain("test1/test3.txt")
expect(content).toContain("test/test1.txt")
expect(content).toContain(".hidden.txt")

content = await g.listFilesInWorkspace("test1", workspaceID)
expect(content.length).toEqual(2)
expect(content).toContain("test1/test2.txt")
expect(content).toContain("test1/test3.txt")

await g.removeAll("test1", workspaceID)

content = await g.listFilesInWorkspace("", workspaceID)
expect(content.length).toEqual(2)
expect(content).toContain("test/test1.txt")
expect(content).toContain(".hidden.txt")

await g.deleteWorkspace(workspaceID)
}, 60000)
})

0 comments on commit ce1d9f1

Please sign in to comment.