Skip to content

Commit c3947ce

Browse files
authored
Merge pull request #44 from thedadams/prompt-support
feat: add prompt support
2 parents f36929e + 7642f51 commit c3947ce

File tree

2 files changed

+57
-3
lines changed

2 files changed

+57
-3
lines changed

src/gptscript.ts

+35-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export enum RunEventType {
2525
CallConfirm = "callConfirm",
2626
CallContinue = "callContinue",
2727
CallFinish = "callFinish",
28+
29+
Prompt = "prompt"
2830
}
2931

3032
let serverProcess: child_process.ChildProcess
@@ -177,6 +179,20 @@ export class Client {
177179
}
178180
}
179181

182+
async promptResponse(response: PromptResponse): Promise<void> {
183+
if (!this.clientReady) {
184+
this.clientReady = await this.testGPTScriptURL(20)
185+
}
186+
const resp = await fetch(`${this.gptscriptURL}/prompt-response/${response.id}`, {
187+
method: "POST",
188+
body: JSON.stringify(response.responses)
189+
})
190+
191+
if (resp.status < 200 || resp.status >= 400) {
192+
throw new Error(`Failed to respond to prompt ${response.id}: ${await resp.text()}`)
193+
}
194+
}
195+
180196
private async testGPTScriptURL(count: number): Promise<boolean> {
181197
try {
182198
await fetch(`${this.gptscriptURL}/healthz`)
@@ -405,6 +421,8 @@ export class Run {
405421
f = obj.run as Frame
406422
} else if (obj.call) {
407423
f = obj.call as Frame
424+
} else if (obj.prompt) {
425+
f = obj.prompt as Frame
408426
} else {
409427
return event
410428
}
@@ -426,8 +444,7 @@ export class Run {
426444
this.state = RunState.Finished
427445
this.stdout = f.output || ""
428446
}
429-
} else {
430-
if (!(f.type as string).startsWith("call")) continue
447+
} else if ((f.type as string).startsWith("call")) {
431448
f = (f as CallFrame)
432449
const idx = this.calls?.findIndex((x) => x.id === f.id)
433450

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

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

659-
export type Frame = RunFrame | CallFrame
677+
export interface PromptFrame {
678+
id: string
679+
type: RunEventType.Prompt
680+
time: string
681+
message: string
682+
fields: string[]
683+
sensitive: boolean
684+
}
685+
686+
export type Frame = RunFrame | CallFrame | PromptFrame
660687

661688
export interface AuthResponse {
662689
id: string
663690
accept: boolean
664691
message?: string
665692
}
666693

694+
export interface PromptResponse {
695+
id: string
696+
responses: Record<string, string>
697+
}
698+
667699
function getCmdPath(): string {
668700
if (process.env.GPTSCRIPT_BIN) {
669701
return process.env.GPTSCRIPT_BIN

tests/gptscript.test.ts

+22
Original file line numberDiff line numberDiff line change
@@ -428,4 +428,26 @@ describe("gptscript module", () => {
428428
expect(run.err).toEqual("")
429429
expect(confirmFound).toBeTruthy()
430430
})
431+
432+
test("prompt", async () => {
433+
let promptFound = false
434+
const t = {
435+
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.",
436+
tools: ["sys.prompt"]
437+
}
438+
const run = await client.evaluate(t as any)
439+
run.on(gptscript.RunEventType.Prompt, async (data: gptscript.PromptFrame) => {
440+
expect(data.message).toContain("first name")
441+
expect(data.fields.length).toEqual(1)
442+
expect(data.fields[0]).toEqual("first name")
443+
expect(data.sensitive).toBeFalsy()
444+
445+
promptFound = true
446+
await client.promptResponse({id: data.id, responses: {[data.fields[0]]: "Clicky"}})
447+
})
448+
449+
expect(await run.text()).toContain("Clicky")
450+
expect(run.err).toEqual("")
451+
expect(promptFound).toBeTruthy()
452+
})
431453
})

0 commit comments

Comments
 (0)