Skip to content

Commit

Permalink
chore: rename Client to GPTScript
Browse files Browse the repository at this point in the history
This change also defaults to the SDK server selecting a random available
port.
  • Loading branch information
thedadams committed Jun 4, 2024
1 parent 9cdc6e2 commit 5b68409
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 118 deletions.
68 changes: 34 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ npm exec -c "gptscript https://get.gptscript.ai/echo.gpt --input 'Hello, World!'

You will see "Hello, World!" in the output of the command.

## Client
## GPTScript

The client allows the caller to run gptscript files, tools, and other operations (see below). There are currently no
options for this singleton client, so `new gptscript.Client()` is all you need. Although, the intention is that a
single client is all you need for the life of your application, you should call `close()` on the client when you are
done.
The GPTScript instance allows the caller to run gptscript files, tools, and other operations (see below). There are
currently no options for this class, so `new gptscript.GPTScript()` is all you need. Although, the intention is that a
single instance is all you need for the life of your application, you should call `close()` on the instance when you
are done.

## Options

Expand Down Expand Up @@ -64,10 +64,10 @@ Lists all the available built-in tools.
const gptscript = require('@gptscript-ai/gptscript');

async function listTools() {
const client = new gptscript.Client();
const tools = await client.listTools();
const g = new gptscript.GPTScript();
const tools = await g.listTools();
console.log(tools);
client.close()
g.close();
}
```

Expand All @@ -82,13 +82,13 @@ const gptscript = require('@gptscript-ai/gptscript');

async function listModels() {
let models = [];
const client = new gptscript.Client();
const g = new gptscript.GPTScript();
try {
models = await client.listModels();
models = await g.listModels();
} catch (error) {
console.error(error);
}
client.close()
g.close();
}
```

Expand All @@ -102,13 +102,13 @@ Get the first of the current `gptscript` binary being used for the calls.
const gptscript = require('@gptscript-ai/gptscript');

async function version() {
const client = new gptscript.Client();
const g = new gptscript.GPTScript();
try {
console.log(await client.version());
console.log(await g.version());
} catch (error) {
console.error(error);
}
client.close()
g.close();
}
```

Expand All @@ -124,14 +124,14 @@ const t = {
instructions: "Who was the president of the united states in 1928?"
};

const client = new gptscript.Client();
const g = new gptscript.GPTScript();
try {
const run = await client.evaluate(t);
const run = await g.evaluate(t);
console.log(await run.text());
} catch (error) {
console.error(error);
}
client.close();
g.close();
```

### run
Expand All @@ -147,14 +147,14 @@ const opts = {
};

async function execFile() {
const client = new gptscript.Client();
const g = new gptscript.GPTScript();
try {
const run = await client.run('./hello.gpt', opts);
const run = await g.run('./hello.gpt', opts);
console.log(await run.text());
} catch (e) {
console.error(e);
}
client.close();
g.close();
}
```

Expand All @@ -175,9 +175,9 @@ const opts = {
};

async function streamExecFileWithEvents() {
const client = new gptscript.Client();
const g = new gptscript.GPTScript();
try {
const run = await client.run('./test.gpt', opts);
const run = await g.run('./test.gpt', opts);

run.on(gptscript.RunEventType.Event, data => {
console.log(`event: ${JSON.stringify(data)}`);
Expand All @@ -187,7 +187,7 @@ async function streamExecFileWithEvents() {
} catch (e) {
console.error(e);
}
client.close();
g.close();
}
```

Expand All @@ -206,15 +206,15 @@ const opts = {
};

async function streamExecFileWithEvents() {
const client = new gptscript.Client();
const g = new gptscript.GPTScript();
try {
const run = await client.run('./test.gpt', opts);
const run = await g.run('./test.gpt', opts);

run.on(gptscript.RunEventType.CallConfirm, async (data: gptscript.CallFrame) => {
// data.Tool has the information for the command being run.
// data.Input has the input for this command

await client.confirm({
await g.confirm({
id: data.id,
accept: true, // false if the command should not be run
message: "", // Explain the denial (ignored if accept is true)
Expand All @@ -225,7 +225,7 @@ async function streamExecFileWithEvents() {
} catch (e) {
console.error(e);
}
client.close();
g.close();
}
```

Expand All @@ -245,14 +245,14 @@ const opts = {
};

async function streamExecFileWithEvents() {
const client = new gptscript.Client();
const g = new gptscript.GPTScript();
try {
const run = await client.run('./test.gpt', opts);
const run = await g.run('./test.gpt', opts);

run.on(gptscript.RunEventType.Prompt, async (data: gptscript.PromptFrame) => {
// data will have the information for what the gptscript is prompting.

await client.promptResponse({
await g.promptResponse({
id: data.id,
// response is a map of fields to values
responses: {[data.fields[0]]: "Some Value"}
Expand All @@ -263,7 +263,7 @@ async function streamExecFileWithEvents() {
} catch (e) {
console.error(e);
}
client.close();
g.close();
}
```

Expand Down Expand Up @@ -292,8 +292,8 @@ const t = {
};

async function streamExecFileWithEvents() {
const client = new gptscript.Client();
let run = await client.evaluate(t, opts);
const g = new gptscript.GPTScript();
let run = await g.evaluate(t, opts);
try {
// Wait for the initial run to complete.
await run.text();
Expand All @@ -312,7 +312,7 @@ async function streamExecFileWithEvents() {
console.error(e);
}

client.close();
g.close();

// The state here should either be RunState.Finished (on success) or RunState.Error (on error).
console.log(run.state)
Expand Down
105 changes: 58 additions & 47 deletions src/gptscript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import http from "http"
import path from "path"
import child_process from "child_process"
import {fileURLToPath} from "url"
import net from "net"

export interface RunOpts {
input?: string
Expand Down Expand Up @@ -31,35 +32,45 @@ export enum RunEventType {
Prompt = "prompt"
}

let serverProcess: child_process.ChildProcess
let clientCount: number = 0
export class GPTScript {
private static serverURL: string = ""
private static serverProcess: child_process.ChildProcess
private static instanceCount: number = 0

export class Client {
private readonly gptscriptURL: string
private clientReady: boolean

constructor() {
this.clientReady = false
this.gptscriptURL = "http://" + (process.env.GPTSCRIPT_URL || "127.0.0.1:9090")
clientCount++
if (clientCount === 1 && process.env.GPTSCRIPT_DISABLE_SERVER !== "true") {
serverProcess = child_process.spawn(getCmdPath(), ["--listen-address", this.gptscriptURL.replace("http://", "").replace("https://", ""), "sdkserver"], {
env: process.env,
stdio: ["pipe"]
})
private ready: boolean

process.on("exit", (code) => {
serverProcess.stdin?.end()
serverProcess.kill(code)
})
constructor() {
this.ready = false
GPTScript.instanceCount++
if (GPTScript.instanceCount === 1 && process.env.GPTSCRIPT_DISABLE_SERVER !== "true") {
GPTScript.serverURL = process.env.GPTSCRIPT_URL || "http://127.0.0.1:0"
const u = new URL(GPTScript.serverURL)
if (u.port === "0") {
const srv = net.createServer()
const s = srv.listen(0, () => {
GPTScript.serverURL = "http://" + u.hostname + ":" + String((s.address() as net.AddressInfo).port)
srv.close()

GPTScript.serverProcess = child_process.spawn(getCmdPath(), ["--listen-address", GPTScript.serverURL.replace("http://", ""), "sdkserver"], {
env: process.env,
stdio: ["pipe"]
})

process.on("exit", (code) => {
GPTScript.serverProcess.stdin?.end()
GPTScript.serverProcess.kill(code)
})
})
}
}
}

close(): void {
clientCount--
if (clientCount === 0 && serverProcess) {
serverProcess.kill("SIGTERM")
serverProcess.stdin?.end()
GPTScript.instanceCount--
if (GPTScript.instanceCount === 0 && GPTScript.serverProcess) {
GPTScript.serverProcess.kill("SIGTERM")
GPTScript.serverProcess.stdin?.end()
}
}

Expand All @@ -76,10 +87,10 @@ export class Client {
}

async runBasicCommand(cmd: string): Promise<string> {
if (!this.clientReady) {
this.clientReady = await this.testGPTScriptURL(20)
if (!this.ready) {
this.ready = await this.testGPTScriptURL(20)
}
const r = new RunSubcommand(cmd, "", "", {}, this.gptscriptURL)
const r = new RunSubcommand(cmd, "", "", {}, GPTScript.serverURL)
r.requestNoStream(null)
return r.text()
}
Expand All @@ -92,10 +103,10 @@ export class Client {
* @return {Run} The Run object representing the running tool.
*/
async run(toolName: string, opts: RunOpts = {}): Promise<Run> {
if (!this.clientReady) {
this.clientReady = await this.testGPTScriptURL(20)
if (!this.ready) {
this.ready = await this.testGPTScriptURL(20)
}
return (new Run("run", toolName, "", opts, this.gptscriptURL)).nextChat(opts.input)
return (new Run("run", toolName, "", opts, GPTScript.serverURL)).nextChat(opts.input)
}

/**
Expand All @@ -106,8 +117,8 @@ export class Client {
* @return {Run} The Run object representing the evaluation.
*/
async evaluate(tool: ToolDef | ToolDef[] | string, opts: RunOpts = {}): Promise<Run> {
if (!this.clientReady) {
this.clientReady = await this.testGPTScriptURL(20)
if (!this.ready) {
this.ready = await this.testGPTScriptURL(20)
}
let toolString: string = ""

Expand All @@ -119,30 +130,30 @@ export class Client {
toolString = toolDefToString(tool)
}

return (new Run("evaluate", "", toolString, opts, this.gptscriptURL)).nextChat(opts.input)
return (new Run("evaluate", "", toolString, opts, GPTScript.serverURL)).nextChat(opts.input)
}

async parse(fileName: string): Promise<Block[]> {
if (!this.clientReady) {
this.clientReady = await this.testGPTScriptURL(20)
if (!this.ready) {
this.ready = await this.testGPTScriptURL(20)
}
const r: Run = new RunSubcommand("parse", fileName, "", {}, this.gptscriptURL)
const r: Run = new RunSubcommand("parse", fileName, "", {}, GPTScript.serverURL)
r.request({file: fileName})
return parseBlocksFromNodes((await r.json()).nodes)
}

async parseTool(toolContent: string): Promise<Block[]> {
if (!this.clientReady) {
this.clientReady = await this.testGPTScriptURL(20)
if (!this.ready) {
this.ready = await this.testGPTScriptURL(20)
}
const r: Run = new RunSubcommand("parse", "", toolContent, {}, this.gptscriptURL)
const r: Run = new RunSubcommand("parse", "", toolContent, {}, GPTScript.serverURL)
r.request({content: toolContent})
return parseBlocksFromNodes((await r.json()).nodes)
}

async stringify(blocks: Block[]): Promise<string> {
if (!this.clientReady) {
this.clientReady = await this.testGPTScriptURL(20)
if (!this.ready) {
this.ready = await this.testGPTScriptURL(20)
}
const nodes: any[] = []

Expand All @@ -162,16 +173,16 @@ export class Client {
}
}

const r: Run = new RunSubcommand("fmt", "", JSON.stringify({nodes: nodes}), {}, this.gptscriptURL)
const r: Run = new RunSubcommand("fmt", "", JSON.stringify({nodes: nodes}), {}, GPTScript.serverURL)
r.request({nodes: nodes})
return r.text()
}

async confirm(response: AuthResponse): Promise<void> {
if (!this.clientReady) {
this.clientReady = await this.testGPTScriptURL(20)
if (!this.ready) {
this.ready = await this.testGPTScriptURL(20)
}
const resp = await fetch(`${this.gptscriptURL}/confirm/${response.id}`, {
const resp = await fetch(`${GPTScript.serverURL}/confirm/${response.id}`, {
method: "POST",
body: JSON.stringify(response)
})
Expand All @@ -182,10 +193,10 @@ export class Client {
}

async promptResponse(response: PromptResponse): Promise<void> {
if (!this.clientReady) {
this.clientReady = await this.testGPTScriptURL(20)
if (!this.ready) {
this.ready = await this.testGPTScriptURL(20)
}
const resp = await fetch(`${this.gptscriptURL}/prompt-response/${response.id}`, {
const resp = await fetch(`${GPTScript.serverURL}/prompt-response/${response.id}`, {
method: "POST",
body: JSON.stringify(response.responses)
})
Expand All @@ -197,7 +208,7 @@ export class Client {

private async testGPTScriptURL(count: number): Promise<boolean> {
try {
await fetch(`${this.gptscriptURL}/healthz`)
await fetch(`${GPTScript.serverURL}/healthz`)
return true
} catch {
if (count === 0) {
Expand Down
Loading

0 comments on commit 5b68409

Please sign in to comment.