import type { ExtensionAPI } from "@oh-my-pi/pi-coding-agent"; const choices = ["welcome", "hours"]; const deskInfo: Record = { welcome: "Welcome to the fictional community seed library. This lesson cannot change real stock. Try /seeds hours.", hours: "Our fictional desk opens Saturday, 10:00-12:00. No booking has been made.", }; type WelcomeDetails = | { op: "discover"; scope: "fictional-desk"; operations: string[]; topics: string[]; quiet: boolean } | { op: "inspect"; scope: "fictional-desk"; topic: "welcome" | "hours" }; export default async function seedWelcome(pi: ExtensionAPI) { const description = await Bun.file(new URL("./tool.txt", import.meta.url)).text(); const z = pi.zod; const parameters = z.object({ op: z.enum(["discover", "inspect"]), topic: z.enum(["welcome", "hours"]).optional() }); pi.registerTool({ name: "seed_welcome", label: "Seed desk welcome", description, parameters, approval: "read", loadMode: "essential", async execute(_id, params, signal) { signal?.throwIfAborted(); if (params.op === "discover") { return { content: [{ type: "text", text: "Fictional seed desk. Inspect topic welcome or hours. No stock-changing operations exist." }], details: { op: "discover", scope: "fictional-desk", operations: ["discover", "inspect"], topics: choices, quiet: pi.getFlag("seed-quiet") === true }, }; } if (!params.topic) throw new Error("Inspect requires topic welcome or hours. Nothing changed."); const text = deskInfo[params.topic]; if (!text) throw new Error("Inspect requires topic welcome or hours. Nothing changed."); return { content: [{ type: "text", text }], details: { op: "inspect", scope: "fictional-desk", topic: params.topic } }; }, }); pi.registerFlag("seed-quiet", { description: "Hide the seed desk's startup notification", type: "boolean", default: false, }); pi.on("session_start", (_event, ctx) => { if (ctx.hasUI && pi.getFlag("seed-quiet") !== true) { ctx.ui.notify("Fictional community seed desk ready. Try /seeds welcome.", "info"); } }); pi.registerCommand("seeds", { description: "Visit the fictional community seed desk: welcome | hours", getArgumentCompletions(prefix) { const matches = choices.filter(value => value.startsWith(prefix.trimStart())); // A completed sole match MUST release Enter to submit the command. if (matches.length === 1 && matches[0] === prefix.trim()) return null; return matches.length ? matches.map(value => ({ value: `${value} `, label: value })) : null; }, async handler(args, ctx) { const verb = args.trim() || "welcome"; const text = Object.hasOwn(deskInfo, verb) ? deskInfo[verb]! : "Unknown request. Use /seeds welcome or /seeds hours. Nothing changed."; if (ctx.hasUI) ctx.ui.notify(text, choices.includes(verb) ? "info" : "warning"); else pi.sendMessage({ customType: "seed-desk", content: text, display: true }, { triggerTurn: false }); }, }); }