diff --git a/README.md b/README.md index e32c872..b4bc286 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ To ensure it is working properly, you can run the following command: npm exec -c "gptscript https://get.gptscript.ai/echo.gpt --input 'Hello, World!'" ``` -you will see "Hello, World!" in the output of the command. +You will see "Hello, World!" in the output of the command. ## Client diff --git a/src/gptscript.ts b/src/gptscript.ts index 10852f3..9a923a4 100644 --- a/src/gptscript.ts +++ b/src/gptscript.ts @@ -80,7 +80,7 @@ export class Client { * @return {Run} The Run object representing the running tool. */ run(toolName: string, opts: RunOpts = {}): Run { - return (new Run("run-file-stream-with-events", toolName, "", opts, this.gptscriptBin, this.gptscriptURL)).nextChat(opts.input) + return (new Run("run", toolName, "", opts, this.gptscriptBin, this.gptscriptURL)).nextChat(opts.input) } /** @@ -101,7 +101,7 @@ export class Client { toolString = toolDefToString(tool) } - return (new Run("run-tool-stream-with-event", "", toolString, opts, this.gptscriptBin, this.gptscriptURL)).nextChat(opts.input) + return (new Run("evaluate", "", toolString, opts, this.gptscriptBin, this.gptscriptURL)).nextChat(opts.input) } async parse(fileName: string): Promise { @@ -117,7 +117,7 @@ export class Client { async parseTool(toolContent: string): Promise { const r: Run = new RunSubcommand("parse", "", toolContent, {}, this.gptscriptBin, this.gptscriptURL) if (this.gptscriptURL) { - r.request({input: toolContent}) + r.request({content: toolContent}) } else { await r.exec(["parse"]) } @@ -196,29 +196,25 @@ export class Run { let run = this if (run.state !== RunState.Creating) { - run = new (this.constructor as any)(run.requestPath, run.filePath, run.content, run.opts, run.gptscriptURL) + run = new (this.constructor as any)(this.requestPath, this.filePath, this.content, this.opts, this.bin, this.gptscriptURL) } run.chatState = this.chatState run.opts.input = input if (run.gptscriptURL) { if (run.content !== "") { - run.request({content: this.content}) + run.request({content: this.content, chatState: JSON.stringify(run.chatState)}) } else { - run.request({file: this.filePath}) + run.request({file: this.filePath, chatState: JSON.stringify(run.chatState)}) } } else { - run.exec().catch((e) => { - run.err = e.toString() - run.state = RunState.Error - } - ) + run.exec() } return run } - async exec(extraArgs: string[] = [], env: NodeJS.Dict = process.env) { + exec(extraArgs: string[] = [], env: NodeJS.Dict = process.env) { extraArgs.push(...toArgs(this.opts)) extraArgs.push("--chat-state=" + (this.chatState ? JSON.stringify(this.chatState) : "null")) this.chatState = undefined @@ -406,9 +402,16 @@ export class Run { }) this.sse.addEventListener("close", () => { - if (this.state === RunState.Running || this.state === RunState.Finished) { - this.state = RunState.Finished - resolve(this.stdout || "") + if (this.state === RunState.Running || this.state === RunState.Finished || this.state === RunState.Continue) { + if (this.stdout) { + if (this.state !== RunState.Continue) { + this.state = RunState.Finished + } + resolve(this.stdout) + } else { + this.state = RunState.Error + reject(this.stderr) + } } else if (this.state === RunState.Error) { reject(this.err) } @@ -458,9 +461,16 @@ export class Run { }) res.on("end", () => { - if (this.state === RunState.Running || this.state === RunState.Finished) { - this.state = RunState.Finished - resolve(this.stdout || "") + if (this.state === RunState.Running || this.state === RunState.Finished || this.state === RunState.Continue) { + if (this.stdout) { + if (this.state !== RunState.Continue) { + this.state = RunState.Finished + } + resolve(this.stdout) + } else { + this.state = RunState.Error + reject(this.stderr) + } } else if (this.state === RunState.Error) { reject(this.err) } diff --git a/tests/fixtures/global-tools.gpt b/tests/fixtures/global-tools.gpt new file mode 100644 index 0000000..f38e599 --- /dev/null +++ b/tests/fixtures/global-tools.gpt @@ -0,0 +1,19 @@ +!title + +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 + +Say "Hello!" + +--- +Name: tool_2 + +What time is it? + +--- +Name: tool_3 + +Give me a paragraph of lorem ipsum \ No newline at end of file diff --git a/tests/gptscript.test.ts b/tests/gptscript.test.ts index 40c44fe..df298be 100644 --- a/tests/gptscript.test.ts +++ b/tests/gptscript.test.ts @@ -115,6 +115,29 @@ describe("gptscript module", () => { expect(err).toEqual("") }) + test("run executes and streams a file with global tools correctly", async () => { + let out = "" + let err = undefined + const testGptPath = path.join(__dirname, "fixtures", "global-tools.gpt") + const opts = { + disableCache: true, + } + + try { + const run = client.run(testGptPath, opts) + run.on(gptscript.RunEventType.CallProgress, data => { + out += `system: ${(data as any).content}` + }) + await run.text() + err = run.err + } catch (e) { + console.error(e) + } + + expect(out).toContain("Hello!") + expect(err).toEqual("") + }, 15000) + test("aborting a run is reported correctly", async () => { let errMessage = "" let err = undefined @@ -338,15 +361,4 @@ describe("gptscript module", () => { expect(run.state).toEqual(gptscript.RunState.Finished) expect(err).toEqual("") }, 60000) - - test("with workspace", async () => { - const t0 = { - tools: ["sys.workspace.ls", "sys.workspace.write"], - instructions: "Write a file named 'test.txt' in the workspace with contents 'Hello!' and then list the files in the workspace.", - } as any - - const response = await client.evaluate(t0, {workspace: "./workspace"}).text() - expect(response).toBeDefined() - expect(response).toContain("test.txt") - }, 30000) })