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

feat: add ability to export chat state #40

Merged
merged 1 commit into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
21 changes: 15 additions & 6 deletions src/gptscript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface RunOpts {
chdir?: string
subTool?: string
workspace?: string
chatState?: string
}

function toArgs(opts: RunOpts): string[] {
Expand Down Expand Up @@ -174,7 +175,7 @@ export class Run {
private req?: any
private stderr?: string
private callbacks: Record<string, ((f: Frame) => void)[]> = {}
private chatState: string | undefined
private chatState?: string

constructor(subCommand: string, path: string, content: string, opts: RunOpts, bin?: string, gptscriptURL?: string) {
this.id = randomId("run-")
Expand All @@ -199,13 +200,17 @@ export class Run {
run = new (this.constructor as any)(this.requestPath, this.filePath, this.content, this.opts, this.bin, this.gptscriptURL)
}

run.chatState = this.chatState
if (this.chatState) {
run.chatState = this.chatState
} else if (this.opts.chatState) {
run.chatState = this.opts.chatState
}
run.opts.input = input
if (run.gptscriptURL) {
if (run.content !== "") {
run.request({content: this.content, chatState: JSON.stringify(run.chatState)})
run.request({content: this.content, chatState: run.chatState})
} else {
run.request({file: this.filePath, chatState: JSON.stringify(run.chatState)})
run.request({file: this.filePath, chatState: run.chatState})
}
} else {
run.exec()
Expand All @@ -216,7 +221,7 @@ export class Run {

exec(extraArgs: string[] = [], env: NodeJS.Dict<string> = process.env) {
extraArgs.push(...toArgs(this.opts))
extraArgs.push("--chat-state=" + (this.chatState ? JSON.stringify(this.chatState) : "null"))
extraArgs.push("--chat-state=" + (this.chatState ? this.chatState : "null"))
this.chatState = undefined

if (this.filePath) {
Expand Down Expand Up @@ -353,7 +358,7 @@ export class Run {

const out = data as ChatState
if (out.done !== undefined && !out.done) {
this.chatState = out.state
this.chatState = JSON.stringify(out.state)
this.state = RunState.Continue
} else {
this.state = RunState.Finished
Expand Down Expand Up @@ -637,6 +642,10 @@ export class Run {
return JSON.parse(await this.text())
}

public currentChatState(): string | undefined {
return this.chatState
}

public close(): void {
if (this.process) {
if (this.process.exitCode === null) {
Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/global-tools.gpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Runbook 3

---
Name: tool_1
Global Tools: sys.workspace.ls, sys.workspace.read, sys.workspace.write, github.com/gptscript-ai/knowledge, github.com/drpebcak/duckdb, github.com/gptscript-ai/browser, github.com/gptscript-ai/browser-search/google, github.com/gptscript-ai/browser-search/google-question-answerer
Global Tools: sys.read, sys.write, github.com/gptscript-ai/knowledge, github.com/drpebcak/duckdb, github.com/gptscript-ai/browser, github.com/gptscript-ai/browser-search/google, github.com/gptscript-ai/browser-search/google-question-answerer

Say "Hello!"

Expand Down
43 changes: 43 additions & 0 deletions tests/gptscript.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,4 +381,47 @@ describe("gptscript module", () => {
expect(run.state).toEqual(gptscript.RunState.Finished)
expect(err).toEqual("")
}, 60000)

test("nextChat on file providing chat state", async () => {
let run = client.run(path.join(__dirname, "fixtures", "chat.gpt"), {disableCache: true})

run = run.nextChat("List the 3 largest of the Great Lakes by volume.")
expect(await run.text()).toContain("Lake Superior")
expect(run.err).toEqual("")
expect(run.state).toEqual(gptscript.RunState.Continue)

run = client.run(path.join(__dirname, "fixtures", "chat.gpt"), {
disableCache: true,
input: "What is the total area of the third one in square miles?",
chatState: run.currentChatState()
})

expect(await run.text()).toContain("Lake Huron")
expect(run.err).toEqual("")
expect(run.state).toEqual(gptscript.RunState.Continue)
}, 10000)

test("nextChat on tool providing chat state", async () => {
const t = {
chat: true,
instructions: "You are a chat bot. Don't finish the conversation until I say 'bye'.",
tools: ["sys.chat.finish"]
}
let run = client.evaluate(t as any, {disableCache: true})

run = run.nextChat("List the three largest states in the United States by area.")
expect(await run.text()).toContain("California")
expect(run.err).toEqual("")
expect(run.state).toEqual(gptscript.RunState.Continue)

run = client.evaluate(t as any, {
disableCache: true,
input: "What is the capital of the second one?",
chatState: run.currentChatState()
})

expect(await run.text()).toContain("Austin")
expect(run.err).toEqual("")
expect(run.state).toEqual(gptscript.RunState.Continue)
}, 10000)
})