idea-manager 0.2.0 → 0.3.1

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 (61) hide show
  1. package/README.md +33 -41
  2. package/next.config.ts +0 -1
  3. package/package.json +2 -2
  4. package/{src/app/icon.svg → public/favicon.svg} +2 -2
  5. package/src/app/api/filesystem/route.ts +49 -0
  6. package/src/app/api/projects/[id]/cleanup/route.ts +32 -0
  7. package/src/app/api/projects/[id]/items/[itemId]/refine/route.ts +36 -0
  8. package/src/app/api/projects/[id]/items/[itemId]/route.ts +23 -1
  9. package/src/app/api/projects/[id]/items/route.ts +51 -1
  10. package/src/app/api/projects/[id]/scan/route.ts +73 -0
  11. package/src/app/api/projects/[id]/scan/stream/route.ts +112 -0
  12. package/src/app/api/projects/[id]/structure/route.ts +34 -3
  13. package/src/app/api/projects/[id]/structure/stream/route.ts +157 -0
  14. package/src/app/api/projects/[id]/sub-projects/[subId]/route.ts +39 -0
  15. package/src/app/api/projects/[id]/sub-projects/[subId]/tasks/[taskId]/chat/route.ts +60 -0
  16. package/src/app/api/projects/[id]/sub-projects/[subId]/tasks/[taskId]/prompt/route.ts +26 -0
  17. package/src/app/api/projects/[id]/sub-projects/[subId]/tasks/[taskId]/route.ts +39 -0
  18. package/src/app/api/projects/[id]/sub-projects/[subId]/tasks/route.ts +33 -0
  19. package/src/app/api/projects/[id]/sub-projects/route.ts +31 -0
  20. package/src/app/api/projects/route.ts +1 -1
  21. package/src/app/globals.css +465 -5
  22. package/src/app/layout.tsx +3 -0
  23. package/src/app/page.tsx +260 -88
  24. package/src/app/projects/[id]/page.tsx +366 -183
  25. package/src/cli.ts +10 -10
  26. package/src/components/DirectoryPicker.tsx +137 -0
  27. package/src/components/ScanPanel.tsx +743 -0
  28. package/src/components/brainstorm/Editor.tsx +20 -4
  29. package/src/components/brainstorm/MemoPin.tsx +91 -5
  30. package/src/components/dashboard/SubProjectCard.tsx +76 -0
  31. package/src/components/dashboard/TabBar.tsx +42 -0
  32. package/src/components/task/ProjectTree.tsx +223 -0
  33. package/src/components/task/PromptEditor.tsx +107 -0
  34. package/src/components/task/StatusFlow.tsx +43 -0
  35. package/src/components/task/TaskChat.tsx +134 -0
  36. package/src/components/task/TaskDetail.tsx +205 -0
  37. package/src/components/task/TaskList.tsx +119 -0
  38. package/src/components/tree/CardView.tsx +206 -0
  39. package/src/components/tree/RefinePopover.tsx +157 -0
  40. package/src/components/tree/TreeNode.tsx +147 -38
  41. package/src/components/tree/TreeView.tsx +270 -26
  42. package/src/components/ui/ConfirmDialog.tsx +88 -0
  43. package/src/lib/ai/chat-responder.ts +4 -2
  44. package/src/lib/ai/cleanup.ts +87 -0
  45. package/src/lib/ai/client.ts +175 -58
  46. package/src/lib/ai/prompter.ts +19 -24
  47. package/src/lib/ai/refiner.ts +128 -0
  48. package/src/lib/ai/structurer.ts +340 -11
  49. package/src/lib/db/queries/context.ts +76 -0
  50. package/src/lib/db/queries/items.ts +133 -12
  51. package/src/lib/db/queries/projects.ts +12 -8
  52. package/src/lib/db/queries/sub-projects.ts +122 -0
  53. package/src/lib/db/queries/task-conversations.ts +27 -0
  54. package/src/lib/db/queries/task-prompts.ts +32 -0
  55. package/src/lib/db/queries/tasks.ts +133 -0
  56. package/src/lib/db/schema.ts +75 -0
  57. package/src/lib/mcp/server.ts +38 -39
  58. package/src/lib/mcp/tools.ts +47 -45
  59. package/src/lib/scanner.ts +573 -0
  60. package/src/lib/task-store.ts +97 -0
  61. package/src/types/index.ts +65 -0
@@ -1,82 +1,84 @@
1
- import type { IItemTree, IItem, IPrompt } from '@/types';
2
-
3
- // Re-export query functions for MCP tools
4
- // These are imported from DB queries when the MCP server initializes
1
+ import type { ITask, ITaskPrompt, ISubProject } from '@/types';
5
2
 
6
3
  export interface McpToolContext {
7
4
  listProjects: () => { id: string; name: string; description: string; created_at: string; updated_at: string }[];
8
5
  getProject: (id: string) => { id: string; name: string; description: string } | undefined;
9
- getItemTree: (projectId: string) => IItemTree[];
10
- getItems: (projectId: string) => IItem[];
11
- getPrompt: (itemId: string) => IPrompt | undefined;
12
- updateItem: (id: string, data: Record<string, unknown>) => IItem | undefined;
6
+ getSubProjects: (projectId: string) => ISubProject[];
7
+ getTasksByProject: (projectId: string) => ITask[];
8
+ getTaskPrompt: (taskId: string) => ITaskPrompt | undefined;
9
+ updateTask: (id: string, data: Record<string, unknown>) => ITask | undefined;
13
10
  }
14
11
 
15
12
  export function getNextTask(ctx: McpToolContext, projectId: string): {
16
- item: IItem;
17
- prompt?: IPrompt;
13
+ task: ITask;
14
+ prompt?: ITaskPrompt;
18
15
  } | null {
19
- const items = ctx.getItems(projectId);
20
-
21
- // Find unlocked + pending items (ready to execute)
22
- const ready = items.filter(i => !i.is_locked && i.status === 'pending');
16
+ const tasks = ctx.getTasksByProject(projectId);
23
17
 
18
+ // Find submitted tasks with prompts (ready to execute)
19
+ const ready = tasks.filter(t => t.status === 'submitted');
24
20
  if (ready.length === 0) return null;
25
21
 
26
- // Sort by sort_order
27
22
  ready.sort((a, b) => a.sort_order - b.sort_order);
28
- const item = ready[0];
29
- const prompt = ctx.getPrompt(item.id);
23
+ const task = ready[0];
24
+ const prompt = ctx.getTaskPrompt(task.id);
30
25
 
31
- return { item, prompt };
26
+ return { task, prompt };
32
27
  }
33
28
 
34
29
  export function getProjectContext(ctx: McpToolContext, projectId: string): {
35
30
  project: { id: string; name: string; description: string } | undefined;
36
- tree: IItemTree[];
37
- stats: { total: number; pending: number; inProgress: number; done: number; unlocked: number };
31
+ subProjects: ISubProject[];
32
+ tasks: ITask[];
33
+ stats: { total: number; idea: number; writing: number; submitted: number; testing: number; done: number; problem: number };
38
34
  } {
39
35
  const project = ctx.getProject(projectId);
40
- const tree = ctx.getItemTree(projectId);
41
- const items = ctx.getItems(projectId);
36
+ const subProjects = ctx.getSubProjects(projectId);
37
+ const tasks = ctx.getTasksByProject(projectId);
42
38
 
43
39
  const stats = {
44
- total: items.length,
45
- pending: items.filter(i => i.status === 'pending').length,
46
- inProgress: items.filter(i => i.status === 'in_progress').length,
47
- done: items.filter(i => i.status === 'done').length,
48
- unlocked: items.filter(i => !i.is_locked).length,
40
+ total: tasks.length,
41
+ idea: tasks.filter(t => t.status === 'idea').length,
42
+ writing: tasks.filter(t => t.status === 'writing').length,
43
+ submitted: tasks.filter(t => t.status === 'submitted').length,
44
+ testing: tasks.filter(t => t.status === 'testing').length,
45
+ done: tasks.filter(t => t.status === 'done').length,
46
+ problem: tasks.filter(t => t.status === 'problem').length,
49
47
  };
50
48
 
51
- return { project, tree, stats };
49
+ return { project, subProjects, tasks, stats };
52
50
  }
53
51
 
54
- export function formatItemForMcp(item: IItem, prompt?: IPrompt): string {
52
+ export function formatTaskForMcp(task: ITask, prompt?: ITaskPrompt): string {
55
53
  const lines = [
56
- `제목: ${item.title}`,
57
- `설명: ${item.description}`,
58
- `유형: ${item.item_type}`,
59
- `우선순위: ${item.priority}`,
60
- `상태: ${item.status}`,
61
- `잠금: ${item.is_locked ? '잠금' : '해제'}`,
54
+ `Title: ${task.title}`,
55
+ `Description: ${task.description}`,
56
+ `Status: ${task.status}`,
57
+ `Priority: ${task.priority}`,
62
58
  ];
63
59
 
64
- if (prompt) {
65
- lines.push('', '--- 프롬프트 ---', prompt.content);
60
+ if (prompt?.content) {
61
+ lines.push('', '--- Prompt ---', prompt.content);
66
62
  }
67
63
 
68
64
  return lines.join('\n');
69
65
  }
70
66
 
71
- export function formatTreeForMcp(tree: IItemTree[], indent = 0): string {
67
+ export function formatProjectForMcp(
68
+ subProjects: ISubProject[],
69
+ tasks: ITask[],
70
+ ): string {
72
71
  const lines: string[] = [];
73
- for (const item of tree) {
74
- const prefix = ' '.repeat(indent);
75
- const lock = item.is_locked ? '🔐' : '🔓';
76
- const status = item.status === 'done' ? '✅' : item.status === 'in_progress' ? '🔄' : '⏳';
77
- lines.push(`${prefix}${lock} ${item.title} ${status}`);
78
- if (item.children.length > 0) {
79
- lines.push(formatTreeForMcp(item.children, indent + 1));
72
+ for (const sp of subProjects) {
73
+ lines.push(`[${sp.name}]`);
74
+ const spTasks = tasks.filter(t => t.sub_project_id === sp.id);
75
+ if (spTasks.length === 0) {
76
+ lines.push(' (no tasks)');
77
+ } else {
78
+ for (const t of spTasks) {
79
+ const icon = t.status === 'done' ? 'v' : t.status === 'submitted' ? '>' : t.status === 'testing' ? '~' : t.status === 'problem' ? '!' : '-';
80
+ lines.push(` ${icon} ${t.title} [${t.status}]`);
81
+ }
80
82
  }
81
83
  }
82
84
  return lines.join('\n');