idea-manager 0.4.0 → 0.6.0

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 (40) hide show
  1. package/package.json +1 -1
  2. package/src/app/projects/[id]/page.tsx +0 -4
  3. package/src/cli.ts +17 -0
  4. package/src/components/brainstorm/Editor.tsx +1 -84
  5. package/src/lib/ai/client.ts +22 -125
  6. package/src/lib/db/schema.ts +0 -70
  7. package/src/lib/watcher.ts +190 -0
  8. package/src/types/index.ts +0 -90
  9. package/src/app/api/projects/[id]/cleanup/route.ts +0 -32
  10. package/src/app/api/projects/[id]/conversations/route.ts +0 -50
  11. package/src/app/api/projects/[id]/items/[itemId]/prompt/route.ts +0 -51
  12. package/src/app/api/projects/[id]/items/[itemId]/refine/route.ts +0 -36
  13. package/src/app/api/projects/[id]/items/[itemId]/route.ts +0 -95
  14. package/src/app/api/projects/[id]/items/route.ts +0 -67
  15. package/src/app/api/projects/[id]/memos/route.ts +0 -18
  16. package/src/app/api/projects/[id]/scan/route.ts +0 -73
  17. package/src/app/api/projects/[id]/scan/stream/route.ts +0 -112
  18. package/src/app/api/projects/[id]/structure/route.ts +0 -59
  19. package/src/app/api/projects/[id]/structure/stream/route.ts +0 -157
  20. package/src/components/ScanPanel.tsx +0 -743
  21. package/src/components/brainstorm/MemoPin.tsx +0 -117
  22. package/src/components/tree/CardView.tsx +0 -206
  23. package/src/components/tree/ItemDetail.tsx +0 -196
  24. package/src/components/tree/LockToggle.tsx +0 -23
  25. package/src/components/tree/RefinePopover.tsx +0 -157
  26. package/src/components/tree/StatusBadge.tsx +0 -32
  27. package/src/components/tree/TreeNode.tsx +0 -227
  28. package/src/components/tree/TreeView.tsx +0 -304
  29. package/src/lib/ai/chat-responder.ts +0 -71
  30. package/src/lib/ai/cleanup.ts +0 -87
  31. package/src/lib/ai/prompter.ts +0 -78
  32. package/src/lib/ai/refiner.ts +0 -128
  33. package/src/lib/ai/structurer.ts +0 -403
  34. package/src/lib/db/queries/context.ts +0 -76
  35. package/src/lib/db/queries/conversations.ts +0 -46
  36. package/src/lib/db/queries/items.ts +0 -268
  37. package/src/lib/db/queries/memos.ts +0 -66
  38. package/src/lib/db/queries/prompts.ts +0 -68
  39. package/src/lib/scanner.ts +0 -573
  40. package/src/lib/task-store.ts +0 -97
@@ -1,59 +0,0 @@
1
- import { NextRequest, NextResponse } from 'next/server';
2
- import { getProject } from '@/lib/db/queries/projects';
3
- import { getBrainstorm } from '@/lib/db/queries/brainstorms';
4
- import { getProjectContextSummary } from '@/lib/db/queries/context';
5
- import { structureWithChat } from '@/lib/ai/structurer';
6
- import { getTask } from '@/lib/task-store';
7
-
8
- export async function GET(
9
- _request: NextRequest,
10
- { params }: { params: Promise<{ id: string }> },
11
- ) {
12
- const { id } = await params;
13
- const task = getTask(id);
14
- if (!task) {
15
- return NextResponse.json({ active: false });
16
- }
17
- return NextResponse.json({
18
- active: task.status === 'running',
19
- status: task.status,
20
- startedAt: task.startedAt,
21
- eventCount: task.events.length,
22
- });
23
- }
24
-
25
- export async function POST(
26
- _request: NextRequest,
27
- { params }: { params: Promise<{ id: string }> },
28
- ) {
29
- const { id } = await params;
30
- const project = getProject(id);
31
- if (!project) {
32
- return NextResponse.json({ error: 'Project not found' }, { status: 404 });
33
- }
34
-
35
- const brainstorm = getBrainstorm(id);
36
- if (!brainstorm) {
37
- return NextResponse.json({ error: 'Project not initialized' }, { status: 400 });
38
- }
39
-
40
- const hasContent = brainstorm.content.trim();
41
- const hasContext = !!getProjectContextSummary(id);
42
-
43
- if (!hasContent && !hasContext) {
44
- return NextResponse.json({ error: '브레인스토밍 내용이나 프로젝트 스캔 결과가 필요합니다' }, { status: 400 });
45
- }
46
-
47
- // If brainstorm is empty but project context exists, use a placeholder prompt
48
- const content = hasContent
49
- ? brainstorm.content
50
- : '프로젝트 스캔 결과를 분석하여 현재 프로젝트의 구조, 진행 상황, TODO 항목을 파악해주세요.';
51
-
52
- try {
53
- const result = await structureWithChat(id, brainstorm.id, content);
54
- return NextResponse.json(result);
55
- } catch (error) {
56
- const message = error instanceof Error ? error.message : 'AI structuring failed';
57
- return NextResponse.json({ error: message }, { status: 500 });
58
- }
59
- }
@@ -1,157 +0,0 @@
1
- import { NextRequest } from 'next/server';
2
- import { getProject } from '@/lib/db/queries/projects';
3
- import { getBrainstorm } from '@/lib/db/queries/brainstorms';
4
- import { getProjectContextSummary } from '@/lib/db/queries/context';
5
- import { structureWithChatDirect } from '@/lib/ai/structurer';
6
- import {
7
- getTask, startTask, addTaskEvent, finishTask, failTask,
8
- addTaskListener, cleanupTasks,
9
- } from '@/lib/task-store';
10
-
11
- export async function GET(
12
- request: NextRequest,
13
- { params }: { params: Promise<{ id: string }> },
14
- ) {
15
- const { id } = await params;
16
- const project = getProject(id);
17
- if (!project) {
18
- return new Response('Project not found', { status: 404 });
19
- }
20
-
21
- cleanupTasks();
22
-
23
- const existingTask = getTask(id);
24
-
25
- // If there's an active task, attach to it (reconnect scenario)
26
- if (existingTask && existingTask.status === 'running') {
27
- return createReconnectStream(id, existingTask);
28
- }
29
-
30
- // If recently finished task exists, replay final result
31
- if (existingTask && existingTask.status === 'done' && existingTask.result) {
32
- return createReplayStream(existingTask);
33
- }
34
-
35
- // Start new task
36
- const brainstorm = getBrainstorm(id);
37
- if (!brainstorm) {
38
- return new Response('Project not initialized', { status: 400 });
39
- }
40
-
41
- const hasContent = brainstorm.content.trim();
42
- const hasContext = !!getProjectContextSummary(id);
43
-
44
- if (!hasContent && !hasContext) {
45
- return new Response('No content to structure', { status: 400 });
46
- }
47
-
48
- // User-provided project description from scan panel
49
- const userDescription = request.nextUrl.searchParams.get('desc') || '';
50
-
51
- let content = hasContent
52
- ? brainstorm.content
53
- : '프로젝트 스캔 결과를 분석하여 현재 프로젝트의 구조, 진행 상황, TODO 항목을 파악해주세요.';
54
-
55
- if (userDescription) {
56
- content = `[사용자가 제공한 프로젝트 설명]\n${userDescription}\n\n${content}`;
57
- }
58
-
59
- const brainstormId = brainstorm.id;
60
-
61
- // Start background task
62
- startTask(id);
63
-
64
- const send = async (event: string, data: unknown) => {
65
- addTaskEvent(id, event, data);
66
- if (event === 'done') {
67
- finishTask(id, data);
68
- }
69
- };
70
-
71
- // Run structuring in background (detached from stream)
72
- (async () => {
73
- try {
74
- await structureWithChatDirect(id, brainstormId, content, send);
75
- } catch (error) {
76
- const msg = error instanceof Error ? error.message : 'Structure failed';
77
- addTaskEvent(id, 'error', { error: msg });
78
- failTask(id, msg);
79
- }
80
- })();
81
-
82
- // Stream events to this client
83
- return createReconnectStream(id, getTask(id)!);
84
- }
85
-
86
- function createReconnectStream(projectId: string, task: ReturnType<typeof getTask>) {
87
- const encoder = new TextEncoder();
88
- let unsubscribe: (() => void) | null = null;
89
-
90
- const stream = new ReadableStream({
91
- start(controller) {
92
- const send = (event: string, data: unknown) => {
93
- try {
94
- controller.enqueue(encoder.encode(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`));
95
- } catch {
96
- // controller may be closed
97
- }
98
- };
99
-
100
- // Replay past events
101
- if (task) {
102
- for (const ev of task.events) {
103
- send(ev.event, ev.data);
104
- }
105
-
106
- // If already finished, close immediately
107
- if (task.status !== 'running') {
108
- controller.close();
109
- return;
110
- }
111
- }
112
-
113
- // Listen for new events
114
- unsubscribe = addTaskListener(projectId, (event, data) => {
115
- send(event, data);
116
- if (event === 'done' || event === 'error') {
117
- try { controller.close(); } catch { /* already closed */ }
118
- unsubscribe?.();
119
- }
120
- });
121
- },
122
- cancel() {
123
- unsubscribe?.();
124
- },
125
- });
126
-
127
- return new Response(stream, {
128
- headers: {
129
- 'Content-Type': 'text/event-stream',
130
- 'Cache-Control': 'no-cache',
131
- 'Connection': 'keep-alive',
132
- 'X-Accel-Buffering': 'no',
133
- },
134
- });
135
- }
136
-
137
- function createReplayStream(task: NonNullable<ReturnType<typeof getTask>>) {
138
- const encoder = new TextEncoder();
139
- const stream = new ReadableStream({
140
- start(controller) {
141
- for (const ev of task.events) {
142
- try {
143
- controller.enqueue(encoder.encode(`event: ${ev.event}\ndata: ${JSON.stringify(ev.data)}\n\n`));
144
- } catch { break; }
145
- }
146
- controller.close();
147
- },
148
- });
149
-
150
- return new Response(stream, {
151
- headers: {
152
- 'Content-Type': 'text/event-stream',
153
- 'Cache-Control': 'no-cache',
154
- 'Connection': 'keep-alive',
155
- },
156
- });
157
- }