idea-manager 0.1.2 → 0.3.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 (63) hide show
  1. package/README.md +19 -10
  2. package/next.config.ts +0 -1
  3. package/package.json +2 -2
  4. package/public/favicon.svg +10 -0
  5. package/public/icon.svg +2 -11
  6. package/src/app/api/filesystem/route.ts +49 -0
  7. package/src/app/api/projects/[id]/cleanup/route.ts +32 -0
  8. package/src/app/api/projects/[id]/items/[itemId]/refine/route.ts +36 -0
  9. package/src/app/api/projects/[id]/items/[itemId]/route.ts +23 -1
  10. package/src/app/api/projects/[id]/items/route.ts +51 -1
  11. package/src/app/api/projects/[id]/scan/route.ts +73 -0
  12. package/src/app/api/projects/[id]/scan/stream/route.ts +112 -0
  13. package/src/app/api/projects/[id]/structure/route.ts +34 -3
  14. package/src/app/api/projects/[id]/structure/stream/route.ts +157 -0
  15. package/src/app/api/projects/[id]/sub-projects/[subId]/route.ts +39 -0
  16. package/src/app/api/projects/[id]/sub-projects/[subId]/tasks/[taskId]/chat/route.ts +60 -0
  17. package/src/app/api/projects/[id]/sub-projects/[subId]/tasks/[taskId]/prompt/route.ts +26 -0
  18. package/src/app/api/projects/[id]/sub-projects/[subId]/tasks/[taskId]/route.ts +39 -0
  19. package/src/app/api/projects/[id]/sub-projects/[subId]/tasks/route.ts +33 -0
  20. package/src/app/api/projects/[id]/sub-projects/route.ts +31 -0
  21. package/src/app/api/projects/route.ts +1 -1
  22. package/src/app/globals.css +465 -5
  23. package/src/app/layout.tsx +3 -0
  24. package/src/app/page.tsx +260 -88
  25. package/src/app/projects/[id]/page.tsx +366 -183
  26. package/src/cli.ts +44 -12
  27. package/src/components/DirectoryPicker.tsx +137 -0
  28. package/src/components/ScanPanel.tsx +743 -0
  29. package/src/components/brainstorm/Editor.tsx +20 -4
  30. package/src/components/brainstorm/MemoPin.tsx +91 -5
  31. package/src/components/dashboard/SubProjectCard.tsx +76 -0
  32. package/src/components/dashboard/TabBar.tsx +42 -0
  33. package/src/components/task/ProjectTree.tsx +223 -0
  34. package/src/components/task/PromptEditor.tsx +107 -0
  35. package/src/components/task/StatusFlow.tsx +43 -0
  36. package/src/components/task/TaskChat.tsx +134 -0
  37. package/src/components/task/TaskDetail.tsx +205 -0
  38. package/src/components/task/TaskList.tsx +119 -0
  39. package/src/components/tree/CardView.tsx +206 -0
  40. package/src/components/tree/RefinePopover.tsx +157 -0
  41. package/src/components/tree/TreeNode.tsx +147 -38
  42. package/src/components/tree/TreeView.tsx +270 -26
  43. package/src/components/ui/ConfirmDialog.tsx +88 -0
  44. package/src/lib/ai/chat-responder.ts +4 -2
  45. package/src/lib/ai/cleanup.ts +87 -0
  46. package/src/lib/ai/client.ts +175 -58
  47. package/src/lib/ai/prompter.ts +19 -24
  48. package/src/lib/ai/refiner.ts +128 -0
  49. package/src/lib/ai/structurer.ts +340 -11
  50. package/src/lib/db/queries/context.ts +76 -0
  51. package/src/lib/db/queries/items.ts +133 -12
  52. package/src/lib/db/queries/projects.ts +12 -8
  53. package/src/lib/db/queries/sub-projects.ts +122 -0
  54. package/src/lib/db/queries/task-conversations.ts +27 -0
  55. package/src/lib/db/queries/task-prompts.ts +32 -0
  56. package/src/lib/db/queries/tasks.ts +133 -0
  57. package/src/lib/db/schema.ts +75 -0
  58. package/src/lib/mcp/server.ts +38 -39
  59. package/src/lib/mcp/tools.ts +47 -45
  60. package/src/lib/scanner.ts +573 -0
  61. package/src/lib/task-store.ts +97 -0
  62. package/src/types/index.ts +65 -0
  63. package/src/app/icon.svg +0 -19
@@ -132,6 +132,111 @@ textarea:focus {
132
132
  line-height: 1.4;
133
133
  }
134
134
 
135
+ /* Memo popover (inline chat) */
136
+ .memo-popover {
137
+ position: absolute;
138
+ right: 24px;
139
+ top: -4px;
140
+ width: 300px;
141
+ background: hsl(var(--card));
142
+ border: 1px solid hsl(var(--border));
143
+ border-radius: 10px;
144
+ box-shadow: 0 8px 24px rgba(0,0,0,0.4);
145
+ z-index: 30;
146
+ display: flex;
147
+ flex-direction: column;
148
+ max-height: 320px;
149
+ }
150
+
151
+ .memo-popover-anchor {
152
+ font-size: 11px;
153
+ color: hsl(var(--muted-foreground));
154
+ font-style: italic;
155
+ padding: 8px 12px 4px;
156
+ overflow: hidden;
157
+ text-overflow: ellipsis;
158
+ white-space: nowrap;
159
+ border-bottom: 1px solid hsl(var(--border));
160
+ }
161
+
162
+ .memo-popover-messages {
163
+ flex: 1;
164
+ overflow-y: auto;
165
+ padding: 8px;
166
+ display: flex;
167
+ flex-direction: column;
168
+ gap: 6px;
169
+ min-height: 0;
170
+ }
171
+
172
+ .memo-popover-bubble {
173
+ padding: 6px 10px;
174
+ border-radius: 10px;
175
+ font-size: 12px;
176
+ line-height: 1.5;
177
+ word-break: break-word;
178
+ max-width: 90%;
179
+ }
180
+
181
+ .memo-popover-bubble-ai {
182
+ background: hsl(var(--muted));
183
+ color: hsl(var(--foreground));
184
+ align-self: flex-start;
185
+ border-bottom-left-radius: 3px;
186
+ }
187
+
188
+ .memo-popover-bubble-user {
189
+ background: hsl(var(--accent));
190
+ color: white;
191
+ align-self: flex-end;
192
+ border-bottom-right-radius: 3px;
193
+ }
194
+
195
+ .memo-popover-input-area {
196
+ display: flex;
197
+ gap: 6px;
198
+ padding: 6px 8px;
199
+ border-top: 1px solid hsl(var(--border));
200
+ }
201
+
202
+ .memo-popover-input {
203
+ flex: 1;
204
+ padding: 5px 10px;
205
+ background: hsl(var(--input));
206
+ border: 1px solid hsl(var(--border));
207
+ border-radius: 6px;
208
+ color: hsl(var(--foreground));
209
+ font-size: 12px;
210
+ resize: none;
211
+ font-family: var(--font-sans);
212
+ }
213
+
214
+ .memo-popover-input::placeholder {
215
+ color: hsl(var(--muted-foreground) / 0.5);
216
+ }
217
+
218
+ .memo-popover-send {
219
+ padding: 5px 10px;
220
+ background: hsl(var(--accent));
221
+ color: white;
222
+ border: none;
223
+ border-radius: 6px;
224
+ font-size: 11px;
225
+ font-weight: 600;
226
+ cursor: pointer;
227
+ transition: opacity 0.15s;
228
+ flex-shrink: 0;
229
+ }
230
+
231
+ .memo-popover-send:hover:not(:disabled) {
232
+ opacity: 0.85;
233
+ }
234
+
235
+ .memo-popover-send:disabled {
236
+ opacity: 0.4;
237
+ cursor: not-allowed;
238
+ }
239
+
135
240
  /* Resize handle */
136
241
  .resize-handle {
137
242
  flex-shrink: 0;
@@ -314,6 +419,97 @@ textarea:focus {
314
419
  cursor: not-allowed;
315
420
  }
316
421
 
422
+ /* Pin toggle */
423
+ .pin-toggle {
424
+ background: none;
425
+ border: none;
426
+ cursor: pointer;
427
+ font-size: 12px;
428
+ padding: 0;
429
+ flex-shrink: 0;
430
+ transition: all 0.15s;
431
+ }
432
+
433
+ .pin-toggle:hover {
434
+ transform: scale(1.2);
435
+ }
436
+
437
+ /* Tree action buttons */
438
+ .tree-action-btn {
439
+ padding: 1px 6px;
440
+ font-size: 10px;
441
+ color: hsl(var(--muted-foreground));
442
+ background: hsl(var(--muted));
443
+ border: 1px solid hsl(var(--border));
444
+ border-radius: 4px;
445
+ cursor: pointer;
446
+ transition: all 0.15s;
447
+ flex-shrink: 0;
448
+ }
449
+
450
+ .tree-action-btn:hover {
451
+ color: hsl(var(--foreground));
452
+ background: hsl(var(--card-hover));
453
+ }
454
+
455
+ .tree-action-btn-danger:hover {
456
+ color: hsl(var(--destructive));
457
+ border-color: hsl(var(--destructive) / 0.3);
458
+ }
459
+
460
+ /* Refine popover */
461
+ .refine-popover {
462
+ margin: 4px 0 8px;
463
+ background: hsl(var(--card));
464
+ border: 1px solid hsl(var(--border));
465
+ border-radius: 10px;
466
+ box-shadow: 0 4px 16px rgba(0,0,0,0.3);
467
+ display: flex;
468
+ flex-direction: column;
469
+ max-height: 300px;
470
+ }
471
+
472
+ .refine-header {
473
+ display: flex;
474
+ align-items: center;
475
+ justify-content: space-between;
476
+ padding: 8px 12px;
477
+ border-bottom: 1px solid hsl(var(--border));
478
+ color: hsl(var(--foreground));
479
+ }
480
+
481
+ .refine-close {
482
+ background: none;
483
+ border: none;
484
+ color: hsl(var(--muted-foreground));
485
+ cursor: pointer;
486
+ font-size: 16px;
487
+ padding: 0 4px;
488
+ line-height: 1;
489
+ }
490
+
491
+ .refine-close:hover {
492
+ color: hsl(var(--foreground));
493
+ }
494
+
495
+ .refine-context {
496
+ padding: 6px 12px;
497
+ font-size: 11px;
498
+ color: hsl(var(--muted-foreground));
499
+ border-bottom: 1px solid hsl(var(--border));
500
+ line-height: 1.4;
501
+ }
502
+
503
+ .refine-messages {
504
+ flex: 1;
505
+ overflow-y: auto;
506
+ padding: 8px;
507
+ display: flex;
508
+ flex-direction: column;
509
+ gap: 6px;
510
+ min-height: 40px;
511
+ }
512
+
317
513
  /* Lock toggle */
318
514
  .lock-toggle {
319
515
  background: none;
@@ -412,8 +608,8 @@ textarea:focus {
412
608
  }
413
609
 
414
610
  .prompt-content {
415
- font-size: 12px;
416
- line-height: 1.6;
611
+ font-size: 14px;
612
+ line-height: 1.7;
417
613
  color: hsl(var(--foreground));
418
614
  background: hsl(var(--background));
419
615
  padding: 8px 12px;
@@ -425,9 +621,9 @@ textarea:focus {
425
621
 
426
622
  .prompt-edit-textarea {
427
623
  width: 100%;
428
- padding: 8px 12px;
429
- font-size: 12px;
430
- line-height: 1.6;
624
+ padding: 10px 14px;
625
+ font-size: 14px;
626
+ line-height: 1.7;
431
627
  color: hsl(var(--foreground));
432
628
  background: hsl(var(--background));
433
629
  border: 1px solid hsl(var(--accent) / 0.5);
@@ -435,3 +631,267 @@ textarea:focus {
435
631
  resize: vertical;
436
632
  font-family: var(--font-mono);
437
633
  }
634
+
635
+ /* Tree node row */
636
+ .tree-node-row {
637
+ display: flex;
638
+ align-items: flex-start;
639
+ gap: 6px;
640
+ padding: 6px 8px;
641
+ border-radius: 6px;
642
+ cursor: pointer;
643
+ transition: background 0.15s;
644
+ }
645
+
646
+ .tree-node-row:hover {
647
+ background: hsl(var(--card-hover));
648
+ }
649
+
650
+ .tree-priority-dot {
651
+ width: 6px;
652
+ height: 6px;
653
+ border-radius: 50%;
654
+ flex-shrink: 0;
655
+ margin-top: 1px;
656
+ }
657
+
658
+ .tree-icon-btn {
659
+ background: none;
660
+ border: none;
661
+ cursor: pointer;
662
+ font-size: 11px;
663
+ padding: 1px 2px;
664
+ flex-shrink: 0;
665
+ transition: transform 0.15s;
666
+ }
667
+
668
+ .tree-icon-btn:hover {
669
+ transform: scale(1.2);
670
+ }
671
+
672
+ .tree-progress-badge {
673
+ font-size: 9px;
674
+ color: hsl(var(--muted-foreground));
675
+ background: hsl(var(--muted));
676
+ padding: 0 5px;
677
+ border-radius: 8px;
678
+ line-height: 16px;
679
+ font-variant-numeric: tabular-nums;
680
+ }
681
+
682
+ .tree-children-group {
683
+ margin-left: 3px;
684
+ border-left: 1px solid hsl(var(--border) / 0.5);
685
+ }
686
+
687
+ /* Card view */
688
+ .card-grid {
689
+ display: grid;
690
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
691
+ gap: 12px;
692
+ padding: 12px;
693
+ }
694
+
695
+ .project-card {
696
+ background: hsl(var(--card));
697
+ border: 1px solid hsl(var(--border));
698
+ border-radius: 12px;
699
+ overflow: hidden;
700
+ transition: border-color 0.2s, box-shadow 0.2s;
701
+ }
702
+
703
+ .project-card:hover {
704
+ border-color: hsl(var(--muted-foreground) / 0.3);
705
+ box-shadow: 0 4px 12px rgba(0,0,0,0.2);
706
+ }
707
+
708
+ .project-card-header {
709
+ padding: 12px 14px 8px;
710
+ display: flex;
711
+ align-items: flex-start;
712
+ gap: 8px;
713
+ }
714
+
715
+ .project-card-icon {
716
+ font-size: 20px;
717
+ flex-shrink: 0;
718
+ margin-top: 1px;
719
+ }
720
+
721
+ .project-card-title {
722
+ font-size: 14px;
723
+ font-weight: 600;
724
+ line-height: 1.3;
725
+ flex: 1;
726
+ min-width: 0;
727
+ }
728
+
729
+ .project-card-desc {
730
+ font-size: 11px;
731
+ color: hsl(var(--muted-foreground));
732
+ line-height: 1.4;
733
+ padding: 0 14px 8px;
734
+ display: -webkit-box;
735
+ -webkit-line-clamp: 2;
736
+ -webkit-box-orient: vertical;
737
+ overflow: hidden;
738
+ }
739
+
740
+ .project-card-progress {
741
+ height: 3px;
742
+ background: hsl(var(--muted));
743
+ margin: 0 14px;
744
+ border-radius: 2px;
745
+ overflow: hidden;
746
+ }
747
+
748
+ .project-card-progress-fill {
749
+ height: 100%;
750
+ border-radius: 2px;
751
+ transition: width 0.3s;
752
+ }
753
+
754
+ .project-card-stats {
755
+ padding: 8px 14px;
756
+ display: flex;
757
+ align-items: center;
758
+ gap: 10px;
759
+ font-size: 10px;
760
+ color: hsl(var(--muted-foreground));
761
+ }
762
+
763
+ .project-card-stat {
764
+ display: flex;
765
+ align-items: center;
766
+ gap: 3px;
767
+ }
768
+
769
+ .project-card-children {
770
+ border-top: 1px solid hsl(var(--border));
771
+ max-height: 240px;
772
+ overflow-y: auto;
773
+ }
774
+
775
+ .project-card-child {
776
+ display: flex;
777
+ align-items: center;
778
+ gap: 6px;
779
+ padding: 5px 14px;
780
+ font-size: 12px;
781
+ transition: background 0.1s;
782
+ }
783
+
784
+ .project-card-child:hover {
785
+ background: hsl(var(--card-hover));
786
+ }
787
+
788
+ .project-card-child-done {
789
+ opacity: 0.4;
790
+ text-decoration: line-through;
791
+ }
792
+
793
+ .project-card-expand {
794
+ padding: 6px 14px;
795
+ border-top: 1px solid hsl(var(--border));
796
+ text-align: center;
797
+ font-size: 11px;
798
+ color: hsl(var(--muted-foreground));
799
+ cursor: pointer;
800
+ transition: background 0.15s, color 0.15s;
801
+ }
802
+
803
+ .project-card-expand:hover {
804
+ background: hsl(var(--card-hover));
805
+ color: hsl(var(--foreground));
806
+ }
807
+
808
+ /* View mode toggle */
809
+ .view-toggle {
810
+ display: flex;
811
+ background: hsl(var(--muted));
812
+ border-radius: 6px;
813
+ padding: 2px;
814
+ }
815
+
816
+ .view-toggle-btn {
817
+ padding: 2px 8px;
818
+ font-size: 11px;
819
+ color: hsl(var(--muted-foreground));
820
+ background: none;
821
+ border: none;
822
+ border-radius: 4px;
823
+ cursor: pointer;
824
+ transition: all 0.15s;
825
+ }
826
+
827
+ .view-toggle-btn:hover {
828
+ color: hsl(var(--foreground));
829
+ }
830
+
831
+ .view-toggle-btn-active {
832
+ background: hsl(var(--card));
833
+ color: hsl(var(--foreground));
834
+ box-shadow: 0 1px 3px rgba(0,0,0,0.2);
835
+ }
836
+
837
+ /* Scan animations */
838
+ @keyframes scanIn {
839
+ from { opacity: 0; transform: translateX(-8px); }
840
+ to { opacity: 1; transform: translateX(0); }
841
+ }
842
+
843
+ .animate-scan-in {
844
+ animation: scanIn 0.2s ease-out;
845
+ }
846
+
847
+ @keyframes progressIndeterminate {
848
+ 0% { width: 0%; margin-left: 0%; }
849
+ 50% { width: 40%; margin-left: 30%; }
850
+ 100% { width: 0%; margin-left: 100%; }
851
+ }
852
+
853
+ .animate-progress-indeterminate {
854
+ animation: progressIndeterminate 1.5s ease-in-out infinite;
855
+ }
856
+
857
+ /* Panel resize handle (vertical) */
858
+ .panel-resize-handle {
859
+ flex-shrink: 0;
860
+ width: 6px;
861
+ cursor: col-resize;
862
+ display: flex;
863
+ align-items: center;
864
+ justify-content: center;
865
+ background: transparent;
866
+ transition: background 0.15s;
867
+ position: relative;
868
+ z-index: 10;
869
+ }
870
+
871
+ .panel-resize-handle:hover,
872
+ .panel-resize-handle:active {
873
+ background: hsl(var(--primary) / 0.15);
874
+ }
875
+
876
+ .panel-resize-handle-bar {
877
+ width: 2px;
878
+ height: 32px;
879
+ border-radius: 1px;
880
+ background: hsl(var(--muted-foreground) / 0.2);
881
+ transition: background 0.15s;
882
+ }
883
+
884
+ .panel-resize-handle:hover .panel-resize-handle-bar,
885
+ .panel-resize-handle:active .panel-resize-handle-bar {
886
+ background: hsl(var(--primary) / 0.6);
887
+ }
888
+
889
+ /* Dialog animation */
890
+ @keyframes dialogIn {
891
+ from { opacity: 0; transform: scale(0.95) translateY(4px); }
892
+ to { opacity: 1; transform: scale(1) translateY(0); }
893
+ }
894
+
895
+ .animate-dialog-in {
896
+ animation: dialogIn 0.15s ease-out;
897
+ }
@@ -15,6 +15,9 @@ const geistMono = Geist_Mono({
15
15
  export const metadata: Metadata = {
16
16
  title: "IM - 아이디어 매니저",
17
17
  description: "자유롭게 아이디어를 쏟아내면, AI가 구조화해드립니다",
18
+ icons: {
19
+ icon: '/favicon.svg',
20
+ },
18
21
  };
19
22
 
20
23
  export default function RootLayout({