Commit 6e9acde29620
Changed files (1)
dots
pi
agent
extensions
org-todos
dots/pi/agent/extensions/org-todos/index.ts
@@ -119,6 +119,47 @@ function formatTodo(todo: any): string {
return parts.join(" ");
}
+/**
+ * Format TODO item for markdown display
+ */
+function formatTodoMarkdown(todo: any): string {
+ const parts: string[] = [];
+
+ // State badge
+ const state = todo.todo || "TODO";
+ parts.push(`**[${state}]**`);
+
+ // Priority
+ if (todo.priority) {
+ parts.push(`\`#${todo.priority}\``);
+ }
+
+ // Heading
+ parts.push(todo.heading);
+
+ // Tags
+ if (todo.tags && todo.tags.length > 0) {
+ const tagStr = todo.tags.map((t: string) => `\`${t}\``).join(" ");
+ parts.push(tagStr);
+ }
+
+ // Scheduled/Deadline on new line
+ const dates: string[] = [];
+ if (todo.scheduled) {
+ dates.push(`๐
${todo.scheduled}`);
+ }
+ if (todo.deadline) {
+ dates.push(`โฐ ${todo.deadline}`);
+ }
+
+ let result = parts.join(" ");
+ if (dates.length > 0) {
+ result += ` *(${dates.join(", ")})*`;
+ }
+
+ return result;
+}
+
export default function (pi: ExtensionAPI) {
// Register the org_todo tool
pi.registerTool({
@@ -350,12 +391,11 @@ export default function (pi: ExtensionAPI) {
},
});
+
// Register /todos command
pi.registerCommand("todos", {
description: "Show today's tasks (scheduled + overdue + NEXT)",
handler: async (args, ctx) => {
- const theme = ctx.ui.theme;
-
// Fetch scheduled, overdue, and NEXT items
const scheduled = execEmacs("(pi/org-todo-scheduled)");
const overdue = execEmacs("(pi/org-todo-overdue)");
@@ -366,61 +406,58 @@ export default function (pi: ExtensionAPI) {
return;
}
+ // Build markdown content
const lines: string[] = [];
- // Header
- lines.push(theme.bold("๐ Today's Tasks"));
- lines.push(theme.fg("dim", "โ".repeat(50)));
+ lines.push("## ๐ Today's Tasks");
+ lines.push("");
// Overdue section
if (overdue.success && overdue.data && overdue.data.length > 0) {
+ lines.push(`### โ ๏ธ Overdue (${overdue.data.length})`);
lines.push("");
- lines.push(theme.fg("error", `โ ๏ธ Overdue (${overdue.data.length})`));
- for (const todo of overdue.data.slice(0, 5)) {
- lines.push(` ${theme.fg("error", "โข")} ${formatTodo(todo)}`);
- }
- if (overdue.data.length > 5) {
- lines.push(theme.fg("dim", ` ... and ${overdue.data.length - 5} more`));
+ for (const todo of overdue.data) {
+ lines.push(`- ${formatTodoMarkdown(todo)}`);
}
+ lines.push("");
}
// Scheduled section
if (scheduled.success && scheduled.data && scheduled.data.length > 0) {
+ lines.push(`### ๐
Scheduled Today (${scheduled.data.length})`);
lines.push("");
- lines.push(theme.fg("accent", `๐
Scheduled Today (${scheduled.data.length})`));
- for (const todo of scheduled.data.slice(0, 5)) {
- lines.push(` ${theme.fg("accent", "โข")} ${formatTodo(todo)}`);
- }
- if (scheduled.data.length > 5) {
- lines.push(theme.fg("dim", ` ... and ${scheduled.data.length - 5} more`));
+ for (const todo of scheduled.data) {
+ lines.push(`- ${formatTodoMarkdown(todo)}`);
}
+ lines.push("");
}
// NEXT section
if (next.success && next.data && next.data.length > 0) {
+ lines.push(`### โก๏ธ Next Actions (${next.data.length})`);
lines.push("");
- lines.push(theme.fg("success", `โก๏ธ Next Actions (${next.data.length})`));
- for (const todo of next.data.slice(0, 5)) {
- lines.push(` ${theme.fg("success", "โข")} ${formatTodo(todo)}`);
- }
- if (next.data.length > 5) {
- lines.push(theme.fg("dim", ` ... and ${next.data.length - 5} more`));
+ for (const todo of next.data) {
+ lines.push(`- ${formatTodoMarkdown(todo)}`);
}
+ lines.push("");
}
// Empty state
- if (lines.length === 2) {
- lines.push("");
- lines.push(theme.fg("dim", "No tasks for today. ๐"));
+ const hasContent =
+ (overdue.success && overdue.data?.length > 0) ||
+ (scheduled.success && scheduled.data?.length > 0) ||
+ (next.success && next.data?.length > 0);
+
+ if (!hasContent) {
+ lines.push("*No tasks for today.* ๐");
}
- // Show as widget
- ctx.ui.setWidget("todos", lines);
-
- // Auto-dismiss after 15 seconds
- setTimeout(() => {
- ctx.ui.setWidget("todos", undefined);
- }, 15000);
+ // Send as a message that appears in the conversation
+ pi.sendMessage({
+ customType: "org-todos",
+ content: lines.join("\n"),
+ display: true,
+ });
},
});
@@ -435,7 +472,6 @@ export default function (pi: ExtensionAPI) {
return;
}
- const theme = ctx.ui.theme;
const result = execEmacs(`(pi/org-todo-search "${query.replace(/"/g, '\\"')}" nil t)`);
if (!result.success) {
@@ -448,24 +484,24 @@ export default function (pi: ExtensionAPI) {
return;
}
+ // Build markdown content
const lines: string[] = [];
- lines.push(theme.bold(`๐ Search: "${query}" (${result.data.length} results)`));
- lines.push(theme.fg("dim", "โ".repeat(50)));
+ lines.push(`## ๐ Search: "${query}"`);
+ lines.push("");
+ lines.push(`*${result.data.length} result(s)*`);
+ lines.push("");
- for (const todo of result.data.slice(0, 10)) {
- const matchedIn = todo.matched_in === "heading" ? "" : theme.fg("dim", " (in content)");
- lines.push(` ${theme.fg("accent", "โข")} ${formatTodo(todo)}${matchedIn}`);
+ for (const todo of result.data) {
+ const matchedIn = todo.matched_in === "heading" ? "" : " *(matched in content)*";
+ lines.push(`- ${formatTodoMarkdown(todo)}${matchedIn}`);
}
- if (result.data.length > 10) {
- lines.push(theme.fg("dim", ` ... and ${result.data.length - 10} more`));
- }
-
- ctx.ui.setWidget("todo-search", lines);
-
- setTimeout(() => {
- ctx.ui.setWidget("todo-search", undefined);
- }, 20000);
+ // Send as a message that appears in the conversation
+ pi.sendMessage({
+ customType: "org-todos-search",
+ content: lines.join("\n"),
+ display: true,
+ });
},
});
}