55 < meta http-equiv ="Cache-Control " content ="no-cache, no-store, must-revalidate ">
66 < meta http-equiv ="Pragma " content ="no-cache ">
77 < meta http-equiv ="Expires " content ="0 ">
8- < title > AION</ title >
8+ < title > AION · Ada‑VELA </ title >
99</ head >
1010< body >
1111 < div id ="chat " style ="height:400px; overflow:auto; border:1px solid #ccc; margin:10px; padding:10px; "> </ div >
1212 < div style ="margin:10px; ">
1313 < input type ="text " id ="input " style ="width:70%; padding:10px; ">
1414 < button onclick ="send() " style ="padding:10px 20px; "> Send</ button >
1515 </ div >
16+ < div style ="margin:10px; font-size:12px; color:#666; ">
17+ < span id ="sessionDisplay "> </ span > |
18+ < span id ="velaDisplay "> ⚖️ VELA: ready</ span >
19+ </ div >
1620
1721 < script >
22+ // ============================================================
23+ // ADA‑VELA v1.0 – Lightweight frontend implementation
24+ // Features: State tracking, Operation recording
25+ // ============================================================
26+
1827 const API = 'https://aion-backend-mu.vercel.app' ;
1928
29+ // ========== Ada‑VELA Core Classes ==========
30+
31+ // Triple timestamp (simplified for browser)
32+ function tripleTimestamp ( ) {
33+ const now = new Date ( ) ;
34+ return {
35+ gregorian : now . toISOString ( ) ,
36+ unix : Math . floor ( now . getTime ( ) / 1000 )
37+ } ;
38+ }
39+
40+ // AdaVariable – tracks state with history
41+ class AdaVariable {
42+ constructor ( name , initialValue ) {
43+ this . name = name ;
44+ this . value = initialValue ;
45+ this . history = [ {
46+ timestamp : tripleTimestamp ( ) ,
47+ value : initialValue ,
48+ operation : 'INIT'
49+ } ] ;
50+ }
51+
52+ get ( ) {
53+ return this . value ;
54+ }
55+
56+ set ( newValue , operation = 'SET' ) {
57+ this . history . push ( {
58+ timestamp : tripleTimestamp ( ) ,
59+ from : this . value ,
60+ to : newValue ,
61+ operation : operation
62+ } ) ;
63+ this . value = newValue ;
64+ return this ;
65+ }
66+
67+ trace ( ) {
68+ return this . history ;
69+ }
70+ }
71+
72+ // AdaOperation – records execution
73+ class AdaOperation {
74+ constructor ( name , description ) {
75+ this . name = name ;
76+ this . description = description ;
77+ this . executions = [ ] ;
78+ this . fn = null ;
79+ }
80+
81+ setFunction ( fn ) {
82+ this . fn = fn ;
83+ return this ;
84+ }
85+
86+ async execute ( input ) {
87+ if ( ! this . fn ) throw new Error ( `Operation ${ this . name } has no function` ) ;
88+
89+ const startTime = tripleTimestamp ( ) ;
90+ let result = null ;
91+ let error = null ;
92+
93+ try {
94+ result = await this . fn ( input ) ;
95+ } catch ( err ) {
96+ error = { message : err . message } ;
97+ }
98+
99+ const endTime = tripleTimestamp ( ) ;
100+ const execution = {
101+ id : crypto . randomUUID ? crypto . randomUUID ( ) : Date . now ( ) + '_' + Math . random ( ) ,
102+ name : this . name ,
103+ startTime,
104+ endTime,
105+ duration : endTime . unix - startTime . unix ,
106+ input,
107+ result : result ,
108+ error : error
109+ } ;
110+
111+ this . executions . push ( execution ) ;
112+
113+ if ( error ) throw new Error ( error . message ) ;
114+ return { result, execution } ;
115+ }
116+
117+ getExecutions ( ) {
118+ return this . executions ;
119+ }
120+ }
121+
122+ // ========== Application State ==========
123+
124+ // Session state with AdaVariable
125+ let sessionVar = new AdaVariable ( 'session' , null ) ;
20126 let sessionId = localStorage . getItem ( 'sessionId' ) ;
21127 if ( ! sessionId ) {
22128 sessionId = 'sess_' + Date . now ( ) + '_' + Math . random ( ) . toString ( 36 ) . substr ( 2 , 6 ) ;
23129 localStorage . setItem ( 'sessionId' , sessionId ) ;
24130 }
131+ sessionVar . set ( sessionId , 'SESSION_LOADED' ) ;
132+
133+ // Chat history with AdaVariable
134+ let chatHistory = new AdaVariable ( 'chatHistory' , [ ] ) ;
135+
136+ // UI state
137+ let isSending = false ;
25138
139+ // DOM elements
26140 const chatDiv = document . getElementById ( 'chat' ) ;
27141 const inputField = document . getElementById ( 'input' ) ;
142+ const sessionDisplay = document . getElementById ( 'sessionDisplay' ) ;
143+ const velaDisplay = document . getElementById ( 'velaDisplay' ) ;
144+
145+ sessionDisplay . textContent = `Session: ${ sessionId . slice ( - 8 ) } ` ;
146+
147+ // ========== Ada‑VELA Operations ==========
148+
149+ // API Call Operation
150+ const assistantOp = new AdaOperation ( 'ASSISTANT_CALL' , 'Calls the AION assistant API' ) ;
151+ assistantOp . setFunction ( async ( message ) => {
152+ const response = await fetch ( `${ API } /api/assistant` , {
153+ method : 'POST' ,
154+ headers : { 'Content-Type' : 'application/json' } ,
155+ body : JSON . stringify ( {
156+ message : message ,
157+ sessionId : sessionId ,
158+ ownerType : 'sheldon' ,
159+ history : [ ]
160+ } )
161+ } ) ;
162+ const data = await response . json ( ) ;
163+ if ( ! response . ok ) throw new Error ( data . error || 'API error' ) ;
164+ return data ;
165+ } ) ;
166+
167+ // ========== Helper Functions ==========
28168
29- function addMessage ( role , text ) {
169+ function addMessage ( role , text , metadata = { } ) {
30170 const msgDiv = document . createElement ( 'div' ) ;
31171 msgDiv . style . margin = '8px 0' ;
32172 msgDiv . style . padding = '8px' ;
173+
33174 if ( role === 'user' ) {
34175 msgDiv . style . backgroundColor = '#e3f2fd' ;
35176 msgDiv . style . textAlign = 'right' ;
36- msgDiv . innerHTML = ' <b>You:</b> ' + text ;
177+ msgDiv . innerHTML = ` <b>You:</b> ${ text } ` ;
37178 } else {
38179 msgDiv . style . backgroundColor = '#f5f5f5' ;
39- msgDiv . innerHTML = '<b>AI:</b> ' + text ;
180+ let metaHtml = '' ;
181+ if ( metadata . vela ) {
182+ metaHtml = `<span style="font-size:10px; color:#888; margin-left:8px;">⚖️ VELA: ${ metadata . vela } </span>` ;
183+ }
184+ msgDiv . innerHTML = `<b>AI:</b> ${ text } ${ metaHtml } ` ;
40185 }
186+
41187 chatDiv . appendChild ( msgDiv ) ;
42188 chatDiv . scrollTop = chatDiv . scrollHeight ;
189+
190+ // Record in chat history
191+ chatHistory . set ( [ ...chatHistory . get ( ) , { role, text, timestamp : tripleTimestamp ( ) } ] , `ADD_MESSAGE_${ role } ` ) ;
43192 }
44193
45194 async function send ( ) {
46195 const message = inputField . value . trim ( ) ;
47196 if ( ! message ) return ;
197+ if ( isSending ) return ;
48198
49199 addMessage ( 'user' , message ) ;
50200 inputField . value = '' ;
51201 inputField . disabled = true ;
202+ isSending = true ;
52203
53204 const thinking = document . createElement ( 'div' ) ;
54205 thinking . style . margin = '8px 0' ;
59210 chatDiv . scrollTop = chatDiv . scrollHeight ;
60211
61212 try {
62- const res = await fetch ( `${ API } /api/assistant` , {
63- method : 'POST' ,
64- headers : { 'Content-Type' : 'application/json' } ,
65- body : JSON . stringify ( {
66- message : message ,
67- sessionId : sessionId ,
68- ownerType : 'sheldon' ,
69- history : [ ]
70- } )
71- } ) ;
72-
73- const data = await res . json ( ) ;
213+ // Execute the operation with Ada‑VELA tracking
214+ const { result, execution } = await assistantOp . execute ( message ) ;
74215
75- if ( res . ok && data . response ) {
76- thinking . innerHTML = '<b>AI:</b> ' + data . response ;
216+ if ( result && result . response ) {
217+ thinking . innerHTML = `<b>AI:</b> ${ result . response } ` ;
218+
219+ // Update VELA display if PAC data available
220+ if ( result . pac ) {
221+ const ppi = result . pac . ppi ;
222+ if ( ppi < 30 ) velaDisplay . innerHTML = '⚠️ VELA: BLOCKED' ;
223+ else if ( ppi < 70 ) velaDisplay . innerHTML = '⚖️ VELA: FLAGGED' ;
224+ else velaDisplay . innerHTML = '⚖️ VELA: PASS' ;
225+ } else {
226+ velaDisplay . innerHTML = '⚖️ VELA: active' ;
227+ }
228+
229+ // Add metadata to the message
230+ const lastMsg = chatDiv . lastChild ;
231+ if ( lastMsg && lastMsg !== thinking ) {
232+ // Already added, but we can add VELA badge to thinking
233+ const velaBadge = document . createElement ( 'span' ) ;
234+ velaBadge . style . fontSize = '10px' ;
235+ velaBadge . style . color = '#888' ;
236+ velaBadge . style . marginLeft = '8px' ;
237+ velaBadge . textContent = result . pac ? ` ⚖️ PPI:${ result . pac . ppi } ` : '' ;
238+ thinking . appendChild ( velaBadge ) ;
239+ }
77240 } else {
78- thinking . innerHTML = ' <b>AI:</b> Error: ' + ( data . error || 'Unknown' ) ;
241+ thinking . innerHTML = ` <b>AI:</b> Error: No response` ;
79242 }
243+
244+ // Log execution trace (view in console)
245+ console . log ( '[Ada‑VELA] Operation execution:' , execution ) ;
246+
80247 } catch ( err ) {
81- thinking . innerHTML = '<b>AI:</b> Connection error: ' + err . message ;
248+ thinking . innerHTML = `<b>AI:</b> Error: ${ err . message } ` ;
249+ velaDisplay . innerHTML = '⚠️ VELA: error' ;
82250 }
83251
84252 inputField . disabled = false ;
85253 inputField . focus ( ) ;
254+ isSending = false ;
255+ }
256+
257+ // View trace in console (for debugging)
258+ function showTrace ( ) {
259+ console . log ( '=== Ada‑VELA Session Trace ===' ) ;
260+ console . log ( 'Session:' , sessionVar . trace ( ) ) ;
261+ console . log ( 'Chat History:' , chatHistory . trace ( ) ) ;
262+ console . log ( 'API Calls:' , assistantOp . getExecutions ( ) ) ;
86263 }
87264
88265 inputField . addEventListener ( 'keypress' , ( e ) => {
89266 if ( e . key === 'Enter' ) send ( ) ;
90267 } ) ;
91268
92- addMessage ( 'ai' , 'Connected. Type a message.' ) ;
269+ // Initial message
270+ addMessage ( 'ai' , 'Ada‑VELA active. State is tracked. Open console to see traces (F12).' ) ;
271+ console . log ( 'Ada‑VELA initialized. Session:' , sessionId ) ;
93272 </ script >
94273</ body >
95274</ html >
0 commit comments