Skip to content

Commit

Permalink
Merge pull request #44 from thedadams/prompt-support
Browse files Browse the repository at this point in the history
feat: add prompt support
  • Loading branch information
thedadams authored May 31, 2024
2 parents f36929e + 7642f51 commit c3947ce
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 3 deletions.
38 changes: 35 additions & 3 deletions src/gptscript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export enum RunEventType {
CallConfirm = "callConfirm",
CallContinue = "callContinue",
CallFinish = "callFinish",

Prompt = "prompt"
}

let serverProcess: child_process.ChildProcess
Expand Down Expand Up @@ -177,6 +179,20 @@ export class Client {
}
}

async promptResponse(response: PromptResponse): Promise<void> {
if (!this.clientReady) {
this.clientReady = await this.testGPTScriptURL(20)
}
const resp = await fetch(`${this.gptscriptURL}/prompt-response/${response.id}`, {
method: "POST",
body: JSON.stringify(response.responses)
})

if (resp.status < 200 || resp.status >= 400) {
throw new Error(`Failed to respond to prompt ${response.id}: ${await resp.text()}`)
}
}

private async testGPTScriptURL(count: number): Promise<boolean> {
try {
await fetch(`${this.gptscriptURL}/healthz`)
Expand Down Expand Up @@ -405,6 +421,8 @@ export class Run {
f = obj.run as Frame
} else if (obj.call) {
f = obj.call as Frame
} else if (obj.prompt) {
f = obj.prompt as Frame
} else {
return event
}
Expand All @@ -426,8 +444,7 @@ export class Run {
this.state = RunState.Finished
this.stdout = f.output || ""
}
} else {
if (!(f.type as string).startsWith("call")) continue
} else if ((f.type as string).startsWith("call")) {
f = (f as CallFrame)
const idx = this.calls?.findIndex((x) => x.id === f.id)

Expand All @@ -447,6 +464,7 @@ export class Run {

public on(event: RunEventType.RunStart | RunEventType.RunFinish, listener: (data: RunFrame) => void): this;
public on(event: RunEventType.CallStart | RunEventType.CallProgress | RunEventType.CallContinue | RunEventType.CallChat | RunEventType.CallConfirm | RunEventType.CallFinish, listener: (data: CallFrame) => void): this;
public on(event: RunEventType.Prompt, listener: (data: PromptFrame) => void): this;
public on(event: RunEventType.Event, listener: (data: Frame) => void): this;
public on(event: RunEventType, listener: (data: any) => void): this {
if (!this.callbacks[event]) {
Expand Down Expand Up @@ -656,14 +674,28 @@ export interface CallFrame {
llmResponse?: any
}

export type Frame = RunFrame | CallFrame
export interface PromptFrame {
id: string
type: RunEventType.Prompt
time: string
message: string
fields: string[]
sensitive: boolean
}

export type Frame = RunFrame | CallFrame | PromptFrame

export interface AuthResponse {
id: string
accept: boolean
message?: string
}

export interface PromptResponse {
id: string
responses: Record<string, string>
}

function getCmdPath(): string {
if (process.env.GPTSCRIPT_BIN) {
return process.env.GPTSCRIPT_BIN
Expand Down
22 changes: 22 additions & 0 deletions tests/gptscript.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,4 +428,26 @@ describe("gptscript module", () => {
expect(run.err).toEqual("")
expect(confirmFound).toBeTruthy()
})

test("prompt", async () => {
let promptFound = false
const t = {
instructions: "Use the sys.prompt user to ask the user for 'first name' which is not sensitive. After you get their first name, say hello.",
tools: ["sys.prompt"]
}
const run = await client.evaluate(t as any)
run.on(gptscript.RunEventType.Prompt, async (data: gptscript.PromptFrame) => {
expect(data.message).toContain("first name")
expect(data.fields.length).toEqual(1)
expect(data.fields[0]).toEqual("first name")
expect(data.sensitive).toBeFalsy()

promptFound = true
await client.promptResponse({id: data.id, responses: {[data.fields[0]]: "Clicky"}})
})

expect(await run.text()).toContain("Clicky")
expect(run.err).toEqual("")
expect(promptFound).toBeTruthy()
})
})

0 comments on commit c3947ce

Please sign in to comment.