interlinked-mapper 0.3.3__tar.gz → 0.3.5__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.
Files changed (45) hide show
  1. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/PKG-INFO +1 -1
  2. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/mcp_server.py +37 -34
  3. interlinked_mapper-0.3.3/interlinked/visualizer/frontend/dist/assets/index-CX3ZrzHg.js → interlinked_mapper-0.3.5/interlinked/visualizer/frontend/dist/assets/index-Dh01aXoE.js +1 -1
  4. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/dist/index.html +1 -1
  5. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/src/App.tsx +15 -10
  6. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked_mapper.egg-info/PKG-INFO +1 -1
  7. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked_mapper.egg-info/SOURCES.txt +1 -1
  8. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/pyproject.toml +1 -1
  9. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/__init__.py +0 -0
  10. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/analyzer/__init__.py +0 -0
  11. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/analyzer/dead_code.py +0 -0
  12. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/analyzer/embeddings.py +0 -0
  13. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/analyzer/graph.py +0 -0
  14. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/analyzer/parser.py +0 -0
  15. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/analyzer/similarity.py +0 -0
  16. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/cli.py +0 -0
  17. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/commander/__init__.py +0 -0
  18. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/commander/llm.py +0 -0
  19. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/commander/query.py +0 -0
  20. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/commander/repl.py +0 -0
  21. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/models.py +0 -0
  22. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/__init__.py +0 -0
  23. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/dist/assets/index-CyhrxsQU.css +0 -0
  24. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/index.html +0 -0
  25. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/index.html.d3-legacy +0 -0
  26. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/package-lock.json +0 -0
  27. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/package.json +0 -0
  28. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/src/graph/GraphCanvas.tsx +0 -0
  29. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/src/graph/nodePrograms.ts +0 -0
  30. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/src/index.css +0 -0
  31. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/src/main.tsx +0 -0
  32. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/src/state/graphStore.ts +0 -0
  33. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/src/state/sseClient.ts +0 -0
  34. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/src/theme.ts +0 -0
  35. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/src/types.ts +0 -0
  36. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/src/vite-env.d.ts +0 -0
  37. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/tsconfig.json +0 -0
  38. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/frontend/vite.config.ts +0 -0
  39. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/layouts.py +0 -0
  40. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked/visualizer/server.py +0 -0
  41. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked_mapper.egg-info/dependency_links.txt +0 -0
  42. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked_mapper.egg-info/entry_points.txt +0 -0
  43. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked_mapper.egg-info/requires.txt +0 -0
  44. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/interlinked_mapper.egg-info/top_level.txt +0 -0
  45. {interlinked_mapper-0.3.3 → interlinked_mapper-0.3.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: interlinked-mapper
3
- Version: 0.3.3
3
+ Version: 0.3.5
4
4
  Summary: A Python program topology explorer — visualize the shape of your codebase
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/austerecryptid/interlinked
@@ -41,46 +41,46 @@ from interlinked.analyzer.dead_code import detect_dead_code
41
41
  from interlinked.commander.query import QueryEngine
42
42
 
43
43
 
44
+ def _start_background_analysis(graph: CodeGraph, engine: QueryEngine, project_path: str) -> None:
45
+ """Run similarity + embeddings in background threads (non-blocking).
46
+
47
+ Mirrors the pattern used by the REST API server: parse returns fast,
48
+ then similarity fingerprinting and embedding builds run in the background.
49
+ """
50
+ import threading
51
+
52
+ # Similarity in background thread
53
+ def _run_similarity():
54
+ try:
55
+ from interlinked.analyzer.similarity import analyze_similarity
56
+ analyze_similarity(graph)
57
+ except Exception:
58
+ pass
59
+ threading.Thread(target=_run_similarity, daemon=True, name="mcp-similarity").start()
60
+
61
+ # Embeddings in background thread (via build_async which spawns its own thread)
62
+ try:
63
+ from interlinked.visualizer.server import _start_embedding_build, _collect_function_sources
64
+ _start_embedding_build(graph, project_path, engine)
65
+ except Exception:
66
+ pass
67
+
68
+
44
69
  def build_graph(project_path: str) -> tuple[CodeGraph, QueryEngine]:
45
- """Parse a project and build the graph + query engine."""
70
+ """Parse a project and build the graph + query engine.
71
+
72
+ Returns immediately after parsing + dead code detection.
73
+ Similarity and embeddings run in background threads.
74
+ """
46
75
  nodes, edges = parse_project(project_path)
47
76
  graph = CodeGraph()
48
77
  graph.build_from(nodes, edges)
49
78
  detect_dead_code(graph)
50
79
 
51
- # Run similarity analysis if available
52
- try:
53
- from interlinked.analyzer.similarity import analyze_similarity
54
- analyze_similarity(graph)
55
- except Exception:
56
- pass
57
-
58
80
  engine = QueryEngine(graph)
59
81
 
60
- # Start embedding build in background (if torch/transformers installed)
61
- try:
62
- from interlinked.analyzer.embeddings import EmbeddingIndex, is_available
63
- if is_available():
64
- from pathlib import Path
65
- emb_index = EmbeddingIndex(project_path)
66
- engine._embedding_index = emb_index
67
- # Collect function sources
68
- from interlinked.models import SymbolType
69
- functions = []
70
- for node in graph.all_nodes(include_proposed=False):
71
- if node.symbol_type not in (SymbolType.FUNCTION, SymbolType.METHOD):
72
- continue
73
- if node.file_path and node.line_start and node.line_end:
74
- try:
75
- lines = Path(node.file_path).read_text(encoding="utf-8", errors="replace").splitlines()
76
- source = "\n".join(lines[max(0, node.line_start - 1):min(len(lines), node.line_end)])
77
- if source:
78
- functions.append({"id": node.id, "source": source})
79
- except Exception:
80
- pass
81
- emb_index.build_async(functions)
82
- except Exception:
83
- pass
82
+ # Kick off similarity + embeddings in background (non-blocking)
83
+ _start_background_analysis(graph, engine, project_path)
84
84
 
85
85
  return graph, engine
86
86
 
@@ -520,7 +520,8 @@ def _dispatch_via_server(name: str, args: dict[str, Any], server_url: str) -> st
520
520
  if method == "GET":
521
521
  r = httpx.get(url, timeout=30.0)
522
522
  else:
523
- r = httpx.post(url, json=body, timeout=30.0)
523
+ timeout = 120.0 if "switch_project" in path else 30.0
524
+ r = httpx.post(url, json=body, timeout=timeout)
524
525
  data = r.json()
525
526
 
526
527
  # Extract the most useful part of the response for the LLM
@@ -621,8 +622,10 @@ def _dispatch_tool(
621
622
 
622
623
  elif name == "interlinked_switch_project":
623
624
  from interlinked.visualizer.server import _rebuild_graph
624
- result = _rebuild_graph(args["path"], graph)
625
+ result = _rebuild_graph(args["path"], graph, run_similarity=False)
625
626
  engine.reset_filter()
627
+ # Background similarity + embeddings — matches REST API pattern
628
+ _start_background_analysis(graph, engine, args["path"])
626
629
  return json.dumps(result, indent=2)
627
630
 
628
631
  elif name == "interlinked_edges_between":
@@ -509,4 +509,4 @@ void main(void) {
509
509
  filter: blur(${_}px) brightness(2.0) saturate(1.6);
510
510
  opacity: ${j};
511
511
  mix-blend-mode: screen;
512
- `,Y.insertBefore(q,Y.firstChild);const me=q.getContext("2d");return me.imageSmoothingEnabled=!0,[q,me]},[ce,Te]=C("sigma-bloom-nodes",10,u),[H,T]=C("sigma-bloom-edges",6,d);g.current=ce,v.current=H;const w=.5,te=.5,ee=()=>{if(!g.current||!oe)return;const E=Math.ceil(oe.width*w),_=Math.ceil(oe.height*w);if((ce.width!==E||ce.height!==_)&&(ce.width=E,ce.height=_),Te.clearRect(0,0,E,_),Te.drawImage(oe,0,0,E,_),K){const j=Math.ceil(K.width*te),q=Math.ceil(K.height*te);(H.width!==j||H.height!==q)&&(H.width=j,H.height=q),T.clearRect(0,0,j,q),T.drawImage(K,0,0,j,q)}};I.on("afterRender",ee),ee()}return I.on("clickNode",C=>{i(C.node)}),I.on("doubleClickNode",C=>{s(C.node)}),I.on("clickStage",()=>{i("")}),()=>{var C,ce;(C=g.current)==null||C.remove(),(ce=v.current)==null||ce.remove(),g.current=null,v.current=null,I.kill(),p.current=null}},[l,U]),Se.useEffect(()=>{g.current&&(g.current.style.opacity=String(u)),v.current&&(v.current.style.opacity=String(d))},[u,d]),Se.useEffect(()=>{var G;(G=p.current)==null||G.refresh()},[r,o]);const F=Se.useRef("");Se.useEffect(()=>{const G=p.current;if(!G)return;const I=(o==null?void 0:o.highlighted_node_ids)??[],Y=I.slice().sort().join(",");if(Y===F.current||I.length===0){I.length===0&&F.current!==""&&(F.current="",G.getCamera().animate({x:.5,y:.5,ratio:1},{duration:400}));return}F.current=Y;const K=[];for(const xe of I)if(l.hasNode(xe)){const he=l.getNodeAttributes(xe);typeof he.x=="number"&&typeof he.y=="number"&&K.push({x:he.x,y:he.y})}if(K.length===0)return;let oe=1/0,De=-1/0,le=1/0,C=-1/0;for(const xe of K)xe.x<oe&&(oe=xe.x),xe.x>De&&(De=xe.x),xe.y<le&&(le=xe.y),xe.y>C&&(C=xe.y);const ce=(oe+De)/2,Te=(le+C)/2,H=G.getCamera(),T=G.getDimensions();if(K.length===1){const xe=G.graphToViewport({x:ce,y:Te}),he=G.viewportToFramedGraph(xe);H.animate({x:he.x,y:he.y,ratio:Math.min(H.ratio,.3)},{duration:400});return}const w=G.graphToViewport({x:oe,y:le}),te=G.graphToViewport({x:De,y:C}),ee=Math.abs(te.x-w.x),E=Math.abs(te.y-w.y),_=1.6,j=ee>0?T.width/(ee*_):1,q=E>0?T.height/(E*_):1,me=Math.min(j,q),Re=Math.max(.02,Math.min(H.ratio/me,1.5)),fe=G.graphToViewport({x:ce,y:Te}),se=G.viewportToFramedGraph(fe);H.animate({x:se.x,y:se.y,ratio:Re},{duration:500})},[o==null?void 0:o.highlighted_node_ids,l]);const V=o==null?void 0:o.context,M=V&&(V.what||V.why||V.where),[W,D]=qo.useState(null);qo.useEffect(()=>{D(null)},[V==null?void 0:V.what]);const $=qo.useMemo(()=>{const G=Math.floor(Math.random()*Zo.length);return Zo[G]},[]);return L.jsxs("div",{className:"graph-container",children:[L.jsx("div",{ref:f,className:"sigma-container",style:{width:"100%",flex:"1 1 0",minHeight:0,position:"relative"}}),U===0&&L.jsxs("div",{className:"empty-state",style:{position:"absolute",inset:0,zIndex:5},children:[L.jsx("div",{className:"gosling-quote",style:{whiteSpace:"pre-line"},children:$[0]}),L.jsx("div",{className:"gosling-sub",children:$[1]}),L.jsx("div",{className:"gosling-sub",style:{marginTop:20,color:"#2a4a6a"},children:"ESTABLISHING UPLINK..."})]}),M&&W!==V.what&&L.jsxs("div",{className:"context-banner",children:[L.jsx("button",{className:"cb-dismiss",onClick:()=>D(V.what),children:"×"}),V.what&&L.jsxs("div",{className:"cb-row",children:[L.jsx("span",{className:"cb-label",children:"WHAT"}),L.jsx("span",{className:"cb-text",children:V.what})]}),V.why&&L.jsxs("div",{className:"cb-row",children:[L.jsx("span",{className:"cb-label",children:"WHY"}),L.jsx("span",{className:"cb-text",children:V.why})]}),V.where&&L.jsxs("div",{className:"cb-row",children:[L.jsx("span",{className:"cb-label",children:"WHERE"}),L.jsx("span",{className:"cb-text",children:V.where})]}),V.source&&L.jsxs("div",{className:"cb-source",children:["VIA ",V.source.toUpperCase()]})]}),L.jsx("div",{className:"interlinked-watermark",children:"INTERLINKED"})]})}const it=wm();function py(){var Qe,Ee,ne,N;const[,l]=Se.useState(0),o=Se.useCallback(()=>l(J=>J+1),[]),[r,i]=Se.useState(null),[s,u]=Se.useState(null),[d,f]=Se.useState("ESTABLISHING UPLINK..."),[p,g]=Se.useState([]),[v,y]=Se.useState(-1),[k,b]=Se.useState("inspect"),[B,U]=Se.useState([]),[F,V]=Se.useState(!1),[M,W]=Se.useState(!1),[D,$]=Se.useState("claude-sonnet-4-20250514"),[G,I]=Se.useState(!0),[Y,K]=Se.useState(!0),[oe,De]=Se.useState(.5),[le,C]=Se.useState(.5),ce=Se.useRef(null),Te=Se.useRef(null),H=Se.useRef(null);Se.useEffect(()=>(fetch("/api/stats").then(de=>de.json()).then(i).catch(()=>{}),fetch("/api/settings").then(de=>de.json()).then(de=>{W(de.has_api_key),$(de.model)}).catch(()=>{}),_m({onSnapshot:de=>{Pd(it,de),u(it.selectedNodeId),o(),fetch("/api/stats").then(ie=>ie.json()).then(i).catch(()=>{})},onDelta:de=>{Em(it,de),u(it.selectedNodeId),o()},onStatus:de=>f(de)})),[o]),Se.useEffect(()=>{H.current&&(H.current.scrollTop=H.current.scrollHeight)},[B]);const T=Se.useCallback(()=>{fetch("/api/snapshot").then(J=>J.json()).then(J=>{Pd(it,J),u(it.selectedNodeId),o()}),fetch("/api/stats").then(J=>J.json()).then(i).catch(()=>{})},[o]),w=Se.useCallback(J=>{if(!J.trim())return;g(O=>[J,...O].slice(0,50)),y(-1);const de=J.includes("view.")||J.includes("graph.")||J.includes("=")||J.includes("(");fetch(de?"/api/command":"/api/nl",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(de?{command:J}:{text:J})}).then(O=>O.json()).then(O=>{if(O.error)f(`ERR: ${O.error}`.toUpperCase());else{const Ue=O.result||JSON.stringify(O).slice(0,200);f(typeof Ue=="string"?Ue.toUpperCase():String(Ue).toUpperCase()),T()}})},[T]),te=Se.useCallback(J=>{J.trim()&&(U(de=>[...de,{role:"user",content:J}]),V(!0),fetch("/api/chat",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:J})}).then(de=>de.json()).then(de=>{if(V(!1),de.error==="no_api_key"){U(ie=>[...ie,{role:"system",content:"No API key configured. Go to Settings tab to add your Anthropic API key, or use the command bar with Python commands."}]);return}U(ie=>[...ie,{role:"assistant",content:de.explanation||"Done.",commands:de.commands_run}]),T()}).catch(de=>{V(!1),U(ie=>[...ie,{role:"system",content:`Error: ${de.message}`}])}))},[T]),ee=Se.useCallback(J=>{fetch("/api/zoom",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({level:J})}).then(de=>de.json()).then(de=>{var ie;f(((ie=de.result)==null?void 0:ie.toUpperCase())||""),T()})},[T]),E=Se.useCallback(J=>{const de=J||null;it.selectedNodeId=de,u(de),J&&b("inspect")},[]),_=Se.useCallback(J=>{fetch("/api/focus",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({node_id:J,depth:2})}).then(de=>de.json()).then(de=>{var ie;f(((ie=de.result)==null?void 0:ie.toUpperCase())||""),T()})},[T]),j=Se.useCallback(J=>{J.key==="Enter"?(w(J.target.value),J.target.value=""):J.key==="ArrowUp"?(J.preventDefault(),y(de=>{const ie=Math.min(de+1,p.length-1);return ce.current&&p[ie]&&(ce.current.value=p[ie]),ie})):J.key==="ArrowDown"&&(J.preventDefault(),y(de=>{const ie=Math.max(de-1,-1);return ce.current&&(ce.current.value=ie>=0?p[ie]:""),ie}))},[w,p]),q=Se.useCallback(J=>{J.key==="Enter"&&!J.shiftKey&&(J.preventDefault(),te(J.target.value),J.target.value="")},[te]),me=Se.useCallback((J,de)=>{fetch("/api/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:J,model:de})}).then(ie=>ie.json()).then(ie=>{W(ie.has_api_key),$(ie.model),f(ie.has_api_key?"API KEY CONFIGURED":"API KEY CLEARED")})},[]),Re=((Qe=it.viewState)==null?void 0:Qe.zoom_level)||"module",fe=it.viewState,se=!!((Ee=fe==null?void 0:fe.highlighted_node_ids)!=null&&Ee.length||(ne=fe==null?void 0:fe.visible_node_ids)!=null&&ne.length||fe!=null&&fe.filter_expression||fe!=null&&fe.trace_node_roles&&Object.keys(fe.trace_node_roles).length>0),xe=((N=it.viewState)==null?void 0:N.visible_edge_types)||["calls","imports","inherits","reads","writes","contains","returns"],he=Se.useCallback(J=>{const de=new Set(xe);de.has(J)?de.delete(J):de.add(J),fetch("/api/edge_types",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({edge_types:[...de]})}).then(()=>T())},[xe,T]),Ae=Se.useMemo(()=>!s||!it.graph.hasNode(s)?null:it.graph.getNodeAttributes(s),[s,it.graph]),Ie=`${G?"260px":"0px"} 1fr ${Y?"320px":"0px"}`;return L.jsxs("div",{className:"app-container",style:{gridTemplateColumns:Ie},children:[L.jsx(gy,{stats:r,currentZoom:Re,onZoom:ee,activeEdgeTypes:xe,onEdgeToggle:he}),!G&&L.jsx("button",{className:"panel-collapse-btn",style:{top:70,left:6},onClick:()=>I(!0),children:"▶"}),G&&L.jsx("button",{className:"panel-collapse-btn",style:{top:70,left:260},onClick:()=>I(!1),children:"◀"}),G&&L.jsx(my,{graph:it.graph,selectedNode:s,onNodeClick:E}),L.jsxs("div",{style:{position:"relative",display:"flex",flexDirection:"column",overflow:"hidden",minHeight:0},children:[L.jsx(hy,{graph:it.graph,viewState:it.viewState,selectedNode:s,onNodeClick:E,onNodeDoubleClick:_,nodeGlow:oe,edgeGlow:le}),L.jsx(Ey,{viewState:it.viewState})]}),!Y&&L.jsx("button",{className:"panel-collapse-btn",style:{top:70,right:6},onClick:()=>K(!0),children:"◀"}),Y&&L.jsx("button",{className:"panel-collapse-btn",style:{top:70,right:320},onClick:()=>K(!1),children:"▶"}),Y&&L.jsxs("div",{className:"sidebar-right",children:[L.jsx("div",{className:"tab-bar",children:["inspect","chat","settings"].map(J=>L.jsx("button",{className:`tab-btn ${k===J?"active":""}`,onClick:()=>b(J),children:J},J))}),k==="inspect"&&L.jsx(vy,{nodeAttrs:Ae,graph:it.graph,selectedNode:s,onNodeClick:E}),k==="chat"&&L.jsx(yy,{messages:B,loading:F,onKeyDown:q,inputRef:Te,scrollRef:H}),k==="settings"&&L.jsx(wy,{hasApiKey:M,llmModel:D,onSave:me,nodeGlow:oe,edgeGlow:le,onNodeGlowChange:De,onEdgeGlowChange:C}),L.jsxs("div",{className:"command-bar",children:[L.jsxs("div",{className:"command-input-wrapper",children:[L.jsx("span",{className:"command-prefix",children:">_"}),L.jsx("input",{ref:ce,className:"command-input",placeholder:"view.isolate('analyzer') or natural language...",onKeyDown:j})]}),se&&L.jsx("button",{className:"clear-filters-btn",onClick:()=>w("view.reset_filter()"),title:"Clear all filters and highlights",children:"✕ CLEAR FILTERS"})]})]}),L.jsx(_y,{message:d,viewState:it.viewState})]})}function gy({stats:l,currentZoom:o,onZoom:r,activeEdgeTypes:i,onEdgeToggle:s}){const u=new Set(i),d=[{type:"calls",color:"#88bbdd"},{type:"imports",color:"#667799"},{type:"inherits",color:"#bb77ee"},{type:"reads",color:"#33ccaa"},{type:"writes",color:"#ff5566"},{type:"returns",color:"#eebb44"},{type:"contains",color:"#556677"}];return L.jsxs("div",{className:"header",children:[L.jsxs("div",{children:[L.jsx("div",{className:"logo",children:"INTERLINKED"}),L.jsx("div",{className:"logo-sub",children:"TOPOLOGY EXPLORER"})]}),L.jsx("span",{className:"separator"}),L.jsx("div",{className:"stats",children:l&&L.jsxs(L.Fragment,{children:[L.jsxs("span",{children:["MOD",L.jsx("span",{className:"stat-value",children:l.modules})]}),L.jsxs("span",{children:["CLS",L.jsx("span",{className:"stat-value",children:l.classes})]}),L.jsxs("span",{children:["FN",L.jsx("span",{className:"stat-value",children:l.functions+l.methods})]}),L.jsxs("span",{children:["VAR",L.jsx("span",{className:"stat-value",children:l.variables})]}),L.jsxs("span",{children:["DEAD",L.jsx("span",{className:"stat-value stat-dead",children:l.dead_nodes})]}),L.jsxs("span",{children:["EDGE",L.jsx("span",{className:"stat-value",children:l.total_edges})]})]})}),L.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:4,marginLeft:"auto"},children:[L.jsx("div",{className:"zoom-controls",children:["all","module","class","function","variable"].map(f=>L.jsx("button",{className:`zoom-btn ${o===f?"active":""}`,onClick:()=>r(f),children:f},f))}),L.jsx("div",{style:{display:"flex",gap:3,justifyContent:"flex-end",alignItems:"center"},children:d.map(({type:f,color:p})=>L.jsx("button",{className:`edge-chip ${u.has(f)?"active":""}`,style:u.has(f)?{borderColor:p+"88",color:p}:{},onClick:()=>s(f),children:f},f))})]})]})}function my({graph:l,selectedNode:o,onNodeClick:r}){const i=Se.useMemo(()=>{const s={};return l.forEachNode((u,d)=>{const f=d.symbolType;s[f]||(s[f]=[]),s[f].push({id:u,name:d.label,symbolType:f,isDead:d.isDead,isProposed:d.isProposed})}),s},[l,l.order]);return L.jsx("div",{className:"sidebar-left",children:["module","class","function","method","variable"].map(s=>i[s]&&i[s].length>0&&L.jsxs("div",{className:"sidebar-section",children:[L.jsxs("div",{className:"sidebar-section-title",children:[s,"s (",i[s].length,")"]}),i[s].slice(0,100).map(u=>L.jsxs("div",{className:`node-list-item ${o===u.id?"active":""}`,onClick:()=>r(u.id),title:u.id,children:[L.jsx("span",{className:`node-badge ${u.symbolType}`,children:u.symbolType.slice(0,3)}),L.jsx("span",{className:"node-name",children:u.name}),u.isDead&&L.jsx("span",{className:"dead-indicator"}),u.isProposed&&L.jsx("span",{className:"proposed-indicator"})]},u.id))]},s))})}function vy({nodeAttrs:l,graph:o,selectedNode:r,onNodeClick:i}){const s=Se.useMemo(()=>Zo[Math.floor(Math.random()*Zo.length)],[]);if(!l||!r)return L.jsx("div",{className:"detail-panel",children:L.jsxs("div",{className:"empty-state",children:[L.jsx("div",{className:"gosling-quote",style:{whiteSpace:"pre-line"},children:s[0]}),L.jsx("div",{className:"gosling-sub",children:s[1]}),L.jsx("div",{className:"gosling-sub",style:{marginTop:12,color:"#2a4a6a",fontSize:9},children:"SELECT A NODE TO INSPECT"})]})});const u=[],d=[];return o.hasNode(r)&&(o.forEachInEdge(r,(f,p,g)=>{u.push({id:g,label:o.getNodeAttribute(g,"label")||g,edgeType:p.edgeType})}),o.forEachOutEdge(r,(f,p,g,v)=>{d.push({id:v,label:o.getNodeAttribute(v,"label")||v,edgeType:p.edgeType})})),L.jsxs("div",{className:"detail-panel",children:[L.jsx("div",{className:"detail-title",children:l.label}),L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"QUALIFIED NAME"}),L.jsx("div",{className:"detail-value",children:L.jsx("code",{children:l.qualifiedName})})]}),L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"TYPE"}),L.jsx("div",{className:"detail-value",children:String(l.symbolType)})]}),!!l.filePath&&L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"FILE"}),L.jsxs("div",{className:"detail-value",children:[String(l.filePath),":",String(l.lineStart)]})]}),!!l.signature&&L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"SIGNATURE"}),L.jsx("div",{className:"detail-value",children:L.jsx("code",{children:String(l.signature)})})]}),!!l.docstring&&L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"DOCSTRING"}),L.jsx("div",{className:"detail-value",style:{whiteSpace:"pre-wrap",fontSize:10},children:String(l.docstring)})]}),u.length>0&&L.jsxs("div",{className:"detail-field",children:[L.jsxs("div",{className:"detail-label",children:["INCOMING (",u.length,")"]}),L.jsx("ul",{style:{listStyle:"none",marginTop:4},children:u.slice(0,30).map((f,p)=>L.jsxs("li",{style:{fontSize:10,padding:"3px 0",color:"#5a8aaa",cursor:"pointer"},onClick:()=>i(f.id),children:[L.jsx("span",{style:{fontFamily:"'Orbitron', sans-serif",fontSize:7,padding:"1px 5px",borderRadius:2,marginRight:6,fontWeight:600,letterSpacing:1,border:`1px solid ${Nr[f.edgeType]||"#334"}`,color:Nr[f.edgeType]||"#556"},children:f.edgeType}),f.label]},p))})]}),d.length>0&&L.jsxs("div",{className:"detail-field",children:[L.jsxs("div",{className:"detail-label",children:["OUTGOING (",d.length,")"]}),L.jsx("ul",{style:{listStyle:"none",marginTop:4},children:d.slice(0,30).map((f,p)=>L.jsxs("li",{style:{fontSize:10,padding:"3px 0",color:"#5a8aaa",cursor:"pointer"},onClick:()=>i(f.id),children:[L.jsx("span",{style:{fontFamily:"'Orbitron', sans-serif",fontSize:7,padding:"1px 5px",borderRadius:2,marginRight:6,fontWeight:600,letterSpacing:1,border:`1px solid ${Nr[f.edgeType]||"#334"}`,color:Nr[f.edgeType]||"#556"},children:f.edgeType}),f.label]},p))})]})]})}function yy({messages:l,loading:o,onKeyDown:r,inputRef:i,scrollRef:s}){return L.jsxs("div",{style:{display:"flex",flexDirection:"column",flex:1,overflow:"hidden"},children:[L.jsxs("div",{className:"chat-messages",ref:s,children:[l.map((u,d)=>L.jsxs("div",{className:`chat-msg ${u.role}`,children:[u.content,u.commands&&u.commands.length>0&&L.jsx("div",{style:{marginTop:6,fontSize:9,color:"#4a7a9a"},children:u.commands.map((f,p)=>L.jsxs("div",{style:{fontFamily:"'Share Tech Mono', monospace"},children:["→ ",f]},p))})]},d)),o&&L.jsx("div",{className:"chat-msg system",style:{animation:"pulse-glow 1s infinite"},children:"PROCESSING..."})]}),L.jsx("div",{className:"chat-input-area",children:L.jsx("textarea",{ref:i,className:"chat-input",rows:2,placeholder:"Ask about the codebase...",onKeyDown:r})})]})}function wy({hasApiKey:l,llmModel:o,onSave:r,nodeGlow:i,edgeGlow:s,onNodeGlowChange:u,onEdgeGlowChange:d}){const[f,p]=Se.useState(""),[g,v]=Se.useState(o),y={width:"100%",accentColor:"#00d4ff",cursor:"pointer"};return L.jsxs("div",{className:"detail-panel",children:[L.jsx("div",{className:"detail-title",children:"SETTINGS"}),L.jsxs("div",{className:"detail-field",children:[L.jsxs("div",{className:"detail-label",children:["GLOBAL GLOW ",L.jsxs("span",{style:{color:"#00d4ff"},children:[Math.round((i+s)/2*100),"%"]})]}),L.jsx("input",{type:"range",min:0,max:1,step:.05,value:(i+s)/2,onChange:k=>{const b=Number(k.target.value);u(b),d(b)},style:y})]}),L.jsxs("div",{className:"detail-field",children:[L.jsxs("div",{className:"detail-label",children:["NODE GLOW ",L.jsxs("span",{style:{color:"#0099dd"},children:[Math.round(i*100),"%"]})]}),L.jsx("input",{type:"range",min:0,max:1,step:.05,value:i,onChange:k=>u(Number(k.target.value)),style:{...y,accentColor:"#0099dd"}})]}),L.jsxs("div",{className:"detail-field",children:[L.jsxs("div",{className:"detail-label",children:["EDGE GLOW ",L.jsxs("span",{style:{color:"#88bbdd"},children:[Math.round(s*100),"%"]})]}),L.jsx("input",{type:"range",min:0,max:1,step:.05,value:s,onChange:k=>d(Number(k.target.value)),style:{...y,accentColor:"#88bbdd"}})]}),L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"API KEY STATUS"}),L.jsx("div",{className:"detail-value",children:l?L.jsx("span",{style:{color:"#39ff14",textShadow:"0 0 6px #39ff1444"},children:"CONFIGURED"}):L.jsx("span",{style:{color:"#ff2975",textShadow:"0 0 6px #ff297544"},children:"NOT SET"})})]}),L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"ANTHROPIC API KEY"}),L.jsx("input",{type:"password",value:f,onChange:k=>p(k.target.value),placeholder:"sk-ant-...",style:{width:"100%",background:"#000",border:"1px solid #1a3a5c",borderRadius:2,color:"#c0dff0",fontFamily:"'Share Tech Mono', monospace",fontSize:11,padding:"6px 8px",outline:"none"}})]}),L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"MODEL"}),L.jsx("input",{type:"text",value:g,onChange:k=>v(k.target.value),style:{width:"100%",background:"#000",border:"1px solid #1a3a5c",borderRadius:2,color:"#c0dff0",fontFamily:"'Share Tech Mono', monospace",fontSize:11,padding:"6px 8px",outline:"none"}})]}),L.jsx("button",{onClick:()=>r(f,g),style:{padding:"8px 20px",background:"transparent",border:"1px solid #00d4ff55",color:"#00d4ff",fontFamily:"'Orbitron', sans-serif",fontSize:10,fontWeight:700,letterSpacing:2,cursor:"pointer",borderRadius:2,textTransform:"uppercase",textShadow:"0 0 6px #00d4ff44",marginTop:8},children:"SAVE"})]})}function Ey({viewState:l}){const[o,r]=Se.useState(!1),i=(l==null?void 0:l.trace_node_roles)&&Object.keys(l.trace_node_roles).length>0||(l==null?void 0:l.trace_edge_roles)&&Object.keys(l.trace_edge_roles).length>0,s=(f,p,g=14)=>{const v=g/2,k=(Nd[f]||Nd.function)(v);return L.jsx("svg",{width:g+2,height:g+2,style:{flexShrink:0,verticalAlign:"middle"},children:L.jsx("g",{transform:`translate(${v+1},${v+1})`,children:L.jsx("path",{d:k,fill:p,stroke:p,strokeWidth:"0.5",style:{filter:`drop-shadow(0 0 3px ${p})`}})})})},u=(f,p,g=1.5)=>L.jsx("svg",{width:30,height:6,style:{flexShrink:0,verticalAlign:"middle"},children:L.jsx("line",{x1:"0",y1:"3",x2:"30",y2:"3",stroke:f,strokeWidth:Math.max(g,1.5),strokeDasharray:p||void 0,style:{filter:`drop-shadow(0 0 2px ${f})`}})}),d=f=>L.jsx("svg",{width:10,height:10,style:{flexShrink:0,verticalAlign:"middle"},children:L.jsx("circle",{cx:"5",cy:"5",r:"4",fill:f,style:{filter:`drop-shadow(0 0 4px ${f})`}})});return o?L.jsx("div",{className:"legend-bar collapsed",onClick:()=>r(!1),children:L.jsx("span",{style:{fontFamily:"'Orbitron', sans-serif",fontSize:9,letterSpacing:2,color:"var(--text-muted)"},children:"▲ LEGEND"})}):L.jsxs("div",{className:"legend-bar",style:{position:"relative"},children:[L.jsx("button",{className:"legend-collapse-btn",onClick:()=>r(!0),children:"▼"}),L.jsxs("div",{className:"legend-group",children:[L.jsx("div",{className:"legend-group-title",children:"SYMBOLS"}),Object.entries(Rl).map(([f,p])=>L.jsxs("div",{className:"legend-row",children:[s(f,p)," ",L.jsx("span",{style:{color:p},children:f})]},f))]}),L.jsxs("div",{className:"legend-group",children:[L.jsx("div",{className:"legend-group-title",children:"RELATIONSHIPS"}),Object.entries(Nr).filter(([f])=>f!=="contains"&&f!=="proposed").map(([f,p])=>L.jsxs("div",{className:"legend-row",children:[u(p,vm[f],ym[f])," ",L.jsx("span",{style:{color:p},children:f})]},f))]}),i&&L.jsxs(L.Fragment,{children:[L.jsxs("div",{className:"legend-group",children:[L.jsx("div",{className:"legend-group-title",children:"TRACE ROLES"}),Object.entries(Di).map(([f,p])=>L.jsxs("div",{className:"legend-row",children:[d(p)," ",L.jsx("span",{style:{color:p},children:f})]},`tr-${f}`))]}),L.jsxs("div",{className:"legend-group",children:[L.jsx("div",{className:"legend-group-title",children:"TRACE EDGES"}),Object.entries(hl).map(([f,p])=>L.jsxs("div",{className:"legend-row",children:[u(p,null,2.5)," ",L.jsx("span",{style:{color:p},children:f})]},`te-${f}`))]})]})]})}function _y({message:l,viewState:o}){const[r,i]=Se.useState(!1),[s,u]=Se.useState(0),[d,f]=Se.useState(.3),[p,g]=Se.useState(""),v=Se.useRef(null),y=Se.useRef(null),k=Ho[s],b=Se.useCallback(()=>{const F=Ho[s];if(!F.nowPlayingUrl){g(F.name+" /// STREAMING LIVE");return}fetch(F.nowPlayingUrl).then(V=>V.json()).then(V=>{var W;let M="";if(F.parser==="somafm"){const D=(W=V.songs)==null?void 0:W[0];D&&(M=`${D.artist} — ${D.title}`)}else if(F.parser==="plaza"){const D=V.song;D&&(M=`${D.artist} — ${D.title}`)}g(M||F.name)}).catch(()=>g(F.name))},[s]);Se.useEffect(()=>(r?(b(),y.current=setInterval(b,15e3)):g(""),()=>{y.current&&clearInterval(y.current)}),[r,b]);const B=Se.useCallback(()=>{var F;r?((F=v.current)==null||F.pause(),v.current.src="",v.current=null,i(!1),g("")):(v.current=new Audio(k.url),v.current.volume=d,v.current.crossOrigin="anonymous",v.current.play().catch(()=>{}),i(!0))},[r,k,d]),U=Se.useCallback(F=>{const V=r;v.current&&(v.current.pause(),v.current.src="",v.current=null,i(!1)),u(F),g(""),V&&setTimeout(()=>{const M=Ho[F];v.current=new Audio(M.url),v.current.volume=d,v.current.crossOrigin="anonymous",v.current.play().catch(()=>{}),i(!0)},100)},[d,r]);return Se.useEffect(()=>{v.current&&(v.current.volume=d)},[d]),L.jsxs("div",{className:"status-bar",children:[L.jsx("span",{className:"status-dot"}),L.jsx("span",{className:"status-msg",children:l}),o&&L.jsxs("span",{style:{color:"#2a4a6a"},children:["ZOOM:",o.zoom_level.toUpperCase()," // VIEW:",o.visible_node_ids.length||"ALL"]}),L.jsxs("div",{className:"radio-container",children:[L.jsx("select",{className:"radio-station-select",value:s,onChange:F=>U(Number(F.target.value)),children:Ho.map((F,V)=>L.jsx("option",{value:V,children:F.name},F.id))}),L.jsx("button",{className:`radio-play-btn ${r?"playing":""}`,onClick:B,children:r?"■":"▶"}),L.jsx("input",{type:"range",className:"radio-volume",min:0,max:1,step:.05,value:d,onChange:F=>f(Number(F.target.value))}),p&&L.jsx("div",{className:"radio-nowplaying",children:L.jsx("span",{className:"radio-nowplaying-text",children:p})})]})]})}ig.createRoot(document.getElementById("root")).render(L.jsx(qo.StrictMode,{children:L.jsx(py,{})}));
512
+ `,Y.insertBefore(q,Y.firstChild);const me=q.getContext("2d");return me.imageSmoothingEnabled=!0,[q,me]},[ce,Te]=C("sigma-bloom-nodes",10,u),[H,T]=C("sigma-bloom-edges",6,d);g.current=ce,v.current=H;const w=.5,te=.5,ee=()=>{if(!g.current||!oe)return;const E=Math.ceil(oe.width*w),_=Math.ceil(oe.height*w);if((ce.width!==E||ce.height!==_)&&(ce.width=E,ce.height=_),Te.clearRect(0,0,E,_),Te.drawImage(oe,0,0,E,_),K){const j=Math.ceil(K.width*te),q=Math.ceil(K.height*te);(H.width!==j||H.height!==q)&&(H.width=j,H.height=q),T.clearRect(0,0,j,q),T.drawImage(K,0,0,j,q)}};I.on("afterRender",ee),ee()}return I.on("clickNode",C=>{i(C.node)}),I.on("doubleClickNode",C=>{s(C.node)}),I.on("clickStage",()=>{i("")}),()=>{var C,ce;(C=g.current)==null||C.remove(),(ce=v.current)==null||ce.remove(),g.current=null,v.current=null,I.kill(),p.current=null}},[l,U]),Se.useEffect(()=>{g.current&&(g.current.style.opacity=String(u)),v.current&&(v.current.style.opacity=String(d))},[u,d]),Se.useEffect(()=>{var G;(G=p.current)==null||G.refresh()},[r,o]);const F=Se.useRef("");Se.useEffect(()=>{const G=p.current;if(!G)return;const I=(o==null?void 0:o.highlighted_node_ids)??[],Y=I.slice().sort().join(",");if(Y===F.current||I.length===0){I.length===0&&F.current!==""&&(F.current="",G.getCamera().animate({x:.5,y:.5,ratio:1},{duration:400}));return}F.current=Y;const K=[];for(const xe of I)if(l.hasNode(xe)){const he=l.getNodeAttributes(xe);typeof he.x=="number"&&typeof he.y=="number"&&K.push({x:he.x,y:he.y})}if(K.length===0)return;let oe=1/0,De=-1/0,le=1/0,C=-1/0;for(const xe of K)xe.x<oe&&(oe=xe.x),xe.x>De&&(De=xe.x),xe.y<le&&(le=xe.y),xe.y>C&&(C=xe.y);const ce=(oe+De)/2,Te=(le+C)/2,H=G.getCamera(),T=G.getDimensions();if(K.length===1){const xe=G.graphToViewport({x:ce,y:Te}),he=G.viewportToFramedGraph(xe);H.animate({x:he.x,y:he.y,ratio:Math.min(H.ratio,.3)},{duration:400});return}const w=G.graphToViewport({x:oe,y:le}),te=G.graphToViewport({x:De,y:C}),ee=Math.abs(te.x-w.x),E=Math.abs(te.y-w.y),_=1.6,j=ee>0?T.width/(ee*_):1,q=E>0?T.height/(E*_):1,me=Math.min(j,q),Re=Math.max(.02,Math.min(H.ratio/me,1.5)),fe=G.graphToViewport({x:ce,y:Te}),se=G.viewportToFramedGraph(fe);H.animate({x:se.x,y:se.y,ratio:Re},{duration:500})},[o==null?void 0:o.highlighted_node_ids,l]);const V=o==null?void 0:o.context,M=V&&(V.what||V.why||V.where),[W,D]=qo.useState(null);qo.useEffect(()=>{D(null)},[V==null?void 0:V.what]);const $=qo.useMemo(()=>{const G=Math.floor(Math.random()*Zo.length);return Zo[G]},[]);return L.jsxs("div",{className:"graph-container",children:[L.jsx("div",{ref:f,className:"sigma-container",style:{width:"100%",flex:"1 1 0",minHeight:0,position:"relative"}}),U===0&&L.jsxs("div",{className:"empty-state",style:{position:"absolute",inset:0,zIndex:5},children:[L.jsx("div",{className:"gosling-quote",style:{whiteSpace:"pre-line"},children:$[0]}),L.jsx("div",{className:"gosling-sub",children:$[1]}),L.jsx("div",{className:"gosling-sub",style:{marginTop:20,color:"#2a4a6a"},children:"ESTABLISHING UPLINK..."})]}),M&&W!==V.what&&L.jsxs("div",{className:"context-banner",children:[L.jsx("button",{className:"cb-dismiss",onClick:()=>D(V.what),children:"×"}),V.what&&L.jsxs("div",{className:"cb-row",children:[L.jsx("span",{className:"cb-label",children:"WHAT"}),L.jsx("span",{className:"cb-text",children:V.what})]}),V.why&&L.jsxs("div",{className:"cb-row",children:[L.jsx("span",{className:"cb-label",children:"WHY"}),L.jsx("span",{className:"cb-text",children:V.why})]}),V.where&&L.jsxs("div",{className:"cb-row",children:[L.jsx("span",{className:"cb-label",children:"WHERE"}),L.jsx("span",{className:"cb-text",children:V.where})]}),V.source&&L.jsxs("div",{className:"cb-source",children:["VIA ",V.source.toUpperCase()]})]}),L.jsx("div",{className:"interlinked-watermark",children:"INTERLINKED"})]})}const it=wm();function py(){var Qe,Ee,ne,N;const[,l]=Se.useState(0),o=Se.useCallback(()=>l(J=>J+1),[]),[r,i]=Se.useState(null),[s,u]=Se.useState(null),[d,f]=Se.useState("ESTABLISHING UPLINK..."),[p,g]=Se.useState([]),[v,y]=Se.useState(-1),[k,b]=Se.useState("inspect"),[B,U]=Se.useState([]),[F,V]=Se.useState(!1),[M,W]=Se.useState(!1),[D,$]=Se.useState("claude-sonnet-4-20250514"),[G,I]=Se.useState(!0),[Y,K]=Se.useState(!0),[oe,De]=Se.useState(.5),[le,C]=Se.useState(.5),ce=Se.useRef(null),Te=Se.useRef(null),H=Se.useRef(null);Se.useEffect(()=>(fetch("/api/stats").then(de=>de.json()).then(i).catch(()=>{}),fetch("/api/settings").then(de=>de.json()).then(de=>{W(de.has_api_key),$(de.model)}).catch(()=>{}),_m({onSnapshot:de=>{Pd(it,de),u(it.selectedNodeId),o(),fetch("/api/stats").then(ie=>ie.json()).then(i).catch(()=>{})},onDelta:de=>{Em(it,de),u(it.selectedNodeId),o()},onStatus:de=>f(de)})),[o]),Se.useEffect(()=>{H.current&&(H.current.scrollTop=H.current.scrollHeight)},[B]);const T=Se.useCallback(()=>{fetch("/api/snapshot").then(J=>J.json()).then(J=>{Pd(it,J),u(it.selectedNodeId),o()}),fetch("/api/stats").then(J=>J.json()).then(i).catch(()=>{})},[o]),w=Se.useCallback(J=>{if(!J.trim())return;g(O=>[J,...O].slice(0,50)),y(-1);const de=J.includes("view.")||J.includes("graph.")||J.includes("=")||J.includes("(");fetch(de?"/api/command":"/api/nl",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(de?{command:J}:{text:J})}).then(O=>O.json()).then(O=>{if(O.error)f(`ERR: ${O.error}`.toUpperCase());else{const Ue=O.result||JSON.stringify(O).slice(0,200);f(typeof Ue=="string"?Ue.toUpperCase():String(Ue).toUpperCase()),T()}})},[T]),te=Se.useCallback(J=>{J.trim()&&(U(de=>[...de,{role:"user",content:J}]),V(!0),fetch("/api/chat",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:J})}).then(de=>de.json()).then(de=>{if(V(!1),de.error==="no_api_key"){U(ie=>[...ie,{role:"system",content:"No API key configured. Go to Settings tab to add your Anthropic API key, or use the command bar with Python commands."}]);return}U(ie=>[...ie,{role:"assistant",content:de.explanation||"Done.",commands:de.commands_run}]),T()}).catch(de=>{V(!1),U(ie=>[...ie,{role:"system",content:`Error: ${de.message}`}])}))},[T]),ee=Se.useCallback(J=>{fetch("/api/zoom",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({level:J})}).then(de=>de.json()).then(de=>{var ie;f(((ie=de.result)==null?void 0:ie.toUpperCase())||""),T()})},[T]),E=Se.useCallback(J=>{const de=J||null;it.selectedNodeId=de,u(de),J&&b("inspect")},[]),_=Se.useCallback(J=>{fetch("/api/focus",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({node_id:J,depth:2})}).then(de=>de.json()).then(de=>{var ie;f(((ie=de.result)==null?void 0:ie.toUpperCase())||""),T()})},[T]),j=Se.useCallback(J=>{J.key==="Enter"?(w(J.target.value),J.target.value=""):J.key==="ArrowUp"?(J.preventDefault(),y(de=>{const ie=Math.min(de+1,p.length-1);return ce.current&&p[ie]&&(ce.current.value=p[ie]),ie})):J.key==="ArrowDown"&&(J.preventDefault(),y(de=>{const ie=Math.max(de-1,-1);return ce.current&&(ce.current.value=ie>=0?p[ie]:""),ie}))},[w,p]),q=Se.useCallback(J=>{J.key==="Enter"&&!J.shiftKey&&(J.preventDefault(),te(J.target.value),J.target.value="")},[te]),me=Se.useCallback((J,de)=>{fetch("/api/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({api_key:J,model:de})}).then(ie=>ie.json()).then(ie=>{W(ie.has_api_key),$(ie.model),f(ie.has_api_key?"API KEY CONFIGURED":"API KEY CLEARED")})},[]),Re=((Qe=it.viewState)==null?void 0:Qe.zoom_level)||"module",fe=it.viewState,se=!!((Ee=fe==null?void 0:fe.highlighted_node_ids)!=null&&Ee.length||(ne=fe==null?void 0:fe.visible_node_ids)!=null&&ne.length||fe!=null&&fe.filter_expression||fe!=null&&fe.trace_node_roles&&Object.keys(fe.trace_node_roles).length>0),xe=((N=it.viewState)==null?void 0:N.visible_edge_types)||["calls","imports","inherits","reads","writes","contains","returns"],he=Se.useCallback(J=>{const de=new Set(xe);de.has(J)?de.delete(J):de.add(J),fetch("/api/edge_types",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({edge_types:[...de]})}).then(()=>T())},[xe,T]),Ae=Se.useMemo(()=>!s||!it.graph.hasNode(s)?null:it.graph.getNodeAttributes(s),[s,it.graph]),Ie=`${G?"260px":"0px"} 1fr ${Y?"320px":"0px"}`;return L.jsxs("div",{className:"app-container",style:{gridTemplateColumns:Ie},children:[L.jsx(gy,{stats:r,currentZoom:Re,onZoom:ee,activeEdgeTypes:xe,onEdgeToggle:he}),!G&&L.jsx("button",{className:"panel-collapse-btn",style:{top:70,left:6},onClick:()=>I(!0),children:"▶"}),G&&L.jsx("button",{className:"panel-collapse-btn",style:{top:70,left:260},onClick:()=>I(!1),children:"◀"}),G&&L.jsx(my,{graph:it.graph,selectedNode:s,onNodeClick:E}),L.jsxs("div",{style:{position:"relative",display:"flex",flexDirection:"column",overflow:"hidden",minHeight:0},children:[L.jsx(hy,{graph:it.graph,viewState:it.viewState,selectedNode:s,onNodeClick:E,onNodeDoubleClick:_,nodeGlow:oe,edgeGlow:le}),L.jsx(Ey,{viewState:it.viewState})]}),!Y&&L.jsx("button",{className:"panel-collapse-btn",style:{top:70,right:6},onClick:()=>K(!0),children:"◀"}),Y&&L.jsx("button",{className:"panel-collapse-btn",style:{top:70,right:320},onClick:()=>K(!1),children:"▶"}),Y&&L.jsxs("div",{className:"sidebar-right",children:[L.jsx("div",{className:"tab-bar",children:["inspect","chat","settings"].map(J=>L.jsx("button",{className:`tab-btn ${k===J?"active":""}`,onClick:()=>b(J),children:J},J))}),k==="inspect"&&L.jsx(vy,{nodeAttrs:Ae,graph:it.graph,selectedNode:s,onNodeClick:E}),k==="chat"&&L.jsx(yy,{messages:B,loading:F,onKeyDown:q,inputRef:Te,scrollRef:H}),k==="settings"&&L.jsx(wy,{hasApiKey:M,llmModel:D,onSave:me,nodeGlow:oe,edgeGlow:le,onNodeGlowChange:De,onEdgeGlowChange:C}),L.jsxs("div",{className:"command-bar",children:[L.jsxs("div",{className:"command-input-wrapper",children:[L.jsx("span",{className:"command-prefix",children:">_"}),L.jsx("input",{ref:ce,className:"command-input",placeholder:"view.isolate('analyzer') or natural language...",onKeyDown:j})]}),se&&L.jsx("button",{className:"clear-filters-btn",onClick:()=>w("view.reset_filter()"),title:"Clear all filters and highlights",children:"✕ CLEAR FILTERS"})]})]}),L.jsx(_y,{message:d,viewState:it.viewState})]})}function gy({stats:l,currentZoom:o,onZoom:r,activeEdgeTypes:i,onEdgeToggle:s}){const u=new Set(i),d=[{type:"calls",color:"#88bbdd"},{type:"imports",color:"#667799"},{type:"inherits",color:"#bb77ee"},{type:"reads",color:"#33ccaa"},{type:"writes",color:"#ff5566"},{type:"returns",color:"#eebb44"},{type:"contains",color:"#556677"}];return L.jsxs("div",{className:"header",children:[L.jsxs("div",{children:[L.jsx("div",{className:"logo",children:"INTERLINKED"}),L.jsx("div",{className:"logo-sub",children:"TOPOLOGY EXPLORER"})]}),L.jsx("span",{className:"separator"}),L.jsx("div",{className:"stats",children:l&&L.jsxs(L.Fragment,{children:[L.jsxs("span",{children:["MOD",L.jsx("span",{className:"stat-value",children:l.modules})]}),L.jsxs("span",{children:["CLS",L.jsx("span",{className:"stat-value",children:l.classes})]}),L.jsxs("span",{children:["FN",L.jsx("span",{className:"stat-value",children:l.functions+l.methods})]}),L.jsxs("span",{children:["VAR",L.jsx("span",{className:"stat-value",children:l.variables})]}),L.jsxs("span",{children:["DEAD",L.jsx("span",{className:"stat-value stat-dead",children:l.dead_nodes})]}),L.jsxs("span",{children:["EDGE",L.jsx("span",{className:"stat-value",children:l.total_edges})]})]})}),L.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:4,marginLeft:"auto"},children:[L.jsx("div",{className:"zoom-controls",children:["all","module","class","function","variable"].map(f=>L.jsx("button",{className:`zoom-btn ${o===f?"active":""}`,onClick:()=>r(f),children:f},f))}),L.jsx("div",{style:{display:"flex",gap:3,justifyContent:"flex-end",alignItems:"center"},children:d.map(({type:f,color:p})=>L.jsx("button",{className:`edge-chip ${u.has(f)?"active":""}`,style:u.has(f)?{borderColor:p+"88",color:p}:{},onClick:()=>s(f),children:f},f))})]})]})}function my({graph:l,selectedNode:o,onNodeClick:r}){const i=Se.useMemo(()=>{const s={};return l.forEachNode((u,d)=>{const f=d.symbolType;s[f]||(s[f]=[]),s[f].push({id:u,name:d.label,symbolType:f,isDead:d.isDead,isProposed:d.isProposed})}),s},[l,l.order]);return L.jsx("div",{className:"sidebar-left",children:["module","class","function","method","variable"].map(s=>i[s]&&i[s].length>0&&L.jsxs("div",{className:"sidebar-section",children:[L.jsxs("div",{className:"sidebar-section-title",children:[s,"s (",i[s].length,")"]}),i[s].slice(0,100).map(u=>L.jsxs("div",{className:`node-list-item ${o===u.id?"active":""}`,onClick:()=>r(u.id),title:u.id,children:[L.jsx("span",{className:`node-badge ${u.symbolType}`,children:u.symbolType.slice(0,3)}),L.jsx("span",{className:"node-name",children:u.name}),u.isDead&&L.jsx("span",{className:"dead-indicator"}),u.isProposed&&L.jsx("span",{className:"proposed-indicator"})]},u.id))]},s))})}function vy({nodeAttrs:l,graph:o,selectedNode:r,onNodeClick:i}){const s=Se.useMemo(()=>Zo[Math.floor(Math.random()*Zo.length)],[]);if(!l||!r)return L.jsx("div",{className:"detail-panel",children:L.jsxs("div",{className:"empty-state",children:[L.jsx("div",{className:"gosling-quote",style:{whiteSpace:"pre-line"},children:s[0]}),L.jsx("div",{className:"gosling-sub",children:s[1]}),L.jsx("div",{className:"gosling-sub",style:{marginTop:12,color:"#2a4a6a",fontSize:9},children:"SELECT A NODE TO INSPECT"})]})});const u=[],d=[];return o.hasNode(r)&&(o.forEachInEdge(r,(f,p,g)=>{u.push({id:g,label:o.getNodeAttribute(g,"label")||g,edgeType:p.edgeType})}),o.forEachOutEdge(r,(f,p,g,v)=>{d.push({id:v,label:o.getNodeAttribute(v,"label")||v,edgeType:p.edgeType})})),L.jsxs("div",{className:"detail-panel",children:[L.jsx("div",{className:"detail-title",children:l.label}),L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"QUALIFIED NAME"}),L.jsx("div",{className:"detail-value",children:L.jsx("code",{children:l.qualifiedName})})]}),L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"TYPE"}),L.jsx("div",{className:"detail-value",children:String(l.symbolType)})]}),!!l.filePath&&L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"FILE"}),L.jsxs("div",{className:"detail-value",children:[String(l.filePath),":",String(l.lineStart)]})]}),!!l.signature&&L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"SIGNATURE"}),L.jsx("div",{className:"detail-value",children:L.jsx("code",{children:String(l.signature)})})]}),!!l.docstring&&L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"DOCSTRING"}),L.jsx("div",{className:"detail-value",style:{whiteSpace:"pre-wrap",fontSize:10},children:String(l.docstring)})]}),u.length>0&&L.jsxs("div",{className:"detail-field",children:[L.jsxs("div",{className:"detail-label",children:["INCOMING (",u.length,")"]}),L.jsx("ul",{style:{listStyle:"none",marginTop:4},children:u.slice(0,30).map((f,p)=>L.jsxs("li",{style:{fontSize:10,padding:"3px 0",color:"#5a8aaa",cursor:"pointer"},onClick:()=>i(f.id),children:[L.jsx("span",{style:{fontFamily:"'Orbitron', sans-serif",fontSize:7,padding:"1px 5px",borderRadius:2,marginRight:6,fontWeight:600,letterSpacing:1,border:`1px solid ${Nr[f.edgeType]||"#334"}`,color:Nr[f.edgeType]||"#556"},children:f.edgeType}),f.label]},p))})]}),d.length>0&&L.jsxs("div",{className:"detail-field",children:[L.jsxs("div",{className:"detail-label",children:["OUTGOING (",d.length,")"]}),L.jsx("ul",{style:{listStyle:"none",marginTop:4},children:d.slice(0,30).map((f,p)=>L.jsxs("li",{style:{fontSize:10,padding:"3px 0",color:"#5a8aaa",cursor:"pointer"},onClick:()=>i(f.id),children:[L.jsx("span",{style:{fontFamily:"'Orbitron', sans-serif",fontSize:7,padding:"1px 5px",borderRadius:2,marginRight:6,fontWeight:600,letterSpacing:1,border:`1px solid ${Nr[f.edgeType]||"#334"}`,color:Nr[f.edgeType]||"#556"},children:f.edgeType}),f.label]},p))})]})]})}function yy({messages:l,loading:o,onKeyDown:r,inputRef:i,scrollRef:s}){return L.jsxs("div",{style:{display:"flex",flexDirection:"column",flex:1,overflow:"hidden"},children:[L.jsxs("div",{className:"chat-messages",ref:s,children:[l.map((u,d)=>L.jsxs("div",{className:`chat-msg ${u.role}`,children:[u.content,u.commands&&u.commands.length>0&&L.jsx("div",{style:{marginTop:6,fontSize:9,color:"#4a7a9a"},children:u.commands.map((f,p)=>L.jsxs("div",{style:{fontFamily:"'Share Tech Mono', monospace"},children:["→ ",f]},p))})]},d)),o&&L.jsx("div",{className:"chat-msg system",style:{animation:"pulse-glow 1s infinite"},children:"PROCESSING..."})]}),L.jsx("div",{className:"chat-input-area",children:L.jsx("textarea",{ref:i,className:"chat-input",rows:2,placeholder:"Ask about the codebase...",onKeyDown:r})})]})}function wy({hasApiKey:l,llmModel:o,onSave:r,nodeGlow:i,edgeGlow:s,onNodeGlowChange:u,onEdgeGlowChange:d}){const[f,p]=Se.useState(""),[g,v]=Se.useState(o),y={width:"100%",accentColor:"#00d4ff",cursor:"pointer"};return L.jsxs("div",{className:"detail-panel",children:[L.jsx("div",{className:"detail-title",children:"SETTINGS"}),L.jsxs("div",{className:"detail-field",children:[L.jsxs("div",{className:"detail-label",children:["GLOBAL GLOW ",L.jsxs("span",{style:{color:"#00d4ff"},children:[Math.round((i+s)/2*100),"%"]})]}),L.jsx("input",{type:"range",min:0,max:1,step:.05,value:(i+s)/2,onChange:k=>{const b=Number(k.target.value);u(b),d(b)},style:y})]}),L.jsxs("div",{className:"detail-field",children:[L.jsxs("div",{className:"detail-label",children:["NODE GLOW ",L.jsxs("span",{style:{color:"#0099dd"},children:[Math.round(i*100),"%"]})]}),L.jsx("input",{type:"range",min:0,max:1,step:.05,value:i,onChange:k=>u(Number(k.target.value)),style:{...y,accentColor:"#0099dd"}})]}),L.jsxs("div",{className:"detail-field",children:[L.jsxs("div",{className:"detail-label",children:["EDGE GLOW ",L.jsxs("span",{style:{color:"#88bbdd"},children:[Math.round(s*100),"%"]})]}),L.jsx("input",{type:"range",min:0,max:1,step:.05,value:s,onChange:k=>d(Number(k.target.value)),style:{...y,accentColor:"#88bbdd"}})]}),L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"API KEY STATUS"}),L.jsx("div",{className:"detail-value",children:l?L.jsx("span",{style:{color:"#39ff14",textShadow:"0 0 6px #39ff1444"},children:"CONFIGURED"}):L.jsx("span",{style:{color:"#ff2975",textShadow:"0 0 6px #ff297544"},children:"NOT SET"})})]}),L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"ANTHROPIC API KEY"}),L.jsx("input",{type:"password",value:f,onChange:k=>p(k.target.value),placeholder:"sk-ant-...",style:{width:"100%",background:"#000",border:"1px solid #1a3a5c",borderRadius:2,color:"#c0dff0",fontFamily:"'Share Tech Mono', monospace",fontSize:11,padding:"6px 8px",outline:"none"}})]}),L.jsxs("div",{className:"detail-field",children:[L.jsx("div",{className:"detail-label",children:"MODEL"}),L.jsx("input",{type:"text",value:g,onChange:k=>v(k.target.value),style:{width:"100%",background:"#000",border:"1px solid #1a3a5c",borderRadius:2,color:"#c0dff0",fontFamily:"'Share Tech Mono', monospace",fontSize:11,padding:"6px 8px",outline:"none"}})]}),L.jsx("button",{onClick:()=>r(f,g),style:{padding:"8px 20px",background:"transparent",border:"1px solid #00d4ff55",color:"#00d4ff",fontFamily:"'Orbitron', sans-serif",fontSize:10,fontWeight:700,letterSpacing:2,cursor:"pointer",borderRadius:2,textTransform:"uppercase",textShadow:"0 0 6px #00d4ff44",marginTop:8},children:"SAVE"})]})}function Ey({viewState:l}){const[o,r]=Se.useState(!1),i=(l==null?void 0:l.trace_node_roles)&&Object.keys(l.trace_node_roles).length>0||(l==null?void 0:l.trace_edge_roles)&&Object.keys(l.trace_edge_roles).length>0,s=(f,p,g=14)=>{const v=g/2,k=(Nd[f]||Nd.function)(v);return L.jsx("svg",{width:g+2,height:g+2,style:{flexShrink:0,verticalAlign:"middle"},children:L.jsx("g",{transform:`translate(${v+1},${v+1})`,children:L.jsx("path",{d:k,fill:p,stroke:p,strokeWidth:"0.5",style:{filter:`drop-shadow(0 0 3px ${p})`}})})})},u=(f,p,g=1.5)=>L.jsx("svg",{width:30,height:6,style:{flexShrink:0,verticalAlign:"middle"},children:L.jsx("line",{x1:"0",y1:"3",x2:"30",y2:"3",stroke:f,strokeWidth:Math.max(g,1.5),strokeDasharray:p||void 0,style:{filter:`drop-shadow(0 0 2px ${f})`}})}),d=f=>L.jsx("svg",{width:10,height:10,style:{flexShrink:0,verticalAlign:"middle"},children:L.jsx("circle",{cx:"5",cy:"5",r:"4",fill:f,style:{filter:`drop-shadow(0 0 4px ${f})`}})});return o?L.jsx("div",{className:"legend-bar collapsed",onClick:()=>r(!1),children:L.jsx("span",{style:{fontFamily:"'Orbitron', sans-serif",fontSize:9,letterSpacing:2,color:"var(--text-muted)"},children:"▲ LEGEND"})}):L.jsxs("div",{className:"legend-bar",style:{position:"relative"},children:[L.jsx("button",{className:"legend-collapse-btn",onClick:()=>r(!0),children:"▼"}),L.jsxs("div",{className:"legend-group",children:[L.jsx("div",{className:"legend-group-title",children:"SYMBOLS"}),Object.entries(Rl).map(([f,p])=>L.jsxs("div",{className:"legend-row",children:[s(f,p)," ",L.jsx("span",{style:{color:p},children:f})]},f))]}),L.jsxs("div",{className:"legend-group",children:[L.jsx("div",{className:"legend-group-title",children:"RELATIONSHIPS"}),Object.entries(Nr).filter(([f])=>f!=="contains"&&f!=="proposed").map(([f,p])=>L.jsxs("div",{className:"legend-row",children:[u(p,vm[f],ym[f])," ",L.jsx("span",{style:{color:p},children:f})]},f))]}),i&&L.jsxs(L.Fragment,{children:[L.jsxs("div",{className:"legend-group",children:[L.jsx("div",{className:"legend-group-title",children:"TRACE ROLES"}),Object.entries(Di).map(([f,p])=>L.jsxs("div",{className:"legend-row",children:[d(p)," ",L.jsx("span",{style:{color:p},children:f})]},`tr-${f}`))]}),L.jsxs("div",{className:"legend-group",children:[L.jsx("div",{className:"legend-group-title",children:"TRACE EDGES"}),Object.entries(hl).map(([f,p])=>L.jsxs("div",{className:"legend-row",children:[u(p,null,2.5)," ",L.jsx("span",{style:{color:p},children:f})]},`te-${f}`))]})]})]})}function _y({message:l,viewState:o}){const[r,i]=Se.useState(!1),[s,u]=Se.useState(0),[d,f]=Se.useState(.3),[p,g]=Se.useState(""),v=Se.useRef(null),y=Se.useRef(null),k=Ho[s],b=Se.useCallback(()=>{const F=Ho[s];if(!F.nowPlayingUrl){g(F.name+" /// STREAMING LIVE");return}fetch(F.nowPlayingUrl).then(V=>V.json()).then(V=>{var W;let M="";if(F.parser==="somafm"){const D=(W=V.songs)==null?void 0:W[0];D&&(M=`${D.artist} — ${D.title}`)}else if(F.parser==="plaza"){const D=V.song;D&&(M=`${D.artist} — ${D.title}`)}g(M||F.name)}).catch(()=>g(F.name))},[s]);Se.useEffect(()=>(r?(b(),y.current=setInterval(b,15e3)):g(""),()=>{y.current&&clearInterval(y.current)}),[r,b]);const B=Se.useCallback(()=>{var F;r?((F=v.current)==null||F.pause(),v.current.src="",v.current=null,i(!1),g("")):(v.current=new Audio(k.url),v.current.volume=d,v.current.crossOrigin="anonymous",v.current.play().catch(()=>{}),i(!0))},[r,k,d]),U=Se.useCallback(F=>{const V=r;v.current&&(v.current.pause(),v.current.src="",v.current=null,i(!1)),u(F),g(""),V&&setTimeout(()=>{const M=Ho[F];v.current=new Audio(M.url),v.current.volume=d,v.current.crossOrigin="anonymous",v.current.play().catch(()=>{}),i(!0)},100)},[d,r]);return Se.useEffect(()=>{v.current&&(v.current.volume=d)},[d]),L.jsxs("div",{className:"status-bar",style:{display:"flex",alignItems:"center"},children:[L.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flex:"1 1 0",minWidth:0},children:[L.jsx("span",{className:"status-dot"}),L.jsx("span",{className:"status-msg",children:l})]}),L.jsxs("div",{className:"radio-container",style:{flex:"0 0 auto"},children:[L.jsx("select",{className:"radio-station-select",value:s,onChange:F=>U(Number(F.target.value)),children:Ho.map((F,V)=>L.jsx("option",{value:V,children:F.name},F.id))}),L.jsx("button",{className:`radio-play-btn ${r?"playing":""}`,onClick:B,children:r?"■":"▶"}),L.jsx("input",{type:"range",className:"radio-volume",min:0,max:1,step:.05,value:d,onChange:F=>f(Number(F.target.value))}),p&&L.jsx("div",{className:"radio-nowplaying",children:L.jsx("span",{className:"radio-nowplaying-text",children:p})})]}),L.jsx("div",{style:{flex:"1 1 0",display:"flex",justifyContent:"flex-end",minWidth:0},children:o&&L.jsxs("span",{style:{color:"#2a4a6a",whiteSpace:"nowrap"},children:["ZOOM:",o.zoom_level.toUpperCase()," // VIEW:",o.visible_node_ids.length||"ALL"]})})]})}ig.createRoot(document.getElementById("root")).render(L.jsx(qo.StrictMode,{children:L.jsx(py,{})}));
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>INTERLINKED</title>
7
7
  <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>⬡</text></svg>" />
8
- <script type="module" crossorigin src="/assets/index-CX3ZrzHg.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-Dh01aXoE.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-CyhrxsQU.css">
10
10
  </head>
11
11
  <body>
@@ -1049,17 +1049,14 @@ function StatusBar({ message, viewState }: { message: string; viewState: ViewSta
1049
1049
  }, [volume]);
1050
1050
 
1051
1051
  return (
1052
- <div className="status-bar">
1053
- <span className="status-dot" />
1054
- <span className="status-msg">{message}</span>
1055
- {viewState && (
1056
- <span style={{ color: '#2a4a6a' }}>
1057
- ZOOM:{viewState.zoom_level.toUpperCase()} // VIEW:{viewState.visible_node_ids.length || 'ALL'}
1058
- </span>
1059
- )}
1052
+ <div className="status-bar" style={{ display: 'flex', alignItems: 'center' }}>
1053
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, flex: '1 1 0', minWidth: 0 }}>
1054
+ <span className="status-dot" />
1055
+ <span className="status-msg">{message}</span>
1056
+ </div>
1060
1057
 
1061
- {/* Radio */}
1062
- <div className="radio-container">
1058
+ {/* Radio — centered */}
1059
+ <div className="radio-container" style={{ flex: '0 0 auto' }}>
1063
1060
  <select
1064
1061
  className="radio-station-select"
1065
1062
  value={stationIdx}
@@ -1089,6 +1086,14 @@ function StatusBar({ message, viewState }: { message: string; viewState: ViewSta
1089
1086
  </div>
1090
1087
  )}
1091
1088
  </div>
1089
+
1090
+ <div style={{ flex: '1 1 0', display: 'flex', justifyContent: 'flex-end', minWidth: 0 }}>
1091
+ {viewState && (
1092
+ <span style={{ color: '#2a4a6a', whiteSpace: 'nowrap' }}>
1093
+ ZOOM:{viewState.zoom_level.toUpperCase()} // VIEW:{viewState.visible_node_ids.length || 'ALL'}
1094
+ </span>
1095
+ )}
1096
+ </div>
1092
1097
  </div>
1093
1098
  );
1094
1099
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: interlinked-mapper
3
- Version: 0.3.3
3
+ Version: 0.3.5
4
4
  Summary: A Python program topology explorer — visualize the shape of your codebase
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/austerecryptid/interlinked
@@ -23,8 +23,8 @@ interlinked/visualizer/frontend/package.json
23
23
  interlinked/visualizer/frontend/tsconfig.json
24
24
  interlinked/visualizer/frontend/vite.config.ts
25
25
  interlinked/visualizer/frontend/dist/index.html
26
- interlinked/visualizer/frontend/dist/assets/index-CX3ZrzHg.js
27
26
  interlinked/visualizer/frontend/dist/assets/index-CyhrxsQU.css
27
+ interlinked/visualizer/frontend/dist/assets/index-Dh01aXoE.js
28
28
  interlinked/visualizer/frontend/src/App.tsx
29
29
  interlinked/visualizer/frontend/src/index.css
30
30
  interlinked/visualizer/frontend/src/main.tsx
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "interlinked-mapper"
7
- version = "0.3.3"
7
+ version = "0.3.5"
8
8
  description = "A Python program topology explorer — visualize the shape of your codebase"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}