Repository navigation
Expand file tree
/
Copy pathuserConfirmation.ts
More file actions
67 lines (63 loc) · 2.07 KB
/
Copy pathuserConfirmation.ts
File metadata and controls
67 lines (63 loc) · 2.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import { defineEvent, sendEvent, vWorkflowId } from "@convex-dev/workflow";
import { v } from "convex/values";
import { components, internal } from "./_generated/api";
import { internalAction, internalMutation } from "./_generated/server";
import { workflow } from "./example";
export const approvalEvent = defineEvent({
name: "approval",
validator: v.union(
v.object({ approved: v.literal(true), choice: v.number() }),
v.object({ approved: v.literal(false), reason: v.string() }),
),
});
/**
* Test this from the CLI:
* ```sh
npx convex run userConfirmation:confirmationWorkflow \
'{ "args": { "prompt": "Generate a recipe for me" } }'
* ```
* Copy the ID it returns, then run:
* ```sh
* npx convex run userConfirmation:chooseProposal '{"workflowId":"...", "choice":1}'
* ```
* Watch the logs from `npx convex dev` or `npx convex logs` to see progress.
*/
export const confirmationWorkflow = workflow
.define({
args: { prompt: v.string() },
returns: v.string(),
})
.handler(async (step, args): Promise<string> => {
console.log("Starting confirmation workflow");
const proposals = await step.runAction(
internal.userConfirmation.generateProposals,
{ prompt: args.prompt },
{ retry: true },
);
console.log("Proposals generated", proposals);
const approval = await step.awaitEvent(approvalEvent);
if (!approval.approved) {
return "rejected: " + approval.reason;
}
const choice = proposals[approval.choice];
console.log("Choice selected", choice);
return choice;
});
export const generateProposals = internalAction({
args: { prompt: v.string() },
handler: async () => {
// imagine this is a call to an LLM
return ["proposal1", "proposal2", "proposal3"];
},
});
export const chooseProposal = internalMutation({
args: { workflowId: vWorkflowId, choice: v.number() },
handler: async (ctx, args) => {
await sendEvent(ctx, components.workflow, {
...approvalEvent,
workflowId: args.workflowId,
value: { approved: true, choice: args.choice },
});
return true;
},
});