@sean.holung/minicode 0.2.4 → 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.
@@ -5,6 +5,10 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>minicode</title>
7
7
  <link rel="stylesheet" href="style.css">
8
+ <script src="https://unpkg.com/cytoscape@3.30.4/dist/cytoscape.min.js"></script>
9
+ <link rel="stylesheet" href="https://unpkg.com/@highlightjs/cdn-assets@11.11.1/styles/tokyo-night-dark.min.css">
10
+ <script src="https://unpkg.com/@highlightjs/cdn-assets@11.11.1/highlight.min.js"></script>
11
+ <script src="https://unpkg.com/@highlightjs/cdn-assets@11.11.1/languages/typescript.min.js"></script>
8
12
  </head>
9
13
  <body>
10
14
  <div id="app">
@@ -15,6 +19,7 @@
15
19
  </div>
16
20
  <div class="header-right">
17
21
  <span id="model-info"></span>
22
+ <button id="graph-toggle" class="header-btn" title="Toggle graph pane">Graph</button>
18
23
  <div class="session-menu">
19
24
  <button id="session-btn" class="header-btn" title="Sessions">Sessions</button>
20
25
  <div id="session-dropdown" class="dropdown hidden">
@@ -33,15 +38,29 @@
33
38
  </div>
34
39
  </header>
35
40
 
36
- <main id="messages"></main>
37
-
38
- <footer>
39
- <form id="chat-form">
40
- <textarea id="chat-input" placeholder="Send a message..." rows="1" autofocus></textarea>
41
- <button type="submit" id="send-btn">Send</button>
42
- <button type="button" id="cancel-btn" class="hidden">Cancel</button>
43
- </form>
44
- </footer>
41
+ <div id="workspace">
42
+ <div id="chat-pane">
43
+ <main id="messages"></main>
44
+ <footer>
45
+ <form id="chat-form">
46
+ <textarea id="chat-input" placeholder="Send a message..." rows="1" autofocus></textarea>
47
+ <button type="submit" id="send-btn">Send</button>
48
+ <button type="button" id="cancel-btn" class="hidden">Cancel</button>
49
+ </form>
50
+ </footer>
51
+ </div>
52
+ <div id="pane-divider"></div>
53
+ <div id="graph-pane">
54
+ <div id="graph-toolbar">
55
+ <input id="graph-search" type="text" placeholder="Search symbols..." autocomplete="off" />
56
+ <button id="graph-fit" class="header-btn">Fit</button>
57
+ <button id="graph-relayout" class="header-btn">Re-layout</button>
58
+ <button id="graph-clear" class="header-btn">Clear</button>
59
+ </div>
60
+ <div id="cy"></div>
61
+ <div id="symbol-detail" class="hidden"></div>
62
+ </div>
63
+ </div>
45
64
  </div>
46
65
 
47
66
  <script type="module" src="app.js"></script>
@@ -33,8 +33,6 @@ html, body {
33
33
  display: flex;
34
34
  flex-direction: column;
35
35
  height: 100vh;
36
- max-width: 900px;
37
- margin: 0 auto;
38
36
  }
39
37
 
40
38
  /* Header */
@@ -210,6 +208,75 @@ h1 {
210
208
  color: var(--red);
211
209
  }
212
210
 
211
+ /* ── Workspace: side-by-side chat + graph ── */
212
+
213
+ #workspace {
214
+ display: flex;
215
+ flex: 1;
216
+ min-height: 0;
217
+ }
218
+
219
+ /* Chat pane (left, default ~33%) */
220
+ #chat-pane {
221
+ display: flex;
222
+ flex-direction: column;
223
+ width: 33%;
224
+ min-width: 280px;
225
+ }
226
+
227
+ /* Pane divider (draggable) */
228
+ #pane-divider {
229
+ width: 1px;
230
+ cursor: col-resize;
231
+ background: var(--border);
232
+ flex-shrink: 0;
233
+ transition: background 0.15s, width 0.15s;
234
+ z-index: 10;
235
+ position: relative;
236
+ }
237
+
238
+ #pane-divider::after {
239
+ content: '';
240
+ position: absolute;
241
+ top: 0;
242
+ left: -3px;
243
+ width: 7px;
244
+ height: 100%;
245
+ }
246
+
247
+ #pane-divider:hover,
248
+ #pane-divider.dragging {
249
+ width: 3px;
250
+ background: var(--accent-dim);
251
+ }
252
+
253
+ /* Graph pane (right, takes remaining space) */
254
+ #graph-pane {
255
+ display: flex;
256
+ flex-direction: column;
257
+ flex: 1;
258
+ min-width: 300px;
259
+ position: relative;
260
+ }
261
+
262
+ /* Chat-only mode: hide graph, expand chat full-width */
263
+ #workspace.chat-only #graph-pane,
264
+ #workspace.chat-only #pane-divider {
265
+ display: none;
266
+ }
267
+
268
+ #workspace.chat-only #chat-pane {
269
+ width: 100%;
270
+ max-width: 900px;
271
+ margin: 0 auto;
272
+ }
273
+
274
+ #graph-toggle.active {
275
+ background: var(--accent);
276
+ color: var(--bg);
277
+ border-color: var(--accent);
278
+ }
279
+
213
280
  /* Messages */
214
281
  main {
215
282
  flex: 1;
@@ -232,7 +299,7 @@ main {
232
299
  background: var(--accent-dim);
233
300
  color: #fff;
234
301
  align-self: flex-end;
235
- max-width: 80%;
302
+ max-width: 90%;
236
303
  border-radius: 8px 8px 2px 8px;
237
304
  }
238
305
 
@@ -240,6 +307,85 @@ main {
240
307
  background: var(--bg-surface);
241
308
  border: 1px solid var(--border);
242
309
  border-radius: 8px 8px 8px 2px;
310
+ white-space: normal;
311
+ }
312
+
313
+ /* Markdown content inside assistant messages and explain */
314
+ .message.assistant p,
315
+ .detail-explain-content p {
316
+ margin: 0 0 8px 0;
317
+ }
318
+
319
+ .message.assistant p:last-child,
320
+ .detail-explain-content p:last-child {
321
+ margin-bottom: 0;
322
+ }
323
+
324
+ .message.assistant pre,
325
+ .detail-explain-content pre {
326
+ background: var(--bg) !important;
327
+ border: 1px solid var(--border);
328
+ border-radius: 4px;
329
+ padding: 8px 10px !important;
330
+ margin: 8px 0;
331
+ overflow-x: auto;
332
+ font-size: 12px;
333
+ line-height: 1.5;
334
+ }
335
+
336
+ .message.assistant code,
337
+ .detail-explain-content code {
338
+ font-family: var(--font-mono);
339
+ font-size: 0.9em;
340
+ }
341
+
342
+ .message.assistant :not(pre) > code,
343
+ .detail-explain-content :not(pre) > code {
344
+ background: rgba(122, 162, 247, 0.1);
345
+ padding: 1px 5px;
346
+ border-radius: 3px;
347
+ color: var(--accent);
348
+ }
349
+
350
+ .message.assistant ul,
351
+ .message.assistant ol,
352
+ .detail-explain-content ul,
353
+ .detail-explain-content ol {
354
+ margin: 6px 0;
355
+ padding-left: 20px;
356
+ }
357
+
358
+ .message.assistant li,
359
+ .detail-explain-content li {
360
+ margin-bottom: 3px;
361
+ }
362
+
363
+ .message.assistant h1,
364
+ .message.assistant h2,
365
+ .message.assistant h3,
366
+ .detail-explain-content h1,
367
+ .detail-explain-content h2,
368
+ .detail-explain-content h3 {
369
+ font-size: 13px;
370
+ font-weight: 600;
371
+ margin: 10px 0 4px 0;
372
+ color: var(--text);
373
+ }
374
+
375
+ .message.assistant h1 { font-size: 15px; }
376
+ .message.assistant h2 { font-size: 14px; }
377
+
378
+ .message.assistant strong,
379
+ .detail-explain-content strong {
380
+ color: var(--text);
381
+ }
382
+
383
+ .message.assistant blockquote,
384
+ .detail-explain-content blockquote {
385
+ border-left: 3px solid var(--border);
386
+ padding-left: 10px;
387
+ margin: 6px 0;
388
+ color: var(--text-dim);
243
389
  }
244
390
 
245
391
  .message.error {
@@ -420,3 +566,357 @@ main::-webkit-scrollbar-thumb {
420
566
  background: var(--border);
421
567
  border-radius: 3px;
422
568
  }
569
+
570
+ /* ── Graph pane ── */
571
+
572
+ #graph-toolbar {
573
+ display: flex;
574
+ align-items: center;
575
+ gap: 10px;
576
+ padding: 8px 16px;
577
+ border-bottom: 1px solid var(--border);
578
+ flex-shrink: 0;
579
+ flex-wrap: wrap;
580
+ }
581
+
582
+ #graph-search {
583
+ background: var(--bg-surface);
584
+ border: 1px solid var(--border);
585
+ border-radius: 4px;
586
+ color: var(--text);
587
+ font-family: var(--font-mono);
588
+ font-size: 12px;
589
+ padding: 5px 10px;
590
+ width: 200px;
591
+ }
592
+
593
+ #graph-search:focus {
594
+ outline: none;
595
+ border-color: var(--accent);
596
+ }
597
+
598
+ /* Search dropdown */
599
+ .search-dropdown {
600
+ position: absolute;
601
+ top: 100%;
602
+ left: 0;
603
+ width: 300px;
604
+ max-height: 320px;
605
+ overflow-y: auto;
606
+ background: var(--bg-surface);
607
+ border: 1px solid var(--border);
608
+ border-radius: 6px;
609
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
610
+ z-index: 200;
611
+ margin-top: 4px;
612
+ }
613
+
614
+ .search-result {
615
+ display: flex;
616
+ align-items: center;
617
+ justify-content: space-between;
618
+ padding: 6px 10px;
619
+ cursor: pointer;
620
+ font-size: 12px;
621
+ transition: background 0.1s;
622
+ }
623
+
624
+ .search-result:hover {
625
+ background: var(--bg-hover);
626
+ }
627
+
628
+ .search-result-name {
629
+ color: var(--text);
630
+ font-weight: 500;
631
+ }
632
+
633
+ .search-result-kind {
634
+ font-size: 11px;
635
+ opacity: 0.7;
636
+ }
637
+
638
+ #cy {
639
+ flex: 1;
640
+ min-height: 0;
641
+ background: var(--bg);
642
+ }
643
+
644
+ .graph-empty {
645
+ display: flex;
646
+ align-items: center;
647
+ justify-content: center;
648
+ height: 100%;
649
+ color: var(--text-dim);
650
+ font-size: 14px;
651
+ padding: 40px;
652
+ text-align: center;
653
+ }
654
+
655
+ /* Symbol detail panel */
656
+ #symbol-detail {
657
+ position: absolute;
658
+ top: 0;
659
+ right: 0;
660
+ width: 320px;
661
+ min-width: 200px;
662
+ max-width: 80%;
663
+ height: 100%;
664
+ background: var(--bg-surface);
665
+ border-left: 1px solid var(--border);
666
+ overflow-y: auto;
667
+ padding: 16px;
668
+ z-index: 50;
669
+ box-shadow: -4px 0 16px rgba(0, 0, 0, 0.3);
670
+ }
671
+
672
+ #symbol-detail .resize-handle {
673
+ position: absolute;
674
+ top: 0;
675
+ left: 0;
676
+ width: 5px;
677
+ height: 100%;
678
+ cursor: col-resize;
679
+ background: transparent;
680
+ z-index: 51;
681
+ }
682
+
683
+ #symbol-detail .resize-handle:hover,
684
+ #symbol-detail .resize-handle.dragging {
685
+ background: var(--accent-dim);
686
+ }
687
+
688
+ .detail-header {
689
+ display: flex;
690
+ align-items: center;
691
+ gap: 8px;
692
+ margin-bottom: 8px;
693
+ }
694
+
695
+ .detail-name {
696
+ font-size: 15px;
697
+ font-weight: 600;
698
+ color: var(--text);
699
+ word-break: break-all;
700
+ }
701
+
702
+ .detail-kind-badge {
703
+ font-size: 11px;
704
+ padding: 2px 8px;
705
+ border-radius: 10px;
706
+ font-weight: 500;
707
+ flex-shrink: 0;
708
+ }
709
+
710
+ .detail-file {
711
+ font-size: 12px;
712
+ color: var(--text-dim);
713
+ margin-bottom: 12px;
714
+ }
715
+
716
+ .detail-signature {
717
+ background: var(--bg);
718
+ border: 1px solid var(--border);
719
+ border-radius: 4px;
720
+ padding: 8px 10px;
721
+ font-size: 12px;
722
+ color: var(--text);
723
+ overflow-x: auto;
724
+ white-space: pre-wrap;
725
+ margin-bottom: 12px;
726
+ font-family: var(--font-mono);
727
+ }
728
+
729
+ .detail-code {
730
+ background: var(--bg) !important;
731
+ border: 1px solid var(--border);
732
+ border-radius: 4px;
733
+ padding: 10px 12px !important;
734
+ font-size: 11px;
735
+ line-height: 1.5;
736
+ color: var(--text);
737
+ overflow: auto;
738
+ max-height: 300px;
739
+ white-space: pre;
740
+ margin-bottom: 12px;
741
+ font-family: var(--font-mono);
742
+ tab-size: 2;
743
+ }
744
+
745
+ .detail-actions {
746
+ display: flex;
747
+ gap: 8px;
748
+ margin-bottom: 16px;
749
+ }
750
+
751
+ .detail-actions .header-btn {
752
+ flex: 1;
753
+ text-align: center;
754
+ }
755
+
756
+ .detail-section {
757
+ margin-bottom: 14px;
758
+ }
759
+
760
+ .detail-section-title {
761
+ font-size: 11px;
762
+ color: var(--text-dim);
763
+ text-transform: uppercase;
764
+ letter-spacing: 0.5px;
765
+ margin-bottom: 6px;
766
+ font-weight: 600;
767
+ }
768
+
769
+ .detail-section-list {
770
+ display: flex;
771
+ flex-direction: column;
772
+ gap: 2px;
773
+ font-size: 12px;
774
+ }
775
+
776
+ .detail-link {
777
+ color: var(--accent);
778
+ cursor: pointer;
779
+ padding: 3px 6px;
780
+ border-radius: 3px;
781
+ transition: background 0.15s;
782
+ }
783
+
784
+ .detail-link:hover {
785
+ background: var(--bg-hover);
786
+ }
787
+
788
+ .detail-empty {
789
+ color: var(--text-dim);
790
+ font-style: italic;
791
+ }
792
+
793
+ /* Agent pulse animation */
794
+ @keyframes agent-pulse {
795
+ 0%, 100% { border-color: #ff9e64; }
796
+ 50% { border-color: #e0af68; }
797
+ }
798
+
799
+ #symbol-detail::-webkit-scrollbar {
800
+ width: 5px;
801
+ }
802
+
803
+ #symbol-detail::-webkit-scrollbar-track {
804
+ background: transparent;
805
+ }
806
+
807
+ #symbol-detail::-webkit-scrollbar-thumb {
808
+ background: var(--border);
809
+ border-radius: 3px;
810
+ }
811
+
812
+ /* Annotation items */
813
+ .detail-annotation-item {
814
+ display: flex;
815
+ align-items: flex-start;
816
+ gap: 6px;
817
+ padding: 4px 6px;
818
+ border-radius: 3px;
819
+ font-size: 12px;
820
+ color: var(--text);
821
+ background: var(--bg);
822
+ margin-bottom: 4px;
823
+ }
824
+
825
+ .detail-annotation-item .annotation-text {
826
+ flex: 1;
827
+ word-break: break-word;
828
+ }
829
+
830
+ .detail-annotation-item .annotation-remove {
831
+ background: none;
832
+ border: none;
833
+ color: var(--text-dim);
834
+ cursor: pointer;
835
+ font-size: 14px;
836
+ padding: 0 2px;
837
+ line-height: 1;
838
+ flex-shrink: 0;
839
+ }
840
+
841
+ .detail-annotation-item .annotation-remove:hover {
842
+ color: var(--red);
843
+ }
844
+
845
+ .detail-annotation-input {
846
+ display: flex;
847
+ gap: 6px;
848
+ margin-top: 6px;
849
+ }
850
+
851
+ .detail-annotation-textarea {
852
+ flex: 1;
853
+ background: var(--bg);
854
+ border: 1px solid var(--border);
855
+ border-radius: 4px;
856
+ color: var(--text);
857
+ font-family: var(--font-mono);
858
+ font-size: 12px;
859
+ padding: 5px 8px;
860
+ resize: none;
861
+ min-height: 28px;
862
+ max-height: 80px;
863
+ }
864
+
865
+ .detail-annotation-textarea:focus {
866
+ outline: none;
867
+ border-color: var(--accent-dim);
868
+ }
869
+
870
+ .detail-annotation-input .dropdown-action {
871
+ align-self: flex-end;
872
+ }
873
+
874
+ /* Explain output area */
875
+ .detail-explain-content {
876
+ white-space: pre-wrap;
877
+ background: var(--bg);
878
+ border: 1px solid var(--border);
879
+ border-radius: 4px;
880
+ padding: 10px 12px;
881
+ font-size: 12px;
882
+ line-height: 1.5;
883
+ color: var(--text);
884
+ max-height: 400px;
885
+ overflow-y: auto;
886
+ font-family: var(--font-mono);
887
+ }
888
+
889
+ .detail-explain-content::-webkit-scrollbar {
890
+ width: 5px;
891
+ }
892
+
893
+ .detail-explain-content::-webkit-scrollbar-track {
894
+ background: transparent;
895
+ }
896
+
897
+ .detail-explain-content::-webkit-scrollbar-thumb {
898
+ background: var(--border);
899
+ border-radius: 3px;
900
+ }
901
+
902
+ .explain-status {
903
+ display: flex;
904
+ align-items: center;
905
+ gap: 8px;
906
+ color: var(--text-dim);
907
+ font-size: 12px;
908
+ }
909
+
910
+ .explain-spinner {
911
+ width: 12px;
912
+ height: 12px;
913
+ border: 2px solid var(--border);
914
+ border-top-color: var(--accent);
915
+ border-radius: 50%;
916
+ animation: spin 0.8s linear infinite;
917
+ flex-shrink: 0;
918
+ }
919
+
920
+ @keyframes spin {
921
+ to { transform: rotate(360deg); }
922
+ }