tritonparse 0.2.1.dev20250917071511__tar.gz → 0.2.1.dev20250919071533__tar.gz
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.
Potentially problematic release.
This version of tritonparse might be problematic. Click here for more details.
- {tritonparse-0.2.1.dev20250917071511/tritonparse.egg-info → tritonparse-0.2.1.dev20250919071533}/PKG-INFO +1 -1
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/structured_logging.py +6 -1
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533/tritonparse.egg-info}/PKG-INFO +1 -1
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse.egg-info/SOURCES.txt +3 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/package-lock.json +2 -2
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/package.json +1 -1
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/App.tsx +144 -51
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/CopyCodeButton.tsx +4 -4
- tritonparse-0.2.1.dev20250919071533/website/src/components/DiffComparisonView.tsx +207 -0
- tritonparse-0.2.1.dev20250919071533/website/src/context/FileDiffSession.tsx +132 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/main.tsx +4 -1
- tritonparse-0.2.1.dev20250919071533/website/src/pages/FileDiffView.tsx +645 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/pages/KernelOverview.tsx +72 -39
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.ci/README.md +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.ci/install-project.sh +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.ci/install-triton-kernels.sh +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.ci/install-triton.sh +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.ci/run-tests.sh +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.ci/setup.sh +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.github/PAGES_SETUP.md +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.github/copilot-instructions.md +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.github/workflows/deploy-pages-standalone.yml +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.github/workflows/deploy-pages.yml +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.github/workflows/nightly-pypi.yml +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.github/workflows/test.yml +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/.gitignore +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/CHANGELOG.md +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/CODE_OF_CONDUCT.md +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/CONTRIBUTING.md +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/LICENSE +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/Makefile +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/README.md +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/__init__.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/docs/README.md +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/docs/screenshots/code-comparison.png +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/docs/screenshots/kernel-overview.png +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/pyproject.toml +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/run.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/setup.cfg +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tests/README.md +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tests/__init__.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tests/example_output/logs/dedicated_log_triton_trace_findhao_.ndjson +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tests/example_output/parsed_output/dedicated_log_triton_trace_findhao__mapped.ndjson.gz +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tests/example_output/parsed_output/f0_fc0_a0_cai-.ndjson.gz +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tests/example_output/parsed_output/log_file_list.json +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tests/example_output/parsed_output_complex/dedicated_log_triton_trace_findhao__mapped.ndjson.gz +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tests/example_output/parsed_output_complex/log_file_list.json +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tests/example_output/repro/repro_context_20250816192455.json +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tests/test_add.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tests/test_tritonparse.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/__init__.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/common.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/event_diff.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/extract_source_mappings.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/ir_parser.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/mapper.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/reproducer/__init__.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/reproducer/utils.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/shared_vars.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/source_type.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/sourcemap_utils.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/tools/__init__.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/tools/decompress_bin_ndjson.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/tools/format_fix.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/tools/load_tensor.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/tools/prettify_ndjson.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/tools/readme.md +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/tp_logger.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/trace_processor.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse/utils.py +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse.egg-info/dependency_links.txt +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse.egg-info/requires.txt +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/tritonparse.egg-info/top_level.txt +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/eslint.config.js +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/index.html +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/postcss.config.js +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/public/dedicated_log_triton_trace_findhao__mapped.ndjson.gz +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/public/f0_fc0_a0_cai-.ndjson +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/public/favicon.ico +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/public/logo.svg +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/scripts/inline-html.js +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/App.css +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/assets/react.svg +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/ArgumentViewer.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/Callstack.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/CodeComparisonView.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/CodeViewer.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/CompilationInfo.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/DataSourceSelector.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/DiffViewer.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/ExternalLink.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/SingleCodeViewer.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/StackDiffViewer.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/ToggleSwitch.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/TritonIRs.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/components/WelcomeScreen.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/index.css +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/pages/CodeView.tsx +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/utils/dataLoader.ts +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/utils/fbDetection.ts +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/utils/safeImport.ts +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/utils/tensor.ts +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/vite-env.d.ts +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/tailwind.config.js +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/tsconfig.app.json +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/tsconfig.json +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/tsconfig.node.json +0 -0
- {tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/vite.config.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tritonparse
|
|
3
|
-
Version: 0.2.1.
|
|
3
|
+
Version: 0.2.1.dev20250919071533
|
|
4
4
|
Summary: TritonParse: A Compiler Tracer, Visualizer, and mini-Reproducer Generator for Triton Kernels
|
|
5
5
|
Author-email: Yueming Hao <yhao@meta.com>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -555,7 +555,12 @@ class TritonTraceHandler(logging.StreamHandler):
|
|
|
555
555
|
)
|
|
556
556
|
should_set_root_dir = False
|
|
557
557
|
# TODO: change to tritonparse knob
|
|
558
|
-
|
|
558
|
+
# The following check is necessary because the possible version mismatch between torch and tritonparse
|
|
559
|
+
elif (
|
|
560
|
+
hasattr(torch, "_utils_internal")
|
|
561
|
+
and hasattr(torch._utils_internal, "justknobs_check")
|
|
562
|
+
and not torch._utils_internal.justknobs_check("pytorch/trace:enable")
|
|
563
|
+
):
|
|
559
564
|
log.info(
|
|
560
565
|
"TritonTraceHandler: disabled because justknobs_check('pytorch/trace:enable') returned False"
|
|
561
566
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tritonparse
|
|
3
|
-
Version: 0.2.1.
|
|
3
|
+
Version: 0.2.1.dev20250919071533
|
|
4
4
|
Summary: TritonParse: A Compiler Tracer, Visualizer, and mini-Reproducer Generator for Triton Kernels
|
|
5
5
|
Author-email: Yueming Hao <yhao@meta.com>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -88,6 +88,7 @@ website/src/components/CodeViewer.tsx
|
|
|
88
88
|
website/src/components/CompilationInfo.tsx
|
|
89
89
|
website/src/components/CopyCodeButton.tsx
|
|
90
90
|
website/src/components/DataSourceSelector.tsx
|
|
91
|
+
website/src/components/DiffComparisonView.tsx
|
|
91
92
|
website/src/components/DiffViewer.tsx
|
|
92
93
|
website/src/components/ExternalLink.tsx
|
|
93
94
|
website/src/components/SingleCodeViewer.tsx
|
|
@@ -95,7 +96,9 @@ website/src/components/StackDiffViewer.tsx
|
|
|
95
96
|
website/src/components/ToggleSwitch.tsx
|
|
96
97
|
website/src/components/TritonIRs.tsx
|
|
97
98
|
website/src/components/WelcomeScreen.tsx
|
|
99
|
+
website/src/context/FileDiffSession.tsx
|
|
98
100
|
website/src/pages/CodeView.tsx
|
|
101
|
+
website/src/pages/FileDiffView.tsx
|
|
99
102
|
website/src/pages/KernelOverview.tsx
|
|
100
103
|
website/src/utils/dataLoader.ts
|
|
101
104
|
website/src/utils/fbDetection.ts
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tritonparse-website",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "tritonparse-website",
|
|
9
|
-
"version": "0.2.
|
|
9
|
+
"version": "0.2.3",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@monaco-editor/react": "^4.7.0",
|
|
12
12
|
"@types/react-syntax-highlighter": "^15.5.7",
|
{tritonparse-0.2.1.dev20250917071511 → tritonparse-0.2.1.dev20250919071533}/website/src/App.tsx
RENAMED
|
@@ -9,18 +9,21 @@ import {
|
|
|
9
9
|
} from "./utils/dataLoader";
|
|
10
10
|
import { checkFbDirectoryExists } from "./utils/fbDetection";
|
|
11
11
|
import CodeView from "./pages/CodeView";
|
|
12
|
+
import FileDiffView from "./pages/FileDiffView";
|
|
12
13
|
import SingleCodeViewer from "./components/SingleCodeViewer";
|
|
13
14
|
import KernelOverview from "./pages/KernelOverview";
|
|
14
15
|
import DataSourceSelector from "./components/DataSourceSelector";
|
|
15
16
|
import WelcomeScreen from "./components/WelcomeScreen";
|
|
16
17
|
import ExternalLink from "./components/ExternalLink";
|
|
17
18
|
import { mapLanguageToHighlighter } from "./components/CodeViewer";
|
|
19
|
+
import { useFileDiffSession } from "./context/FileDiffSession";
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* Main application component that handles data loading,
|
|
21
23
|
* state management, and rendering different views.
|
|
22
24
|
*/
|
|
23
25
|
function App() {
|
|
26
|
+
const sess = useFileDiffSession();
|
|
24
27
|
// Store processed kernel data from log file
|
|
25
28
|
const [kernels, setKernels] = useState<ProcessedKernel[]>([]);
|
|
26
29
|
// Track loading state for displaying loading indicator
|
|
@@ -67,6 +70,9 @@ function App() {
|
|
|
67
70
|
const newUrl = new URL(window.location.href);
|
|
68
71
|
newUrl.searchParams.set("json_url", jsonUrl);
|
|
69
72
|
window.history.replaceState({}, "", newUrl.toString());
|
|
73
|
+
} else if (view === "file_diff") {
|
|
74
|
+
// Allow direct navigation to File Diff even without json_url
|
|
75
|
+
setActiveTab("file_diff");
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
// Check if fb directory exists and load internal utils if available
|
|
@@ -129,6 +135,8 @@ function App() {
|
|
|
129
135
|
// Then, determine which view to show
|
|
130
136
|
if (view === "ir_code_comparison") {
|
|
131
137
|
setActiveTab("comparison");
|
|
138
|
+
} else if (view === "file_diff") {
|
|
139
|
+
setActiveTab("file_diff");
|
|
132
140
|
}
|
|
133
141
|
|
|
134
142
|
setDataLoaded(true);
|
|
@@ -198,6 +206,8 @@ function App() {
|
|
|
198
206
|
// Then, determine which view to show
|
|
199
207
|
if (initialView === "ir_code_comparison") {
|
|
200
208
|
setActiveTab("comparison");
|
|
209
|
+
} else if (initialView === "file_diff") {
|
|
210
|
+
setActiveTab("file_diff");
|
|
201
211
|
}
|
|
202
212
|
setDataLoaded(true);
|
|
203
213
|
setLoadedUrl(url);
|
|
@@ -209,6 +219,8 @@ function App() {
|
|
|
209
219
|
// Add view and kernel_hash parameters if applicable
|
|
210
220
|
if (initialView === "ir_code_comparison") {
|
|
211
221
|
newUrl.searchParams.set("view", "ir_code_comparison");
|
|
222
|
+
} else if (initialView === "file_diff") {
|
|
223
|
+
newUrl.searchParams.set("view", "file_diff");
|
|
212
224
|
}
|
|
213
225
|
|
|
214
226
|
if (kernelHash) {
|
|
@@ -278,6 +290,20 @@ function App() {
|
|
|
278
290
|
}
|
|
279
291
|
};
|
|
280
292
|
|
|
293
|
+
// Register app controls for FileDiffSession navigation
|
|
294
|
+
useEffect(() => {
|
|
295
|
+
sess.registerAppControls({
|
|
296
|
+
setActiveTab,
|
|
297
|
+
});
|
|
298
|
+
}, [sess, setActiveTab]);
|
|
299
|
+
|
|
300
|
+
// Clear FileDiff preview when entering/returning to File Diff to avoid preview intercepting other views
|
|
301
|
+
useEffect(() => {
|
|
302
|
+
if (activeTab === 'file_diff' && sess.preview.active) {
|
|
303
|
+
sess.clearPreview();
|
|
304
|
+
}
|
|
305
|
+
}, [activeTab, sess]);
|
|
306
|
+
|
|
281
307
|
// Show loading indicator while data is being fetched
|
|
282
308
|
if (loading) {
|
|
283
309
|
return (
|
|
@@ -323,8 +349,45 @@ function App() {
|
|
|
323
349
|
onBack={handleBackFromIRView}
|
|
324
350
|
/>
|
|
325
351
|
);
|
|
352
|
+
} else if (sess.preview.active) {
|
|
353
|
+
const side = sess.preview.side === 'left' ? sess.left : sess.right;
|
|
354
|
+
const idx = side.selectedIdx ?? 0;
|
|
355
|
+
const kernelsSrc = side.kernels ?? [];
|
|
356
|
+
if (!kernelsSrc || kernelsSrc.length === 0) {
|
|
357
|
+
return <div className="text-red-600">Error: Preview kernel data not available.</div>;
|
|
358
|
+
}
|
|
359
|
+
if (sess.preview.view === 'overview') {
|
|
360
|
+
return (
|
|
361
|
+
<KernelOverview
|
|
362
|
+
key={`preview-overview-${sess.preview.side}-${idx}`}
|
|
363
|
+
kernels={kernelsSrc}
|
|
364
|
+
onViewIR={handleViewSingleIR}
|
|
365
|
+
selectedKernel={idx}
|
|
366
|
+
onSelectKernel={() => {}}
|
|
367
|
+
/>
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
if (sess.preview.view === 'ir') {
|
|
371
|
+
return (
|
|
372
|
+
<CodeView
|
|
373
|
+
key={`preview-ir-${sess.preview.side}-${idx}`}
|
|
374
|
+
kernels={kernelsSrc}
|
|
375
|
+
selectedKernel={idx}
|
|
376
|
+
/>
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
return null;
|
|
326
380
|
} else if (!dataLoaded) {
|
|
327
|
-
// Show welcome screen if no data is loaded
|
|
381
|
+
// Show welcome screen if no data is loaded, but allow File Diff tab to render its view when selected
|
|
382
|
+
if (activeTab === 'file_diff') {
|
|
383
|
+
return (
|
|
384
|
+
<FileDiffView
|
|
385
|
+
kernelsLeft={kernels}
|
|
386
|
+
selectedLeftIndex={Math.max(0, selectedKernel)}
|
|
387
|
+
leftLoadedUrl={loadedUrl}
|
|
388
|
+
/>
|
|
389
|
+
);
|
|
390
|
+
}
|
|
328
391
|
return (
|
|
329
392
|
<WelcomeScreen
|
|
330
393
|
loadDefaultData={loadDefaultData}
|
|
@@ -346,17 +409,36 @@ function App() {
|
|
|
346
409
|
</div>
|
|
347
410
|
);
|
|
348
411
|
} else {
|
|
349
|
-
// Show either overview
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
412
|
+
// Show either overview, IR code, or file diff based on active tab
|
|
413
|
+
if (activeTab === "overview") {
|
|
414
|
+
return (
|
|
415
|
+
<KernelOverview
|
|
416
|
+
kernels={kernels}
|
|
417
|
+
onViewIR={handleViewSingleIR}
|
|
418
|
+
selectedKernel={selectedKernel}
|
|
419
|
+
onSelectKernel={handleSelectKernel}
|
|
420
|
+
/>
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
if (activeTab === "comparison") {
|
|
424
|
+
return (
|
|
425
|
+
<CodeView
|
|
426
|
+
key={`codeview-main-${selectedKernel}`}
|
|
427
|
+
kernels={kernels}
|
|
428
|
+
selectedKernel={selectedKernel}
|
|
429
|
+
/>
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
if (activeTab === "file_diff") {
|
|
433
|
+
return (
|
|
434
|
+
<FileDiffView
|
|
435
|
+
kernelsLeft={kernels}
|
|
436
|
+
selectedLeftIndex={Math.max(0, selectedKernel)}
|
|
437
|
+
leftLoadedUrl={loadedUrl}
|
|
438
|
+
/>
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
return null;
|
|
360
442
|
}
|
|
361
443
|
};
|
|
362
444
|
|
|
@@ -430,45 +512,56 @@ function App() {
|
|
|
430
512
|
isLoading={loading}
|
|
431
513
|
/>
|
|
432
514
|
|
|
433
|
-
{/* Tab navigation
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
515
|
+
{/* Tab navigation: File Diff button placed as the last (rightmost) button */}
|
|
516
|
+
<div className="flex space-x-4">
|
|
517
|
+
{dataLoaded && kernels.length > 0 && !selectedIR && (
|
|
518
|
+
<>
|
|
519
|
+
<button
|
|
520
|
+
className={`px-3 py-2 text-sm font-medium rounded-md ${activeTab === "overview" ? "bg-blue-700 text-white shadow-md" : "bg-blue-100 text-blue-700 hover:bg-blue-200"
|
|
521
|
+
}`}
|
|
522
|
+
onClick={() => {
|
|
523
|
+
if (sess.preview?.active) sess.clearPreview();
|
|
524
|
+
setActiveTab("overview");
|
|
525
|
+
|
|
526
|
+
if (loadedUrl) {
|
|
527
|
+
const newUrl = new URL(window.location.href);
|
|
528
|
+
newUrl.searchParams.delete("view");
|
|
529
|
+
window.history.replaceState({}, "", newUrl.toString());
|
|
530
|
+
}
|
|
531
|
+
}}
|
|
532
|
+
>
|
|
533
|
+
Kernel Overview
|
|
534
|
+
</button>
|
|
535
|
+
<button
|
|
536
|
+
className={`px-3 py-2 text-sm font-medium rounded-md ${activeTab === "comparison" ? "bg-blue-700 text-white shadow-md" : "bg-blue-100 text-blue-700 hover:bg-blue-200"
|
|
537
|
+
}`}
|
|
538
|
+
onClick={() => {
|
|
539
|
+
if (sess.preview?.active) sess.clearPreview();
|
|
540
|
+
setActiveTab("comparison");
|
|
541
|
+
|
|
542
|
+
if (loadedUrl) {
|
|
543
|
+
const newUrl = new URL(window.location.href);
|
|
544
|
+
newUrl.searchParams.set("view", "ir_code_comparison");
|
|
545
|
+
window.history.replaceState({}, "", newUrl.toString());
|
|
546
|
+
}
|
|
547
|
+
}}
|
|
548
|
+
>
|
|
549
|
+
IR Code
|
|
550
|
+
</button>
|
|
551
|
+
</>
|
|
552
|
+
)}
|
|
553
|
+
|
|
554
|
+
<button
|
|
555
|
+
className={`px-3 py-2 text-sm font-medium rounded-md ${activeTab === "file_diff" ? "bg-blue-700 text-white shadow-md" : "bg-blue-100 text-blue-700 hover:bg-blue-200"
|
|
556
|
+
}`}
|
|
557
|
+
onClick={() => {
|
|
558
|
+
if (sess.preview?.active) sess.clearPreview();
|
|
559
|
+
setActiveTab("file_diff");
|
|
560
|
+
}}
|
|
561
|
+
>
|
|
562
|
+
File Diff
|
|
563
|
+
</button>
|
|
564
|
+
</div>
|
|
472
565
|
</div>
|
|
473
566
|
</div>
|
|
474
567
|
</header>
|
|
@@ -41,15 +41,15 @@ const CopyCodeButton: React.FC<CopyCodeButtonProps> = ({
|
|
|
41
41
|
// https://heroicons.com/
|
|
42
42
|
<span>
|
|
43
43
|
{/* Checkmark SVG icon */}
|
|
44
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
45
|
-
<path
|
|
44
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="size-5">
|
|
45
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="m4.5 12.75 6 6 9-13.5" />
|
|
46
46
|
</svg>
|
|
47
47
|
</span>
|
|
48
48
|
) : (
|
|
49
49
|
<span>
|
|
50
50
|
{/* Clipboard copy icon */}
|
|
51
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
|
52
|
-
<path
|
|
51
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="size-5">
|
|
52
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M8.25 7.5V6.108c0-1.135.845-2.098 1.976-2.192.373-.03.748-.057 1.123-.08M15.75 18H18a2.25 2.25 0 0 0 2.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 0 0-1.123-.08M15.75 18.75v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5A3.375 3.375 0 0 0 6.375 7.5H5.25m11.9-3.664A2.251 2.251 0 0 0 15 2.25h-1.5a2.251 2.251 0 0 0-2.15 1.586m5.8 0c.065.21.1.433.1.664v.75h-6V4.5c0-.231.035-.454.1-.664M6.75 7.5H4.875c-.621 0-1.125.504-1.125 1.125v12c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V16.5a9 9 0 0 0-9-9Z" />
|
|
53
53
|
</svg>
|
|
54
54
|
</span>
|
|
55
55
|
)}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { DiffEditor } from "@monaco-editor/react";
|
|
3
|
+
|
|
4
|
+
interface DiffOptions {
|
|
5
|
+
ignoreWhitespace?: boolean;
|
|
6
|
+
wordLevel?: boolean; // kept for future, Monaco uses its own algorithm
|
|
7
|
+
context?: number; // lines of context when hiding unchanged regions
|
|
8
|
+
wordWrap?: "off" | "on";
|
|
9
|
+
onlyChanged?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface DiffComparisonViewProps {
|
|
13
|
+
leftContent: string;
|
|
14
|
+
rightContent: string;
|
|
15
|
+
language?: string;
|
|
16
|
+
height?: string;
|
|
17
|
+
options?: DiffOptions;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const DiffComparisonView: React.FC<DiffComparisonViewProps> = ({
|
|
21
|
+
leftContent,
|
|
22
|
+
rightContent,
|
|
23
|
+
language = "plaintext",
|
|
24
|
+
height = "calc(100vh - 12rem)",
|
|
25
|
+
options,
|
|
26
|
+
}) => {
|
|
27
|
+
const monacoOptions = useMemo(() => {
|
|
28
|
+
const hideUnchanged = options?.onlyChanged
|
|
29
|
+
? {
|
|
30
|
+
enabled: true,
|
|
31
|
+
revealLineCount: Math.max(0, options?.context ?? 3),
|
|
32
|
+
}
|
|
33
|
+
: undefined;
|
|
34
|
+
|
|
35
|
+
const opts = {
|
|
36
|
+
readOnly: true,
|
|
37
|
+
renderSideBySide: true,
|
|
38
|
+
renderOverviewRuler: true,
|
|
39
|
+
renderIndicators: true,
|
|
40
|
+
// Enable diff-editor level word wrap (VSCode has a separate setting for this)
|
|
41
|
+
diffWordWrap: "on",
|
|
42
|
+
wordWrap: options?.wordWrap ?? "on",
|
|
43
|
+
// Force both sides to honor wrap regardless of per-side defaults
|
|
44
|
+
wordWrapOverride1: "on",
|
|
45
|
+
wordWrapOverride2: "on",
|
|
46
|
+
wordWrapMinified: true,
|
|
47
|
+
wrappingStrategy: "advanced",
|
|
48
|
+
// Ensure even original (left) honors wrapping consistently
|
|
49
|
+
originalEditable: false,
|
|
50
|
+
ignoreTrimWhitespace: options?.ignoreWhitespace ?? true,
|
|
51
|
+
// @ts-ignore - monaco types may vary by version; it's safe to pass through
|
|
52
|
+
hideUnchangedRegions: hideUnchanged,
|
|
53
|
+
// @ts-ignore - prefer advanced algorithm if available
|
|
54
|
+
diffAlgorithm: "advanced",
|
|
55
|
+
// @ts-ignore - hide horizontal scrollbar when wrapping
|
|
56
|
+
scrollbar: {
|
|
57
|
+
vertical: 'auto',
|
|
58
|
+
horizontal: 'hidden',
|
|
59
|
+
horizontalScrollbarSize: 0,
|
|
60
|
+
},
|
|
61
|
+
// keep view lean
|
|
62
|
+
minimap: { enabled: false },
|
|
63
|
+
scrollBeyondLastLine: false,
|
|
64
|
+
automaticLayout: true,
|
|
65
|
+
} as any;
|
|
66
|
+
return opts;
|
|
67
|
+
}, [options]);
|
|
68
|
+
|
|
69
|
+
const editorRef = useRef<any>(null);
|
|
70
|
+
|
|
71
|
+
// Keep both panes in sync when options change
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
const editor = editorRef.current;
|
|
74
|
+
if (!editor) return;
|
|
75
|
+
try {
|
|
76
|
+
const wrap = options?.wordWrap ?? "on";
|
|
77
|
+
const original = editor.getOriginalEditor?.();
|
|
78
|
+
const modified = editor.getModifiedEditor?.();
|
|
79
|
+
const shared = { wordWrap: wrap, wordWrapMinified: true, wrappingStrategy: 'advanced', scrollbar: { horizontal: 'hidden', horizontalScrollbarSize: 0 } } as any;
|
|
80
|
+
original?.updateOptions?.(shared);
|
|
81
|
+
modified?.updateOptions?.(shared);
|
|
82
|
+
} catch {}
|
|
83
|
+
}, [options?.wordWrap]);
|
|
84
|
+
|
|
85
|
+
// Ensure diff editor is fully disposed on unmount to avoid Monaco race conditions
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
return () => {
|
|
88
|
+
try {
|
|
89
|
+
const editor: any = editorRef.current;
|
|
90
|
+
if (editor) {
|
|
91
|
+
try { editor.setModel?.(null); } catch {}
|
|
92
|
+
try { editor.getOriginalEditor?.()?.setModel?.(null); } catch {}
|
|
93
|
+
try { editor.getModifiedEditor?.()?.setModel?.(null); } catch {}
|
|
94
|
+
try { editor.dispose?.(); } catch {}
|
|
95
|
+
}
|
|
96
|
+
} catch {}
|
|
97
|
+
editorRef.current = null as any;
|
|
98
|
+
try { (window as any).__DIFF = undefined; } catch {}
|
|
99
|
+
};
|
|
100
|
+
}, []);
|
|
101
|
+
|
|
102
|
+
// Vertical resizable container: keep width 100%, allow drag to change height
|
|
103
|
+
const initialPxHeight = useMemo(() => {
|
|
104
|
+
// If a pixel value is provided, use it directly
|
|
105
|
+
if (typeof height === 'string') {
|
|
106
|
+
const pxMatch = height.match(/(\d+)px$/);
|
|
107
|
+
if (pxMatch) {
|
|
108
|
+
try { return parseInt(pxMatch[1], 10); } catch { /* ignore */ }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Support calc(100vh - Xrem)
|
|
112
|
+
const calcRemMatch = height.match(/calc\(100vh\s*-\s*(\d+(?:\.\d+)?)rem\)/i);
|
|
113
|
+
if (calcRemMatch && typeof window !== 'undefined') {
|
|
114
|
+
const rem = parseFloat(calcRemMatch[1]);
|
|
115
|
+
const remPx = rem * 16; // assume 1rem = 16px baseline
|
|
116
|
+
return Math.max(240, Math.round(window.innerHeight - remPx));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Support plain vh values (e.g., 80vh)
|
|
120
|
+
const vhMatch = height.match(/(\d+(?:\.\d+)?)vh/i);
|
|
121
|
+
if (vhMatch && typeof window !== 'undefined') {
|
|
122
|
+
const vh = parseFloat(vhMatch[1]);
|
|
123
|
+
return Math.max(240, Math.round(window.innerHeight * (vh / 100)));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Fallback: viewport height minus 16rem (~256px) if available; otherwise 600px
|
|
128
|
+
if (typeof window !== 'undefined') {
|
|
129
|
+
return Math.max(240, window.innerHeight - 256);
|
|
130
|
+
}
|
|
131
|
+
return 600;
|
|
132
|
+
}, [height]);
|
|
133
|
+
|
|
134
|
+
const [containerHeight, setContainerHeight] = useState<number>(initialPxHeight);
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<div className="w-full border border-gray-200 rounded bg-white">
|
|
138
|
+
<div
|
|
139
|
+
className="w-full resize-y overflow-auto"
|
|
140
|
+
style={{ height: `${containerHeight}px`, minHeight: 240 }}
|
|
141
|
+
// Browser native resize-y changes element height; Monaco autoLayout observes size
|
|
142
|
+
onMouseUp={() => {
|
|
143
|
+
// Capture final height after drag (optional state sync)
|
|
144
|
+
try {
|
|
145
|
+
const node = (editorRef.current as any)?.getDomNode?.();
|
|
146
|
+
if (node && (node as HTMLElement).parentElement) {
|
|
147
|
+
const h = (node as HTMLElement).parentElement!.clientHeight;
|
|
148
|
+
if (h > 0) setContainerHeight(h);
|
|
149
|
+
}
|
|
150
|
+
} catch {}
|
|
151
|
+
}}
|
|
152
|
+
>
|
|
153
|
+
<DiffEditor
|
|
154
|
+
height="100%"
|
|
155
|
+
language={language === "python" ? "python" : "plaintext"}
|
|
156
|
+
original={leftContent ?? ""}
|
|
157
|
+
modified={rightContent ?? ""}
|
|
158
|
+
options={monacoOptions}
|
|
159
|
+
theme="light"
|
|
160
|
+
// Ensure both panes use the same wrapping and scrollbar behavior
|
|
161
|
+
onMount={(editor: any) => {
|
|
162
|
+
try {
|
|
163
|
+
editorRef.current = editor;
|
|
164
|
+
|
|
165
|
+
const applyWrap = (_when: string) => {
|
|
166
|
+
try {
|
|
167
|
+
const wrap = options?.wordWrap ?? "on";
|
|
168
|
+
const original = editor.getOriginalEditor?.();
|
|
169
|
+
const modified = editor.getModifiedEditor?.();
|
|
170
|
+
const shared = { wordWrap: wrap, wordWrapMinified: true, wrappingStrategy: 'advanced', wrappingIndent: 'same', scrollbar: { horizontal: 'hidden', horizontalScrollbarSize: 0 } } as any;
|
|
171
|
+
original?.updateOptions?.(shared);
|
|
172
|
+
modified?.updateOptions?.(shared);
|
|
173
|
+
// Force layout after changing wrap
|
|
174
|
+
try { original?.layout?.(); } catch {}
|
|
175
|
+
try { modified?.layout?.(); } catch {}
|
|
176
|
+
} catch (e) {
|
|
177
|
+
// swallow errors
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// Apply at several timing points to avoid initialization overwrites
|
|
182
|
+
applyWrap('onMount immediate');
|
|
183
|
+
requestAnimationFrame(() => applyWrap('onMount rAF'));
|
|
184
|
+
setTimeout(() => applyWrap('onMount t=0'), 0);
|
|
185
|
+
setTimeout(() => applyWrap('onMount t=100'), 100);
|
|
186
|
+
setTimeout(() => applyWrap('onMount t=300'), 300);
|
|
187
|
+
|
|
188
|
+
// Re-apply on diff/layout/model changes
|
|
189
|
+
try { editor.onDidUpdateDiff?.(() => applyWrap('onDidUpdateDiff')); } catch {}
|
|
190
|
+
try { editor.getOriginalEditor?.()?.onDidLayoutChange?.(() => applyWrap('original onDidLayoutChange')); } catch {}
|
|
191
|
+
try { editor.getModifiedEditor?.()?.onDidLayoutChange?.(() => applyWrap('modified onDidLayoutChange')); } catch {}
|
|
192
|
+
try { editor.getOriginalEditor?.()?.onDidChangeModel?.(() => applyWrap('original onDidChangeModel')); } catch {}
|
|
193
|
+
try { editor.getModifiedEditor?.()?.onDidChangeModel?.(() => applyWrap('modified onDidChangeModel')); } catch {}
|
|
194
|
+
} catch (e) {
|
|
195
|
+
// swallow errors
|
|
196
|
+
}
|
|
197
|
+
}}
|
|
198
|
+
loading={<div className="p-4 text-gray-600">Loading diff viewer...</div>}
|
|
199
|
+
/>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export default DiffComparisonView;
|
|
206
|
+
|
|
207
|
+
|