import $ from 'jquery'; import * as JSX from './jsx'; import * as api from './api'; import * as user from './user'; import * as chat from './chat'; import { Page } from './components'; import { ChatInput, ChatList } from './chat'; let start_w = 0, start_h = 0; let start_mx = 0, start_my = 0; let is_resizing = false; let has_listener = false; function startResize( e: MouseEvent ) { const terminal = $( "#terminal" ); start_mx = e.pageX; start_my = e.pageY; if( terminal[0].style.width ) start_w = parseInt( terminal[0].style.width ); else start_w = terminal[0].clientWidth; if( terminal[0].style.height ) start_h = parseInt( terminal[0].style.height ); else start_h = terminal[0].clientHeight * 1.05; window.addEventListener( "touchmove", resize ); window.addEventListener( "touchend", saveSize ); window.addEventListener( "touchcancel", saveSize ); window.addEventListener( "mousemove", resize ); window.addEventListener( "mouseup", saveSize ); is_resizing = true; } function resize( e: MouseEvent ) { if( !is_resizing ) return; let new_w = start_w + ( e.pageX - start_mx ) * 2.0; let new_h = start_h + ( ( e.pageY - start_my ) * 1.05 ); const body = $( "body" ); const max_h = body.outerHeight() - 60; if( new_h > max_h ) new_h = max_h; const terminal = $( "#terminal" ); terminal.css( `width`, `${ new_w }px` ); terminal.css( `height`, `${ new_h }px` ); } function saveSize() { if( !is_resizing ) return; const terminal = $( "#terminal" ); let size = { width: terminal[0].style.width, height: terminal[0].style.height, }; is_resizing = false; localStorage.setItem( "terminal-size", JSON.stringify( size ) ); window.removeEventListener( "touchmove", resize ); window.removeEventListener( "touchend", saveSize ); window.removeEventListener( "touchcancel", saveSize ); window.removeEventListener( "mousemove", resize ); window.removeEventListener( "mouseup", saveSize ); } function getStyleForSize() { let style = ""; if( window.innerWidth > 768 ) { const size_settings = localStorage.getItem( "terminal-size" ); if( size_settings ) { const parsed = JSON.parse( size_settings ); style = `width: ${ parsed.width }; height: ${ parsed.height };`; } } else { style = `width: 95%; height: ${Math.floor( window.innerHeight - 130 )}px`; } return style; } function onWindowResize() { const terminal = $( "#terminal" ); const style = getStyleForSize(); terminal.attr( "style", style ); if( window.innerWidth < 768 ) $( "#terminal-resizer" ).hide(); else $( "#terminal-resizer" ).show(); } function focusInput( e: Event ) { const sel = window.getSelection(); if( sel && sel.type == 'Range' ) return; const input = $( "#cmd-input" ); const content = input.find( "#input-content" ); if( !input.length || !content.length ) return; for( let iclass of ( e.target as HTMLElement )?.classList ) { if( iclass.startsWith( "tool-call" ) ) return; } input[0].focus(); // move cursor to the end of text if( sel.anchorNode != content[0] && sel.anchorNode.parentElement != content[0] ) { const range = document.createRange(); if( content.length ) { const child = content[0].firstChild; if( child ) { range.setStart( child, 0 ); range.setEnd( child, child.textContent.length ); } else { range.selectNodeContents( content[0] ); } range.collapse( false ); sel.removeAllRanges(); sel.addRange( range ); } } } function TerminalResizer( props: any ) { return
} let promptc = 0; function writePrompt( promptTxt: string ) { let el = $(
inputPrompt( promptTxt ) }>
); let writeChar = ( str: string, i: number ) => { if( i >= str.length ) return; let char = str.charAt( i ); let link = el.find( 'a' ); let text = link.text(); link.text( text + char ); setTimeout( () => writeChar( str, i + 1 ), 50 ); }; writeChar( promptTxt, 0 ); $( '#suggested-prompts' ).append( el ); } async function getPrompts() { const prompts_req = await fetch( `${window.location.origin}/static/prompts.json` ); const data = await prompts_req.json(); const { prompts } = data; const shuffled = prompts.sort( () => Math.random() - 0.5 ); const random_prompts = shuffled.slice( 0, 5 ); random_prompts.forEach( ( p: string ) => { writePrompt( p ); } ); } function inputPrompt( txt: string ) { const input = $( "#cmd-input" ); const el = input[0] as HTMLInputElement; input.text( txt ); input[0].focus(); let range = document.createRange() let sel = window.getSelection() range.setStart( el.childNodes[0], txt.length ); range.collapse( true ) sel.removeAllRanges() sel.addRange( range ) } function SuggestedPrompts() { setTimeout( () => { if( !chat.msglog.length ) getPrompts(); } ); return
} function TerminalWindow() { if( !has_listener ) { window.onresize = onWindowResize; has_listener = true; } const style = getStyleForSize(); return
} function ModelCapabilities() { const model = api.getModelFromName( user.settings.site_prefs.model! ); if( !model ) return
const capabilities = model.capabilities; if( !capabilities ) return
let model_str = `${model.name} | `; model_str += `vision ${capabilities.vision ? '✔' : '✘'} | `; model_str += `web ${capabilities.web ? '✔' : '✘'} | `; model_str += `notes ${capabilities.notes ? '✔' : '✘'} | `; model_str += `memory lookup ${capabilities.remind ? '✔' : '✘'}`; // todo: later // model_str += ` | reasoning ${capabilities.reasoning ? '✔' : '✘'}`; return
{ model_str }
} export function updateCapabilitiesDisplay() { const div = $( "#model-capabilities" ); if( div.length > 0 ) div.replaceWith( ); } export default function Terminal() { if( !user.is_loggedin ) { setTimeout( () => JSX.navigate( "/" ) ); return not logged in } return }