Ashutosh1975270 commited on
Commit
d737dbb
·
1 Parent(s): aa9b339

feat: implement 3D visualization toggle and Retrieval Context Preview

Browse files
frontend/package-lock.json CHANGED
@@ -16,9 +16,11 @@
16
  "react": "^18.3.1",
17
  "react-dom": "^18.3.1",
18
  "react-force-graph-2d": "^1.25.5",
 
19
  "react-markdown": "^9.0.1",
20
  "recharts": "^2.12.7",
21
  "tailwind-merge": "^2.4.0",
 
22
  "zustand": "^4.5.4"
23
  },
24
  "devDependencies": {
@@ -26,6 +28,7 @@
26
  "@types/node": "^20.14.13",
27
  "@types/react": "^18.3.3",
28
  "@types/react-dom": "^18.3.0",
 
29
  "autoprefixer": "^10.4.19",
30
  "eslint": "^8.57.0",
31
  "eslint-config-next": "14.2.5",
@@ -57,6 +60,13 @@
57
  "node": ">=6.9.0"
58
  }
59
  },
 
 
 
 
 
 
 
60
  "node_modules/@eslint-community/eslint-utils": {
61
  "version": "4.9.1",
62
  "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
@@ -661,12 +671,48 @@
661
  "@types/react": "^18.0.0"
662
  }
663
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
664
  "node_modules/@types/unist": {
665
  "version": "3.0.3",
666
  "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
667
  "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
668
  "license": "MIT"
669
  },
 
 
 
 
 
 
 
670
  "node_modules/@typescript-eslint/parser": {
671
  "version": "7.2.0",
672
  "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz",
@@ -821,6 +867,22 @@
821
  "linux"
822
  ]
823
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
824
  "node_modules/accessor-fn": {
825
  "version": "1.5.3",
826
  "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz",
@@ -1923,6 +1985,18 @@
1923
  "dev": true,
1924
  "license": "BSD-2-Clause"
1925
  },
 
 
 
 
 
 
 
 
 
 
 
 
1926
  "node_modules/data-view-buffer": {
1927
  "version": "1.0.2",
1928
  "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
@@ -2911,6 +2985,13 @@
2911
  "reusify": "^1.0.4"
2912
  }
2913
  },
 
 
 
 
 
 
 
2914
  "node_modules/file-entry-cache": {
2915
  "version": "6.0.1",
2916
  "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -4610,6 +4691,13 @@
4610
  "node": ">= 8"
4611
  }
4612
  },
 
 
 
 
 
 
 
4613
  "node_modules/micromark": {
4614
  "version": "4.0.2",
4615
  "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
@@ -5258,6 +5346,44 @@
5258
  "node": "^10 || ^12 || >=14"
5259
  }
5260
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5261
  "node_modules/node-exports-info": {
5262
  "version": "1.6.2",
5263
  "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz",
@@ -5690,6 +5816,18 @@
5690
  "node": ">=18"
5691
  }
5692
  },
 
 
 
 
 
 
 
 
 
 
 
 
5693
  "node_modules/possible-typed-array-names": {
5694
  "version": "1.1.0",
5695
  "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
@@ -6016,6 +6154,23 @@
6016
  "react": "*"
6017
  }
6018
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6019
  "node_modules/react-is": {
6020
  "version": "16.13.1",
6021
  "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -7096,6 +7251,55 @@
7096
  "node": ">=0.8"
7097
  }
7098
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7099
  "node_modules/tiny-invariant": {
7100
  "version": "1.3.3",
7101
  "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
 
16
  "react": "^18.3.1",
17
  "react-dom": "^18.3.1",
18
  "react-force-graph-2d": "^1.25.5",
19
+ "react-force-graph-3d": "^1.29.1",
20
  "react-markdown": "^9.0.1",
21
  "recharts": "^2.12.7",
22
  "tailwind-merge": "^2.4.0",
23
+ "three": "^0.185.1",
24
  "zustand": "^4.5.4"
25
  },
26
  "devDependencies": {
 
28
  "@types/node": "^20.14.13",
29
  "@types/react": "^18.3.3",
30
  "@types/react-dom": "^18.3.0",
31
+ "@types/three": "^0.185.1",
32
  "autoprefixer": "^10.4.19",
33
  "eslint": "^8.57.0",
34
  "eslint-config-next": "14.2.5",
 
60
  "node": ">=6.9.0"
61
  }
62
  },
63
+ "node_modules/@dimforge/rapier3d-compat": {
64
+ "version": "0.12.0",
65
+ "resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz",
66
+ "integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==",
67
+ "dev": true,
68
+ "license": "Apache-2.0"
69
+ },
70
  "node_modules/@eslint-community/eslint-utils": {
71
  "version": "4.9.1",
72
  "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
 
671
  "@types/react": "^18.0.0"
672
  }
673
  },
674
+ "node_modules/@types/stats.js": {
675
+ "version": "0.17.4",
676
+ "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz",
677
+ "integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==",
678
+ "dev": true,
679
+ "license": "MIT"
680
+ },
681
+ "node_modules/@types/three": {
682
+ "version": "0.185.1",
683
+ "resolved": "https://registry.npmjs.org/@types/three/-/three-0.185.1.tgz",
684
+ "integrity": "sha512-db1xTb+EgYF2didW+eudSvVPtn75zo+fGsY8ShQrJY/B5ZBmC2Fiaykv3aImHAlCNEGuMPkPGXBJGLwzu5mC7A==",
685
+ "dev": true,
686
+ "license": "MIT",
687
+ "dependencies": {
688
+ "@dimforge/rapier3d-compat": "~0.12.0",
689
+ "@tweenjs/tween.js": "~23.1.3",
690
+ "@types/stats.js": "*",
691
+ "@types/webxr": ">=0.5.17",
692
+ "fflate": "~0.8.2",
693
+ "meshoptimizer": "~1.1.1"
694
+ }
695
+ },
696
+ "node_modules/@types/three/node_modules/@tweenjs/tween.js": {
697
+ "version": "23.1.3",
698
+ "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz",
699
+ "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==",
700
+ "dev": true,
701
+ "license": "MIT"
702
+ },
703
  "node_modules/@types/unist": {
704
  "version": "3.0.3",
705
  "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
706
  "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
707
  "license": "MIT"
708
  },
709
+ "node_modules/@types/webxr": {
710
+ "version": "0.5.24",
711
+ "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz",
712
+ "integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==",
713
+ "dev": true,
714
+ "license": "MIT"
715
+ },
716
  "node_modules/@typescript-eslint/parser": {
717
  "version": "7.2.0",
718
  "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz",
 
867
  "linux"
868
  ]
869
  },
870
+ "node_modules/3d-force-graph": {
871
+ "version": "1.80.0",
872
+ "resolved": "https://registry.npmjs.org/3d-force-graph/-/3d-force-graph-1.80.0.tgz",
873
+ "integrity": "sha512-tzI353gW1nXPpnC7VTa3JjMg+3cp77qOLUFO0vucPTfF+q5R6sQsNsIqVTbRIb7RSypn14nBa4yfkOe9ThxASw==",
874
+ "license": "MIT",
875
+ "dependencies": {
876
+ "accessor-fn": "1",
877
+ "kapsule": "^1.16",
878
+ "three": ">=0.179 <1",
879
+ "three-forcegraph": "1",
880
+ "three-render-objects": "^1.41"
881
+ },
882
+ "engines": {
883
+ "node": ">=12"
884
+ }
885
+ },
886
  "node_modules/accessor-fn": {
887
  "version": "1.5.3",
888
  "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz",
 
1985
  "dev": true,
1986
  "license": "BSD-2-Clause"
1987
  },
1988
+ "node_modules/data-bind-mapper": {
1989
+ "version": "1.0.3",
1990
+ "resolved": "https://registry.npmjs.org/data-bind-mapper/-/data-bind-mapper-1.0.3.tgz",
1991
+ "integrity": "sha512-QmU3lyEnbENQPo0M1F9BMu4s6cqNNp8iJA+b/HP2sSb7pf3dxwF3+EP1eO69rwBfH9kFJ1apmzrtogAmVt2/Xw==",
1992
+ "license": "MIT",
1993
+ "dependencies": {
1994
+ "accessor-fn": "1"
1995
+ },
1996
+ "engines": {
1997
+ "node": ">=12"
1998
+ }
1999
+ },
2000
  "node_modules/data-view-buffer": {
2001
  "version": "1.0.2",
2002
  "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
 
2985
  "reusify": "^1.0.4"
2986
  }
2987
  },
2988
+ "node_modules/fflate": {
2989
+ "version": "0.8.3",
2990
+ "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz",
2991
+ "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==",
2992
+ "dev": true,
2993
+ "license": "MIT"
2994
+ },
2995
  "node_modules/file-entry-cache": {
2996
  "version": "6.0.1",
2997
  "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
 
4691
  "node": ">= 8"
4692
  }
4693
  },
4694
+ "node_modules/meshoptimizer": {
4695
+ "version": "1.1.1",
4696
+ "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.1.1.tgz",
4697
+ "integrity": "sha512-oRFNWJRDA/WTrVj7NWvqa5HqE1t9MYDj2VaWirQCzCCrAd2GHrqR/sQezCxiWATPNlKTcRaPRHPJwIRoPBAp5g==",
4698
+ "dev": true,
4699
+ "license": "MIT"
4700
+ },
4701
  "node_modules/micromark": {
4702
  "version": "4.0.2",
4703
  "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
 
5346
  "node": "^10 || ^12 || >=14"
5347
  }
5348
  },
5349
+ "node_modules/ngraph.events": {
5350
+ "version": "1.4.0",
5351
+ "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-1.4.0.tgz",
5352
+ "integrity": "sha512-NeDGI4DSyjBNBRtA86222JoYietsmCXbs8CEB0dZ51Xeh4lhVl1y3wpWLumczvnha8sFQIW4E0vvVWwgmX2mGw==",
5353
+ "license": "BSD-3-Clause"
5354
+ },
5355
+ "node_modules/ngraph.forcelayout": {
5356
+ "version": "3.3.1",
5357
+ "resolved": "https://registry.npmjs.org/ngraph.forcelayout/-/ngraph.forcelayout-3.3.1.tgz",
5358
+ "integrity": "sha512-MKBuEh1wujyQHFTW57y5vd/uuEOK0XfXYxm3lC7kktjJLRdt/KEKEknyOlc6tjXflqBKEuYBBcu7Ax5VY+S6aw==",
5359
+ "license": "BSD-3-Clause",
5360
+ "dependencies": {
5361
+ "ngraph.events": "^1.0.0",
5362
+ "ngraph.merge": "^1.0.0",
5363
+ "ngraph.random": "^1.0.0"
5364
+ }
5365
+ },
5366
+ "node_modules/ngraph.graph": {
5367
+ "version": "20.1.2",
5368
+ "resolved": "https://registry.npmjs.org/ngraph.graph/-/ngraph.graph-20.1.2.tgz",
5369
+ "integrity": "sha512-W/G3GBR3Y5UxMLHTUCPP9v+pbtpzwuAEIqP5oZV+9IwgxAIEZwh+Foc60iPc1idlnK7Zxu0p3puxAyNmDvBd0Q==",
5370
+ "license": "BSD-3-Clause",
5371
+ "dependencies": {
5372
+ "ngraph.events": "^1.4.0"
5373
+ }
5374
+ },
5375
+ "node_modules/ngraph.merge": {
5376
+ "version": "1.0.0",
5377
+ "resolved": "https://registry.npmjs.org/ngraph.merge/-/ngraph.merge-1.0.0.tgz",
5378
+ "integrity": "sha512-5J8YjGITUJeapsomtTALYsw7rFveYkM+lBj3QiYZ79EymQcuri65Nw3knQtFxQBU1r5iOaVRXrSwMENUPK62Vg==",
5379
+ "license": "MIT"
5380
+ },
5381
+ "node_modules/ngraph.random": {
5382
+ "version": "1.2.0",
5383
+ "resolved": "https://registry.npmjs.org/ngraph.random/-/ngraph.random-1.2.0.tgz",
5384
+ "integrity": "sha512-4EUeAGbB2HWX9njd6bP6tciN6ByJfoaAvmVL9QTaZSeXrW46eNGA9GajiXiPBbvFqxUWFkEbyo6x5qsACUuVfA==",
5385
+ "license": "BSD-3-Clause"
5386
+ },
5387
  "node_modules/node-exports-info": {
5388
  "version": "1.6.2",
5389
  "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz",
 
5816
  "node": ">=18"
5817
  }
5818
  },
5819
+ "node_modules/polished": {
5820
+ "version": "4.3.1",
5821
+ "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz",
5822
+ "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==",
5823
+ "license": "MIT",
5824
+ "dependencies": {
5825
+ "@babel/runtime": "^7.17.8"
5826
+ },
5827
+ "engines": {
5828
+ "node": ">=10"
5829
+ }
5830
+ },
5831
  "node_modules/possible-typed-array-names": {
5832
  "version": "1.1.0",
5833
  "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
 
6154
  "react": "*"
6155
  }
6156
  },
6157
+ "node_modules/react-force-graph-3d": {
6158
+ "version": "1.29.1",
6159
+ "resolved": "https://registry.npmjs.org/react-force-graph-3d/-/react-force-graph-3d-1.29.1.tgz",
6160
+ "integrity": "sha512-5Vp+PGpYnO+zLwgK2NvNqdXHvsWLrFzpDfJW1vUA1twjo9SPvXqfUYQrnRmAbD+K2tOxkZw1BkbH31l5b4TWHg==",
6161
+ "license": "MIT",
6162
+ "dependencies": {
6163
+ "3d-force-graph": "^1.79",
6164
+ "prop-types": "15",
6165
+ "react-kapsule": "^2.5"
6166
+ },
6167
+ "engines": {
6168
+ "node": ">=12"
6169
+ },
6170
+ "peerDependencies": {
6171
+ "react": "*"
6172
+ }
6173
+ },
6174
  "node_modules/react-is": {
6175
  "version": "16.13.1",
6176
  "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
 
7251
  "node": ">=0.8"
7252
  }
7253
  },
7254
+ "node_modules/three": {
7255
+ "version": "0.185.1",
7256
+ "resolved": "https://registry.npmjs.org/three/-/three-0.185.1.tgz",
7257
+ "integrity": "sha512-5aojFCXKwnjBRZvUnt3WFfEcvUJgkN5LlijRFN95hMy8WVkG4I0QNcJE+OuWvuJ0bOdStrbfXn0pkd6/QyiAlg==",
7258
+ "license": "MIT"
7259
+ },
7260
+ "node_modules/three-forcegraph": {
7261
+ "version": "1.43.4",
7262
+ "resolved": "https://registry.npmjs.org/three-forcegraph/-/three-forcegraph-1.43.4.tgz",
7263
+ "integrity": "sha512-FtmiZP/T16ZQaHza3JDaDn0YTXFtg9e7pGnTeU8nzu0NNkx7MpWbF/GvmpbQsWHx3rukHtkRv1fTorLPB3FDEA==",
7264
+ "license": "MIT",
7265
+ "dependencies": {
7266
+ "accessor-fn": "1",
7267
+ "d3-array": "1 - 3",
7268
+ "d3-force-3d": "2 - 3",
7269
+ "d3-scale": "1 - 4",
7270
+ "d3-scale-chromatic": "1 - 3",
7271
+ "data-bind-mapper": "1",
7272
+ "kapsule": "^1.16",
7273
+ "ngraph.forcelayout": "3",
7274
+ "ngraph.graph": "20",
7275
+ "tinycolor2": "1"
7276
+ },
7277
+ "engines": {
7278
+ "node": ">=12"
7279
+ },
7280
+ "peerDependencies": {
7281
+ "three": ">=0.118.3"
7282
+ }
7283
+ },
7284
+ "node_modules/three-render-objects": {
7285
+ "version": "1.42.0",
7286
+ "resolved": "https://registry.npmjs.org/three-render-objects/-/three-render-objects-1.42.0.tgz",
7287
+ "integrity": "sha512-KYfkPrYGEbIK8ChFocWqOF1aAN80FBUBWVYB8mB2oBpVuVN+52FvvngVYB5ieFANQu7Rt21rPYZ/xKaAgVWWRQ==",
7288
+ "license": "MIT",
7289
+ "dependencies": {
7290
+ "@tweenjs/tween.js": "18 - 25",
7291
+ "accessor-fn": "1",
7292
+ "float-tooltip": "^1.7",
7293
+ "kapsule": "^1.16",
7294
+ "polished": "4"
7295
+ },
7296
+ "engines": {
7297
+ "node": ">=12"
7298
+ },
7299
+ "peerDependencies": {
7300
+ "three": ">=0.179"
7301
+ }
7302
+ },
7303
  "node_modules/tiny-invariant": {
7304
  "version": "1.3.3",
7305
  "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
frontend/package.json CHANGED
@@ -11,30 +11,33 @@
11
  "test:e2e:install": "playwright install --with-deps chromium"
12
  },
13
  "dependencies": {
 
 
 
 
14
  "next": "14.2.5",
15
  "react": "^18.3.1",
16
  "react-dom": "^18.3.1",
17
- "zustand": "^4.5.4",
18
- "axios": "^1.7.3",
19
  "react-force-graph-2d": "^1.25.5",
20
- "recharts": "^2.12.7",
21
  "react-markdown": "^9.0.1",
22
- "lucide-react": "^0.417.0",
23
- "clsx": "^2.1.1",
24
  "tailwind-merge": "^2.4.0",
25
- "class-variance-authority": "^0.7.0"
 
26
  },
27
  "devDependencies": {
28
  "@playwright/test": "^1.47.0",
29
  "@types/node": "^20.14.13",
30
  "@types/react": "^18.3.3",
31
  "@types/react-dom": "^18.3.0",
 
32
  "autoprefixer": "^10.4.19",
 
 
33
  "postcss": "^8.4.40",
34
  "tailwindcss": "^3.4.7",
35
  "tailwindcss-animate": "^1.0.7",
36
- "typescript": "^5.5.4",
37
- "eslint": "^8.57.0",
38
- "eslint-config-next": "14.2.5"
39
  }
40
  }
 
11
  "test:e2e:install": "playwright install --with-deps chromium"
12
  },
13
  "dependencies": {
14
+ "axios": "^1.7.3",
15
+ "class-variance-authority": "^0.7.0",
16
+ "clsx": "^2.1.1",
17
+ "lucide-react": "^0.417.0",
18
  "next": "14.2.5",
19
  "react": "^18.3.1",
20
  "react-dom": "^18.3.1",
 
 
21
  "react-force-graph-2d": "^1.25.5",
22
+ "react-force-graph-3d": "^1.29.1",
23
  "react-markdown": "^9.0.1",
24
+ "recharts": "^2.12.7",
 
25
  "tailwind-merge": "^2.4.0",
26
+ "three": "^0.185.1",
27
+ "zustand": "^4.5.4"
28
  },
29
  "devDependencies": {
30
  "@playwright/test": "^1.47.0",
31
  "@types/node": "^20.14.13",
32
  "@types/react": "^18.3.3",
33
  "@types/react-dom": "^18.3.0",
34
+ "@types/three": "^0.185.1",
35
  "autoprefixer": "^10.4.19",
36
+ "eslint": "^8.57.0",
37
+ "eslint-config-next": "14.2.5",
38
  "postcss": "^8.4.40",
39
  "tailwindcss": "^3.4.7",
40
  "tailwindcss-animate": "^1.0.7",
41
+ "typescript": "^5.5.4"
 
 
42
  }
43
  }
frontend/src/components/dashboard/MainQueryView.tsx CHANGED
@@ -23,6 +23,7 @@ interface QueryResult {
23
  entities?: string[];
24
  paths?: string[];
25
  hops?: Hop[];
 
26
  }
27
 
28
  export function MainQueryView() {
@@ -68,6 +69,7 @@ export function MainQueryView() {
68
  entities: res.highlighted_entities,
69
  paths: res.paths,
70
  hops: res.hops,
 
71
  };
72
  setResult(mapped);
73
  setHighlighted(mapped.entities || [], mapped.paths || []);
@@ -142,6 +144,7 @@ export function MainQueryView() {
142
  method={result.method || mode}
143
  entityCount={result.entities?.length || 0}
144
  chunkCount={result.citations?.length || 0}
 
145
  />
146
  )}
147
  </div>
 
23
  entities?: string[];
24
  paths?: string[];
25
  hops?: Hop[];
26
+ context?: string;
27
  }
28
 
29
  export function MainQueryView() {
 
69
  entities: res.highlighted_entities,
70
  paths: res.paths,
71
  hops: res.hops,
72
+ context: res.context,
73
  };
74
  setResult(mapped);
75
  setHighlighted(mapped.entities || [], mapped.paths || []);
 
144
  method={result.method || mode}
145
  entityCount={result.entities?.length || 0}
146
  chunkCount={result.citations?.length || 0}
147
+ context={result.context}
148
  />
149
  )}
150
  </div>
frontend/src/components/graph/ForceGraphWrapper.tsx CHANGED
@@ -2,9 +2,19 @@
2
 
3
  import React, { forwardRef } from 'react';
4
  import ForceGraph2D from 'react-force-graph-2d';
 
5
 
6
- const ForceGraphWrapper = forwardRef((props: any, ref: any) => {
7
- return <ForceGraph2D {...props} ref={ref} />;
 
 
 
 
 
 
 
 
 
8
  });
9
 
10
  ForceGraphWrapper.displayName = 'ForceGraphWrapper';
 
2
 
3
  import React, { forwardRef } from 'react';
4
  import ForceGraph2D from 'react-force-graph-2d';
5
+ import ForceGraph3D from 'react-force-graph-3d';
6
 
7
+ interface ForceGraphWrapperProps {
8
+ dim?: 2 | 3;
9
+ [key: string]: any;
10
+ }
11
+
12
+ const ForceGraphWrapper = forwardRef<any, ForceGraphWrapperProps>((props, ref) => {
13
+ const { dim = 2, ...rest } = props;
14
+ if (dim === 3) {
15
+ return <ForceGraph3D {...rest} ref={ref as any} />;
16
+ }
17
+ return <ForceGraph2D {...rest} ref={ref as any} />;
18
  });
19
 
20
  ForceGraphWrapper.displayName = 'ForceGraphWrapper';
frontend/src/components/graph/GraphControls.tsx CHANGED
@@ -2,10 +2,21 @@
2
 
3
  import { Plus, Minus, Maximize, Crosshair } from 'lucide-react';
4
  import { graphController } from './graphController';
 
5
 
6
  export function GraphControls() {
 
 
 
7
  return (
8
  <div className="absolute right-3 top-3 flex flex-col gap-1.5">
 
 
 
 
 
 
 
9
  <button
10
  onClick={() => graphController.zoomIn?.()}
11
  className="flex h-9 w-9 items-center justify-center rounded-md border border-border bg-bg-elevated/90 text-text-secondary shadow-sm backdrop-blur hover:text-text-primary"
 
2
 
3
  import { Plus, Minus, Maximize, Crosshair } from 'lucide-react';
4
  import { graphController } from './graphController';
5
+ import { useGraphStore } from '@/store/graph';
6
 
7
  export function GraphControls() {
8
+ const dim = useGraphStore((s) => s.dim);
9
+ const setDim = useGraphStore((s) => s.setDim);
10
+
11
  return (
12
  <div className="absolute right-3 top-3 flex flex-col gap-1.5">
13
+ <button
14
+ onClick={() => setDim(dim === 2 ? 3 : 2)}
15
+ className="flex h-9 w-9 items-center justify-center rounded-md border border-border bg-bg-elevated/90 text-xs font-bold text-accent-cyan shadow-sm backdrop-blur hover:bg-bg-surface hover:text-text-primary transition-all duration-200"
16
+ aria-label="Toggle 2D/3D"
17
+ >
18
+ {dim === 2 ? '3D' : '2D'}
19
+ </button>
20
  <button
21
  onClick={() => graphController.zoomIn?.()}
22
  className="flex h-9 w-9 items-center justify-center rounded-md border border-border bg-bg-elevated/90 text-text-secondary shadow-sm backdrop-blur hover:text-text-primary"
frontend/src/components/graph/GraphVisualization.tsx CHANGED
@@ -34,6 +34,7 @@ export function GraphVisualization({ height = '100%' }: { height?: string | numb
34
  const visibleRelationships = useGraphStore((s) => s.visibleRelationships);
35
  const selectEntity = useGraphStore((s) => s.selectEntity);
36
  const setHighlighted = useGraphStore((s) => s.setHighlighted);
 
37
 
38
  const fgRef = useRef<any>(null);
39
  const [hoverNode, setHoverNode] = useState<FGNode | null>(null);
@@ -42,10 +43,10 @@ export function GraphVisualization({ height = '100%' }: { height?: string | numb
42
  const closeContextMenu = useCallback(() => setContextMenu(null), []);
43
 
44
  useEffect(() => {
45
- graphController.zoomIn = () => fgRef.current?.zoom(fgRef.current.zoom() * 1.4, 300);
46
- graphController.zoomOut = () => fgRef.current?.zoom(fgRef.current.zoom() / 1.4, 300);
47
  graphController.resetView = () => {
48
- fgRef.current?.zoomToFit(400, 40);
49
  };
50
  }, []);
51
 
@@ -99,8 +100,12 @@ export function GraphVisualization({ height = '100%' }: { height?: string | numb
99
  );
100
  setSearchHit(match ? (match as any).id : null);
101
  if (match && fgRef.current) {
102
- fgRef.current.centerAt((match as any).x, (match as any).y, 600);
103
- fgRef.current.zoom(2.5, 600);
 
 
 
 
104
  }
105
  }, [searchTerm, graphData.nodes]);
106
 
@@ -108,6 +113,7 @@ export function GraphVisualization({ height = '100%' }: { height?: string | numb
108
  <div className="graph-canvas relative h-full w-full" style={{ height }}>
109
  <ForceGraph2D
110
  ref={fgRef}
 
111
  graphData={graphData}
112
  width={undefined}
113
  backgroundColor="transparent"
 
34
  const visibleRelationships = useGraphStore((s) => s.visibleRelationships);
35
  const selectEntity = useGraphStore((s) => s.selectEntity);
36
  const setHighlighted = useGraphStore((s) => s.setHighlighted);
37
+ const dim = useGraphStore((s) => s.dim);
38
 
39
  const fgRef = useRef<any>(null);
40
  const [hoverNode, setHoverNode] = useState<FGNode | null>(null);
 
43
  const closeContextMenu = useCallback(() => setContextMenu(null), []);
44
 
45
  useEffect(() => {
46
+ graphController.zoomIn = () => fgRef.current?.zoom?.(fgRef.current.zoom() * 1.4, 300);
47
+ graphController.zoomOut = () => fgRef.current?.zoom?.(fgRef.current.zoom() / 1.4, 300);
48
  graphController.resetView = () => {
49
+ fgRef.current?.zoomToFit?.(400, 40);
50
  };
51
  }, []);
52
 
 
100
  );
101
  setSearchHit(match ? (match as any).id : null);
102
  if (match && fgRef.current) {
103
+ if (fgRef.current.centerAt) {
104
+ fgRef.current.centerAt((match as any).x, (match as any).y, 600);
105
+ }
106
+ if (fgRef.current.zoom) {
107
+ fgRef.current.zoom(2.5, 600);
108
+ }
109
  }
110
  }, [searchTerm, graphData.nodes]);
111
 
 
113
  <div className="graph-canvas relative h-full w-full" style={{ height }}>
114
  <ForceGraph2D
115
  ref={fgRef}
116
+ dim={dim}
117
  graphData={graphData}
118
  width={undefined}
119
  backgroundColor="transparent"
frontend/src/components/query/SourceToggle.tsx CHANGED
@@ -3,14 +3,16 @@
3
  import { useState } from 'react';
4
  import { Network, Type, Layers, ChevronDown } from 'lucide-react';
5
  import { cn } from '@/lib/utils';
 
6
 
7
  interface SourceToggleProps {
8
  method: string;
9
  entityCount: number;
10
  chunkCount: number;
 
11
  }
12
 
13
- export function SourceToggle({ method, entityCount, chunkCount }: SourceToggleProps) {
14
  const [open, setOpen] = useState(false);
15
  return (
16
  <div className="border-t border-border bg-bg-surface px-4 py-2">
@@ -19,9 +21,9 @@ export function SourceToggle({ method, entityCount, chunkCount }: SourceTogglePr
19
  <span
20
  className={cn(
21
  'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium',
22
- method === 'Graph'
23
  ? 'bg-accent-violet/15 text-accent-violet'
24
- : method === 'Vector'
25
  ? 'bg-accent-indigo/15 text-accent-indigo'
26
  : 'bg-accent-cyan/15 text-accent-cyan'
27
  )}
@@ -39,19 +41,27 @@ export function SourceToggle({ method, entityCount, chunkCount }: SourceTogglePr
39
  onClick={() => setOpen((o) => !o)}
40
  className="inline-flex items-center gap-1 text-xs text-text-secondary hover:text-text-primary"
41
  >
42
- <Layers className="h-3.5 w-3.5" /> Context
43
  <ChevronDown className={cn('h-3.5 w-3.5 transition-transform', open && 'rotate-180')} />
44
  </button>
45
  </div>
46
  {open && (
47
- <div className="mt-2 rounded-md border border-border bg-bg-base p-3 text-xs text-text-secondary">
48
- <p className="mb-1 font-medium text-text-primary">Retrieval context</p>
49
- <p>
50
- GRAPH CONTEXT: {entityCount} entities and their relationships were traversed in Neo4j.
51
- </p>
52
- <p>
53
- TEXT CONTEXT: {chunkCount} semantically similar text chunks were retrieved from the vector store.
54
- </p>
 
 
 
 
 
 
 
 
55
  </div>
56
  )}
57
  </div>
 
3
  import { useState } from 'react';
4
  import { Network, Type, Layers, ChevronDown } from 'lucide-react';
5
  import { cn } from '@/lib/utils';
6
+ import ReactMarkdown from 'react-markdown';
7
 
8
  interface SourceToggleProps {
9
  method: string;
10
  entityCount: number;
11
  chunkCount: number;
12
+ context?: string;
13
  }
14
 
15
+ export function SourceToggle({ method, entityCount, chunkCount, context }: SourceToggleProps) {
16
  const [open, setOpen] = useState(false);
17
  return (
18
  <div className="border-t border-border bg-bg-surface px-4 py-2">
 
21
  <span
22
  className={cn(
23
  'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium',
24
+ method === 'Graph' || method === 'GRAPH_ONLY'
25
  ? 'bg-accent-violet/15 text-accent-violet'
26
+ : method === 'Vector' || method === 'VECTOR_ONLY'
27
  ? 'bg-accent-indigo/15 text-accent-indigo'
28
  : 'bg-accent-cyan/15 text-accent-cyan'
29
  )}
 
41
  onClick={() => setOpen((o) => !o)}
42
  className="inline-flex items-center gap-1 text-xs text-text-secondary hover:text-text-primary"
43
  >
44
+ <Layers className="h-3.5 w-3.5" /> Context Preview
45
  <ChevronDown className={cn('h-3.5 w-3.5 transition-transform', open && 'rotate-180')} />
46
  </button>
47
  </div>
48
  {open && (
49
+ <div className="mt-2 max-h-[300px] overflow-y-auto rounded-md border border-border bg-bg-base p-3 text-xs text-text-secondary scrollbar-thin">
50
+ {context ? (
51
+ <div className="prose prose-invert max-w-none text-xs leading-relaxed text-text-secondary space-y-2">
52
+ <ReactMarkdown>{context}</ReactMarkdown>
53
+ </div>
54
+ ) : (
55
+ <div>
56
+ <p className="mb-1 font-medium text-text-primary">Retrieval context</p>
57
+ <p>
58
+ GRAPH CONTEXT: {entityCount} entities and their relationships were traversed in Neo4j.
59
+ </p>
60
+ <p>
61
+ TEXT CONTEXT: {chunkCount} semantically similar text chunks were retrieved from the vector store.
62
+ </p>
63
+ </div>
64
+ )}
65
  </div>
66
  )}
67
  </div>
frontend/src/store/graph.ts CHANGED
@@ -32,6 +32,7 @@ interface GraphState {
32
  visibleTypes: Record<string, boolean>;
33
  visibleRelationships: Record<string, boolean>;
34
  selectedEntity: GraphNode | null;
 
35
  setData: (data: GraphData) => void;
36
  setHighlighted: (entities: string[], paths?: string[]) => void;
37
  clearHighlighted: () => void;
@@ -39,6 +40,7 @@ interface GraphState {
39
  toggleType: (type: string) => void;
40
  toggleRelationship: (rel: string) => void;
41
  selectEntity: (entity: GraphNode | null) => void;
 
42
  }
43
 
44
  export const useGraphStore = create<GraphState>((set) => ({
@@ -49,6 +51,7 @@ export const useGraphStore = create<GraphState>((set) => ({
49
  visibleTypes: {},
50
  visibleRelationships: {},
51
  selectedEntity: null,
 
52
  setData: (data) => set({ data }),
53
  setHighlighted: (entities, paths = []) =>
54
  set({ highlightedEntities: entities, highlightedPaths: paths }),
@@ -66,4 +69,5 @@ export const useGraphStore = create<GraphState>((set) => ({
66
  },
67
  })),
68
  selectEntity: (entity) => set({ selectedEntity: entity }),
 
69
  }));
 
32
  visibleTypes: Record<string, boolean>;
33
  visibleRelationships: Record<string, boolean>;
34
  selectedEntity: GraphNode | null;
35
+ dim: 2 | 3;
36
  setData: (data: GraphData) => void;
37
  setHighlighted: (entities: string[], paths?: string[]) => void;
38
  clearHighlighted: () => void;
 
40
  toggleType: (type: string) => void;
41
  toggleRelationship: (rel: string) => void;
42
  selectEntity: (entity: GraphNode | null) => void;
43
+ setDim: (dim: 2 | 3) => void;
44
  }
45
 
46
  export const useGraphStore = create<GraphState>((set) => ({
 
51
  visibleTypes: {},
52
  visibleRelationships: {},
53
  selectedEntity: null,
54
+ dim: 2,
55
  setData: (data) => set({ data }),
56
  setHighlighted: (entities, paths = []) =>
57
  set({ highlightedEntities: entities, highlightedPaths: paths }),
 
69
  },
70
  })),
71
  selectEntity: (entity) => set({ selectedEntity: entity }),
72
+ setDim: (dim) => set({ dim }),
73
  }));