1use phi_ext::phi;
4
5fn main() -> Result<(), phi::Error> {
6 let mut m = phi::Extension::new("full", "0.1.0");
7
8 m.register_tool(
9 phi::Tool::new(
10 "echo",
11 "Echo the input back",
12 phi::Schema::object()
13 .property("text", phi::Schema::string())
14 .required(["text"]),
15 |args| {
16 let text = String::from_utf8_lossy(args);
17 Ok(phi::ToolResult {
18 content: format!("echo: {text}"),
19 ..Default::default()
20 })
21 },
22 )
23 .detail_from_args(|args| String::from_utf8_lossy(args).into_owned()),
24 );
25
26 m.register_tool(
27 phi::Tool::new_async(
28 "async-echo",
29 "Echo the input back (async handler)",
30 phi::Schema::object()
31 .property("text", phi::Schema::string())
32 .required(["text"]),
33 |args| async move {
34 tokio::task::yield_now().await;
37 let text = String::from_utf8_lossy(&args);
38 Ok(phi::ToolResult {
39 content: format!("async echo: {text}"),
40 ..Default::default()
41 })
42 },
43 )
44 .timeout_sec(10),
45 );
46
47 m.register_command(
48 "ask",
49 phi::Command::new("Ask a yes/no question", |_args, ctx| {
50 let reply = ctx.confirm("Confirm?", "Proceed with /tmp/x?");
51 if reply.ok {
52 ctx.notify("info", "Confirmed!");
53 } else {
54 ctx.notify("warning", "Declined.");
55 }
56 ctx.submit("follow-up from ask");
57 Ok(())
58 }),
59 );
60
61 m.run()
62}