File size: 5,168 Bytes
3befc15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
from pathlib import Path

# Clean BOM
for path in Path("app").rglob("*.py"):
    text = path.read_text(encoding="utf-8-sig")
    text = text.replace("\ufeff", "")
    path.write_text(text, encoding="utf-8")

hf_path = Path("app/deployment/hf_status.py")
text = hf_path.read_text(encoding="utf-8-sig")
text = text.replace("\ufeff", "")

append_code = r'''
# =====================================================
# Phase 36 override: restore graph actions in user app
# =====================================================

try:
    _phase36_previous_get_product_app_html = get_product_app_html
except NameError:
    _phase36_previous_get_product_app_html = None


def get_product_app_html() -> str:
    if _phase36_previous_get_product_app_html is None:
        return "<h1>GraphResearcher App</h1><p>App UI is unavailable.</p>"

    html = _phase36_previous_get_product_app_html()

    graph_section = """
        <div class="panel-section" id="graphActionsPhase36">
            <h3>Graph View</h3>
            <button class="green" onclick="buildGraphPhase36()">Build / Rebuild Graph</button>
            <button class="secondary" onclick="openGraphViewerPhase36()">View Graph</button>
            <p class="small" style="color:#64748b;margin-top:8px;">
                Open the entity-relation graph created from the selected document.
            </p>
        </div>
"""

    if "id=\"graphActionsPhase36\"" not in html:
        if '<div class="panel-section">' in html and "Advanced Settings" in html:
            html = html.replace(
                '<div class="panel-section">\n            <h3>Advanced Settings</h3>',
                graph_section + '\n        <div class="panel-section">\n            <h3>Advanced Settings</h3>',
                1
            )
        elif "</aside>" in html:
            html = html.replace("</aside>", graph_section + "\n    </aside>", 1)

    sidebar_buttons = """
        <button class="full secondary" onclick="buildGraphPhase36()">Build / Rebuild Graph</button>
        <button class="full secondary" onclick="openGraphViewerPhase36()">View Graph</button>
"""

    if "openGraphViewerPhase36" not in html.split("</aside>", 1)[0]:
        if "Clear Workspace Cache" in html:
            html = html.replace(
                '<button class="full secondary" onclick="clearWorkspaceCache()">Clear Workspace Cache</button>',
                '<button class="full secondary" onclick="clearWorkspaceCache()">Clear Workspace Cache</button>\n' + sidebar_buttons,
                1
            )
        elif '<button class="full secondary" onclick="window.location.href=\'/\'">Home</button>' in html:
            html = html.replace(
                '<button class="full secondary" onclick="window.location.href=\'/\'">Home</button>',
                '<button class="full secondary" onclick="window.location.href=\'/\'">Home</button>\n' + sidebar_buttons,
                1
            )

    js = """
<script>
/*
Phase 36: restore View Graph in the normal user app.
This is not a developer-only feature. It helps users inspect the document entity-relation graph.
*/

async function buildGraphPhase36() {
    const doc = getSelectedDocument();

    if (!doc) {
        alert('Select a document first.');
        return;
    }

    setStatus('Building graph...');

    try {
        const response = await fetch(`/documents/${doc.id}/graph/build`, {
            method: 'POST'
        });

        const data = await response.json();

        if (!response.ok) {
            throw new Error(JSON.stringify(data));
        }

        doc.graphStatus = 'graph built';
        doc.graphData = {
            entities: data.total_entities ?? data.entity_count ?? null,
            relations: data.total_relations ?? data.relation_count ?? null
        };

        saveDocuments();
        renderDocuments();

        const metricsBox = document.getElementById('metricsBox');
        if (metricsBox) {
            metricsBox.innerHTML = `
                <span class="metric">graph built</span>
                <span class="metric">entities: ${doc.graphData.entities ?? 'NA'}</span>
                <span class="metric">relations: ${doc.graphData.relations ?? 'NA'}</span>
            `;
        }

        setStatus('Graph ready');
        alert('Graph built. Click View Graph to open it.');

    } catch (error) {
        setStatus('Graph build failed');
        alert('Graph build failed. Re-index or re-upload the document if Hugging Face rebuilt recently. Error: ' + error.message);
    }
}

function openGraphViewerPhase36() {
    const doc = getSelectedDocument();

    if (!doc) {
        alert('Select a document first.');
        return;
    }

    window.open(`/documents/${doc.id}/graph/view`, '_blank');
}
</script>
"""

    if "Phase 36: restore View Graph" not in html:
        html = html.replace("</body>", js + "\n</body>")

    return html
'''

if "Phase 36 override: restore graph actions in user app" not in text:
    text += "\n\n" + append_code
    print("Phase 36 restore View Graph patch added.")
else:
    print("Phase 36 patch already exists.")

hf_path.write_text(text, encoding="utf-8")
print("Done.")