phaibel 4.0.7 → 4.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +229 -245
  2. package/dist/commands/chat.d.ts +5 -2
  3. package/dist/commands/chat.d.ts.map +1 -1
  4. package/dist/commands/chat.js +168 -172
  5. package/dist/commands/chat.js.map +1 -1
  6. package/dist/commands/cron.d.ts.map +1 -1
  7. package/dist/commands/cron.js +1 -0
  8. package/dist/commands/cron.js.map +1 -1
  9. package/dist/commands/init.d.ts.map +1 -1
  10. package/dist/commands/init.js +54 -52
  11. package/dist/commands/init.js.map +1 -1
  12. package/dist/config.js +2 -2
  13. package/dist/config.js.map +1 -1
  14. package/dist/entities/entity-summary.js +3 -3
  15. package/dist/entities/entity-type-config.d.ts +3 -0
  16. package/dist/entities/entity-type-config.d.ts.map +1 -1
  17. package/dist/entities/entity-type-config.js +67 -1
  18. package/dist/entities/entity-type-config.js.map +1 -1
  19. package/dist/entities/entity-types-defaults.d.ts.map +1 -1
  20. package/dist/entities/entity-types-defaults.js +2 -0
  21. package/dist/entities/entity-types-defaults.js.map +1 -1
  22. package/dist/entities/spawner.d.ts.map +1 -1
  23. package/dist/entities/spawner.js +4 -2
  24. package/dist/entities/spawner.js.map +1 -1
  25. package/dist/feral/catalog/entity-catalog-source.js +31 -31
  26. package/dist/feral/node-code/abstract-node-code.js +1 -1
  27. package/dist/feral/node-code/abstract-node-code.js.map +1 -1
  28. package/dist/feral/node-code/data/set-context-value-node-code.d.ts.map +1 -1
  29. package/dist/feral/node-code/data/set-context-value-node-code.js +10 -1
  30. package/dist/feral/node-code/data/set-context-value-node-code.js.map +1 -1
  31. package/dist/feral/node-code/entity/create-entity-type-node-code.js +20 -20
  32. package/dist/feral/node-code/entity/load-vault-context-node-code.d.ts.map +1 -1
  33. package/dist/feral/node-code/entity/load-vault-context-node-code.js +7 -15
  34. package/dist/feral/node-code/entity/load-vault-context-node-code.js.map +1 -1
  35. package/dist/feral/node-code/entity/update-entity-type-node-code.js +20 -20
  36. package/dist/feral/node-code/input/prompt-input-node-code.d.ts.map +1 -1
  37. package/dist/feral/node-code/input/prompt-input-node-code.js +6 -0
  38. package/dist/feral/node-code/input/prompt-input-node-code.js.map +1 -1
  39. package/dist/feral/node-code/input/prompt-select-node-code.d.ts.map +1 -1
  40. package/dist/feral/node-code/input/prompt-select-node-code.js +6 -0
  41. package/dist/feral/node-code/input/prompt-select-node-code.js.map +1 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +5 -39
  44. package/dist/index.js.map +1 -1
  45. package/dist/llm/router.js +27 -27
  46. package/dist/personalities.js +4 -4
  47. package/dist/phaibel.txt +81 -81
  48. package/dist/service/api-router.d.ts.map +1 -1
  49. package/dist/service/api-router.js +42 -2
  50. package/dist/service/api-router.js.map +1 -1
  51. package/dist/service/cron/feedback-analysis.js +14 -14
  52. package/dist/service/cron/innovate.d.ts +2 -0
  53. package/dist/service/cron/innovate.d.ts.map +1 -0
  54. package/dist/service/cron/innovate.js +354 -0
  55. package/dist/service/cron/innovate.js.map +1 -0
  56. package/dist/service/cron/process-lifecycle.js +36 -36
  57. package/dist/service/cron/scheduler.d.ts.map +1 -1
  58. package/dist/service/cron/scheduler.js +8 -0
  59. package/dist/service/cron/scheduler.js.map +1 -1
  60. package/dist/service/index.d.ts.map +1 -1
  61. package/dist/service/index.js +27 -20
  62. package/dist/service/index.js.map +1 -1
  63. package/dist/service/web-client.html +1984 -1569
  64. package/dist/service/web-server.d.ts +1 -0
  65. package/dist/service/web-server.d.ts.map +1 -1
  66. package/dist/service/web-server.js +188 -6
  67. package/dist/service/web-server.js.map +1 -1
  68. package/dist/tools/daily.js +2 -2
  69. package/package.json +69 -66
  70. package/dist/agentary.txt +0 -82
  71. package/dist/commands/event.d.ts +0 -4
  72. package/dist/commands/event.d.ts.map +0 -1
  73. package/dist/commands/event.js +0 -515
  74. package/dist/commands/event.js.map +0 -1
  75. package/dist/commands/goal.d.ts +0 -4
  76. package/dist/commands/goal.d.ts.map +0 -1
  77. package/dist/commands/goal.js +0 -14
  78. package/dist/commands/goal.js.map +0 -1
  79. package/dist/commands/interview.d.ts +0 -14
  80. package/dist/commands/interview.d.ts.map +0 -1
  81. package/dist/commands/interview.js +0 -343
  82. package/dist/commands/interview.js.map +0 -1
  83. package/dist/commands/note.d.ts +0 -4
  84. package/dist/commands/note.d.ts.map +0 -1
  85. package/dist/commands/note.js +0 -548
  86. package/dist/commands/note.js.map +0 -1
  87. package/dist/commands/pamp.d.ts +0 -4
  88. package/dist/commands/pamp.d.ts.map +0 -1
  89. package/dist/commands/pamp.js +0 -323
  90. package/dist/commands/pamp.js.map +0 -1
  91. package/dist/commands/person.d.ts +0 -4
  92. package/dist/commands/person.d.ts.map +0 -1
  93. package/dist/commands/person.js +0 -185
  94. package/dist/commands/person.js.map +0 -1
  95. package/dist/commands/project.d.ts +0 -4
  96. package/dist/commands/project.d.ts.map +0 -1
  97. package/dist/commands/project.js +0 -70
  98. package/dist/commands/project.js.map +0 -1
  99. package/dist/commands/remember.d.ts +0 -4
  100. package/dist/commands/remember.d.ts.map +0 -1
  101. package/dist/commands/remember.js +0 -70
  102. package/dist/commands/remember.js.map +0 -1
  103. package/dist/commands/research.d.ts +0 -4
  104. package/dist/commands/research.d.ts.map +0 -1
  105. package/dist/commands/research.js +0 -14
  106. package/dist/commands/research.js.map +0 -1
  107. package/dist/commands/shell.d.ts +0 -3
  108. package/dist/commands/shell.d.ts.map +0 -1
  109. package/dist/commands/shell.js +0 -346
  110. package/dist/commands/shell.js.map +0 -1
  111. package/dist/commands/today.d.ts +0 -4
  112. package/dist/commands/today.d.ts.map +0 -1
  113. package/dist/commands/today.js +0 -112
  114. package/dist/commands/today.js.map +0 -1
  115. package/dist/commands/todo.d.ts +0 -4
  116. package/dist/commands/todo.d.ts.map +0 -1
  117. package/dist/commands/todo.js +0 -678
  118. package/dist/commands/todo.js.map +0 -1
  119. package/dist/commands/todont.d.ts +0 -19
  120. package/dist/commands/todont.d.ts.map +0 -1
  121. package/dist/commands/todont.js +0 -209
  122. package/dist/commands/todont.js.map +0 -1
  123. package/dist/commands/week.d.ts +0 -4
  124. package/dist/commands/week.d.ts.map +0 -1
  125. package/dist/commands/week.js +0 -267
  126. package/dist/commands/week.js.map +0 -1
  127. package/dist/dobbai.txt +0 -55
  128. package/dist/dobbi.txt +0 -55
  129. package/dist/dobbie-bundle.cjs +0 -73313
  130. package/dist/dobbie.txt +0 -55
  131. package/dist/feral/node-code/output/dobbai-speak-node-code.d.ts +0 -11
  132. package/dist/feral/node-code/output/dobbai-speak-node-code.d.ts.map +0 -1
  133. package/dist/feral/node-code/output/dobbai-speak-node-code.js +0 -56
  134. package/dist/feral/node-code/output/dobbai-speak-node-code.js.map +0 -1
  135. package/dist/feral/node-code/output/dobbi-speak-node-code.d.ts +0 -15
  136. package/dist/feral/node-code/output/dobbi-speak-node-code.d.ts.map +0 -1
  137. package/dist/feral/node-code/output/dobbi-speak-node-code.js +0 -60
  138. package/dist/feral/node-code/output/dobbi-speak-node-code.js.map +0 -1
  139. package/dist/feral/node-code/output/dobbie-speak-node-code.d.ts +0 -11
  140. package/dist/feral/node-code/output/dobbie-speak-node-code.d.ts.map +0 -1
  141. package/dist/feral/node-code/output/dobbie-speak-node-code.js +0 -56
  142. package/dist/feral/node-code/output/dobbie-speak-node-code.js.map +0 -1
  143. package/dist/service/cron/process-evaluator.d.ts +0 -6
  144. package/dist/service/cron/process-evaluator.d.ts.map +0 -1
  145. package/dist/service/cron/process-evaluator.js +0 -126
  146. package/dist/service/cron/process-evaluator.js.map +0 -1
  147. package/dist/tools/project.d.ts +0 -2
  148. package/dist/tools/project.d.ts.map +0 -1
  149. package/dist/tools/project.js +0 -112
  150. package/dist/tools/project.js.map +0 -1
@@ -1,678 +0,0 @@
1
- import { Command } from 'commander';
2
- import chalk from 'chalk';
3
- import inquirer from 'inquirer';
4
- import { promises as fs } from 'fs';
5
- import path from 'path';
6
- import matter from 'gray-matter';
7
- import { getVaultRoot } from '../state/manager.js';
8
- import { getEnrichedContext } from '../context/reader.js';
9
- import { getModelForCapability, createSystemPrompt } from '../llm/router.js';
10
- import { getResponse } from '../responses.js';
11
- import { renderEntityHeader, entityPrompt, todoHeaderConfig } from '../ui/entity-prompt.js';
12
- import { pushCrumb, popCrumb } from '../ui/breadcrumb.js';
13
- import { debug } from '../utils/debug.js';
14
- import { listEntities } from './list.js';
15
- import { getEntityIndex } from '../entities/entity-index.js';
16
- import { findEntityByTitle, trashEntity, generateEntityId, entityFilename } from '../entities/entity.js';
17
- async function findExistingTodo(titleOrFilename) {
18
- const found = await findEntityByTitle('task', titleOrFilename);
19
- if (!found)
20
- return null;
21
- return {
22
- filepath: found.filepath,
23
- title: found.meta.title,
24
- content: found.content,
25
- priority: found.meta.priority || 'medium',
26
- dueDate: found.meta.dueDate,
27
- completed: found.meta.status === 'done',
28
- };
29
- }
30
- async function breakdownTodo(state) {
31
- console.log(chalk.gray('\n' + getResponse('todo_breakdown')));
32
- const context = await getEnrichedContext('todos', state.content);
33
- const llm = await getModelForCapability('reason');
34
- const systemPrompt = createSystemPrompt(context);
35
- const response = await llm.chat([
36
- {
37
- role: 'user',
38
- content: `Break down the following todo into smaller, actionable subtasks. Format as a markdown checklist with [ ] for each item. Keep each subtask specific and achievable.
39
-
40
- Title: ${state.title}
41
-
42
- Current Content:
43
- ${state.content || '(No details yet)'}`,
44
- },
45
- ], { systemPrompt });
46
- // Strip code fences if present
47
- let formatted = response.trim();
48
- if (formatted.startsWith('```markdown')) {
49
- formatted = formatted.slice(11);
50
- }
51
- else if (formatted.startsWith('```')) {
52
- formatted = formatted.slice(3);
53
- }
54
- if (formatted.endsWith('```')) {
55
- formatted = formatted.slice(0, -3);
56
- }
57
- return formatted.trim();
58
- }
59
- async function clarifyTodo(state) {
60
- console.log(chalk.gray('\n' + getResponse('processing')));
61
- const context = await getEnrichedContext('todos', state.content);
62
- const llm = await getModelForCapability('reason');
63
- const systemPrompt = createSystemPrompt(context);
64
- const response = await llm.chat([
65
- {
66
- role: 'user',
67
- content: `Review and clarify the following todo. Make the description clearer, add context if helpful, and ensure the goal is specific and measurable. Return ONLY the improved content, no explanations.
68
-
69
- Title: ${state.title}
70
- Priority: ${state.priority}
71
- ${state.dueDate ? `Due: ${state.dueDate}` : ''}
72
-
73
- Content:
74
- ${state.content || '(No details yet)'}`,
75
- },
76
- ], { systemPrompt });
77
- // Strip code fences if present
78
- let formatted = response.trim();
79
- if (formatted.startsWith('```markdown')) {
80
- formatted = formatted.slice(11);
81
- }
82
- else if (formatted.startsWith('```')) {
83
- formatted = formatted.slice(3);
84
- }
85
- if (formatted.endsWith('```')) {
86
- formatted = formatted.slice(0, -3);
87
- }
88
- return formatted.trim();
89
- }
90
- async function estimateTodo(state) {
91
- console.log(chalk.gray('\n' + getResponse('thinking')));
92
- const context = await getEnrichedContext('todos', state.content);
93
- const llm = await getModelForCapability('reason');
94
- const systemPrompt = createSystemPrompt(context);
95
- const response = await llm.chat([
96
- {
97
- role: 'user',
98
- content: `Analyze the following todo and provide:
99
- 1. Time estimate (how long it will take)
100
- 2. Complexity rating (simple/moderate/complex)
101
- 3. Dependencies (what needs to be done first)
102
- 4. Suggested priority based on the content
103
-
104
- Keep the analysis brief and actionable.
105
-
106
- Title: ${state.title}
107
- Current Priority: ${state.priority}
108
- ${state.dueDate ? `Due: ${state.dueDate}` : ''}
109
-
110
- Content:
111
- ${state.content || '(No details yet)'}`,
112
- },
113
- ], { systemPrompt });
114
- return response.trim();
115
- }
116
- async function modifyTodo(state, feedback) {
117
- console.log(chalk.gray('\n' + getResponse('processing')));
118
- const context = await getEnrichedContext('todos', state.content);
119
- const llm = await getModelForCapability('reason');
120
- const systemPrompt = createSystemPrompt(context);
121
- const response = await llm.chat([
122
- {
123
- role: 'user',
124
- content: `Modify the following todo based on the user's feedback. Return ONLY the modified content, no explanations.
125
-
126
- Title: ${state.title}
127
-
128
- Current Content:
129
- ${state.content || '(No details yet)'}
130
-
131
- User Feedback: ${feedback}`,
132
- },
133
- ], { systemPrompt });
134
- // Strip code fences if present
135
- let formatted = response.trim();
136
- if (formatted.startsWith('```markdown')) {
137
- formatted = formatted.slice(11);
138
- }
139
- else if (formatted.startsWith('```')) {
140
- formatted = formatted.slice(3);
141
- }
142
- if (formatted.endsWith('```')) {
143
- formatted = formatted.slice(0, -3);
144
- }
145
- return formatted.trim();
146
- }
147
- async function formatTodo(state) {
148
- console.log(chalk.gray('\n' + getResponse('processing')));
149
- try {
150
- const context = await getEnrichedContext('todos', state.content);
151
- const llm = await getModelForCapability('format');
152
- const systemPrompt = createSystemPrompt(context);
153
- const response = await llm.chat([
154
- {
155
- role: 'user',
156
- content: `Format the following todo content as clean, well-structured markdown. Use appropriate headers, lists, and emphasis. Keep all information intact.
157
-
158
- IMPORTANT: Return ONLY the raw markdown content. Do NOT wrap in code fences.
159
-
160
- Title: ${state.title}
161
-
162
- Content:
163
- ${state.content}`,
164
- },
165
- ], { systemPrompt });
166
- // Strip code fences if present
167
- let formatted = response.trim();
168
- if (formatted.startsWith('```markdown')) {
169
- formatted = formatted.slice(11);
170
- }
171
- else if (formatted.startsWith('```md')) {
172
- formatted = formatted.slice(5);
173
- }
174
- else if (formatted.startsWith('```')) {
175
- formatted = formatted.slice(3);
176
- }
177
- if (formatted.endsWith('```')) {
178
- formatted = formatted.slice(0, -3);
179
- }
180
- return formatted.trim();
181
- }
182
- catch (err) {
183
- debug('todo', err);
184
- console.log(chalk.yellow('Formatting skipped (configure AI for formatting)'));
185
- return state.content;
186
- }
187
- }
188
- async function saveTodo(state) {
189
- const vaultRoot = await getVaultRoot();
190
- const todosDir = path.join(vaultRoot, 'todos');
191
- // Ensure todos directory exists
192
- await fs.mkdir(todosDir, { recursive: true });
193
- // Use existing filepath or create new one
194
- let filepath = state.filepath;
195
- let entityId;
196
- if (filepath) {
197
- // Editing — read id from existing frontmatter
198
- const raw = await fs.readFile(filepath, 'utf-8');
199
- const parsed = matter(raw);
200
- entityId = parsed.data.id ?? path.basename(filepath, '.md');
201
- }
202
- else {
203
- entityId = generateEntityId('task');
204
- filepath = path.join(todosDir, entityFilename(state.title, entityId));
205
- }
206
- // Format content before saving
207
- const finalContent = await formatTodo(state);
208
- // Create markdown with frontmatter
209
- const today = new Date().toISOString().split('T')[0];
210
- const markdown = `---
211
- id: ${entityId}
212
- title: "${state.title}"
213
- created: ${today}
214
- priority: ${state.priority}
215
- ${state.dueDate ? `dueDate: ${state.dueDate}` : ''}
216
- completed: ${state.completed}
217
- tags: [todo]
218
- ---
219
-
220
- ${finalContent}
221
- `;
222
- await fs.writeFile(filepath, markdown);
223
- // Update entity index
224
- const index = getEntityIndex();
225
- if (index.isBuilt) {
226
- await index.addOrUpdate('task', entityId, state.title, filepath);
227
- }
228
- return filepath;
229
- }
230
- function displayTodo(state) {
231
- const priorityColors = {
232
- low: chalk.gray,
233
- medium: chalk.yellow,
234
- high: chalk.red,
235
- };
236
- const priorityColor = priorityColors[state.priority];
237
- const statusIcon = state.completed ? 'āœ…' : '⬜';
238
- console.log(chalk.cyan('\n' + '─'.repeat(50)));
239
- console.log(`${statusIcon} ${chalk.bold.cyan(state.title)} ${priorityColor(`[${state.priority}]`)}`);
240
- if (state.dueDate) {
241
- console.log(chalk.gray(` Due: ${state.dueDate}`));
242
- }
243
- console.log(chalk.cyan('─'.repeat(50)));
244
- console.log(state.content || chalk.gray('(No details yet)'));
245
- console.log(chalk.cyan('─'.repeat(50) + '\n'));
246
- }
247
- function showHelp() {
248
- console.log(chalk.gray(`
249
- Commands:
250
- ${chalk.bold('breakdown')} - AI breaks the todo into subtasks
251
- ${chalk.bold('clarify')} - AI clarifies and improves the description
252
- ${chalk.bold('estimate')} - AI estimates time, complexity, dependencies
253
- ${chalk.bold('modify')} - AI modifies the todo based on your feedback
254
- ${chalk.bold('save')} - Save the current version
255
- ${chalk.bold('show')} - Display the current todo
256
- ${chalk.bold('edit')} - Edit the todo content
257
- ${chalk.bold('title')} - Change the title
258
- ${chalk.bold('priority')} - Set priority (low|medium|high)
259
- ${chalk.bold('due')} - Set due date
260
- ${chalk.bold('done')} - Mark as completed
261
- ${chalk.bold('exit')} - Save and go back
262
- ${chalk.bold('back')} - Save and go back
263
- ${chalk.bold('abort')} - Discard changes and go back
264
- ${chalk.bold('quit')} - Quit entirely
265
- ${chalk.bold('help')} - Show this help
266
- `));
267
- }
268
- export const todoCommand = new Command('todo')
269
- .description('Interactive todo management with AI assistance')
270
- .argument('[words...]', 'Title and optional inline description (e.g. "fix-login The login 500s with plus signs")')
271
- .action(async (words) => {
272
- try {
273
- // Handle: todo list
274
- if (words[0] === 'list') {
275
- await listEntities('todos');
276
- return;
277
- }
278
- // Handle: todo done <title>
279
- if (words[0] === 'done') {
280
- const doneTitle = words.slice(1).join(' ');
281
- if (!doneTitle) {
282
- console.log(chalk.yellow('\n Please specify which task to complete: todo done <title>\n'));
283
- return;
284
- }
285
- const existing = await findExistingTodo(doneTitle);
286
- if (!existing) {
287
- console.log(chalk.red(`\n āœ— Task "${doneTitle}" not found\n`));
288
- return;
289
- }
290
- const doneState = {
291
- title: existing.title,
292
- content: existing.content,
293
- priority: existing.priority,
294
- dueDate: existing.dueDate,
295
- filepath: existing.filepath,
296
- isExisting: true,
297
- completed: true,
298
- };
299
- const filepath = await saveTodo(doneState);
300
- const msg = getResponse('task_complete');
301
- console.log(chalk.green(`\n āœ“ ${msg}`));
302
- console.log(chalk.gray(` ${filepath}\n`));
303
- return;
304
- }
305
- // Handle: todo remove <title>
306
- if (words[0] === 'remove' || words[0] === 'delete') {
307
- const removeTitle = words.slice(1).join(' ');
308
- if (!removeTitle) {
309
- console.log(chalk.yellow('\n Please specify which task to remove: todo remove <title>\n'));
310
- return;
311
- }
312
- const existing = await findExistingTodo(removeTitle);
313
- if (!existing) {
314
- console.log(chalk.red(`\n āœ— Task "${removeTitle}" not found\n`));
315
- return;
316
- }
317
- // Read id from frontmatter before trashing
318
- const raw = await fs.readFile(existing.filepath, 'utf-8');
319
- const taskId = matter(raw).data.id ?? path.basename(existing.filepath, '.md');
320
- const trashPath = await trashEntity(existing.filepath);
321
- // Update entity index
322
- const idx = getEntityIndex();
323
- if (idx.isBuilt) {
324
- idx.remove('task', taskId);
325
- }
326
- console.log(chalk.green(`\n šŸ—‘ Moved to trash: ${existing.title}`));
327
- console.log(chalk.gray(` ${trashPath}\n`));
328
- return;
329
- }
330
- // Parse: first word = title, rest = inline description
331
- let title = words.length > 0 ? words[0] : undefined;
332
- const inlineBody = words.length > 1 ? words.slice(1).join(' ') : undefined;
333
- // Get title if not provided
334
- if (!title) {
335
- const { todoTitle } = await inquirer.prompt([
336
- {
337
- type: 'input',
338
- name: 'todoTitle',
339
- message: 'What task should be tracked?',
340
- validate: (input) => input.length > 0 || 'Title is required',
341
- },
342
- ]);
343
- title = todoTitle;
344
- }
345
- // Check if todo already exists
346
- const existing = await findExistingTodo(title);
347
- let state;
348
- if (existing) {
349
- // Open existing todo — if inline body, append to it
350
- if (inlineBody) {
351
- const updatedContent = existing.content
352
- ? existing.content + '\n\n' + inlineBody
353
- : inlineBody;
354
- state = {
355
- title: existing.title,
356
- content: updatedContent,
357
- priority: existing.priority,
358
- dueDate: existing.dueDate,
359
- filepath: existing.filepath,
360
- isExisting: true,
361
- completed: existing.completed,
362
- };
363
- const filepath = await saveTodo(state);
364
- console.log(chalk.green(`\nāœ“ Appended to "${existing.title}" → ${filepath}`));
365
- return;
366
- }
367
- console.log(chalk.green(`\nāœ“ Opening existing todo "${existing.title}"`));
368
- state = {
369
- title: existing.title,
370
- content: existing.content,
371
- priority: existing.priority,
372
- dueDate: existing.dueDate,
373
- filepath: existing.filepath,
374
- isExisting: true,
375
- completed: existing.completed,
376
- };
377
- }
378
- else if (inlineBody) {
379
- // Quick todo — save immediately with medium priority
380
- state = {
381
- title: title,
382
- content: inlineBody,
383
- priority: 'medium',
384
- dueDate: undefined,
385
- isExisting: false,
386
- completed: false,
387
- };
388
- const filepath = await saveTodo(state);
389
- console.log(chalk.green(`\nāœ“ Quick todo saved → ${filepath}`));
390
- return;
391
- }
392
- else {
393
- // Create new todo - get initial details
394
- const { priority } = await inquirer.prompt([
395
- {
396
- type: 'list',
397
- name: 'priority',
398
- message: 'Priority level?',
399
- choices: [
400
- { name: 'Low', value: 'low' },
401
- { name: 'Medium', value: 'medium' },
402
- { name: 'High', value: 'high' },
403
- ],
404
- default: 'medium',
405
- },
406
- ]);
407
- const { dueDate } = await inquirer.prompt([
408
- {
409
- type: 'input',
410
- name: 'dueDate',
411
- message: 'Due date (YYYY-MM-DD, or leave empty):',
412
- validate: (input) => {
413
- if (!input)
414
- return true;
415
- return /^\d{4}-\d{2}-\d{2}$/.test(input) || 'Use format YYYY-MM-DD';
416
- },
417
- },
418
- ]);
419
- const { content } = await inquirer.prompt([
420
- {
421
- type: 'editor',
422
- name: 'content',
423
- message: 'Todo details (optional):',
424
- },
425
- ]);
426
- state = {
427
- title: title,
428
- content: content.trim(),
429
- priority,
430
- dueDate: dueDate || undefined,
431
- isExisting: false,
432
- completed: false,
433
- };
434
- console.log(chalk.green(`\nāœ“ Todo created`));
435
- }
436
- pushCrumb('todo');
437
- renderEntityHeader(todoHeaderConfig(state));
438
- showHelp();
439
- displayTodo(state);
440
- // Interactive loop
441
- let running = true;
442
- while (running) {
443
- const { command } = await inquirer.prompt([
444
- {
445
- type: 'input',
446
- name: 'command',
447
- message: entityPrompt('todo'),
448
- prefix: '',
449
- },
450
- ]);
451
- const cmd = command.trim().toLowerCase();
452
- const parts = cmd.split(' ');
453
- const action = parts[0];
454
- const args = parts.slice(1).join(' ');
455
- switch (action) {
456
- case 'save': {
457
- const filepath = await saveTodo(state);
458
- console.log(chalk.green(`\nāœ“ Todo saved to ${filepath}, sir!`));
459
- break;
460
- }
461
- case 'exit': {
462
- const filepath = await saveTodo(state);
463
- console.log(chalk.green(`\nāœ“ Todo saved to ${filepath}, sir!`));
464
- running = false;
465
- break;
466
- }
467
- case 'back':
468
- case 'b': {
469
- const filepath = await saveTodo(state);
470
- console.log(chalk.green(`\nāœ“ Todo saved to ${filepath}, sir!`));
471
- running = false;
472
- break;
473
- }
474
- case 'abort': {
475
- const { confirm } = await inquirer.prompt([
476
- {
477
- type: 'confirm',
478
- name: 'confirm',
479
- message: 'There is unsaved work. Discard changes?',
480
- default: false,
481
- },
482
- ]);
483
- if (confirm) {
484
- console.log(chalk.yellow(getResponse('task_discarded')));
485
- running = false;
486
- }
487
- break;
488
- }
489
- case 'quit':
490
- case 'q': {
491
- const { confirm: quitConfirm } = await inquirer.prompt([
492
- {
493
- type: 'confirm',
494
- name: 'confirm',
495
- message: 'There is unsaved work. Quit entirely?',
496
- default: false,
497
- },
498
- ]);
499
- if (quitConfirm) {
500
- console.log(chalk.yellow(getResponse('farewell')));
501
- process.exit(42);
502
- }
503
- break;
504
- }
505
- case 'breakdown': {
506
- try {
507
- const breakdown = await breakdownTodo(state);
508
- state.content = state.content ? state.content + '\n\n## Subtasks\n\n' + breakdown : breakdown;
509
- console.log(chalk.green('āœ“ Todo broken down into subtasks!'));
510
- displayTodo(state);
511
- }
512
- catch (error) {
513
- console.error(chalk.red('Error breaking down todo:'), error);
514
- }
515
- break;
516
- }
517
- case 'clarify': {
518
- try {
519
- state.content = await clarifyTodo(state);
520
- console.log(chalk.green('āœ“ Todo clarified!'));
521
- displayTodo(state);
522
- }
523
- catch (error) {
524
- console.error(chalk.red('Error clarifying todo:'), error);
525
- }
526
- break;
527
- }
528
- case 'estimate': {
529
- try {
530
- const estimate = await estimateTodo(state);
531
- console.log(chalk.cyan('\nšŸ“Š Estimate:\n'));
532
- console.log(estimate);
533
- console.log('');
534
- }
535
- catch (error) {
536
- console.error(chalk.red('Error estimating todo:'), error);
537
- }
538
- break;
539
- }
540
- case 'modify': {
541
- if (!args) {
542
- const { feedback } = await inquirer.prompt([
543
- {
544
- type: 'input',
545
- name: 'feedback',
546
- message: 'How should the todo be modified?',
547
- },
548
- ]);
549
- if (feedback) {
550
- try {
551
- state.content = await modifyTodo(state, feedback);
552
- console.log(chalk.green('āœ“ Todo modified!'));
553
- displayTodo(state);
554
- }
555
- catch (error) {
556
- console.error(chalk.red('Error modifying todo:'), error);
557
- }
558
- }
559
- }
560
- else {
561
- try {
562
- state.content = await modifyTodo(state, args);
563
- console.log(chalk.green('āœ“ Todo modified!'));
564
- displayTodo(state);
565
- }
566
- catch (error) {
567
- console.error(chalk.red('Error modifying todo:'), error);
568
- }
569
- }
570
- break;
571
- }
572
- case 'show': {
573
- displayTodo(state);
574
- break;
575
- }
576
- case 'edit': {
577
- const { newContent } = await inquirer.prompt([
578
- {
579
- type: 'editor',
580
- name: 'newContent',
581
- message: 'Edit todo:',
582
- default: state.content,
583
- },
584
- ]);
585
- state.content = newContent.trim();
586
- console.log(chalk.green('āœ“ Todo updated!'));
587
- displayTodo(state);
588
- break;
589
- }
590
- case 'title': {
591
- const { newTitle } = await inquirer.prompt([
592
- {
593
- type: 'input',
594
- name: 'newTitle',
595
- message: 'New title:',
596
- default: state.title,
597
- },
598
- ]);
599
- state.title = newTitle;
600
- console.log(chalk.green(`āœ“ Title changed to "${newTitle}"`));
601
- break;
602
- }
603
- case 'priority': {
604
- const newPriority = args;
605
- if (['low', 'medium', 'high'].includes(newPriority)) {
606
- state.priority = newPriority;
607
- console.log(chalk.green(`āœ“ Priority set to ${newPriority}`));
608
- }
609
- else {
610
- const { selectedPriority } = await inquirer.prompt([
611
- {
612
- type: 'list',
613
- name: 'selectedPriority',
614
- message: 'Select priority:',
615
- choices: ['low', 'medium', 'high'],
616
- default: state.priority,
617
- },
618
- ]);
619
- state.priority = selectedPriority;
620
- console.log(chalk.green(`āœ“ Priority set to ${selectedPriority}`));
621
- }
622
- displayTodo(state);
623
- break;
624
- }
625
- case 'due': {
626
- if (args && /^\d{4}-\d{2}-\d{2}$/.test(args)) {
627
- state.dueDate = args;
628
- console.log(chalk.green(`āœ“ Due date set to ${args}`));
629
- }
630
- else {
631
- const { newDueDate } = await inquirer.prompt([
632
- {
633
- type: 'input',
634
- name: 'newDueDate',
635
- message: 'Due date (YYYY-MM-DD):',
636
- default: state.dueDate || '',
637
- validate: (input) => {
638
- if (!input)
639
- return true;
640
- return /^\d{4}-\d{2}-\d{2}$/.test(input) || 'Use format YYYY-MM-DD';
641
- },
642
- },
643
- ]);
644
- state.dueDate = newDueDate || undefined;
645
- console.log(chalk.green(newDueDate ? `āœ“ Due date set to ${newDueDate}` : 'āœ“ Due date cleared'));
646
- }
647
- displayTodo(state);
648
- break;
649
- }
650
- case 'done': {
651
- state.completed = !state.completed;
652
- console.log(chalk.green(state.completed ? 'āœ“ Marked as completed!' : 'āœ“ Marked as incomplete'));
653
- displayTodo(state);
654
- break;
655
- }
656
- case 'help':
657
- case '?': {
658
- showHelp();
659
- break;
660
- }
661
- case '': {
662
- // Empty command, ignore
663
- break;
664
- }
665
- default: {
666
- console.log(chalk.yellow(`Unknown command: ${action}. Type 'help' for options.`));
667
- break;
668
- }
669
- }
670
- }
671
- popCrumb();
672
- }
673
- catch (error) {
674
- console.error(chalk.red(getResponse('error')), error);
675
- }
676
- });
677
- export default todoCommand;
678
- //# sourceMappingURL=todo.js.map