Skip to content

src/create.ts

71 lines · 2.4 KB · TypeScript
Raw
import { parseInput } from './lib/validate.ts'
import { byField, tzField, ctxField, dueField, kindField, notesField, priorityField, tagsField, titleField } from './lib/fields.ts'
import { insertTodo, line, normalizeTags, parseDue, resolveTimeZone, type Kind, type Priority, type Todo } from './lib/store.ts'

/**
 * Create a todo or task in the shared multi-agent todo list (reminder, action item, follow-up).
 * Call whenever the user asks any agent to "note", "remind me", "add a todo/task". Dates use the store time zone (see ./settings) unless `timeZone` is passed.
 *
 * @param input - `{ title: string, by: string (your agent name), notes?: string, due?: "YYYY-MM-DD" | "YYYY-MM-DDTHH:MM" (store zone) | ISO with offset | "today" | "tomorrow", priority?: "low"|"normal"|"high", tags?: string[], kind?: "todo"|"task", project?: string, client?: string, timeZone?: IANA zone override for parsing `due` }`
 * @returns `{ todo, line }` — the stored record (id like "T12") and a one-line summary
 *
 * @example
 * import createTodo from 'kody:@charlesmatte/todos/create'
 *
 * const { todo } = await createTodo({ title: 'Send the quarterly report', due: '2026-10-14T09:00', priority: 'high', tags: ['finance'], client: 'Acme', by: 'research-agent' })
 */
export default async function createTodo(input: unknown) {
	const p = parseInput<{
		title: string
		by: string
		notes?: string
		due?: string
		priority?: Priority
		tags?: Array<string>
		kind?: Kind
		project?: string
		client?: string
		timeZone?: string
	}>(
		input,
		{
			title: { ...titleField, required: true },
			by: byField,
			notes: notesField,
			due: dueField,
			priority: priorityField,
			tags: tagsField,
			kind: kindField,
			project: ctxField,
			client: ctxField,
			timeZone: tzField,
		},
		'todos/create',
	)
	const tz = await resolveTimeZone(p.timeZone)
	const due = p.due ? parseDue(p.due, tz) : null
	const todo = await insertTodo(
		(id, now): Todo => ({
			id,
			kind: p.kind ?? 'todo',
			title: p.title,
			notes: p.notes?.trim() ? p.notes.trim() : null,
			status: 'open',
			deleted: false,
			priority: p.priority ?? 'normal',
			tags: normalizeTags(p.tags ?? []),
			project: p.project ?? null,
			client: p.client ?? null,
			due,
			createdAt: now,
			updatedAt: now,
			completedAt: null,
			deletedAt: null,
			createdBy: p.by,
			updatedBy: p.by,
			version: 1,
			history: [{ at: now, by: p.by, action: 'created' }],
		}),
	)
	return { todo, line: line(todo, tz), timeZone: tz }
}