1+ defmodule Zixir.ContextAggregator do
2+ @ moduledoc """
3+ Aggregates real-time context about workflows, databases, and system state
4+ for AI assistant consumption.
5+
6+ Provides a unified view of:
7+ - Active and recent workflows
8+ - Configured database connections and schemas
9+ - System metrics and performance data
10+ - Vector collection status
11+ - Recent logs and events
12+
13+ ## Usage
14+
15+ context = Zixir.ContextAggregator.build_full_context()
16+ # Returns structured map with all system context
17+
18+ """
19+
20+ alias Zixir.Cache
21+ require Logger
22+
23+ @ doc """
24+ Build comprehensive context for AI assistant.
25+ """
26+ @ spec build_full_context ( ) :: map ( )
27+ def build_full_context do
28+ % {
29+ workflows: get_workflows_context ( ) ,
30+ databases: get_databases_context ( ) ,
31+ system: get_system_metrics ( ) ,
32+ vectors: get_vector_context ( ) ,
33+ timestamp: DateTime . utc_now ( ) |> DateTime . to_iso8601 ( )
34+ }
35+ end
36+
37+ @ doc """
38+ Get comprehensive workflow context.
39+ """
40+ @ spec get_workflows_context ( ) :: map ( )
41+ def get_workflows_context do
42+ # Fetch from cache where workflows are stored
43+ workflows = fetch_all_workflows ( )
44+
45+ % {
46+ total: length ( workflows ) ,
47+ active: Enum . count ( workflows , & ( & 1 . status == "active" ) ) ,
48+ paused: Enum . count ( workflows , & ( & 1 . status == "paused" ) ) ,
49+ failed: Enum . count ( workflows , & ( & 1 . status == "failed" ) ) ,
50+ completed: Enum . count ( workflows , & ( & 1 . status == "completed" ) ) ,
51+ recent: get_recent_workflow_runs ( workflows , 5 ) ,
52+ list: workflows |> Enum . take ( 10 ) |> Enum . map ( & format_workflow / 1 )
53+ }
54+ end
55+
56+ @ doc """
57+ Get database connections and schema context.
58+ """
59+ @ spec get_databases_context ( ) :: map ( )
60+ def get_databases_context do
61+ connections = fetch_connections ( )
62+
63+ % {
64+ total: length ( connections ) ,
65+ connections: Enum . map ( connections , fn conn ->
66+ % {
67+ id: conn . id ,
68+ name: conn . name ,
69+ type: conn . type ,
70+ host: Map . get ( conn , :host , "localhost" ) ,
71+ status: Map . get ( conn , :status , "unknown" ) ,
72+ tables: fetch_table_list ( conn . id )
73+ }
74+ end )
75+ }
76+ end
77+
78+ defp fetch_connections do
79+ # Try to get connections from cache
80+ case Cache . get ( "connections:all" ) do
81+ { :ok , connections } when is_list ( connections ) -> connections
82+ _ -> fetch_sample_connections ( )
83+ end
84+ end
85+
86+ defp fetch_sample_connections do
87+ # Return sample connections for demo/development
88+ [
89+ % {
90+ id: "conn_001" ,
91+ name: "SQL Server Production" ,
92+ type: "sqlserver" ,
93+ host: "localhost" ,
94+ status: "connected"
95+ } ,
96+ % {
97+ id: "conn_002" ,
98+ name: "PostgreSQL Analytics" ,
99+ type: "postgresql" ,
100+ host: "localhost" ,
101+ status: "connected"
102+ } ,
103+ % {
104+ id: "conn_003" ,
105+ name: "MySQL Legacy" ,
106+ type: "mysql" ,
107+ host: "localhost" ,
108+ status: "disconnected"
109+ }
110+ ]
111+ end
112+
113+ @ doc """
114+ Get system metrics and performance data.
115+ """
116+ @ spec get_system_metrics ( ) :: map ( )
117+ def get_system_metrics do
118+ % {
119+ uptime_minutes: get_uptime ( ) ,
120+ memory_usage: get_memory_usage ( ) ,
121+ active_connections: get_active_connection_count ( ) ,
122+ queue_depth: get_queue_depth ( ) ,
123+ recent_errors: get_recent_errors ( 5 ) ,
124+ version: get_zixir_version ( )
125+ }
126+ end
127+
128+ @ doc """
129+ Get vector database context.
130+ """
131+ @ spec get_vector_context ( ) :: map ( )
132+ def get_vector_context do
133+ case Cache . get ( "vector:collections" ) do
134+ { :ok , collections } when is_list ( collections ) ->
135+ % {
136+ total_collections: length ( collections ) ,
137+ collections: Enum . map ( collections , fn coll ->
138+ % {
139+ name: coll . name ,
140+ dimensions: coll . dimensions || 1536 ,
141+ document_count: coll . document_count || 0 ,
142+ size_mb: coll . size_mb || 0
143+ }
144+ end )
145+ }
146+ _ ->
147+ % {
148+ total_collections: 0 ,
149+ collections: [ ]
150+ }
151+ end
152+ end
153+
154+ # Private functions
155+
156+ defp fetch_all_workflows do
157+ # Try to get workflows from cache
158+ case Cache . get ( "workflows:all" ) do
159+ { :ok , workflows } when is_list ( workflows ) -> workflows
160+ _ -> fetch_workflows_from_storage ( )
161+ end
162+ end
163+
164+ defp fetch_workflows_from_storage do
165+ # Fallback: return sample/demo workflows if cache is empty
166+ # In production, this would query the database
167+ [
168+ % {
169+ id: "wf_001" ,
170+ name: "order_processing" ,
171+ status: "active" ,
172+ last_run: DateTime . utc_now ( ) |> DateTime . add ( - 3600 , :second ) ,
173+ total_runs: 47 ,
174+ success_rate: 0.94
175+ } ,
176+ % {
177+ id: "wf_002" ,
178+ name: "data_sync" ,
179+ status: "paused" ,
180+ last_run: DateTime . utc_now ( ) |> DateTime . add ( - 86400 , :second ) ,
181+ total_runs: 12 ,
182+ success_rate: 1.0
183+ } ,
184+ % {
185+ id: "wf_003" ,
186+ name: "report_generation" ,
187+ status: "completed" ,
188+ last_run: DateTime . utc_now ( ) |> DateTime . add ( - 7200 , :second ) ,
189+ total_runs: 8 ,
190+ success_rate: 0.88
191+ }
192+ ]
193+ end
194+
195+ defp get_recent_workflow_runs ( workflows , limit ) do
196+ workflows
197+ |> Enum . sort_by ( & & 1 . last_run , { :desc , DateTime } )
198+ |> Enum . take ( limit )
199+ |> Enum . map ( fn wf ->
200+ % {
201+ id: wf . id ,
202+ name: wf . name ,
203+ status: wf . status ,
204+ time_ago: format_time_ago ( wf . last_run )
205+ }
206+ end )
207+ end
208+
209+ defp format_workflow ( wf ) do
210+ % {
211+ id: wf . id ,
212+ name: wf . name ,
213+ status: wf . status ,
214+ runs: wf . total_runs ,
215+ success_rate: Float . round ( wf . success_rate * 100 , 1 )
216+ }
217+ end
218+
219+ defp get_connection_status ( conn_id ) do
220+ case Cache . get ( "connection:#{ conn_id } :status" ) do
221+ { :ok , status } -> status
222+ _ -> "unknown"
223+ end
224+ end
225+
226+ defp fetch_table_list ( conn_id ) do
227+ case Cache . get ( "connection:#{ conn_id } :tables" ) do
228+ { :ok , tables } when is_list ( tables ) ->
229+ Enum . take ( tables , 20 )
230+ _ ->
231+ [ ]
232+ end
233+ end
234+
235+ defp get_uptime do
236+ # Get system uptime in minutes
237+ case :erlang . statistics ( :wall_clock ) do
238+ { ms , _ } -> div ( ms , 60000 )
239+ _ -> 0
240+ end
241+ end
242+
243+ defp get_memory_usage do
244+ # Get memory usage in MB
245+ case :erlang . memory ( :total ) do
246+ bytes -> div ( bytes , 1024 * 1024 )
247+ _ -> 0
248+ end
249+ end
250+
251+ defp get_active_connection_count do
252+ # Count active WebSocket/HTTP connections
253+ # This is a simplified version
254+ 3
255+ end
256+
257+ defp get_queue_depth do
258+ # Get job queue depth
259+ case Cache . get ( "queue:depth" ) do
260+ { :ok , depth } when is_integer ( depth ) -> depth
261+ _ -> 0
262+ end
263+ end
264+
265+ defp get_recent_errors ( limit ) do
266+ # Fetch recent errors from cache/logs
267+ case Cache . get ( "logs:errors:recent" ) do
268+ { :ok , errors } when is_list ( errors ) ->
269+ Enum . take ( errors , limit )
270+ _ ->
271+ [ ]
272+ end
273+ end
274+
275+ defp get_zixir_version do
276+ # Get version from application
277+ case Application . spec ( :zixir , :vsn ) do
278+ vsn when is_list ( vsn ) -> List . to_string ( vsn )
279+ _ -> "7.0.0"
280+ end
281+ end
282+
283+ defp format_time_ago ( datetime ) do
284+ now = DateTime . utc_now ( )
285+ diff = DateTime . diff ( now , datetime , :second )
286+
287+ cond do
288+ diff < 60 -> "#{ diff } s ago"
289+ diff < 3600 -> "#{ div ( diff , 60 ) } m ago"
290+ diff < 86400 -> "#{ div ( diff , 3600 ) } h ago"
291+ true -> "#{ div ( diff , 86400 ) } d ago"
292+ end
293+ end
294+ end
0 commit comments