/// import { derive, handler, JSONSchema, llm, NAME, recipe, Schema, str, UI, } from "commontools"; const ItemSchema = { type: "object", properties: { title: { type: "string" }, question: { type: "string" }, }, default: { title: "", question: "", }, } as const satisfies JSONSchema; export type TodoItem = Schema; const ListSchema = { type: "object", properties: { title: { type: "string", default: "untitled", }, items: { type: "array", items: ItemSchema, default: [], }, }, required: ["title", "items"], } as const satisfies JSONSchema; const ResultSchema = { type: "object", properties: { items: { type: "array", items: ItemSchema }, questions: { type: "array", items: { type: "string" } }, addItem: { asStream: true, type: "object", properties: { title: { type: "string" }, }, examples: [{ title: "New item" }], required: ["title"], }, }, required: ["items", "/action/drop/schema", "/action/drop/handler"], } as const satisfies JSONSchema; const addTask = handler<{ detail: { message: string } }, { items: TodoItem[] }>( (event, { items }) => { const task = event.detail?.message?.trim(); if (task) items.push({ title: task, question: "..." }); }, ); const addItem = handler( { type: "object", properties: { title: { type: "string" }, question: { type: "string" } }, required: ["title", "question"], }, { type: "object", properties: { items: { asCell: true, ...ListSchema.properties.items }, }, default: { items: [] }, }, ({ title, question }, { items }) => { items.push({ title, question }); }, ); const updateTitle = handler<{ detail: { value: string } }, { title: string }>( ({ detail }, state) => { state.title = detail?.value ?? "untitled"; }, ); const deleteItem = handler( (_, { item, items }) => { const idx = items.findIndex((i) => i.title === item.title); if (idx !== -1) items.splice(idx, 1); }, ); const Questions = recipe({ type: "object", properties: { items: { type: "array", items: ItemSchema } }, }, { type: "object", properties: { questions: { type: "array", items: { type: "string" } }, results: { type: "array", items: { type: "string" } }, }, }, ({ items }) => { const results = items.map((item) => { const question = llm({ system: `Ask a snarky, sarcastic, clever question about the attached item:`, messages: [ str`${item.title}`, ], }); return { title: item.title, question: question.result, item }; }) as any; const questions = derive( results, (r) => r.map((i: { title: string; question: string; item: any }) => i.question), ); return { questions, results, }; }); export default recipe(ListSchema, ResultSchema, ({ title, items }) => { derive(items, (items) => { console.log("todo list items changed", { items }); }); // TODO(@bf): why any needed? const { results, questions } = Questions({ items }) as any; return { [NAME]: title, [UI]: ( {results.map(( { title, question, item }: { title: string; question: string; item: any; }, ) => (
  • {title}
    {question} Delete
  • ))}
    ), title, items: results, questions, addItem: addItem({ items }), }; });