import express from 'express'; import * as api from './api-connection.js'; import * as tools from './tools.js'; import * as notes from './notes.js'; import * as wget from './wget.js'; import * as chat from './chat.js'; const app = express(); app.use( express.json() ); var PORT = 3001; var DOMAIN = 'http://localhost'; export function listen( port: number, domain: string ) { PORT = port; DOMAIN = domain; api.setStatus( { domain: `${DOMAIN}:${(port == 443 || port == 80)? '' : port}` } ); app.listen( PORT, () => { console.log( `Server listening on ${DOMAIN}:${PORT}` ); }); } app.post( '/chat', async( req: any, res: any ) => { let messages: chat.Msg[] | undefined = req.body.messages; let options: chat.Options | undefined = req.body.options; if( !options || !messages ) return res.status( 401 ).json( { status: 'error', msg: 'options not provided' } ); if( api.status.isBusy ) return res.status( 401 ).json( { status: 'busy', msg: 'please wait' } ); res.header( 'Transfer-Encoding', 'chunked' ); api.serverNotify( { isBusy: true } ); wget.resetUseCount(); tools.resetUseCount(); let onChunk = ( chunk: string, isTool: boolean ) => { const chatStream: chat.Stream = { response: chunk, status: 'ok', done: false, tool: !!isTool }; res.write( JSON.stringify( chatStream ) + '\n' ); }; try { const notelog = notes.load( options.uuid ); const chatRes = await chat.run( messages, options, false, notelog, onChunk ); messages.push( chatRes ); const stream: chat.Stream = { status: 'ok', done: false, finalMsg: chatRes.content, } if( chatRes.toolCall ) { res.write( JSON.stringify( stream ) + '\n' ); const toolRes = await tools.run( messages, options, chatRes.toolCall, notelog, onChunk ); res.end( JSON.stringify( { status: 'ok', done: true, finalMsg: toolRes.content, title: chatRes.title } ) + "\n" ); } else { res.end( JSON.stringify( { status: 'ok', done: true, finalMsg: chatRes.content, title: chatRes.title } ) + "\n" ); } if( options.chatfile ) chat.save( messages, options.chatfile ); } catch( e: any ) { console.log( e ); res.end( JSON.stringify( { status: 'error', msg: e.message } ) ); } api.serverNotify( { isBusy: false } ); } ); app.post( '/generate', async( req: any, res: any ) => { let { prompt, suffix, options } = req.body; if( api.status.isBusy ) return res.status( 401 ).json( { status: 'busy', msg: 'please wait' } ); if( !options ) return res.status( 401 ).json( { status: 'error', msg: 'options not provided' } ); res.header( 'Transfer-Encoding', 'chunked' ); api.serverNotify( { isBusy: true } ); let onChunk = ( chunk: string ) => { const chatStream: chat.Stream = { response: chunk, status: 'ok', done: false }; res.write( JSON.stringify( chatStream ) + '\n' ); } try { const gen = await chat.generate( prompt, suffix, options, onChunk ); const end: chat.Stream = { status: 'ok', done: true, finalMsg: gen }; res.end( JSON.stringify( end ) ); } catch( e: any ) { console.log( e ); res.end( JSON.stringify( { status: 'error', msg: e.message } ) ); } api.serverNotify( { isBusy: false } ); } ); // todo later app.post( '/get-chat', async( _: any, res: any ) => { return res.status( 400 ).json( { status: 'err', msg: 'not implemented' } ); } ); // todo later app.post( '/list-chats', async( _: any, res: any ) => { return res.status( 400 ).json( { status: 'err', msg: 'not implemented' } ); } );